Skip to content

Commit 37cebe3

Browse files
[Server] Add support for SupportsFilteredRetain (#2913)
* Work In Progress * Working Implementation of SupportsFilteredRetain * Potential solution Contains test debug messages that should be cleaned up * Update comments showing discussion required * Address Comments * Use the NodeId from the ConditionState for the ConditionId. Existing case was not guaranteed to be correct.
1 parent 23d167a commit 37cebe3

File tree

3 files changed

+753
-1
lines changed

3 files changed

+753
-1
lines changed

Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ public virtual void QueueEvent(IFilterTarget instance, bool bypassFilter)
10421042
// apply filter.
10431043
if (!bypassFilter)
10441044
{
1045-
if (!filter.WhereClause.Evaluate(context, instance))
1045+
if ( !CanSendFilteredAlarm( context, filter, instance ) )
10461046
{
10471047
return;
10481048
}
@@ -1079,6 +1079,78 @@ public virtual void QueueEvent(EventFieldList fields)
10791079
}
10801080
}
10811081

1082+
/// <summary>
1083+
/// Determines whether an event can be sent with SupportsFilteredRetain in consideration.
1084+
/// </summary>
1085+
/// <returns></returns>
1086+
protected bool CanSendFilteredAlarm(FilterContext context, EventFilter filter, IFilterTarget instance)
1087+
{
1088+
bool passedFilter = filter.WhereClause.Evaluate(context, instance);
1089+
1090+
ConditionState alarmCondition = null;
1091+
NodeId conditionId = null;
1092+
InstanceStateSnapshot instanceStateSnapshot = instance as InstanceStateSnapshot;
1093+
if (instanceStateSnapshot != null)
1094+
{
1095+
alarmCondition = instanceStateSnapshot.Handle as ConditionState;
1096+
1097+
if (alarmCondition != null &&
1098+
alarmCondition.SupportsFilteredRetain != null &&
1099+
alarmCondition.SupportsFilteredRetain.Value &&
1100+
filter.SelectClauses != null)
1101+
{
1102+
conditionId = alarmCondition.NodeId;
1103+
}
1104+
}
1105+
1106+
bool canSend = passedFilter;
1107+
1108+
// ConditionId is valid only if FilteredRetain is set for the alarm condition
1109+
if (conditionId != null && alarmCondition != null)
1110+
{
1111+
HashSet<string> conditionIds = GetFilteredRetainConditionIds();
1112+
1113+
string key = conditionId.ToString();
1114+
1115+
bool saved = conditionIds.Contains(key);
1116+
1117+
if ( saved )
1118+
{
1119+
conditionIds.Remove(key);
1120+
}
1121+
1122+
if ( passedFilter )
1123+
{
1124+
// Archie - December 17 2024
1125+
// Requires discussion with Part 9 Editor
1126+
// if (alarmCondition.Retain.Value)
1127+
{
1128+
conditionIds.Add(key);
1129+
}
1130+
}
1131+
else
1132+
{
1133+
if ( saved )
1134+
{
1135+
canSend = true;
1136+
}
1137+
}
1138+
}
1139+
1140+
return canSend;
1141+
}
1142+
1143+
private HashSet<string> GetFilteredRetainConditionIds()
1144+
{
1145+
if (m_filteredRetainConditionIds == null)
1146+
{
1147+
m_filteredRetainConditionIds = new HashSet<string>();
1148+
}
1149+
1150+
return m_filteredRetainConditionIds;
1151+
}
1152+
1153+
10821154
/// <summary>
10831155
/// Whether the item has notifications that are ready to publish.
10841156
/// </summary>
@@ -1873,6 +1945,9 @@ private void QueueOverflowHandler()
18731945
private IAggregateCalculator m_calculator;
18741946
private bool m_triggered;
18751947
private bool m_resendData;
1948+
private HashSet<string> m_filteredRetainConditionIds = null;
1949+
1950+
18761951
#endregion
18771952
}
18781953
}

Stack/Opc.Ua.Core/Stack/State/ConditionState.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ protected override void OnAfterCreate(ISystemContext context, NodeState node)
4949
}
5050
#endregion
5151

52+
#region Public Properties
53+
54+
/// <remarks />
55+
public PropertyState<bool> SupportsFilteredRetain
56+
{
57+
get
58+
{
59+
return m_supportsFilteredRetain;
60+
}
61+
62+
set
63+
{
64+
if (!Object.ReferenceEquals(m_supportsFilteredRetain, value))
65+
{
66+
ChangeMasks |= NodeStateChangeMasks.Children;
67+
}
68+
69+
m_supportsFilteredRetain = value;
70+
}
71+
}
72+
73+
#endregion
74+
5275
#region Public Methods
5376
/// <summary>
5477
/// Gets or sets a value indicating whether the condition will automatically report an event when a method call completes.
@@ -762,6 +785,7 @@ protected bool IsBranch()
762785
///
763786
/// </summary>
764787
protected Dictionary<string, ConditionState> m_branches = null;
788+
private PropertyState<bool> m_supportsFilteredRetain = null;
765789

766790
#endregion
767791
}

0 commit comments

Comments
 (0)