/// <summary>
        /// Method exposed as a node in the server to publish a node to IoT Hub that it is connected to
        /// </summary>
        private ServiceResult PublishNodeMethod(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments)
        {
            if (inputArguments[0] == null || inputArguments[1] == null)
            {
                Trace("PublishNodeMethod: Invalid Arguments!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!"));
            }

            NodeToPublish nodeToPublish;
            string        nodeId      = inputArguments[0] as string;
            string        endpointUrl = inputArguments[1] as string;

            if (string.IsNullOrEmpty(nodeId) || string.IsNullOrEmpty(endpointUrl))
            {
                Trace($"PublishNodeMethod: Arguments (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}') are not valid strings!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!"));
            }

            try
            {
                nodeToPublish = new NodeToPublish(nodeId, endpointUrl);
            }
            catch (UriFormatException)
            {
                Trace($"PublishNodeMethod: The endpointUrl is invalid (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}')!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!"));
            }

            // Create session and add item to monitor, what ever is needed.
            try
            {
                // find the session we need to monitor the node
                OpcSession opcSession = OpcSessions.First(s => s.EndpointUri == nodeToPublish.EndPointUri);

                // Add a new session.
                if (opcSession == null)
                {
                    // create new session info.
                    opcSession = new OpcSession(nodeToPublish.EndPointUri, OpcSessionCreationTimeout);
                    OpcSessions.Add(opcSession);
                    Trace($"DoPublish: No matching session found for endpoint '{nodeToPublish.EndPointUri.AbsolutePath}'. Requested to create a new one.");
                }
                else
                {
                    Trace($"DoPublish: Session found for endpoint '{nodeToPublish.EndPointUri.AbsolutePath}'");
                }

                // add the node info to the sessions monitored items list.
                opcSession.AddNodeForMonitoring(nodeToPublish.NodeId);
                Trace("DoPublish: Requested to monitor item.");

                // start monitoring the node
                Task monitorTask = Task.Run(async() => await opcSession.ConnectAndMonitor());
                monitorTask.Wait();
                Trace("DoPublish: Session processing completed.");

                // update our data
                NodesToPublish.Add(nodeToPublish);

                // persist it to disk
                File.WriteAllText(NodesToPublishAbsFilename, JsonConvert.SerializeObject(NodesToPublish));

                Trace($"DoPublish: Now publishing: {nodeToPublish.ToString()}");
                return(ServiceResult.Good);
            }
            catch (Exception e)
            {
                Trace(e, $"DoPublish: Exception while trying to configure publishing node '{nodeToPublish.ToString()}'");
                return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}"));
            }
        }
        /// <summary>
        /// Method exposed as a node in the server to stop monitoring it and no longer publish telemetry of it.
        /// </summary>
        private ServiceResult UnPublishNodeMethod(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments)
        {
            if (inputArguments[0] == null || inputArguments[1] == null)
            {
                Trace("UnPublishNodeMethod: Invalid arguments!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!"));
            }

            string nodeId      = inputArguments[0] as string;
            string endpointUrl = inputArguments[1] as string;

            if (string.IsNullOrEmpty(nodeId) || string.IsNullOrEmpty(endpointUrl))
            {
                Trace($"UnPublishNodeMethod: Arguments (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}') are not valid strings!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!"));
            }

            NodeToPublish nodeToUnpublish = new NodeToPublish();

            try
            {
                nodeToUnpublish = new NodeToPublish(nodeId, endpointUrl);
            }
            catch (UriFormatException)
            {
                Trace($"UnPublishNodeMethod: The endpointUrl is invalid (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}')!");
                return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!"));
            }

            // Find the session and stop monitoring the node.
            try
            {
                // find the session we need to monitor the node
                OpcSession opcSession = OpcSessions.First(s => s.EndpointUri == nodeToUnpublish.EndPointUri);
                if (opcSession == null)
                {
                    // do nothing if there is no session for this endpoint.
                    Trace($"UnPublishNodeMethod: Session for endpoint '{nodeToUnpublish.EndPointUri.AbsolutePath}' not found.");
                    return(ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for endpoint of published node not found!"));
                }
                else
                {
                    Trace($"UnPublishNodeMethod: Session found for endpoint '{nodeToUnpublish.EndPointUri.AbsolutePath}'");
                }

                // remove the node from the sessions monitored items list.
                opcSession.TagNodeForMonitoringStop(nodeToUnpublish.NodeId);
                Trace("UnPublishNodeMethod: Requested to stop monitoring of node.");

                // stop monitoring the node
                Task monitorTask = Task.Run(async() => await opcSession.ConnectAndMonitor());
                monitorTask.Wait();
                Trace("UnPublishNodeMethod: Session processing completed.");

                // remove node from our persisted data set.
                var itemToRemove = NodesToPublish.Find(l => l.NodeId == nodeToUnpublish.NodeId && l.EndPointUri == nodeToUnpublish.EndPointUri);
                NodesToPublish.Remove(itemToRemove);

                // persist data
                File.WriteAllText(NodesToPublishAbsFilename, JsonConvert.SerializeObject(NodesToPublish));
            }
            catch (Exception e)
            {
                Trace(e, $"DoPublish: Exception while trying to configure publishing node '{nodeToUnpublish.ToString()}'");
                return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}"));
            }
            return(ServiceResult.Good);
        }