Files
lmxopcua/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/ApplicationAlarmConditions.cs
T

64 lines
3.8 KiB
C#

using Opc.Ua;
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
/// <summary>Preserves the application's repeat-method contract at the SDK's supported validation seam.</summary>
internal static class ApplicationAlarmConditions
{
internal static AlarmConditionState Create(string type, NodeState parent) => type switch
{
"OffNormalAlarm" => new OffNormal(parent),
"DiscreteAlarm" => new Discrete(parent),
_ => new Alarm(parent),
};
private static ServiceResult CurrentTrunkRepeat(ServiceResult result, AcknowledgeableConditionState condition,
ISystemContext context, ByteString eventId, LocalizedText comment, bool acknowledge)
{
var repeated = acknowledge ? StatusCodes.BadConditionBranchAlreadyAcked : StatusCodes.BadConditionBranchAlreadyConfirmed;
var callback = acknowledge ? condition.OnAcknowledge : condition.OnConfirm;
if (result.StatusCode != repeated || callback is null || eventId.IsEmpty
|| condition.BranchId is not { Value.IsNull: true }
|| condition.EventId is not { } current || current.Value != eventId
|| !ReferenceEquals(condition.GetEventByEventId(eventId), condition)
|| (acknowledge ? condition.AckedState?.Id?.Value : condition.ConfirmedState?.Id?.Value) != true)
return result;
// In exact SDK 2.0.1, the Already* guards precede the application callback. Invoke it once
// here; every other SDK validation result, superseded EventId and branch retains the base path.
try { return callback(context, condition, eventId, comment); }
catch (Exception error)
{
return ServiceResult.Create(error, StatusCodes.BadUnexpectedError,
acknowledge ? "Unexpected error acknowledging a Condition." : "Unexpected error confirming a Condition.");
}
}
private sealed class OffNormal(NodeState parent) : OffNormalAlarmState(parent)
{
protected override ServiceResult ProcessBeforeAcknowledge(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeAcknowledge(context, id, comment), this, context, id, comment, true);
protected override ServiceResult ProcessBeforeConfirm(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeConfirm(context, id, comment), this, context, id, comment, false);
protected override ConditionState CreateBranchInstance() => new OffNormal(this);
}
private sealed class Discrete(NodeState parent) : DiscreteAlarmState(parent)
{
protected override ServiceResult ProcessBeforeAcknowledge(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeAcknowledge(context, id, comment), this, context, id, comment, true);
protected override ServiceResult ProcessBeforeConfirm(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeConfirm(context, id, comment), this, context, id, comment, false);
protected override ConditionState CreateBranchInstance() => new Discrete(this);
}
private sealed class Alarm(NodeState parent) : AlarmConditionState(parent)
{
protected override ServiceResult ProcessBeforeAcknowledge(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeAcknowledge(context, id, comment), this, context, id, comment, true);
protected override ServiceResult ProcessBeforeConfirm(ISystemContext context, ByteString id, LocalizedText comment) =>
CurrentTrunkRepeat(base.ProcessBeforeConfirm(context, id, comment), this, context, id, comment, false);
protected override ConditionState CreateBranchInstance() => new Alarm(this);
}
}