Commit Graph

2 Commits

Author SHA1 Message Date
Joseph Doherty 380ec541c2 feat(cli): historyread --events reads event history over the wire (lmxopcua#776)
v2-ci / unit-tests (push) Has been cancelled
Item 1 of #776 (the B2 over-the-wire ask): Client.CLI had no way to issue a
HistoryReadEvents. `historyread --events` now sends ReadEventDetails to an
event notifier and prints one line per event in select-clause order.
--fields picks the select clauses (default EventId, EventType, Time,
SourceName, Severity, Message, ConditionName (on ConditionType), SourceNode);
--of-type adds an OfType where-clause. --events is exclusive with --modified /
--aggregate, and --fields / --of-type require it.

Client.Shared gains IOpcUaClientService/ISessionAdapter.HistoryReadEventsAsync
(default-implemented as NotSupported for other implementations) backed by the
real session adapter through HistoryReadPaging, so continuation points are
followed up to --max and a Bad node status is surfaced, not printed as empty.

Tests: CLI tests over the fake service (default filter, --fields/--of-type
filter, option conflicts); an over-the-wire test drives the shared client's
event read against the in-process server — the default fields come back
non-null, OfType filters, an invalid where-clause is BadEventFilterInvalid.
The other #776 items are decisions and are left open.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 16:17:24 -05:00
Joseph Doherty 29665c1872 feat(opcua): HistoryReadEvents projects EventType, ConditionName, SourceNode; honours the where-clause (lmxopcua#746)
HistoryReadEvents projected only EventId / SourceName / Time / ReceiveTime /
Message / Severity: a select clause asking for EventType, ConditionName or
SourceNode (what most generic alarm viewers ask for) got nulls, and the
event filter's where-clause (an OfType) was ignored.

- HistoricalEvent gains optional EventTypeName, ConditionName and AlarmId.
  SqlServer, QuestDB and Gateway event reads fill them from what their
  alarm writers already store (AlarmTypeName / AlarmName / AlarmId; the
  gateway event Type and its AlarmName / AlarmId properties).
- The node manager maps the type name to its Part 9 event type (unknown or
  non-event => AlarmConditionType), projects ConditionName, and resolves
  SourceNode to the materialised condition the alarm id names (the live
  events' SourceNode), else null.
- The where-clause is evaluated per event with the SDK content filter
  through an IFilterTarget (OfType via the type tree; other operators
  against the projected fields), after the page's cursor is taken, so
  paging is unchanged.

Tested in the node manager, over a real client session (the Client.CLI has
no `historyread --events` mode yet; filed as a follow-up), and by alarm
writer -> event read round trips on SqlServer and QuestDB.

Rebased from the unpushed remed/lane-H2 branch (originally authored 2026-10-22
in session_01Ub9hGmYLQvn9XETzw7CMsT) onto current master.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 15:40:47 -05:00