FOCAS: native alarms never reach their Part 9 conditions #647
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the #641 work (see reports/641.md, docs/drivers/FOCAS.md).
FocasDriver.SubscribeAsync treats its sourceNodeIds argument as a device-host filter, but the host passes RawPaths, so nothing is ever polled. Events it does raise carry a decorated ConditionId "{host}#{Type}:{AlarmNumber}" and no Kind, so they cannot match a materialised condition (ConditionId = RawPath).
Needs a design for mapping a CNC's flat per-device alarm list onto per-RawPath conditions (which raw tag owns which alarm number/type; how unmatched alarms surface). Read-only (no ack upstream). Out of scope of #641, which only fixed carry-over across rebuilds.
Landed on master (
482bafdf+89961af6+bac93744, mergede7dd7425), opus-reviewed twice. Design: anALARM:address on a raw tag carrying thealarmobject = one Part 9 condition, ConditionId = RawPath, with a Kind. Selectors*,<Type>,<Type>/<n>,<Type>/<lo>-<hi>,T<code>,OTHER. All 7 triage defects fixed (failed read ≠ empty list; told-record dedup; no throw when the projection is off; half-authored tags skipped + reported).Review-driven host change (affects every native driver): a Raise on an already-Active condition with the same message is a re-statement — keeps the ack, writes no duplicate /alerts row — so a deploy that respawns a driver no longer un-acks active alarms (MTConnect had the same latent defect). OpcUaClient and the Galaxy snapshot now send Retrigger for an unacked condition with no prior record. Outages: transport fault ⇒ quality-only BadNoCommunication + Degraded health (alarm-only drivers can trip the watchdog); a CNC refusal of cnc_rdalmmsg2 ⇒ BadNotSupported, warn once, health untouched (no reconnect loop on a production control). Read-only: no FOCAS write path reachable; ack is server-side only.
Tests: FOCAS 506/506, Runtime 752/3 skip, full suite 12,994/0 failed. Left open for the live gate: fixture raise/clear/ack-survives-respawn/outage on docker-dev, AdminUI picker /run, passive read-only watch on the Makino. Known limit: the alarm-type names follow the 16i-era table; 31i codes unconfirmed (use
ALARM:T<code>).Live-gated and closing (master
ec375538).Driver.FOCAS.IntegrationTests14/14 (incl.Alarm_selectors), none env-skipped.otopcua-focas-fixture:ALARM:OvertravelandALARM:*produce one event per transition — Raise, Retrigger onALARM:*when a second alarm joins, Clear./alerts. (Ack on the non-Primary is refused0x80AF0000, by design.)BadNoCommunication, still Active+Acked,/hostsDEGRADED; pause/unpause recovery to Good with no un-ack / re-raise./raw: tag editor loadsALARM:*with the native-alarm toggle; reversed rangeALARM:Servo/10-5rejected on Save; address builder composesALARM:*.ALARM:*,ALARM:OTHER,ALARM:Servo,ALARM:T6— everycnc_rdalmmsg2OK and empty, zero events, health Healthy. No alarm occurred, so the CNC-refusal (BadNotSupported) path and 30i type codes were not observed live.Found and fixed along the way:
ObjectDisposedException). Per-device connect gate inFocasDriver.EnsureConnectedAsync; a caller's own cancellation no longer opens the backoff window. (c940349f,54a00fd7)alarmsnever printedEventId/ConditionNodeId, soackwas unusable from the CLI. (c6ab783c)FocasAlarmProjectionTests(quality-only events beforePauseAsync) — test fix only. (f594b29a)