src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SlowPluginNodes.cs (133 lines of code) (raw):
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------
namespace Plc.PluginNodes
{
using Plc.PluginNodes.Models;
using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Test;
using System.Collections.Generic;
using System.Timers;
/// <summary>
/// Nodes with slow changing values.
/// </summary>
public class SlowPluginNodes : IPluginNodes
{
public IReadOnlyCollection<NodeWithIntervals> Nodes { get; private set; } = new List<NodeWithIntervals>();
public TimeService TimeService { get; set; }
public ILogger Logger { get; set; }
public uint ScaleUnits { get; set; }
private uint NodeCount => ScaleUnits == 0 ? 3u : ScaleUnits * 1000;
/// <summary>
/// ms.
/// </summary>
private uint NodeRate { get; } = 10000;
private NodeType NodeType { get; } = NodeType.UIntScalar;
private string NodeMinValue { get; }
private string NodeMaxValue { get; }
private string NodeStepSize { get; } = "1";
/// <summary>
/// ms.
/// </summary>
private uint NodeSamplingInterval { get; }
private PlcNodeManager _plcNodeManager;
private SlowFastCommon _slowFastCommon;
private BaseDataVariableState[] _nodes;
private BaseDataVariableState[] _badNodes;
private ITimer _nodeGenerator;
private bool _updateNodes = true;
public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager)
{
_plcNodeManager = plcNodeManager;
_slowFastCommon = new SlowFastCommon(_plcNodeManager, TimeService, Logger);
var folder = _plcNodeManager.CreateFolder(
telemetryFolder,
path: "Slow",
name: "Slow",
NamespaceType.PlcApplications);
// Used for methods to limit the number of updates to a fixed count.
var simulatorFolder = _plcNodeManager.CreateFolder(
telemetryFolder.Parent, // Root.
path: "SimulatorConfiguration",
name: "SimulatorConfiguration",
NamespaceType.PlcApplications);
AddNodes(folder, simulatorFolder);
AddMethods(methodsFolder);
}
private void AddMethods(FolderState methodsFolder)
{
var stopUpdateMethod = _plcNodeManager.CreateMethod(
methodsFolder,
path: "StopUpdateSlowNodes",
name: "StopUpdateSlowNodes",
"Stop the increase of value of slow nodes",
NamespaceType.PlcApplications);
SetStopUpdateSlowNodesProperties(ref stopUpdateMethod);
var startUpdateMethod = _plcNodeManager.CreateMethod(
methodsFolder,
path: "StartUpdateSlowNodes",
name: "StartUpdateSlowNodes",
"Start the increase of value of slow nodes",
NamespaceType.PlcApplications);
SetStartUpdateSlowNodesProperties(ref startUpdateMethod);
}
public void StartSimulation()
{
_nodeGenerator = TimeService.NewTimer(UpdateNodes, NodeRate);
}
public void StopSimulation()
{
if (_nodeGenerator != null)
{
_nodeGenerator.Enabled = false;
}
}
private void AddNodes(FolderState folder, FolderState simulatorFolder)
{
(_nodes, _badNodes) = _slowFastCommon.CreateNodes(NodeType, "Slow", NodeCount,
folder, simulatorFolder, false, NodeStepSize, NodeMinValue,
NodeMaxValue, NodeRate, NodeSamplingInterval);
ExposeNodesWithIntervals();
}
/// <summary>
/// Expose node information for dumping pn.json.
/// </summary>
private void ExposeNodesWithIntervals()
{
var nodes = new List<NodeWithIntervals>();
foreach (var node in _nodes)
{
nodes.Add(new NodeWithIntervals
{
NodeId = node.NodeId.Identifier.ToString(),
NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType),
Namespace = Plc.Namespaces.PlcApplications,
PublishingInterval = NodeRate,
SamplingInterval = NodeSamplingInterval
});
}
foreach (var node in _badNodes)
{
nodes.Add(new NodeWithIntervals
{
NodeId = node.NodeId.Identifier.ToString(),
NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType),
Namespace = Plc.Namespaces.PlcApplications,
PublishingInterval = NodeRate,
SamplingInterval = NodeSamplingInterval
});
}
Nodes = nodes;
}
private void SetStopUpdateSlowNodesProperties(ref MethodState method)
{
method.OnCallMethod += OnStopUpdateSlowNodes;
}
private void SetStartUpdateSlowNodesProperties(ref MethodState method)
{
method.OnCallMethod += OnStartUpdateSlowNodes;
}
/// <summary>
/// Method to stop updating the slow nodes.
/// </summary>
/// <param name="context"></param>
/// <param name="method"></param>
/// <param name="inputArguments"></param>
/// <param name="outputArguments"></param>
private ServiceResult OnStopUpdateSlowNodes(ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments)
{
_updateNodes = false;
Logger.LogDebug("StopUpdateSlowNodes method called");
return ServiceResult.Good;
}
/// <summary>
/// Method to start updating the slow nodes.
/// </summary>
/// <param name="context"></param>
/// <param name="method"></param>
/// <param name="inputArguments"></param>
/// <param name="outputArguments"></param>
private ServiceResult OnStartUpdateSlowNodes(ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments)
{
_updateNodes = true;
Logger.LogDebug("StartUpdateSlowNodes method called");
return ServiceResult.Good;
}
private void UpdateNodes(object state, ElapsedEventArgs elapsedEventArgs)
{
_slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes);
}
}
}