fix(client-cli): call Part 9 ack/confirm/enable/shelve methods on the condition node itself
The client appended .Condition / .ShelvingState to the condition id; neither child exists on the OtOpcUa server (conditions are their own SourceNode, ShelvingState is an SDK numeric ns0 node), so every CLI ack/confirm/shelve/enable/disable returned BadNodeIdUnknown. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -370,10 +370,9 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotConnected();
|
||||
|
||||
// The Acknowledge method lives on the .Condition child node, not the source node itself
|
||||
var conditionObjId = conditionNodeId.EndsWith(".Condition")
|
||||
? NodeId.Parse(conditionNodeId)
|
||||
: NodeId.Parse(conditionNodeId + ".Condition");
|
||||
// OtOpcUa conditions are their own event source (SourceNode == ConditionId), so the Part 9 methods are
|
||||
// invoked on that node directly. There is no ".Condition" child to append.
|
||||
var conditionObjId = NodeId.Parse(conditionNodeId);
|
||||
var acknowledgeMethodId = MethodIds.AcknowledgeableConditionType_Acknowledge;
|
||||
|
||||
// CallMethodAsync throws ServiceResultException on a bad call result;
|
||||
@@ -406,10 +405,8 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotConnected();
|
||||
|
||||
// Confirm lives on the same .Condition child node as Acknowledge
|
||||
var conditionObjId = conditionNodeId.EndsWith(".Condition")
|
||||
? NodeId.Parse(conditionNodeId)
|
||||
: NodeId.Parse(conditionNodeId + ".Condition");
|
||||
// Confirm is invoked on the condition node itself, like Acknowledge.
|
||||
var conditionObjId = NodeId.Parse(conditionNodeId);
|
||||
var confirmMethodId = MethodIds.AcknowledgeableConditionType_Confirm;
|
||||
|
||||
try
|
||||
@@ -438,11 +435,11 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotConnected();
|
||||
|
||||
// The shelve methods live on the ShelvingState child of the condition node.
|
||||
// conditionNodeId is the alarm/condition node; append .ShelvingState to get the state machine node.
|
||||
var shelvingStateNodeId = conditionNodeId.EndsWith(".ShelvingState")
|
||||
? NodeId.Parse(conditionNodeId)
|
||||
: NodeId.Parse(conditionNodeId + ".ShelvingState");
|
||||
// The server's ShelvingState child is SDK-created with a numeric namespace-0 id, so a synthesized
|
||||
// "<condition>.ShelvingState" node id never exists. The shelve methods are called on the condition
|
||||
// object itself with the AlarmConditionType_ShelvingState_* method ids, which the server dispatches
|
||||
// to the condition's ShelvingState methods.
|
||||
var shelvingStateNodeId = NodeId.Parse(conditionNodeId);
|
||||
|
||||
NodeId methodId;
|
||||
object[] inputArgs;
|
||||
@@ -495,8 +492,8 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
/// <summary>
|
||||
/// Shared body for the H4 Enable/Disable client path. Invokes the OPC UA Part 9 ConditionType
|
||||
/// <c>Enable</c>/<c>Disable</c> method (no input arguments) on the condition object node, mirroring
|
||||
/// the <see cref="AcknowledgeAlarmAsync"/> convention: the methods live on the <c>.Condition</c>
|
||||
/// child node, and a bad call result surfaces as the returned <see cref="StatusCode"/> rather than
|
||||
/// the <see cref="AcknowledgeAlarmAsync"/> convention: the methods are invoked on the condition
|
||||
/// node itself, and a bad call result surfaces as the returned <see cref="StatusCode"/> rather than
|
||||
/// escaping as an uncaught <see cref="ServiceResultException"/>.
|
||||
/// </summary>
|
||||
/// <param name="conditionNodeId">The condition node associated with the alarm.</param>
|
||||
@@ -507,10 +504,8 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotConnected();
|
||||
|
||||
// Enable/Disable live on the same .Condition child node as Acknowledge/Confirm.
|
||||
var conditionObjId = conditionNodeId.EndsWith(".Condition")
|
||||
? NodeId.Parse(conditionNodeId)
|
||||
: NodeId.Parse(conditionNodeId + ".Condition");
|
||||
// Enable/Disable are invoked on the condition node itself, like Acknowledge/Confirm.
|
||||
var conditionObjId = NodeId.Parse(conditionNodeId);
|
||||
var methodId = enabling ? MethodIds.ConditionType_Enable : MethodIds.ConditionType_Disable;
|
||||
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user