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
56 lines
2.4 KiB
Markdown
56 lines
2.4 KiB
Markdown
# 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`](../v2/driver-stability.md)).
|
|
|
|
For range-validation and per-series capability surface see
|
|
[`docs/v2/focas-version-matrix.md`](../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
|
|
|
|
```jsonc
|
|
{
|
|
"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` (see
|
|
[`docs/v2/implementation/focas-wire-protocol.md`](../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`.
|