Audit of docs/ against src/ surfaced shipped features without current-reference coverage (FOCAS CLI, Core.Scripting+VirtualTags, Core.ScriptedAlarms, Core.AlarmHistorian), an out-of-date driver count + capability matrix, ADR-002's virtual-tag dispatch not reflected in data-path docs, broken cross-references, and OpcUaServerReqs declaring OPC-020..022 that were never scoped. This commit closes all of those so operators + integrators can stay inside docs/ without falling back to v2/implementation/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.4 KiB
otopcua-focas-cli — Fanuc FOCAS test client
Ad-hoc probe / read / write / subscribe tool for Fanuc CNCs via the FOCAS/2
protocol. Uses the same FocasDriver the OtOpcUa server does — PMC R/G/F
file registers, axis bits, parameters, and macro variables — all through
FocasAddressParser syntax.
Sixth of the driver test-client CLIs, added alongside the Tier-C isolation work tracked in task #220.
Architecture note
FOCAS is a Tier-C driver: Fwlib32.dll is a proprietary 32-bit Fanuc library
with a documented habit of crashing its hosting process on network errors.
The target runtime deployment splits the driver into an in-process
FocasProxyDriver (.NET 10 x64) and an out-of-process Driver.FOCAS.Host
(.NET 4.8 x86 Windows service) that owns the DLL — see
v2/implementation/focas-isolation-plan.md
and
v2/implementation/phase-6-1-resilience-and-observability.md
for topology + supervisor / respawn / back-pressure design.
The CLI skips the proxy and loads FocasDriver directly (via
FwlibFocasClientFactory, which P/Invokes Fwlib32.dll in the CLI's own
process). There is no public simulator for FOCAS; a meaningful probe
requires a real CNC + a licensed Fwlib32.dll on PATH (or next to the
executable). On a dev box without the DLL, every wire call surfaces as
BadCommunicationError — still useful as a "CLI wire-up is correct" signal.
Build + run
dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli -- --help
Or publish a self-contained binary:
dotnet publish src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli -c Release -o publish/focas-cli
publish/focas-cli/otopcua-focas-cli.exe --help
Common flags
Every command accepts:
| Flag | Default | Purpose |
|---|---|---|
-h / --cnc-host |
required | CNC IP address or hostname |
-p / --cnc-port |
8193 |
FOCAS TCP port (FOCAS-over-EIP default) |
-s / --series |
Unknown |
CNC series — Unknown / Zero_i_D / Zero_i_F / Zero_i_MF / Zero_i_TF / Sixteen_i / Thirty_i / ThirtyOne_i / ThirtyTwo_i / PowerMotion_i |
--timeout-ms |
2000 |
Per-operation timeout |
--verbose |
off | Serilog debug output |
Addressing
FocasAddressParser syntax — the same format the server + FocasTagDefinition
use. Common shapes:
| Address | Meaning |
|---|---|
R100 |
PMC R-file word register 100 |
X0.0 |
PMC X-file bit 0 of byte 0 |
G50.3 |
PMC G-file bit 3 of byte 50 |
F1.4 |
PMC F-file bit 4 of byte 1 |
PARAM:1815/0 |
Parameter 1815, axis 0 |
MACRO:500 |
Macro variable 500 |
Data types
Bit, Byte, Int16, Int32, Float32, Float64, String. Default is
Int16 (matches PMC R-file word width).
Commands
probe — is the CNC reachable?
Opens a FOCAS session, reads one sample address, prints driver health.
# Default: read R100 as Int16
otopcua-focas-cli probe -h 192.168.1.50
# Explicit series + address
otopcua-focas-cli probe -h 192.168.1.50 -s ThirtyOne_i --address R200 --type Int16
read — single address
# PMC R-file word
otopcua-focas-cli read -h 192.168.1.50 -a R100 -t Int16
# PMC X-bit
otopcua-focas-cli read -h 192.168.1.50 -a X0.0 -t Bit
# Parameter (axis 0)
otopcua-focas-cli read -h 192.168.1.50 -a PARAM:1815/0 -t Int32
# Macro variable
otopcua-focas-cli read -h 192.168.1.50 -a MACRO:500 -t Float64
write — single value
Values parse per --type with invariant culture. Booleans accept
true / false / 1 / 0 / yes / no / on / off.
otopcua-focas-cli write -h 192.168.1.50 -a R100 -t Int16 -v 42
otopcua-focas-cli write -h 192.168.1.50 -a G50.3 -t Bit -v on
otopcua-focas-cli write -h 192.168.1.50 -a MACRO:500 -t Float64 -v 3.14
PMC G/R writes land on a running machine — be careful which file you hit. Parameter writes may require the CNC to be in MDI mode with the parameter-write switch enabled.
Writes are non-idempotent by default — a timeout after the CNC already applied the write will NOT auto-retry (plan decisions #44 + #45).
subscribe — watch an address until Ctrl+C
FOCAS has no push model; the shared PollGroupEngine handles the tick
loop.
otopcua-focas-cli subscribe -h 192.168.1.50 -a R100 -t Int16 -i 500
Output format
Identical to the other driver CLIs via SnapshotFormatter:
probe/reademit a multi-line block:Tag / Value / Status / Source Time / Server Time.probeprefixes it withCNC,Series,Health, andLast errorlines.writeemits one line:Write <address>: 0x... (Good | BadCommunicationError | …).subscribeemits one line per change:[HH:mm:ss.fff] <address> = <value> (<status>).
Typical workflows
"Is the CNC alive?" → probe.
"Does my parameter write land?" → write + read back against the
same address. Check the parameter-write switch + MDI mode if the write
fails.
"Why did this macro flip?" → subscribe to the macro, let the
operator reproduce the cycle, watch the HH:mm:ss.fff timeline.
"Is the Fwlib32 DLL wired up?" → probe against any host. A
DllNotFoundException surfacing as BadCommunicationError with a
matching Last error line means the driver is loading but the DLL is
missing; anything else means a transport-layer problem.