From 2e537dc6cadb8024ec88e95e5b5c4c5f166803ab Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 13 Nov 2026 00:36:11 -0500 Subject: [PATCH] docs(heidenhain): honest provenance for alarm class/group codes (#853) No public source exists for DNC_ERROR_CLASS / DNC_ERROR_GROUP or their numbers (the table was written from memory). The iTNC 530 Technical Manual's PLC error table documents the same class and group NAMES without codes; three real iTNC 530 records corroborate 7/4, 7/3 and 1/3. DNC and LSV2 numberings are known to differ (ProgramStatus vs R_RI 26), so the numbers stay unproven. Docs/comments only; no behaviour change. Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk --- .claude/rules/drivers.md | 2 +- docs/drivers/Heidenhain.md | 25 ++++++++++++++----- .../HeidenhainAlarmClasses.cs | 13 ++++++---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.claude/rules/drivers.md b/.claude/rules/drivers.md index a29393667..26baeb186 100644 --- a/.claude/rules/drivers.md +++ b/.claude/rules/drivers.md @@ -370,7 +370,7 @@ panel with the NAT/IPv6-zone/loose-match caveats) / CLI `--validate-host-name`. allowlist is unchanged. FOCAS transition rules; identity = class+group+number+TEXT (numbers repeat, `-1`). A failed walk (refusal/overflow/comms) is quality-only, never a clear. ⚠️ Ack is LOCAL-ONLY (`AcknowledgeAsync` no-op success) — never add an LSV2 ack/write to the allowlist for it. Class/group codes have no invented SEVERITIES; since #839 they - carry HEIDENHAIN DNC-interface names (labels + browse leaves only — corroborated by one iTNC 530 record, else + carry class/group names (labels + browse leaves only; names per the iTNC 530 PET table, numbers from memory — corroborated by three iTNC 530 records, else hardware-unproven) and set the Part 9 `ConditionClass` (class 5 ⇒ Safety; group 1/2 ⇒ Process; 4/5 ⇒ System; else Base) via the new optional `AlarmEventArgs.ConditionClass` (projector keeps it across class-less events; node manager writes it; rebuild carries it). The browse picker offers `AlarmConditions/` selector leaves; alarms no selector claims are diff --git a/docs/drivers/Heidenhain.md b/docs/drivers/Heidenhain.md index 8cec0cc62..9e22939a9 100644 --- a/docs/drivers/Heidenhain.md +++ b/docs/drivers/Heidenhain.md @@ -311,12 +311,25 @@ are 0–65535 (wire uint16), NUMBER is int32. Selectors always filter on the **r `Alarms/Groups` or a condition message, then filter. One parser (`HeidenhainAlarmSelector`) backs the editor, the deploy inspector and the driver. -**Class / group names and the Part 9 condition class (Gitea #839).** LSV2 documents neither field (pyLSV2 and the Java -port keep them raw). `HeidenhainAlarmClasses` carries HEIDENHAIN's own names from the **DNC interface** (RemoTools SDK -`DNC_ERROR_CLASS` / `DNC_ERROR_GROUP`), which describe the same control error list. That the LSV2 codes share that -numbering is corroborated by the one real record we hold — the captured iTNC 530 "Run test of cutout channels" is class 7 -`INFO`, group 4 `GENERAL`, a power-up self-test notice — and is otherwise **hardware-unproven** (the commissioning gate -should confirm it on a live control). +**Class / group names and the Part 9 condition class (Gitea #839, #853).** LSV2 documents neither field (pyLSV2 and the +Java port keep them raw — pyLSV2's `decode_error_message` is class/group/number/text only). The names in +`HeidenhainAlarmClasses` were originally written as the DNC interface's `DNC_ERROR_CLASS` / `DNC_ERROR_GROUP` enums +**from memory**; a 2026-11-13 search found **no public source for those enums or their numeric values**. What the +public sources do establish: + +- **Names (vendor-documented, numbers not).** The iTNC 530 HSCI Technical Manual's PLC error table (`.PET`) has a + **Class** column — ERROR (collective), FEED HOLD, PGM HOLD, PGM ABORT, EMERG. STOP, RESET — and a **Group** column — + GENERAL, OPERATING, PROGRAMMING, PLC — plus a separate E/W/I message-type column. That is the same class set as our + 2–6 (and in the same order) and the same group set as our 1–4; WARNING/INFO/NOTE look like the message type folded + into the LSV2 class code, which is unconfirmed. +- **Observed records (real iTNC 530, read-only).** class 7 / group 4 "Run test of cutout channels" (power-up self-test); + class 7 / group 3 "701550 Cabin unlocked! B301" (Hermle70, Hermle29); class 1 / group 3 "700520 Tool life exceeded" + (Hermle49). Both 7xxxxx records are machine-builder PET messages and both report group 3 — consistent with 3 = PLC. +- ⚠️ **"LSV2 shares the DNC numbering" is not a safe general assumption.** The DNC COM interface's `ExecutionMode` + (0 MANUAL, 1 MDI, 2 RPF, 3 SINGLESTEP, 4 AUTOMATIC) matches LSV2 `R_RI 23`, but its `ProgramStatus` (0 IDLE, + 1 RUNNING, …) does **not** match LSV2 `R_RI 26` (0 Started … 7 Idle, which real controls confirm). So the class/group + numbers stay **hardware-unproven** except where a record above shows them; the Safety branch (class 5) has never + been observed. | Class | 1 Warning · 2 FeedHold · 3 ProgramHold · 4 ProgramAbort · **5 EmergencyStop** · 6 Reset · 7 Info · 8 Error · 9 Note | |---|---| diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Contracts/HeidenhainAlarmClasses.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Contracts/HeidenhainAlarmClasses.cs index 00b6275b7..ba2d9d5f6 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Contracts/HeidenhainAlarmClasses.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Heidenhain.Contracts/HeidenhainAlarmClasses.cs @@ -8,11 +8,14 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Heidenhain; /// /// /// Provenance. LSV2 itself documents neither field (pyLSV2 and the ignitionoee Java port keep them -/// raw). The names are HEIDENHAIN's own error enums from the DNC interface (RemoTools SDK / HeidenhainDNC -/// DNC_ERROR_CLASS, DNC_ERROR_GROUP), which describe the same control error list. That the LSV2 -/// R_RI 27/28 codes use the same numbering is corroborated by the one real record we hold — the captured -/// iTNC 530 alarm "Run test of cutout channels" is class 7 (INFO), group 4 (GENERAL), a power-up -/// self-test notice — but is not otherwise proven on hardware. Treat the names as labels, never as behaviour: +/// raw). The names were first written as the DNC interface's DNC_ERROR_CLASS / +/// DNC_ERROR_GROUP enums from memory; no public source for those enums or their numbers was found +/// (lmxopcua#853). The iTNC 530 Technical Manual's PLC error table documents the same NAMES (class: ERROR, +/// FEED HOLD, PGM HOLD, PGM ABORT, EMERG. STOP, RESET; group: GENERAL, OPERATING, PROGRAMMING, PLC) but no +/// numeric codes. Real iTNC 530 records corroborate class 7 / group 4, class 7 / group 3 and class 1 / group 3 +/// (both group-3 records are machine-builder PLC messages). The DNC and LSV2 numberings are known to differ +/// elsewhere (program status), so the numbers stay hardware-unproven. Treat the names as labels, never as +/// behaviour: /// they drive no selection and no severity (an authored alarm.severity, else High, still decides that). /// Part 9 mapping — only where the code says where the alarm comes from. /// EMERGENCY_STOP (class 5) is a safety reaction ⇒ , whatever its