Skip to content

Commit

Permalink
Implement ConditionRefresh2 (#1353)
Browse files Browse the repository at this point in the history
* Implement ConditionRefresh2
  • Loading branch information
Archie-Miller committed Apr 19, 2021
1 parent 0c735eb commit 88b16b3
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 13 deletions.
38 changes: 38 additions & 0 deletions Libraries/Opc.Ua.Server/Diagnostics/DiagnosticsNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,22 @@ protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context

return activeNode;
}
else if (passiveMethod.NodeId == MethodIds.ConditionType_ConditionRefresh2)
{
ConditionRefresh2MethodState activeNode = new ConditionRefresh2MethodState(passiveMethod.Parent);
activeNode.Create(context, passiveMethod);

// replace the node in the parent.
if (passiveMethod.Parent != null)
{
passiveMethod.Parent.ReplaceChild(context, activeNode);
}

activeNode.OnCall = OnConditionRefresh2;

return activeNode;
}


return predefinedNode;
}
Expand Down Expand Up @@ -387,6 +403,28 @@ protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context
return ServiceResult.Good;
}

/// <summary>
/// Handles a request to refresh conditions for a subscription and specific monitored item.
/// </summary>
private ServiceResult OnConditionRefresh2(
ISystemContext context,
MethodState method,
NodeId objectId,
uint subscriptionId,
uint monitoredItemId)
{
ServerSystemContext systemContext = context as ServerSystemContext;

if (systemContext == null)
{
systemContext = this.SystemContext;
}

Server.ConditionRefresh2(systemContext.OperationContext, subscriptionId, monitoredItemId);

return ServiceResult.Good;
}

/// <summary>
/// Returns true of the node is a diagnostics node.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions Libraries/Opc.Ua.Server/Server/IServerInternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,14 @@ public interface IServerInternal
/// <param name="context">The context.</param>
/// <param name="subscriptionId">The subscription identifier.</param>
void ConditionRefresh(OperationContext context, uint subscriptionId);

/// <summary>
/// Refreshes the conditions for the specified subscription and monitored item.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="subscriptionId">The subscription identifier.</param>
/// <param name="monitoredItemId">The monitored item identifier.</param>
void ConditionRefresh2(OperationContext context, uint subscriptionId, uint monitoredItemId);

}
}
12 changes: 12 additions & 0 deletions Libraries/Opc.Ua.Server/Server/ServerInternalData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,18 @@ public void ConditionRefresh(OperationContext context, uint subscriptionId)
{
m_subscriptionManager.ConditionRefresh(context, subscriptionId);
}

/// <summary>
/// Refreshes the conditions for the specified subscription.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="subscriptionId">The subscription identifier.</param>
/// <param name="monitoredItemId">The monitored item identifier.</param>
public void ConditionRefresh2(OperationContext context, uint subscriptionId, uint monitoredItemId)
{
m_subscriptionManager.ConditionRefresh2(context, subscriptionId, monitoredItemId);
}

#endregion

#region Private Methods
Expand Down
117 changes: 104 additions & 13 deletions Libraries/Opc.Ua.Server/Subscription/Subscription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1960,24 +1960,117 @@ public void ValidateConditionRefresh(OperationContext context)
}
}

/// <summary>
/// Verifies that a condition refresh operation is permitted.
/// </summary>
public void ValidateConditionRefresh2(OperationContext context, uint monitoredItemId)
{
ValidateConditionRefresh(context);

lock (m_lock)
{
if (!m_monitoredItems.ContainsKey(monitoredItemId))
{
throw new ServiceResultException(StatusCodes.BadMonitoredItemIdInvalid,
"Cannot refresh conditions for a monitored item that does not exist.");
}
}
}


/// <summary>
/// Refreshes the conditions.
/// </summary>
public void ConditionRefresh()
{
ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(m_session);
List<IEventMonitoredItem> monitoredItems = new List<IEventMonitoredItem>();

lock (m_lock)
{
// build list of items to refresh.
foreach (LinkedListNode<IMonitoredItem> monitoredItem in m_monitoredItems.Values)
{
MonitoredItem eventMonitoredItem = monitoredItem.Value as MonitoredItem;

if (eventMonitoredItem != null && eventMonitoredItem.EventFilter != null)
{
// add to list that gets reported to the NodeManagers.
monitoredItems.Add(eventMonitoredItem);
}
}

// nothing to do if no event subscriptions.
if (monitoredItems.Count == 0)
{
return;
}
}

ConditionRefresh(monitoredItems, 0);
}

