chore(docker-dev): seed OpcUaClient driver for opc-plc + doc native-alarm source semantics (#619)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -201,3 +201,33 @@ IF NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-modbus-hr200')
|
|||||||
VALUES ('MAIN-modbus-hr200', 'MAIN-modbus-dev', NULL, 'HR200', 'UInt16', 'ReadWrite', 1,
|
VALUES ('MAIN-modbus-hr200', 'MAIN-modbus-dev', NULL, 'HR200', 'UInt16', 'ReadWrite', 1,
|
||||||
N'{ "region": "HoldingRegisters", "address": 200, "dataType": "UInt16", "writable": true }');
|
N'{ "region": "HoldingRegisters", "address": 200, "dataType": "UInt16", "writable": true }');
|
||||||
SELECT DriverInstanceId, ClusterId, DriverType, Enabled FROM dbo.DriverInstance WHERE ClusterId='MAIN';
|
SELECT DriverInstanceId, ClusterId, DriverType, Enabled FROM dbo.DriverInstance WHERE ClusterId='MAIN';
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- #619: OpcUaClient driver against the opc-plc fixture (10.100.0.35:50000, started by
|
||||||
|
-- tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.IntegrationTests/Docker with --alm).
|
||||||
|
-- Tag identity under v3 is the RawPath; the upstream node is authored in TagConfig.nodeId.
|
||||||
|
-- * FastUInt1 (ns=3;s=FastUInt1) is the always-moving VALUE control: proves the driver is connected and
|
||||||
|
-- the RawPath -> nodeId table resolves before any alarm assertion is trusted.
|
||||||
|
-- * The ALARM tag's nodeId must be the SourceNode opc-plc stamps on its condition events - the driver
|
||||||
|
-- matches events on it. It is NOT guessable (and opc-plc was not running when this was authored), so
|
||||||
|
-- it is supplied at seed time: browse opc-plc (Client.CLI `browse -r -d 4`, or `alarms --refresh`
|
||||||
|
-- which prints each event's source) and set @OpcPlcAlarmSourceNodeId below. Empty = no alarm tag.
|
||||||
|
-- Idempotent.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
DECLARE @OpcPlcAlarmSourceNodeId nvarchar(400) = N''; -- e.g. N'ns=3;s=<source from opc-plc>'
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM dbo.DriverInstance WHERE DriverInstanceId = 'MAIN-opcua')
|
||||||
|
INSERT dbo.DriverInstance(DriverInstanceId, ClusterId, RawFolderId, Name, DriverType, DriverConfig, Enabled)
|
||||||
|
VALUES ('MAIN-opcua', 'MAIN', NULL, 'opcplc', 'OpcUaClient',
|
||||||
|
N'{ "SecurityPolicy": "None", "SecurityMode": "None", "AuthType": "Anonymous", "AutoAcceptCertificates": true }', 1);
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM dbo.Device WHERE DeviceId = 'MAIN-opcua-dev')
|
||||||
|
INSERT dbo.Device(DeviceId, DriverInstanceId, Name, Enabled, DeviceConfig)
|
||||||
|
VALUES ('MAIN-opcua-dev', 'MAIN-opcua', 'plc', 1, N'{ "EndpointUrl": "opc.tcp://10.100.0.35:50000" }');
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-opcua-fastuint1')
|
||||||
|
INSERT dbo.Tag(TagId, DeviceId, TagGroupId, Name, DataType, AccessLevel, WriteIdempotent, TagConfig)
|
||||||
|
VALUES ('MAIN-opcua-fastuint1', 'MAIN-opcua-dev', NULL, 'FastUInt1', 'UInt32', 'Read', 0,
|
||||||
|
N'{ "nodeId": "ns=3;s=FastUInt1" }');
|
||||||
|
IF LEN(@OpcPlcAlarmSourceNodeId) > 0 AND NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-opcua-alarm1')
|
||||||
|
INSERT dbo.Tag(TagId, DeviceId, TagGroupId, Name, DataType, AccessLevel, WriteIdempotent, TagConfig)
|
||||||
|
VALUES ('MAIN-opcua-alarm1', 'MAIN-opcua-dev', NULL, 'Alarm1', 'Boolean', 'Read', 0,
|
||||||
|
N'{ "nodeId": "' + @OpcPlcAlarmSourceNodeId + N'", "alarm": { "alarmType": "AlarmCondition", "severity": 500 } }');
|
||||||
|
SELECT DriverInstanceId, ClusterId, DriverType, Enabled FROM dbo.DriverInstance WHERE DriverInstanceId = 'MAIN-opcua';
|
||||||
|
|||||||
@@ -91,6 +91,13 @@ rather than surfacing as a runtime surprise.
|
|||||||
| `IAlarmSource` | `SubscribeAlarmsAsync` (EventFilter) + `AcknowledgeAsync` | Subscribes to upstream alarm/condition events and forwards acks |
|
| `IAlarmSource` | `SubscribeAlarmsAsync` (EventFilter) + `AcknowledgeAsync` | Subscribes to upstream alarm/condition events and forwards acks |
|
||||||
| `IHistoryProvider` | `ReadRawAsync` / `ReadProcessedAsync` / `ReadAtTimeAsync` → `Session.HistoryReadAsync` | **Unique to this driver** — passthrough history read against the upstream server |
|
| `IHistoryProvider` | `ReadRawAsync` / `ReadProcessedAsync` / `ReadAtTimeAsync` → `Session.HistoryReadAsync` | **Unique to this driver** — passthrough history read against the upstream server |
|
||||||
|
|
||||||
|
> **Native alarms (#619).** An alarm raw tag is `TagConfig` `{ "nodeId": "<upstream SourceNode>", "alarm": {...} }`.
|
||||||
|
> The host subscribes with RawPaths and routes on (driver, RawPath), so the driver matches each event's
|
||||||
|
> `SourceNode` against the tag's authored `nodeId` and reports the **RawPath** as `ConditionId`; the upstream
|
||||||
|
> condition node (last seen per RawPath) is what `Acknowledge` is called on. `nodeId` must therefore be the
|
||||||
|
> event's *source*, not the condition node. docker-dev seeds an opc-plc driver (`MAIN-opcua`); the alarm tag is
|
||||||
|
> created only when `@OpcPlcAlarmSourceNodeId` is set in `docker-dev/seed/seed-clusters.sql`.
|
||||||
|
|
||||||
> This driver does **not** implement `IRediscoverable` — there is no
|
> This driver does **not** implement `IRediscoverable` — there is no
|
||||||
> push-driven rediscovery signal from a remote OPC UA server in this driver.
|
> push-driven rediscovery signal from a remote OPC UA server in this driver.
|
||||||
> `IHistoryProvider` is implemented by no other driver; history reads for every
|
> `IHistoryProvider` is implemented by no other driver; history reads for every
|
||||||
|
|||||||
Reference in New Issue
Block a user