Auto: twincat-5.1 — IAlarmSource via TC3 EventLogger (gated, scaffold)
Closes #316
This commit is contained in:
@@ -278,6 +278,88 @@ dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests `
|
||||
--filter "FullyQualifiedName~TwinCATSymbolVersionTests"
|
||||
```
|
||||
|
||||
## Alarm scenarios
|
||||
|
||||
PR 5.1 (#316) ships an opt-in TC3 EventLogger bridge. The driver's
|
||||
`IAlarmSource` implementation surfaces alarms by opening a second
|
||||
`AdsClient` against AMS port `110` (`AMSPORT_EVENTLOG`) and adding a
|
||||
device notification on `ADSIGRP_TCEVENTLOG_ALARMS`. The decode is
|
||||
best-effort because Beckhoff doesn't ship a managed `TcEventLogger`
|
||||
wrapper (only C++ TcCOM headers); some fields surface as `Unknown`
|
||||
until a follow-up PR lands a binary-protocol decoder. Spike output
|
||||
captured at `docs/v3/twincat-eventlogger-spike.md`.
|
||||
|
||||
The integration test
|
||||
(`TwinCATAlarmIntegrationTests.Driver_raises_alarm_event_when_PLC_logs_event`)
|
||||
ships build-only in PR 5.1 — once the XAR project imports the GVL +
|
||||
FB_AlarmHarness below, swap the `Assert.Skip` in the test body for the
|
||||
live flow:
|
||||
|
||||
1. Init the driver with `EnableAlarms=true`.
|
||||
2. `SubscribeAlarmsAsync([], ct)`.
|
||||
3. `WriteAsync` to flip `GVL_Alarms.bTriggerEvent` from `FALSE` to
|
||||
`TRUE` — `FB_AlarmHarness` sees the rising edge and calls
|
||||
`FB_TcLogEvent` on the PLC side.
|
||||
4. Assert `OnAlarmEvent` fires within `~5 s` with non-empty
|
||||
`Source` + `Message`.
|
||||
|
||||
### Global Variable List: `GVL_Alarms`
|
||||
|
||||
```st
|
||||
VAR_GLOBAL
|
||||
bTriggerEvent : BOOL := FALSE;
|
||||
bAcked : BOOL := FALSE;
|
||||
nLastEventClass : DINT := 0;
|
||||
nLastSeverity : USINT := 0;
|
||||
fbAlarmHarness : FB_AlarmHarness;
|
||||
END_VAR
|
||||
```
|
||||
|
||||
The XAE-form GVL ships at `PLC/GVLs/GVL_Alarms.TcGVL`; import it
|
||||
alongside the other fixture GVLs.
|
||||
|
||||
### POU: `FB_AlarmHarness`
|
||||
|
||||
```st
|
||||
FUNCTION_BLOCK FB_AlarmHarness
|
||||
VAR
|
||||
fbTrigger : R_TRIG;
|
||||
fbLogEvent : FB_TcLogEvent; // declared in Tc3_EventLogger
|
||||
sMessage : STRING(255) := 'Integration-fixture EventLogger trigger';
|
||||
END_VAR
|
||||
|
||||
fbTrigger(CLK := GVL_Alarms.bTriggerEvent);
|
||||
IF fbTrigger.Q THEN
|
||||
fbLogEvent.eSeverity := TcEventSeverity.Warning;
|
||||
fbLogEvent.bConfirmable := TRUE;
|
||||
fbLogEvent.Execute(bExecute := TRUE);
|
||||
GVL_Alarms.nLastEventClass := 1;
|
||||
GVL_Alarms.nLastSeverity := 100;
|
||||
END_IF
|
||||
fbLogEvent.Execute(bExecute := FALSE);
|
||||
```
|
||||
|
||||
The XAE-form POU ships at `PLC/POUs/FB_AlarmHarness.TcPOU`. Wire it
|
||||
into `MAIN`:
|
||||
|
||||
```st
|
||||
GVL_Alarms.fbAlarmHarness();
|
||||
```
|
||||
|
||||
### Event class IDs / severity buckets / cleared-on transitions
|
||||
|
||||
| Symbol | Value | Notes |
|
||||
| --- | --- | --- |
|
||||
| `nLastEventClass` | `DINT`, fixture-side echo (`1` after a rising edge) | Watch-window aid; the actual EventLogger event class is configured in the TC3 GUI per project. |
|
||||
| `nLastSeverity` | `USINT`, fixed `100` after a rising edge | Maps to `AlarmSeverity.Medium` via `TwinCATAlarmSource.MapSeverity` (≤128 = Medium). |
|
||||
| `bTriggerEvent` | `BOOL`, operator/test writes | Rising edge only — flip back to `FALSE` then `TRUE` to re-fire. |
|
||||
| `bAcked` | `BOOL`, driver writes when `AcknowledgeAsync` runs | Cleared by next event raise. |
|
||||
|
||||
The TC3 EventLogger surfaces the cleared transition automatically when
|
||||
`fbLogEvent.bConfirmable=TRUE` and an operator confirms; the driver
|
||||
projects the clear as a second `OnAlarmEvent` with the same condition
|
||||
id.
|
||||
|
||||
## How to run the TwinCAT-tier tests
|
||||
|
||||
On the dev box:
|
||||
|
||||
Reference in New Issue
Block a user