/// <summary>
/// Refreshes the conditions.
/// </summary>
public void ConditionRefresh2(uint monitoredItemId)
{
List<IEventMonitoredItem> monitoredItems = new List<IEventMonitoredItem>();

lock (m_lock)
{
// build list of items to refresh.
if ( m_monitoredItems.ContainsKey(monitoredItemId) )
{
LinkedListNode<IMonitoredItem> monitoredItem = m_monitoredItems[monitoredItemId];

MonitoredItem eventMonitoredItem = monitoredItem.Value as MonitoredItem;

if (eventMonitoredItem != null && eventMonitoredItem.EventFilter != null)
{
// add to list that gets reported to the NodeManagers.
monitoredItems.Add(eventMonitoredItem);
}
}
else
{
throw new ServiceResultException(StatusCodes.BadMonitoredItemIdInvalid,
"Cannot refresh conditions for a monitored item that does not exist.") ;
}

// nothing to do if no event subscriptions.
if (monitoredItems.Count == 0)
{
return;
}
}

ConditionRefresh(monitoredItems, monitoredItemId);
}

/// <summary>
/// Refreshes the conditions. Works for both ConditionRefresh and ConditionRefresh2
/// </summary>
private void ConditionRefresh(List<IEventMonitoredItem> monitoredItems, uint monitoredItemId )
{
ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(m_session);

string messageTemplate = String.Format("Condition refresh {{0}} for subscription {0}.", m_id);
if ( monitoredItemId > 0 )
{
messageTemplate = String.Format("Condition refresh {{0}} for subscription {0}, monitored item {1}.", m_id, monitoredItemId);
}

lock (m_lock)
{
// generate start event.
RefreshStartEventState e = new RefreshStartEventState(null);

TranslationInfo message = new TranslationInfo(
TranslationInfo message = null;

message = new TranslationInfo(
"RefreshStartEvent",
"en-US",
"Condition refresh started for subscription {0}.",
m_id);
String.Format(messageTemplate, "started") );

e.Initialize(
systemContext,
Expand All @@ -1990,17 +2083,14 @@ public void ConditionRefresh()
e.SetChildValue(systemContext, BrowseNames.ReceiveTime, DateTime.UtcNow, false);

// build list of items to refresh.
foreach (LinkedListNode<IMonitoredItem> monitoredItem in m_monitoredItems.Values)
foreach (IEventMonitoredItem monitoredItem in monitoredItems)
{
MonitoredItem eventMonitoredItem = monitoredItem.Value as MonitoredItem;
MonitoredItem eventMonitoredItem = monitoredItem as MonitoredItem;

if (eventMonitoredItem.EventFilter != null)
if (eventMonitoredItem != null && eventMonitoredItem.EventFilter != null)
{
// queue start refresh event.
eventMonitoredItem.QueueEvent(e, true);

// add to list that gets reported to the NodeManagers.
monitoredItems.Add(eventMonitoredItem);
}
}

Expand Down Expand Up @@ -2029,11 +2119,12 @@ public void ConditionRefresh()
// generate start event.
RefreshEndEventState e = new RefreshEndEventState(null);

TranslationInfo message = new TranslationInfo(
TranslationInfo message = null;

message = new TranslationInfo(
"RefreshEndEvent",
"en-US",
"Condition refresh completed for subscription {0}.",
m_id);
String.Format(messageTemplate, "completed"));

e.Initialize(
systemContext,
Expand Down
46 changes: 46 additions & 0 deletions Libraries/Opc.Ua.Server/Subscription/SubscriptionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,32 @@ public void ConditionRefresh(OperationContext context, uint subscriptionId)
});
}

/// <summary>
/// Refreshes the conditions for the specified subscription and monitored item.
/// </summary>
public void ConditionRefresh2(OperationContext context, uint subscriptionId, uint monitoredItemId)
{
Subscription subscription = null;

lock (m_lock)
{
if (!m_subscriptions.TryGetValue(subscriptionId, out subscription))
{
throw ServiceResultException.Create(
StatusCodes.BadSubscriptionIdInvalid,
"Cannot refresh conditions for a subscription that does not exist.");
}
}

// ensure a condition refresh is allowed.
subscription.ValidateConditionRefresh2(context, monitoredItemId);

// do the actual refresh in the background.
Task.Run(() => {
DoConditionRefresh2(subscription, monitoredItemId);
});
}

/// <summary>
/// Completes a refresh conditions request.
/// </summary>
Expand All @@ -371,6 +397,26 @@ private void DoConditionRefresh(object state)
}
}

/// <summary>
/// Completes a refresh conditions request.
/// </summary>
private void DoConditionRefresh2(object state, uint monitoredItemId)
{
try
{
Subscription subscription = state as Subscription;

if (subscription != null)
{
subscription.ConditionRefresh2( monitoredItemId );
}
}
catch (Exception e)
{
Utils.Trace(e, "Server: Publish Subscriptions Thread Exited Unexpectedly");
}
}

/// <summary>
/// Deletes the specified subscription.
/// </summary>
Expand Down

0 comments on commit 88b16b3

Please sign in to comment.