Auto: focas-f3a — cnc_rdalmhistry alarm-history extension
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
This commit is contained in:
@@ -106,6 +106,42 @@ Tier-C pipeline end-to-end without any CNC.
|
||||
| "Does `Fwlib32.dll` crash on concurrent reads?" | no | yes (stress) |
|
||||
| "Do macro variables round-trip across power cycles?" | no | yes (required) |
|
||||
|
||||
## Alarm history (`cnc_rdalmhistry`) — issue #267, plan PR F3-a
|
||||
|
||||
`FocasAlarmProjection` ships two modes:
|
||||
|
||||
- **`ActiveOnly`** (default) — surfaces only currently-active alarms.
|
||||
No history poll. Same back-compat shape every prior FOCAS deployment used.
|
||||
- **`ActivePlusHistory`** — additionally polls `cnc_rdalmhistry` on connect
|
||||
+ on the configured cadence (`HistoryPollInterval`, default 5 min). Each
|
||||
unseen entry fires an `OnAlarmEvent` with `SourceTimestampUtc` set from
|
||||
the CNC's reported timestamp, not Now.
|
||||
|
||||
Unit-test coverage in `FocasAlarmProjectionTests`:
|
||||
|
||||
- mode `ActiveOnly` — no `ReadAlarmHistoryAsync` call ever issued
|
||||
- mode `ActivePlusHistory` — first poll fires on subscribe (== "on connect")
|
||||
- dedup — same `(OccurrenceTime, AlarmNumber, AlarmType)` triple across two
|
||||
polls only emits once
|
||||
- distinct entries with different timestamps each emit separately
|
||||
- same alarm number / different type still emits both (type is part of the
|
||||
dedup key)
|
||||
- `OccurrenceTime` is the wire timestamp (round-trips a year-old stamp
|
||||
without bleeding into Now)
|
||||
- `HistoryDepth` clamp — user-supplied 500 collapses to 250 on the wire;
|
||||
zero / negative falls back to the 100 default
|
||||
- `FocasAlarmHistoryDecoder` — round-trips through `Encode` / `Decode` and
|
||||
pins the simulator command id at `0x0F1A`
|
||||
|
||||
Future integration coverage (not yet shipped — no FOCAS integration test
|
||||
project exists):
|
||||
|
||||
- a focas-mock with a per-profile ring buffer and `mock_patch_alarmhistory`
|
||||
admin endpoint will let `cnc_rdalmhistry` round-trip end-to-end through
|
||||
the wire protocol
|
||||
- `FocasSimFixture.SeedAlarmHistoryAsync` will let series tests prime canned
|
||||
history without per-test JSON
|
||||
|
||||
## Follow-up candidates
|
||||
|
||||
1. **Nothing public** — Fanuc's FOCAS Developer Kit ships an emulator DLL
|
||||
|
||||
55
docs/drivers/FOCAS.md
Normal file
55
docs/drivers/FOCAS.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user