Adds FocasAlarmProjection with two modes (ActiveOnly default, ActivePlusHistory) that polls cnc_rdalmhistry on connect + on a configurable cadence (5 min default, HistoryDepth=100 capped at 250). Emits historic events via IAlarmSource with SourceTimestampUtc set from the CNC's reported timestamp; dedup keyed on (OccurrenceTime, AlarmNumber, AlarmType). Ships the ODBALMHIS packed-buffer decoder + encoder in Wire/FocasAlarmHistoryDecoder.cs and threads ReadAlarmHistoryAsync through IFocasClient (default no-op so existing transport variants stay back-compat). FocasDriver now implements IAlarmSource. 13 new unit tests cover: mode switch, dedup, distinct-timestamp emission, type-as-key behaviour, OccurrenceTime passthrough (not Now), HistoryDepth clamp/fallback, and decoder round-trip. All 341 FOCAS unit tests still pass. Docs: docs/drivers/FOCAS.md (new), docs/v2/focas-deployment.md (new), docs/v2/implementation/focas-wire-protocol.md (new), docs/v2/implementation/focas-simulator-plan.md (new), docs/drivers/FOCAS-Test-Fixture.md (alarm-history bullet appended). Closes #267
2.4 KiB
FOCAS driver
Fanuc CNC driver for the FS 0i / 16i / 18i / 21i / 30i / 31i / 32i / 35i /
Power Mate i families. Talks to the controller via the licensed
Fwlib32.dll (Tier C, process-isolated per
docs/v2/driver-stability.md).
For range-validation and per-series capability surface see
docs/v2/focas-version-matrix.md.
Alarm history (cnc_rdalmhistry) — issue #267, plan PR F3-a
FocasAlarmProjection exposes two modes via FocasDriverOptions.AlarmProjection:
| Mode | Behaviour |
|---|---|
ActiveOnly (default) |
Subscribe / unsubscribe / acknowledge wire up so capability negotiation works, but no history poll runs. Back-compat with every pre-F3-a deployment. |
ActivePlusHistory |
On subscribe (== "on connect") and on every HistoryPollInterval tick, the projection issues cnc_rdalmhistry for the most recent HistoryDepth entries. Each previously-unseen entry fires an OnAlarmEvent with SourceTimestampUtc set from the CNC's reported timestamp — OPC UA dashboards see the real occurrence time, not the moment the projection polled. |
Config knobs
{
"AlarmProjection": {
"Mode": "ActivePlusHistory", // "ActiveOnly" (default) | "ActivePlusHistory"
"HistoryPollInterval": "00:05:00", // default 5 min
"HistoryDepth": 100 // default 100, capped at 250
}
}
Dedup key
(OccurrenceTime, AlarmNumber, AlarmType). The same triple across two
polls only emits once. The dedup set is in-memory and resets on
reconnect — first poll after reconnect re-emits everything in the ring
buffer. OPC UA clients that need exactly-once semantics dedupe client-side
on the same triple (the timestamp + type + number tuple is stable across
the boundary).
HistoryDepth cap
Capped at FocasAlarmProjectionOptions.MaxHistoryDepth = 250 so an
operator who types 10000 by accident can't blast the wire session with a
giant request. Typical FANUC ring buffers cap at ~100 entries; the default
HistoryDepth = 100 matches the most common ring-buffer size.
Wire surface
- Wire-protocol command id:
0x0F1A(seedocs/v2/implementation/focas-wire-protocol.md). - ODBALMHIS struct decoder:
Wire/FocasAlarmHistoryDecoder.cs. - Tier-C Fwlib32 backend short-circuits the packed-buffer decoder by
surfacing the FWLIB struct fields directly into
FocasAlarmHistoryEntry.