Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Server] Add support for SupportsFilteredRetain #2913

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 87 additions & 1 deletion Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@
// apply filter.
if (!bypassFilter)
{
if (!filter.WhereClause.Evaluate(context, instance))
if ( !CanSendFilteredAlarm( context, filter, instance ) )
{
return;
}
Expand Down Expand Up @@ -1079,6 +1079,89 @@
}
}

/// <summary>
/// Determines whether an event can be sent with SupportsFilteredRetain in consideration.
/// </summary>
/// <returns></returns>
protected bool CanSendFilteredAlarm(FilterContext context, EventFilter filter, IFilterTarget instance)
romanett marked this conversation as resolved.
Show resolved Hide resolved
{
bool passedFilter = filter.WhereClause.Evaluate(context, instance);

Check warning on line 1088 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1088 was not covered by tests

ConditionState alarmCondition = null;
NodeId conditionId = null;
InstanceStateSnapshot instanceStateSnapshot = instance as InstanceStateSnapshot;

Check warning on line 1092 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs#L1090-L1092

Added lines #L1090 - L1092 were not covered by tests
if (instanceStateSnapshot != null)
{
alarmCondition = instanceStateSnapshot.Handle as ConditionState;

Check warning on line 1095 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1095 was not covered by tests

if (alarmCondition != null &&
alarmCondition.SupportsFilteredRetain != null &&
alarmCondition.SupportsFilteredRetain.Value &&
filter.SelectClauses != null)

Check warning on line 1100 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs#L1098-L1100

Added lines #L1098 - L1100 were not covered by tests
{
int lastIndex = filter.SelectClauses.Count - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does lastIndex allways point to the ConditionId ? Can't the client request it in another order together with other SelectClauses?

object value = instance.GetAttributeValue(
context,
filter.SelectClauses[lastIndex].TypeDefinitionId,
filter.SelectClauses[lastIndex].BrowsePath,
filter.SelectClauses[lastIndex].AttributeId,
filter.SelectClauses[lastIndex].ParsedIndexRange);

Check warning on line 1108 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs#L1102-L1108

Added lines #L1102 - L1108 were not covered by tests

if (value != null)
{
conditionId = value as NodeId;

Check warning on line 1112 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1112 was not covered by tests
}
}
}

bool canSend = passedFilter;

Check warning on line 1117 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1117 was not covered by tests

// ConditionId is valid only if FilteredRetain is set for the alarm condition
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the ConditionId only valid if FilteredRetain is set ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is specifically for SupportsFilterRetain, so if it is not set, the remainder of the function is not required, only the filter check at the top of the function.

This is still a work in progress, I'm going to move it to draft for now.

if (conditionId != null && alarmCondition != null)
{
HashSet<string> conditionIds = GetFilteredRetainConditionIds();

Check warning on line 1122 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1122 was not covered by tests

string key = conditionId.ToString();

Check warning on line 1124 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1124 was not covered by tests

bool saved = conditionIds.Contains(key);

Check warning on line 1126 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1126 was not covered by tests

if ( saved )
{
conditionIds.Remove(key);

Check warning on line 1130 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1130 was not covered by tests
}

if ( passedFilter )
{
// Archie - December 17 2024
// Requires discussion with Part 9 Editor
// if (alarmCondition.Retain.Value)
{
conditionIds.Add(key);

Check warning on line 1139 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1139 was not covered by tests
}
}
else
{
if ( saved )
{
canSend = true;

Check warning on line 1146 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1146 was not covered by tests
}
}
}

return canSend;

Check warning on line 1151 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1151 was not covered by tests
}

private HashSet<string> GetFilteredRetainConditionIds()
{
if (m_filteredRetainConditionIds == null)
{
m_filteredRetainConditionIds = new HashSet<string>();

Check warning on line 1158 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1158 was not covered by tests
}

return m_filteredRetainConditionIds;

Check warning on line 1161 in Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L1161 was not covered by tests
}


/// <summary>
/// Whether the item has notifications that are ready to publish.
/// </summary>
Expand Down Expand Up @@ -1873,6 +1956,9 @@
private IAggregateCalculator m_calculator;
private bool m_triggered;
private bool m_resendData;
private HashSet<string> m_filteredRetainConditionIds = null;


#endregion
}
}
24 changes: 24 additions & 0 deletions Stack/Opc.Ua.Core/Stack/State/ConditionState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@
}
#endregion

#region Public Properties

/// <remarks />
public PropertyState<bool> SupportsFilteredRetain
{
get
{
return m_supportsFilteredRetain;

Check warning on line 59 in Stack/Opc.Ua.Core/Stack/State/ConditionState.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L59 was not covered by tests
}

set
{
if (!Object.ReferenceEquals(m_supportsFilteredRetain, value))
{
ChangeMasks |= NodeStateChangeMasks.Children;

Check warning on line 66 in Stack/Opc.Ua.Core/Stack/State/ConditionState.cs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L66 was not covered by tests
}

m_supportsFilteredRetain = value;
}

Check warning on line 70 in Stack/Opc.Ua.Core/Stack/State/ConditionState.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Stack/State/ConditionState.cs#L69-L70

Added lines #L69 - L70 were not covered by tests
}

#endregion

#region Public Methods
/// <summary>
/// Gets or sets a value indicating whether the condition will automatically report an event when a method call completes.
Expand Down Expand Up @@ -762,6 +785,7 @@
///
/// </summary>
protected Dictionary<string, ConditionState> m_branches = null;
private PropertyState<bool> m_supportsFilteredRetain = null;

#endregion
}
Expand Down
Loading
Loading