Пример #1
0
        public async Task <MsgOPCUAMethodCallResponse> CallMethodAsync(string methodId, Dictionary <string, object> parameters, bool returnRawJSON = false)
        {
            MethodRegistration methodRegistration;

            if (!_MethodRegistrations.TryGetValue(methodId, out methodRegistration))
            {
                return(null);
            }
            if (methodRegistration.MethodThingAddress == null)
            {
                await UpdateRegistrationsAsync(false);
            }
            if (methodRegistration.MethodThingAddress == null)
            {
                return(null);
            }

            var methodCall = new MsgOPCUAMethodCall {
                Arguments = parameters, ReturnRawJSON = returnRawJSON
            };
            MsgOPCUAMethodCallResponse response;

            if (methodRegistration.MethodInfo.CallTimeout > 0)
            {
                response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAMethodCall, MsgOPCUAMethodCallResponse>(OwnerAddress, methodRegistration.MethodThingAddress,
                                                                                                                                 methodCall, new TimeSpan(0, 0, 0, 0, methodRegistration.MethodInfo.CallTimeout + 15));
            }
            else
            {
                response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAMethodCall, MsgOPCUAMethodCallResponse>(OwnerAddress, methodRegistration.MethodThingAddress,
                                                                                                                                 methodCall);
            }
            return(response);
        }
Пример #2
0
        public override void HandleMessage(ICDEThing sender, object pIncoming)
        {
            TheProcessMessage pMsg = pIncoming as TheProcessMessage;

            if (pMsg == null || pMsg.Message == null)
            {
                return;
            }

            var cmd = TheCommonUtils.cdeSplit(pMsg.Message.TXT, ":", false, false);

            switch (cmd[0])
            {
            case nameof(MsgAddConnectionThing <TConnectionThingParam>):
                var addMsg = TheCommRequestResponse.ParseRequestMessageJSON <MsgAddConnectionThing <TConnectionThingParam> >(pMsg.Message);

                var responseMsg = new MsgAddConnectionThingResponse {
                    Error = "Unexpected"
                };
                if (addMsg != null)
                {
                    var thingToAdd = addMsg.ThingToAdd;

                    if (thingToAdd != null)
                    {
                        var currentThing = MyConnectionThings.MyMirrorCache.GetEntryByID(thingToAdd.cdeMID);
                        var newThing     = new TConnectionThing();
                        newThing.Initialize(thingToAdd);

                        if (currentThing == null)
                        {
                            MyConnectionThings.AddAnItem(newThing);
                            responseMsg.Error = null;
                        }
                        else
                        {
                            if (!newThing.IsEqual(currentThing))
                            {
                                UpdateConnectionThing(currentThing, newThing);
                                MyConnectionThings.UpdateItem(newThing);
                                Connect();
                            }
                            responseMsg.Error = null;
                        }
                    }
                    else
                    {
                        responseMsg.Error = "INVALIDARGS";
                    }
                }
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, responseMsg);
                break;

            default:
                base.HandleMessage(sender, pIncoming);
                break;
            }
        }
Пример #3
0
        public async Task <string> DisconnectAsync()
        {
            var response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUADisconnect, MsgOPCUADisconnectResponse>(OwnerAddress, OpcThingAddress, new MsgOPCUADisconnect());

            if (response == null)
            {
                return("Error sending disconnect message");
            }
            return(response.Error);
        }
Пример #4
0
        public async Task <MsgOPCUAReadTagsResponse> ReadTagsAsync(List <string> nodeIds, TimeSpan callTimeout)
        {
            var response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAReadTags, MsgOPCUAReadTagsResponse>(OwnerAddress, OpcThingAddress, new MsgOPCUAReadTags
            {
                Tags = nodeIds.Select((n) => new MsgOPCUAReadTags.TagInfo {
                    NodeId = n
                }).ToList()
            }, callTimeout);

            return(response);
        }
Пример #5
0
            public void HandleMessage(TSM message)
            {
                var cmd = TheCommonUtils.cdeSplit(message.TXT, ":", false, false);

                switch (cmd[0])
                {
                case nameof(TheThing.MsgSubscribeToThings):
                {
                    TheCommRequestResponse.DoHandleMessage <MsgSubscribeToThings <TSubscription>, MsgSubscribeToThingsResponse>(message,
#if !CDE_NET4
                                                                                                                                async
#endif
                                                                                                                                    (request, response) =>
                        {
                            response.SubscriptionStatus = new List <TheThing.TheThingSubscriptionStatus>();
                            foreach (var subscription in request.SubscriptionRequests)
                            {
#if !CDE_NET4
                                response.SubscriptionStatus.Add(await _subscribeHandler(subscription));
#else
                                response.SubscriptionStatus.Add(_subscribeHandler(subscription).Result);
#endif
                            }
                            _refreshSubscriptionStateHandler();
                        }
                                                                                                                                );
                    break;
                }

                case nameof(TheThing.MsgGetThingSubscriptions):
                {
                    TheCommRequestResponse.DoHandleMessage <MsgGetThingSubscriptions, MsgGetThingSubscriptionsResponse <TSubscription> >(message, (request, response) =>
                        {
                            response.ThingSubscriptions = _getSubscriptionsHandler(request.Generalize ?? false);
                        });
                    break;
                }

                case nameof(TheThing.MsgUnsubscribeFromThings):
                {
                    TheCommRequestResponse.DoHandleMessage <TheThing.MsgUnsubscribeFromThings, TheThing.MsgUnsubscribeFromThingsResponse>(message, (request, response) =>
                        {
                            response.Failed = _unsubscribeHandler(request.SubscriptionIds, request.UnsubscribeAll);
                        }
                                                                                                                                          );
                    break;
                }

                default:
                    break;
                }
            }
Пример #6
0
        public Task <MsgUnsubscribeSensorsResponse> UnsubscribeSensorsAsync(MsgUnsubscribeSensors unsubscribeRequest, bool bypassCapabilityCheck)
        {
            if (!bypassCapabilityCheck && !this.Capabilities.Contains(eThingCaps.SensorProvider))
            {
                return(TheCommonUtils.TaskFromResult(new MsgUnsubscribeSensorsResponse {
                    Error = "Thing is not a sensor provider"
                }));
            }
            ;
            var unsubscribeResponseTask = TheCommRequestResponse.PublishRequestJSonAsync <MsgUnsubscribeSensors, MsgUnsubscribeSensorsResponse>(this, unsubscribeRequest);

            return(unsubscribeResponseTask);
        }
Пример #7
0
        public Task <MsgGetSensorSubscriptionsResponse> GetSensorProviderSubscriptionsAsync(MsgGetSensorSubscriptions getSubscriptionsRequest, bool bypassCapabilityCheck)
        {
            if (!bypassCapabilityCheck && !this.Capabilities.Contains(eThingCaps.SensorProvider))
            {
                return(TheCommonUtils.TaskFromResult(new MsgGetSensorSubscriptionsResponse {
                    Error = "Thing is not a sensor provider"
                }));
            }
            ;
            var getSubscriptionResponseTask = TheCommRequestResponse.PublishRequestJSonAsync <MsgGetSensorSubscriptions, MsgGetSensorSubscriptionsResponse>(this, getSubscriptionsRequest);

            return(getSubscriptionResponseTask);
        }
Пример #8
0
        public Task <MsgSubscribeSensorsResponse <subscriptionT> > SubscribeSensorsAsync <subscriptionT>(MsgSubscribeSensors <subscriptionT> subscribeRequest, bool bypassCapabilityCheck) where subscriptionT : TheSensorSubscription
        {
            if (!bypassCapabilityCheck && !this.Capabilities.Contains(eThingCaps.SensorProvider))
            {
                return(TheCommonUtils.TaskFromResult(new MsgSubscribeSensorsResponse <subscriptionT> {
                    Error = "Thing is not a sensor provider"
                }));
            }
            ;
            var subscribeResponseTask = TheCommRequestResponse.PublishRequestJSonAsync <TheThing.MsgSubscribeSensors <subscriptionT>, TheThing.MsgSubscribeSensorsResponse <subscriptionT> >(this, subscribeRequest);

            return(subscribeResponseTask);
        }
Пример #9
0
        public Task <MsgBrowseSensorsResponse> ProviderBrowseSensorsAsync(TheThing.MsgBrowseSensors browseRequest, bool bypassCapabilityCheck)
        {
            if (!bypassCapabilityCheck && !this.Capabilities.Contains(eThingCaps.SensorProvider))
            {
                return(TheCommonUtils.TaskFromResult(new MsgBrowseSensorsResponse {
                    Error = "Thing is not a sensor provider"
                }));
            }
            ;
            var browseResponseTask = TheCommRequestResponse.PublishRequestJSonAsync <TheThing.MsgBrowseSensors, TheThing.MsgBrowseSensorsResponse>(this, browseRequest);

            return(browseResponseTask);
        }
Пример #10
0
        public static TheRecordHolder MeshQueryRecordHolder(int idRecord, Guid node, string strEngineName, Guid cdeMIdThing)
        {
            TheRecordHolder trh = null;

            // Package up request info.
            MsgMileRecordHolder msgRequest = new MsgMileRecordHolder()
            {
                id = idRecord
            };

            // Start asynchronous task to send a message and wait for a reply.
            // Sends a message named nameof(MsgMileRecordHolder)
            // Receives a reply named nameof(MsgMileRecordHolderResponse)
            // See function "HandleMessage" for actual handling.

            Task <MsgMileRecordHolderResponse> t = null;

            try
            {
                TheMessageAddress tma = new TheMessageAddress()
                {
                    Node       = Guid.Empty,
                    EngineName = strEngineName,
                    ThingMID   = cdeMIdThing,
                    SendToProvisioningService = false,
                };
                t = TheCommRequestResponse.PublishRequestJSonAsync <MsgMileRecordHolder, MsgMileRecordHolderResponse>(tma, msgRequest);
            }
            catch (Exception ex)
            {
                string strMessage = ex.Message;
            }

            // Wait for a bit
            t.Wait(20000);
            bool bTaskCompleted = t.IsCompleted;

            // Check for success.
            if (bTaskCompleted)
            {
                MsgMileRecordHolderResponse msgResponse = t.Result;
                trh = msgResponse.data;
            }

            return(trh);
        }
Пример #11
0
        public async Task <string> ConnectAsync(OPCUAConnectParameters connectParams = null, bool logEssentialOnly = false)
        {
            if (connectParams != null)
            {
                ConnectParameters = new OPCUAConnectParameters(connectParams);
            }

            if (ConnectParameters != null)
            {
                // TODO make this work for remote things as well
                var tThing = GetOpcThing();
                TheThing.SetSafePropertyString(tThing, "UserName", ConnectParameters.UserName);
                TheThing.SetSafePropertyString(tThing, "Password", ConnectParameters.Password);
            }

            var response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAConnect, MsgOPCUAConnectResponse>(OwnerAddress, OpcThingAddress, new MsgOPCUAConnect { LogEssentialOnly = logEssentialOnly });

            if (response == null)
            {
                return("Error sending connect message");
            }
            return(response.Error);
        }
Пример #12
0
        private void SendButton_Click(object sender, RoutedEventArgs e)
        {
            var msgHello = new MsgChatHello
            {
                Message    = MessageText.Text,
                SenderName = UserName.Text,
            };

            var target = new TheMessageAddress
            {
                EngineName = strChatEngine, // Send to this engine
                Node       = Guid.Empty     // Send to all nodes in the mesh
            };

            var response = TheCommRequestResponse.PublishRequestJSonAsync <MsgChatHello, MsgChatHelloResponse>(
                TheThingRegistry.GetBaseEngineAsThing(eEngineName.ThingService), // Since we have no plug-in, use an arbitrary existing thing in the system as the originator
                target,
                msgHello,
                new TimeSpan(0, 0, 10)) // Wait 10 seconds for ackknowledge message
                           .Result;

            if (response == null)
            {
                MessageBox.Show("Error sending message or no acknowlege received.");
            }
            else
            {
                if (response.Acknowledged)
                {
                }
                else
                {
                    MessageBox.Show("Message not acknowledged.");
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Handles Messages sent from a host sub-engine to its clients
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="pIncoming"></param>
        public void HandleMessage(ICDEThing sender, object pIncoming)
        {
            TheProcessMessage pMsg = pIncoming as TheProcessMessage;

            if (pMsg == null)
            {
                return;
            }

            string[] cmd = pMsg.Message.TXT.Split(':');
            switch (cmd[0])
            {
            case "CDE_INITIALIZED":
                MyBaseEngine.SetInitialized(pMsg.Message);
                break;

            case nameof(MsgMileRecordHolder):
                if (g_EnableMeshDataResponse)
                {
                    // Request from another node for mile record holder information.
                    var request     = TheCommRequestResponse.ParseRequestMessageJSON <MsgMileRecordHolder>(pMsg.Message);
                    var MsgResponse = new MsgMileRecordHolderResponse();
                    if (request != null)
                    {
                        MsgResponse.data = TheRecordHolder.QueryRecordHolder(request.id);
                    }
                    TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, MsgResponse);

                    MsgResponse = null;       // Prevent legacy response handler for being sent.
                }
                break;

            default:
                break;
            }
        }
Пример #14
0
        virtual void HandleMessage(ICDEThing sender, object pIncoming)
        {
            TheProcessMessage pMsg = pIncoming as TheProcessMessage;

            if (pMsg == null || pMsg.Message == null)
            {
                return;
            }

            var cmd = TheCommonUtils.cdeSplit(pMsg.Message.TXT, ":", false, false);

            switch (cmd[0])
            {
            case "RUREADY":
                if (cmd.Length > 1 && cmd[1] == TheCommonUtils.cdeGuidToString(MyBaseThing.cdeMID))
                {
                    TheCommCore.PublishToOriginator(pMsg.Message, new TSM(pMsg.Message.ENG, "IS_READY:" + TheCommonUtils.cdeGuidToString(MyBaseThing.cdeMID), mIsInitialized.ToString())
                    {
                        FLG = 8
                    }, true);
                }
                break;

            case "CONNECT_SERVER":
                Connect();
                break;

            case nameof(MsgConnectDisconnect):
            {
                var request     = TheCommRequestResponse.ParseRequestMessageJSON <MsgConnectDisconnect>(pMsg.Message);
                var responseMsg = new MsgConnectDisconnectResponse();
                if (request == null)
                {
                    responseMsg.Error = "Error parsing request message";
                }
                else
                {
                    try
                    {
                        if (request.Connect.HasValue && request.Reconnect.HasValue)
                        {
                            responseMsg.Error = "Can specify at most one of Connect Reconnect";
                        }
                        else if (!request.Connect.HasValue && !request.Reconnect.HasValue && !request.AutoConnect.HasValue)
                        {
                            responseMsg.Error = "Must specify at least one of Connect Reconnect AutoConnect";
                        }
                        else
                        {
                            if (request.Connect.HasValue)
                            {
                                if (request.Connect == true)
                                {
                                    Connect();
                                }
                                else
                                {
                                    Disconnect(true);
                                }
                            }
                            if (request.Reconnect.HasValue)
                            {
                                Disconnect(true);
                                if (request.WaitTimeBeforeReconnect.HasValue)
                                {
                                    try
                                    {
#if !NET40
                                        await TheCommonUtils.TaskDelayOneEye(request.WaitTimeBeforeReconnect.Value, 100).ConfigureAwait(false);
#else
                                        TheCommonUtils.TaskDelayOneEye(request.WaitTimeBeforeReconnect.Value, 100).Wait();
#endif
                                    }
                                    catch (System.Threading.Tasks.TaskCanceledException) { }
                                }
                                Connect();
                            }
                            if (request.AutoConnect.HasValue)
                            {
                                AutoConnect = request.AutoConnect.Value;
                            }
                            responseMsg.Connected = IsConnected;
                        }
                    }
                    catch (Exception e)
                    {
                        responseMsg.Error = e.Message;
                    }
                }
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, responseMsg);
            }
            break;
            }
        }
Пример #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="reRegisterAll"></param>
        /// <returns></returns>
        public async Task <List <RegistrationError> > UpdateRegistrationsAsync(bool reRegisterAll = false, bool bulkApply = false)
        {
            var tags    = new List <TagRegistration>();
            var methods = new List <MethodRegistration>();
            var events  = new List <EventRegistration>();

            foreach (var tagRegistration in _TagRegistrations.Values)
            {
                if (reRegisterAll || !String.IsNullOrEmpty(tagRegistration.Error))
                {
                    tagRegistration.Error = "pending";
                    tags.Add(tagRegistration);
                }
            }
            foreach (var methodRegistration in _MethodRegistrations.Values)
            {
                if (reRegisterAll || !String.IsNullOrEmpty(methodRegistration.Error))
                {
                    methodRegistration.Error = "pending";
                    methods.Add(methodRegistration);
                }
            }

            foreach (var eventRegistration in _EventRegistrations.Values)
            {
                if (reRegisterAll || !String.IsNullOrEmpty(eventRegistration.Error))
                {
                    eventRegistration.Error = "pending";
                    events.Add(eventRegistration);
                }
            }

            if (tags.Count == 0 && methods.Count == 0 && events.Count == 0)
            {
                return(new List <RegistrationError>());
            }

            var response = await TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUACreateTags, MsgOPCUACreateTagsResponse>(OwnerAddress, OpcThingAddress, new MsgOPCUACreateTags
            {
                Tags      = tags.Count > 0 ? tags.Select((t) => t.TagInfo).ToList() : null,
                Methods   = methods.Count > 0 ? methods.Select((m) => m.MethodInfo).ToList() : null,
                Events    = events.Count > 0 ? events.Select(e => e.EventInfo).ToList() : null,
                BulkApply = bulkApply
            });

            if (response == null)
            {
                return(null);
            }
            if (response.Results == null)
            {
                return(new List <RegistrationError> {
                    new RegistrationError {
                        Error = response.Error,
                    }
                });
            }

            if (response.Results.Count != tags.Count + methods.Count + events.Count)
            {
                return(new List <RegistrationError> {
                    new RegistrationError {
                        Error = String.Format("Internal error (result count mismatch: {0}, expected {1}", response.Results.Count, tags.Count + methods.Count),
                    }
                });
            }

            var registrationErrors = new List <RegistrationError>();

            int resultIndex = 0;
            var results     = response.Results;

            foreach (var tag in tags)
            {
                var error = results[resultIndex].Error;
                if (String.IsNullOrEmpty(error))
                {
                    tag.Error = null;
                }
                else
                {
                    tag.Error = error;
                    registrationErrors.Add(new RegistrationError
                    {
                        PropertyName = tag.PropertyName,
                        NodeId       = tag.TagInfo.NodeId,
                        Error        = error,
                    });
                }
                resultIndex++;
            }
            foreach (var method in methods)
            {
                var error = results[resultIndex].Error;
                if (String.IsNullOrEmpty(error))
                {
                    method.Error = null;
                    method.MethodThingAddress = results[resultIndex].MethodThingAddress;
                }
                else
                {
                    method.Error = error;
                    registrationErrors.Add(new RegistrationError
                    {
                        MethodId = method.MethodId,
                        Error    = error,
                    });
                }
                resultIndex++;
            }
            foreach (var eventRegistration in events)
            {
                var error = results[resultIndex].Error;
                if (String.IsNullOrEmpty(error))
                {
                    eventRegistration.Error = null;
                }
                else
                {
                    eventRegistration.Error = error;
                    registrationErrors.Add(new RegistrationError
                    {
                        PropertyName = eventRegistration.PropertyName,
                        NodeId       = eventRegistration.EventInfo.NodeId,
                        Error        = error,
                    });
                }
                resultIndex++;
            }

            return(registrationErrors);
        }
Пример #16
0
 public Task <MsgSubscribeToThingsResponse> SubscribeToThingsAsync(MsgSubscribeToThings subscribeThingsRequest)
 {
     return(TheCommRequestResponse.PublishRequestJSonAsync <MsgSubscribeToThings, MsgSubscribeToThingsResponse>(this, subscribeThingsRequest));
 }
Пример #17
0
        private void HandleMessage(ICDEThing arg1, object arg2)
        {
            var msg = (arg2 as TheProcessMessage).Message;

            if (msg == null)
            {
                return;
            }

            var messageName = TheCommRequestResponse.ParseRequestOrResponseMessage(msg, out var messageParameters, out var correlationToken);

            switch (messageName)
            {
            case nameof(MsgChatHello):
            {
                var request = TheCommRequestResponse.ParseRequestMessageJSON <MsgChatHello>(msg);
                if (request != null)
                {
                    // Messages come in on a .Net Threadpool thread, so need to dispatch it to the WPF main thread before we can access any WPF controls
                    this.Dispatcher.InvokeAsync(() =>
                        {
                            var chatMessage = new ChatMessage
                            {
                                MessageId  = correlationToken,
                                SenderName = request.SenderName,
                                Message    = request.Message,
                                SeenBy     = 0,
                                Sent       = msg.TIM,
                                Received   = DateTimeOffset.Now,
                            };
                            MessageList.Items.Insert(0, chatMessage);
                        });
                    TheCommRequestResponse.PublishResponseMessageJson(msg, new MsgChatHelloResponse {
                            Acknowledged = true
                        });
                }
                else
                {
                    TheCommRequestResponse.PublishResponseMessageJson(msg, new MsgChatHelloResponse {
                            Acknowledged = false
                        });
                }
            }
            break;

            case nameof(MsgChatHello) + "_RESPONSE":
            {
                var request = TheCommRequestResponse.ParseRequestMessageJSON <MsgChatHelloResponse>(msg);
                if (request != null)
                {
                    this.Dispatcher.InvokeAsync(() =>
                        {
                            if (request.Acknowledged)
                            {
                                int i = 0;
                                foreach (var item in MessageList.Items)
                                {
                                    var chatMessage = item as ChatMessage;
                                    if (chatMessage != null)
                                    {
                                        if (chatMessage.MessageId == correlationToken)
                                        {
                                            chatMessage.SeenBy++;
                                            MessageList.Items.RemoveAt(i);
                                            MessageList.Items.Insert(i, chatMessage);
                                            break;
                                        }
                                    }
                                    i++;
                                }
                            }
                            else
                            {
                                MessageBox.Show($"Somebody ({msg.ORG}) rejected our message {correlationToken}");
                            }
                        });
                }
                else
                {
                    // Somebody is sending MsgChatHelloResponse messages in an unknown/incompatible format, or somebody rejected a message for some reason
                    this.Dispatcher.InvokeAsync(() =>
                        {
                            MessageBox.Show($"Received invalid MsgChatHelloResponse: {msg}");
                        });
                }
            }
            break;
            }
        }
Пример #18
0
        public override void HandleMessage(ICDEThing sender, object pIncoming)
        {
            TheProcessMessage pMsg = pIncoming as TheProcessMessage;

            if (pMsg == null || pMsg.Message == null)
            {
                return;
            }

            var cmd = pMsg.Message.TXT.Split(':');

            switch (cmd[0])
            {
            case "CALL_METHOD":
            case nameof(MsgOPCUAMethodCall):
                string error         = "Unexpected";
                string exceptionText = "";

                MsgOPCUAMethodCall callInfo        = null;
                byte[]             largeOutput     = null;
                string             outParamsAsJson = null;
                IList <object>     outputArguments = null;
                if (m_Method == null)
                {
                    error = "Method meta data not initialized";
                }
                else if (m_Method.MyOPCServer == null)
                {
                    error = "Method not inititialized";
                }
                else if (m_Method.MyOPCServer.m_session == null)
                {
                    error = "OPC UA session not created";
                }
                else
                {
                    try
                    {
                        if (TheCommonUtils.cdeIsLocked(m_Method))
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(78401, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM(MyBaseThing.EngineName, String.Format("[{0}] Method called concurrently", m_Method.MyOPCServer.GetLogAddress()), eMsgLevel.l4_Message, String.Format("{0}", MyBaseThing.Address)));
                        }
                        lock (m_Method)
                        {
                            if (m_Method.Args == null)
                            {
                                var browseError = m_Method.MyOPCServer.MethodBrowser(m_Method.TagRef, m_Method.DisplayName, m_Method);
                                if (!string.IsNullOrEmpty(browseError))
                                {
                                    error = "Unable to retrieve method metadata from server: " + browseError;
                                }
                            }
                            if (m_Method.Args == null)
                            {
                                error = "Unable to retrieve method metadata from server";
                            }
                            else
                            {
                                if (!string.IsNullOrEmpty(pMsg.Message.PLS))
                                {
                                    if (cmd[0] == nameof(MsgOPCUAMethodCall))
                                    {
                                        callInfo = TheCommRequestResponse.ParseRequestMessageJSON <MsgOPCUAMethodCall>(pMsg.Message);
                                        foreach (var argument in callInfo.Arguments)
                                        {
                                            TheThing.SetSafeProperty(this, argument.Key, argument.Value, ePropertyTypes.NOCHANGE);
                                        }
                                    }
                                    else
                                    {
                                        var tLst = TheCommonUtils.cdeSplit(pMsg.Message.PLS, ":;:", true, true).ToList();
                                        foreach (string t in tLst)
                                        {
                                            TheThing.SetPropertyFromBagItem(this, t);
                                        }
                                    }
                                }
                                object[] tArgs = new object[InputArgCnt];
                                for (int i = 0; i < InputArgCnt; i++)
                                {
                                    tArgs[i] = TheOPCTag.GetOPCValueFromCDEValue(InputArgs[i].cdeProperty == null ? null : InputArgs[i].cdeProperty.Value, InputArgs[i].OPCType);
                                }
#if OLD_UA
                                outputArguments = m_Method.MyOPCServer.m_session.CallWithTimeout(m_Method.ParentId, m_Method.TagRef, MethodCallTimeout, tArgs);
#else
                                outputArguments = m_Method.MyOPCServer.m_session.Call(m_Method.ParentId, m_Method.TagRef, tArgs);     //CM: C-labs extension: .CallWithTimeout(m_Method.ParentId, m_Method.TagRef, MethodCallTimeout, tArgs);
#endif
                                if (cmd[0] != nameof(MsgOPCUAMethodCall))
                                {
                                    if (TheThing.GetSafePropertyBool(this, "ReturnOutputAsJson"))
                                    {
                                        outParamsAsJson = TheCommonUtils.SerializeObjectToJSONString(outputArguments);
                                        //TheThing.SetSafePropertyString(this, "OutputAsJson", outParamsAsJson);
                                    }
                                    else
                                    {
                                        if (outputArguments != null && outputArguments.Count > 0)
                                        {
                                            for (int i = 0; i < outputArguments.Count; i++)
                                            {
                                                if (i < OutputArgs.Count)
                                                {
                                                    object value;
                                                    if (outputArguments[i] is byte[] && (outputArguments[i] as byte[]).Length > 4096 && largeOutput == null)
                                                    {
                                                        largeOutput = outputArguments[i] as byte[];
                                                        value       = "";
                                                    }
                                                    else
                                                    {
                                                        value = outputArguments[i];
                                                    }

                                                    cdeP tP = OutputArgs[i].cdeProperty;
                                                    if (tP != null)
                                                    {
                                                        //TheOPCTag.UpdateValueProperty(outputArguments[i] as DataValue, tP, outputArguments[i] as DataValue);
                                                        tP.Value = value;
                                                        // tP.SetValue(outputArguments[i], pMsg.Message.GetOriginator().ToString()); // CODE REVIEW: Why did we set the originator here? It's only really needed for remote things to break update cycles...
                                                    }
                                                }
                                                else
                                                {
                                                    TheBaseAssets.MySYSLOG.WriteToLog(78402, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM(MyBaseThing.EngineName, String.Format("[{0}] Error processing method response for OPC Server", m_Method.MyOPCServer.GetLogAddress()), eMsgLevel.l2_Warning, String.Format("{0}: too many out parameters in method", MyBaseThing.Address)));
                                                }
                                            }
                                        }
                                    }
                                    MyBaseThing.LastUpdate = DateTimeOffset.Now;
                                    LastMessage            = string.Format("Success at {0}", MyBaseThing.LastUpdate);
                                }
                                error = "";
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        error         = "Method Call failed: " + e.Message;
                        exceptionText = e.ToString();
                        LastMessage   = error;
                        TheBaseAssets.MySYSLOG.WriteToLog(78403, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(MyBaseThing.EngineName, String.Format("[{0}] Method Call failed", m_Method.MyOPCServer.GetLogAddress()), eMsgLevel.l1_Error, String.Format("{0}:{1}", MyBaseThing.Address, e.ToString())));
                    }
                }
                if (cmd[0] == nameof(MsgOPCUAMethodCall))
                {
                    if (callInfo?.ReturnRawJSON == true)
                    {
                        TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, new MsgOPCUAMethodCallResponse {
                            OutputArguments = new List <object> {
                                TheCommonUtils.SerializeObjectToJSONString(outputArguments)
                            }, Error = error
                        });
                    }
                    else
                    {
                        TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, new MsgOPCUAMethodCallResponse {
                            OutputArguments = (List <object>)outputArguments, Error = error
                        });
                    }
                }
                else
                {
                    TSM tTSN = new TSM(MyBaseThing.EngineName, string.Format(String.IsNullOrEmpty(error) ? "CALL_METHOD_RESPONSE:{0}:{1}" : "CALL_METHOD_RESPONSE:{0}:{1}:{2}:{3}", MyBaseThing.ID, cmd[1], error.Replace(":", " "), exceptionText.Replace(":", " ")));
                    if (largeOutput != null && String.IsNullOrEmpty(error))
                    {
                        tTSN.PLB = largeOutput;
                    }
                    if (outParamsAsJson != null && String.IsNullOrEmpty(error))
                    {
                        tTSN.PLS = outParamsAsJson;
                    }
                    if (pMsg.LocalCallback != null)
                    {
                        pMsg.LocalCallback(tTSN);
                    }
                    else
                    {
                        TheCommCore.PublishToOriginator(pMsg.Message, tTSN);
                    }
                }
                break;
            }

            base.HandleMessage(this, pMsg);
        }
Пример #19
0
        static protected TheThing StartOPCServer(bool disableSecurity)
        {
#if OPCUASERVER
            // TODO Actually use our own OPC Server for the unit test
            var opcServerThing = TheThingRegistry.GetThingsOfEngine("CDMyOPCUAServer.cdeMyOPCServerService").FirstOrDefault();
            Assert.IsNotNull(opcServerThing, $"Unable to obtain OPC Server thing: error loading plug-in or server not yet initialized?");

            lock (opcServerStartupLock)
            {
                if (!TheThing.GetSafePropertyBool(opcServerThing, "IsRunning"))
                {
                    TheThing.SetSafePropertyBool(opcServerThing, "DisableSecurity", disableSecurity);
                    TheThing.SetSafePropertyBool(opcServerThing, "NoServerCertificate", disableSecurity);

                    var theOpcThing = new TheThing();
                    theOpcThing.EngineName = "OPCTestEng";
                    theOpcThing.DeviceType = "OPCTestDT";
                    theOpcThing.Address    = "OPCTestAddress";
                    theOpcThing.SetProperty("OpcProp01", "0001");
                    theOpcThing.SetProperty("OpcProp02", "0002");
                    theOpcThing.SetProperty("OpcProp03", "0003");
                    theOpcThing.SetProperty("OpcProp04", "0004");
                    theOpcThing.SetProperty("OpcProp05", "0005");
                    theOpcThing.SetProperty("OpcProp06", "0006");
                    theOpcThing.SetProperty("OpcProp07", "0007");
                    theOpcThing.SetProperty("OpcProp08", "0008");
                    theOpcThing.SetProperty("OpcProp09", "0009");
                    theOpcThing.SetProperty("OpcProp10", "0010");
                    var tThing = TheThingRegistry.RegisterThing(theOpcThing);
                    Assert.IsNotNull(tThing);

                    var addThingResponse = TheCommRequestResponse.PublishRequestJSonAsync <MsgAddThingsToServer, MsgAddThingsToServerResponse>(myContentService, opcServerThing, new MsgAddThingsToServer
                                                                                                                                               (
                                                                                                                                                   new TheThingToAddToServer
                    {
                        cdeMID = Guid.NewGuid(),
                        ReplaceExistingThing = false,
                        ThingMID             = TheCommonUtils.cdeGuidToString(theOpcThing.cdeMID),
                    }
                                                                                                                                               ), new TimeSpan(0, 0, 30)).Result;

                    Assert.IsNotNull(addThingResponse, "No reply to OPC Server MsgAddThingToServer");
                    Assert.IsTrue(string.IsNullOrEmpty(addThingResponse.Error), $"Error adding thing to OPC Server: '{addThingResponse.Error}'.");
                    Assert.AreEqual(1, addThingResponse.ThingStatus.Count, $"Error adding thing to OPC Server.");
                    Assert.IsTrue(string.IsNullOrEmpty(addThingResponse.ThingStatus[0].Error), $"Error adding thing to OPC Server: '{addThingResponse.ThingStatus[0].Error}'.");

                    MsgStartStopServerResponse responseStart;
                    int retryCount = 1;
                    do
                    {
                        responseStart = TheCommRequestResponse.PublishRequestJSonAsync <MsgStartStopServer, MsgStartStopServerResponse>(myContentService, opcServerThing,
                                                                                                                                        new MsgStartStopServer
                        {
                            Restart = true,
                        },
                                                                                                                                        new TimeSpan(0, 0, 30)).Result;
                        retryCount--;
                    } while (retryCount >= 0 && responseStart == null);

                    Assert.IsNotNull(responseStart, "Failed to send MsgStartStopServer message to restart OPC UA Server");
                    Assert.IsTrue(string.IsNullOrEmpty(responseStart.Error), $"Error restarting OPC Server: '{addThingResponse.Error}'.");
                    Assert.IsTrue(responseStart.Running, $"OPC Server not running after MsgStartStopServer Restart message");
                }
            }
            return(opcServerThing);
#else
            return(null);
#endif
        }
Пример #20
0
        public void CreateOPCWizard()
        {
            TheFieldInfo tTargetButton = null;
            var          flds          = TheNMIEngine.AddNewWizard <TheOPCSetClass>(new Guid("{56565656-6AD1-45AE-BE61-96AF02329614}"), Guid.Empty, TheNMIEngine.GetEngineDashBoardByThing(MyBaseThing).cdeMID, "Welcome to the OPC Wizard",
                                                                                    new nmiCtrlWizard {
                PanelTitle = "<i class='fa faIcon fa-3x'>&#xf0d0;</i></br>New OPC Client", SideBarTitle = "New OPC Client Wizard", SideBarIconFA = "&#xf545;", TileThumbnail = "FA5:f545"
            },
                                                                                    (myClass, pClientInfo) =>
            {
                myClass.cdeMID   = Guid.Empty;
                TheThing tMemTag = null;
                if (myClass.CreateMemoryTag)
                {
                    var tReq = new TheThingRegistry.MsgCreateThingRequestV1()
                    {
                        EngineName       = "CDMyVThings.TheVThings",
                        DeviceType       = "Memory Tag",
                        FriendlyName     = myClass.ClientName,
                        OwnerAddress     = MyBaseThing,
                        InstanceId       = Guid.NewGuid().ToString(),
                        CreateIfNotExist = true
                    };
                    tMemTag = TheThingRegistry.CreateOwnedThingAsync(tReq).Result;
                }

                var tOPCReq = new TheThingRegistry.MsgCreateThingRequestV1()
                {
                    EngineName       = "CDMyOPCUAClient.cdeOPCUaClient",
                    DeviceType       = "OPC-UA Remote Server",
                    FriendlyName     = myClass.ClientName,
                    Address          = myClass.OPCAddress,
                    OwnerAddress     = MyBaseThing,
                    InstanceId       = Guid.NewGuid().ToString(),
                    CreateIfNotExist = true
                };
                tOPCReq.Properties = new Dictionary <string, object>();
                //tOPCReq.Properties["ID"] = Guid.NewGuid().ToString();
                tOPCReq.Properties["AutoConnect"]     = myClass.AutoConnect;
                tOPCReq.Properties["SendOpcDataType"] = true;
                if (!myClass.DisableSecurity)
                {
                    tOPCReq.Properties["DisableSecurity"]            = true;
                    tOPCReq.Properties["AcceptUntrustedCertificate"] = true;
                    tOPCReq.Properties["DisableDomainCheck"]         = true;
                    tOPCReq.Properties["AcceptInvalidCertificate"]   = true;
                    tOPCReq.Properties["Anonymous"] = true;
                }
                if (tMemTag != null)
                {
                    tOPCReq.Properties["TagHostThingForSubscribeAll"] = tMemTag.cdeMID;
                }
                var tOPCServer = TheThingRegistry.CreateOwnedThingAsync(tOPCReq).Result;
                try
                {
                    if (tOPCServer != null && myClass.Prop2Tag && myClass.AutoConnect)
                    {
                        var response = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAConnect, MsgOPCUAConnectResponse>(MyBaseThing, tOPCServer, new MsgOPCUAConnect {
                            LogEssentialOnly = true, WaitUntilConnected = true
                        }).Result;
                        if (response != null && string.IsNullOrEmpty(response.Error))
                        {
                            var tBrowseResponse = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUABrowse, MsgOPCUABrowseResponse>(MyBaseThing, tOPCServer, new MsgOPCUABrowse()).Result;
                            if (string.IsNullOrEmpty(tBrowseResponse.Error))
                            {
                                TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", $"OPC UA Client browse error: {tBrowseResponse.Error}"));
                                return;
                            }
                            else
                            {
                                List <MsgOPCUACreateTags.TagInfo> tTagList = tBrowseResponse.Tags;
                                if (tTagList != null && tTagList.Count > 0)
                                {
                                    var tres = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUACreateTags, MsgOPCUACreateTagsResponse>(MyBaseThing, tOPCServer, new MsgOPCUACreateTags {
                                        Tags = tTagList, BulkApply = true
                                    }).Result;
                                    if (tres != null && string.IsNullOrEmpty(tres.Error))
                                    {
                                        TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "OPC UA Client Created and memory tag ready"));
                                    }
                                }
                            }
                        }
                    }
                    TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "OPC UA Client Created and ready"));
                }
                catch (Exception)
                {
                    TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "Something went wrong! Check the OPC and Memory Tag settings"));
                }
                tTargetButton.SetUXProperty(pClientInfo.NodeID, $"OnClick=TTS:{tOPCServer.GetBaseThing().cdeMID}");
                TheCommonUtils.SleepOneEye(2000, 100);
            });

            var tMyForm2 = flds["Form"] as TheFormInfo;

            var tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 0, 1, 2, null /*"Name and Address"*/);

            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleEnded, 1, 1, 2, 0, "Connection Name", "ClientName", new TheNMIBaseControl {
                Explainer = "1. Enter name for the new OPC connection.",
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleEnded, 1, 2, 2, 0, "OPC Server Address", "OPCAddress", new TheNMIBaseControl {
                Explainer = "1. Enter address of the OPC server.",
            });

            tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 1, 2, 3, null /* "Settings"*/);
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 1, 2, 0, "OPC Server requires Security", "DisableSecurity", new nmiCtrlSingleCheck {
                Explainer = "Check if the OPC Server requires security"
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 2, 2, 0, "Create a Memory Tag", "CreateMemoryTag", new nmiCtrlSingleCheck {
                TileWidth = 3, Explainer = "Check to create a Memory Tag and check to subscribes all Tags into it"
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 3, 2, 0, "All Tags in Memory Tag", "Prop2Tag", new nmiCtrlSingleCheck {
                TileWidth = 3
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 4, 2, 0, "Auto Connect to Server", "AutoConnect", new nmiCtrlSingleCheck {
                TileWidth = 3, Explainer = "Don't select this if your server requires security settings"
            });

            tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 2, 3, 0, null /*"Final Settings"*/);
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 3, 2, 0, 0, null, null, new nmiCtrlSmartLabel {
                Text = "Once you click finish, the Wizard will create the items you requested. It will notify you with a toast when its done", TileHeight = 5, TileWidth = 7, NoTE = true
            });
            //HELP SECTION final step help section

            TheNMIEngine.AddWizardProcessPage(MyBaseThing, tMyForm2, 4);
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 4, 1, 0, 0, null, null, new nmiCtrlSmartLabel {
                NoTE = true, TileWidth = 7, Text = "Creating the new instance..please wait", TileHeight = 2
            });

            TheNMIEngine.AddWizardFinishPage(MyBaseThing, tMyForm2, 5);
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 5, 1, 0, 0, null, null, new nmiCtrlSmartLabel {
                NoTE = true, TileWidth = 7, Text = "Done...what do you want to do next?", TileHeight = 2
            });

            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileGroup, 5, 2, 0, 0, null, null, new nmiCtrlTileGroup {
                TileWidth = 1, TileHeight = 2, TileFactorX = 2
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileButton, 5, 3, 2, 0, "Go to Dashboard", null, new nmiCtrlTileButton {
                NoTE = true, TileHeight = 2, TileWidth = 3, OnClick = $"TTS:{mMyDashboard.cdeMID}", ClassName = "cdeTransitButton"
            });
            TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileGroup, 5, 4, 0, 0, null, null, new nmiCtrlTileGroup {
                TileWidth = 1, TileHeight = 2
            });
            tTargetButton = TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileButton, 5, 5, 2, 0, "Go to New OPC Client", null, new nmiCtrlTileButton {
                NoTE = true, TileHeight = 2, TileWidth = 3, ClassName = "cdeTransitButton"
            });
        }
Пример #21
0
 public Task <MsgGetThingSubscriptionsResponse> GetThingSubscriptionsAsync(MsgGetThingSubscriptions getSubscriptionsRequest)
 {
     return(TheCommRequestResponse.PublishRequestJSonAsync <MsgGetThingSubscriptions, MsgGetThingSubscriptionsResponse>(this, getSubscriptionsRequest));
 }
Пример #22
0
        /// <summary>
        /// Handles Messages sent from a host sub-engine to its clients
        /// </summary>
        /// <param name="Command"></param>
        /// <param name="pMessage"></param>
        public override void HandleMessage(ICDEThing sender, object pIncoming)
        {
            TheProcessMessage pMsg = pIncoming as TheProcessMessage;

            if (pMsg == null)
            {
                return;
            }

            string[] cmd = pMsg.Message.TXT.Split(':');
            switch (cmd[0])
            {
            case nameof(TheThing.MsgBrowseSensors):
                var browseRequest  = TheCommRequestResponse.ParseRequestMessageJSON <TheThing.MsgBrowseSensors>(pMsg.Message);
                var browseResponse = new TheThing.MsgBrowseSensorsResponse {
                    Error = "Internal error", Sensors = new List <TheThing.TheSensorSourceInfo>()
                };
                foreach (FieldMapping fld in MyModFieldStore.TheValues)
                {
                    browseResponse.Sensors.Add(new TheThing.TheSensorSourceInfo
                    {
                        SourceType    = fld.SourceType,
                        cdeType       = ePropertyTypes.TNumber,
                        SensorId      = TheCommonUtils.CStr(fld.cdeMID),
                        ExtensionData = new Dictionary <string, object>
                        {
                            { nameof(FieldMapping.SourceOffset), fld.SourceOffset },
                            { nameof(FieldMapping.SourceSize), fld.SourceSize },
                            { nameof(FieldMapping.AllowWrite), fld.AllowWrite }
                        },
                        DisplayNamePath = new string[] { MyBaseEngine.GetEngineName(), MyBaseThing.FriendlyName, fld.PropertyName }
                    });
                }
                browseResponse.Error = null;
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, browseResponse);
                break;

            case nameof(TheThing.MsgSubscribeSensors):
                var subscribeRequest  = TheCommRequestResponse.ParseRequestMessageJSON <TheThing.MsgSubscribeSensors>(pMsg.Message);
                var subscribeResponse = new TheThing.MsgSubscribeSensorsResponse {
                    Error = "Internal error", SubscriptionStatus = new List <TheThing.TheSensorSubscriptionStatus>()
                };
                if (subscribeRequest.ReplaceAll)
                {
                    MyModFieldStore.RemoveAllItems();
                }
                var subscriptionStatus = new List <TheThing.TheSensorSubscriptionStatus>();
                foreach (TheThing.TheSensorSubscription sub in subscribeRequest.SubscriptionRequests)
                {
                    FieldMapping fld = new FieldMapping()
                    {
                        PropertyName = sub.TargetProperty,
                        cdeMID       = TheCommonUtils.CGuid(sub.SensorId)
                    };
                    if (fld.cdeMID == Guid.Empty)
                    {
                        fld.cdeMID = Guid.NewGuid();
                    }
                    object sourceType;
                    if (sub.ExtensionData != null)
                    {
                        if (sub.ExtensionData.TryGetValue(nameof(TheThing.TheSensorSourceInfo.SourceType), out sourceType))
                        {
                            fld.SourceType = TheCommonUtils.CStr(sourceType);
                        }
                        object offset;
                        if (sub.ExtensionData.TryGetValue("SourceOffset", out offset))
                        {
                            fld.SourceOffset = TheCommonUtils.CInt(offset);
                        }
                        object size;
                        if (sub.ExtensionData.TryGetValue("SourceSize", out size))
                        {
                            fld.SourceSize = TheCommonUtils.CInt(size);
                        }
                        object allowWrite;
                        if (sub.ExtensionData.TryGetValue("AllowWrite", out allowWrite))
                        {
                            fld.AllowWrite = TheCommonUtils.CBool(allowWrite);
                        }
                        MyModFieldStore.AddAnItem(fld);
                        subscriptionStatus.Add(CreateSubscriptionStatusFromFieldMapping(fld));
                    }
                    else
                    {
                        subscriptionStatus.Add(new TheThing.TheSensorSubscriptionStatus
                        {
                            Error        = "Missing source info",
                            Subscription = sub,
                        });
                    }
                }
                subscribeResponse.SubscriptionStatus = subscriptionStatus;
                subscribeResponse.Error = null;
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, subscribeResponse);
                break;

            case nameof(TheThing.MsgGetSensorSubscriptions):
                var getResponse = new TheThing.MsgGetSensorSubscriptionsResponse {
                    Error = "Internal error"
                };
                getResponse.Subscriptions = MyModFieldStore.TheValues.Select(fld => CreateSubscriptionStatusFromFieldMapping(fld).Subscription).ToList();
                getResponse.Error         = null;
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, getResponse);
                break;

            case nameof(TheThing.MsgUnsubscribeSensors):
                var unsubscribeRequest  = TheCommRequestResponse.ParseRequestMessageJSON <TheThing.MsgUnsubscribeSensors>(pMsg.Message);
                var unsubscribeResponse = new TheThing.MsgUnsubscribeSensorsResponse {
                    Error = "Internal error", Failed = new List <TheThing.TheSensorSubscriptionStatus>()
                };
                if (unsubscribeRequest.UnsubscribeAll)
                {
                    MyModFieldStore.RemoveAllItems();
                    if (MyModFieldStore.GetCount() > 0)
                    {
                        unsubscribeResponse.Failed = MyModFieldStore.TheValues.Select(fld => CreateSubscriptionStatusFromFieldMapping(fld)).ToList();
                    }
                }
                else
                {
                    List <FieldMapping> toRemove = MyModFieldStore.TheValues.FindAll(fld => unsubscribeRequest.SubscriptionIds.Contains(fld.cdeMID));
                    MyModFieldStore.RemoveItems(toRemove, null);
                    foreach (FieldMapping fld in MyModFieldStore.TheValues)
                    {
                        if (toRemove.Any(t => t.cdeMID == fld.cdeMID))
                        {
                            unsubscribeResponse.Failed.Add(CreateSubscriptionStatusFromFieldMapping(fld));
                        }
                    }
                }
                unsubscribeResponse.Error = null;
                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, unsubscribeResponse);
                break;

            case nameof(TheThing.MsgExportConfig):
                var exportRequest  = TheCommRequestResponse.ParseRequestMessageJSON <TheThing.MsgExportConfig>(pMsg.Message);
                var exportResponse = new TheThing.MsgExportConfigResponse {
                    Error = "Internal error"
                };

                // No custom config beyond config properties and subscriptions
                exportResponse.Error = null;

                TheCommRequestResponse.PublishResponseMessageJson(pMsg.Message, exportResponse);
                break;

            case nameof(TheThing.MsgApplyConfig):
                break;

            default:
                break;
            }

            TheThing.TheSensorSubscriptionStatus CreateSubscriptionStatusFromFieldMapping(FieldMapping fld)
            {
                return(new TheThing.TheSensorSubscriptionStatus
                {
                    Subscription = new TheThing.TheSensorSubscription
                    {
                        TargetProperty = fld.PropertyName,
                        SensorId = TheCommonUtils.CStr(fld.cdeMID),
                        SubscriptionId = fld.cdeMID,
                        ExtensionData = new Dictionary <string, object>
                        {
                            { nameof(FieldMapping.SourceType), fld.SourceType },
                            { nameof(FieldMapping.SourceOffset), fld.SourceOffset },
                            { nameof(FieldMapping.SourceSize), fld.SourceSize },
                            { nameof(FieldMapping.AllowWrite), fld.AllowWrite }
                        },
                        TargetThing = new TheThingReference(MyBaseThing),
                        SampleRate = (int?)this.Interval
                    },
                    Error = null,
                });
            }
        }
Пример #23
0
        private async Task RunScriptAsync(TheScript script, TheThing variables, int stepNumber = 1, bool replay = false)
        {
            TheThing variablesSnapshot;

            try
            {
                for (; stepNumber <= script.Steps.Length; stepNumber++)
                {
                    //Clone thing before step occurs
                    variablesSnapshot = new TheThing();
                    variables.CloneThingAndPropertyMetaData(variablesSnapshot, true);

                    var step = script.Steps[stepNumber - 1];

                    var existingSnapshot = MyScriptTableStorage.MyMirrorCache.GetEntryByFunc(snapshot => snapshot.ScriptName == script.Name && snapshot.ScriptStep == stepNumber);
                    if (existingSnapshot?.Disabled == true)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(175002, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Finished script step: skipped step because it was disabled", eMsgLevel.l3_ImportantMessage, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                            { "Script", script.Name },
                            { "Step", stepNumber },
                            { "Message", step.Message.MessageName },
                            { "Target", step.Message.Target },
                        })));

                        UpdateStorageList(script.Name, "Disabled", stepNumber, script, variablesSnapshot, replay);
                        continue;
                    }

                    if (step.Condition != null)
                    {
                        var condition = TheCommonUtils.GenerateFinalStr(step.Condition, variables);
                        if (
                            (condition == "" || condition.ToLowerInvariant() == "false" || condition.Trim() == "0") ||
                            (condition.StartsWith("!") && condition.Length >= 1 && (condition.Substring(1).ToLowerInvariant() == "true") || condition.Substring(1).Trim() == "1"))
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(175002, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Finished script step: skipped step due to condition not met", eMsgLevel.l3_ImportantMessage, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                { "Script", script.Name },
                                { "Step", stepNumber },
                                { "Message", step.Message.MessageName },
                                { "Target", step.Message.Target },
                                { "Condition", step.Condition },
                                { "ConditionEvaluated", condition },
                            })));

                            UpdateStorageList(script.Name, "Condition Not Met", stepNumber, script, variablesSnapshot, replay);

                            continue;
                        }
                    }
                    var messageType = TheCommonUtils.GenerateFinalStr(step.Message.MessageName, variables);
                    var txtPayload  = TheCommonUtils.GenerateFinalStr(step.Message.Parameters?.ToString(), variables);
                    {
                        var txtPayload2 = txtPayload?.Replace("\"\\\"", "");
                        var txtPayload3 = txtPayload2?.Replace("\\\"\"", "");
                        txtPayload = txtPayload3;
                    }

                    // TODO Need a simpler and more flexible way to specify thing address in the script JSON
                    var target = step.Message.Target;
                    if (target == null)
                    {
                        if (txtPayload.Contains("EngineName"))
                        {
                            var    payloadDict        = TheCommonUtils.DeserializeJSONStringToObject <Dictionary <string, object> >(txtPayload);
                            object engineNameInferred = null;
                            if (payloadDict?.TryGetValue("EngineName", out engineNameInferred) == true && !string.IsNullOrEmpty(engineNameInferred?.ToString()))
                            {
                                target = new TheMessageAddress {
                                    EngineName = engineNameInferred.ToString()
                                };
                            }
                        }
                    }
                    if (target.EngineName.StartsWith("%") || target.EngineName.StartsWith("{"))
                    {
                        target.EngineName = TheCommonUtils.GenerateFinalStr(target.EngineName, variables);
                        // TODO Clean this up: support a serialized TheMessageAddress in the engine name, so that an output variable can be fed into a method invocation
                        try
                        {
                            var newTarget = TheCommonUtils.DeserializeJSONStringToObject <TheMessageAddress>(target.EngineName);
                            if (newTarget != null)
                            {
                                target = newTarget;
                            }
                        }
                        catch
                        {
                            // parsing error: ignore, will result in other errors downstream
                        }
                    }

                    await TheThingRegistry.WaitForInitializeAsync(target);

                    bool bDoRetry;
                    int  remainingRetryCount = step.RetryCount ?? 0;
                    do
                    {
                        existingSnapshot = MyScriptTableStorage.MyMirrorCache.GetEntryByFunc(snapshot => snapshot.ScriptName == script.Name && snapshot.ScriptStep == stepNumber);
                        if (existingSnapshot?.Disabled == true)
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(175002, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Finished script step: skipped step because it was disabled", eMsgLevel.l3_ImportantMessage, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                { "Script", script.Name },
                                { "Step", stepNumber },
                                { "Message", step.Message.MessageName },
                                { "Target", step.Message.Target },
                            })));

                            UpdateStorageList(script.Name, "Disabled", stepNumber, script, variablesSnapshot, replay);
                            break;
                        }

                        bDoRetry = false;
                        var response = await TheCommRequestResponse.PublishRequestAsync(MyBaseThing, target, messageType, new TimeSpan(0, 0, 0, 0, step.Message.timeout), null, txtPayload, null);

                        if (!string.IsNullOrEmpty(response?.PLS))
                        {
                            var outputs = TheCommonUtils.DeserializeJSONStringToObject <Dictionary <string, object> >(response.PLS);
                            if (outputs != null)
                            {
                                if (step.Message.outputs != null)
                                {
                                    foreach (var output in step.Message.outputs)
                                    {
                                        if (output.Key == "*")
                                        {
                                            variables.SetProperty(output.Value, response.PLS);
                                        }
                                        else if (outputs.TryGetValue(output.Key, out var outputValue))
                                        {
                                            variables.SetProperty(output.Value, outputValue);
                                            if (output.Value.Contains("Error") && !string.IsNullOrEmpty(TheCommonUtils.CStr(outputValue)))
                                            {
                                                TheBaseAssets.MySYSLOG.WriteToLog(175004, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error in script step: output reported error", eMsgLevel.l1_Error, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                                    { "Script", script.Name },
                                                    { "Step", stepNumber },
                                                    { "Message", messageType },
                                                    { "Target", target },
                                                    { "PLS", txtPayload },
                                                    { "Response", response },
                                                    { "ResponsePLS", response?.PLS },
                                                })));

                                                UpdateStorageList(script.Name, $"Error {outputValue} in output", stepNumber, script, variablesSnapshot, replay);

                                                if (remainingRetryCount < 0 || remainingRetryCount > 0)
                                                {
                                                    remainingRetryCount--;
                                                    bDoRetry = true;
                                                }
                                                string retriesRemaining = bDoRetry ? (remainingRetryCount >= 0 ? $"{remainingRetryCount + 1}" : "infinite") : "none";
                                                MyBaseThing.SetStatus(3, $"Error in script '{script?.Name}', step {stepNumber}: output '{output.Value}' reported error {outputValue}. Retries remaining: {retriesRemaining}");
                                            }
                                        }
                                        else
                                        {
                                            // TODO provide access to sub-elements in the JSON
                                            //var outputParts = output.Key.Split('/');
                                            //dynamic currentNode = outputs;
                                            //foreach (var outputPart in outputParts)
                                            //{
                                            //    if (currentNode.TryGetValue(outputPart, out var nextNode))
                                            //    {
                                            //        currentNode = nextNode;
                                            //    }
                                            //}
                                        }
                                    }
                                }
                                TheBaseAssets.MySYSLOG.WriteToLog(175003, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Finished script step", eMsgLevel.l3_ImportantMessage, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                    { "Script", script.Name },
                                    { "Step", stepNumber },
                                    { "Message", messageType },
                                    { "Target", target },
                                    { "PLS", txtPayload },
                                    { "ResponsePLS", response.PLS },
                                })));

                                UpdateStorageList(script.Name, "Finished", stepNumber, script, variablesSnapshot, replay);
                            }
                            else
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(175004, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error in script step: no outputs found in response", eMsgLevel.l1_Error, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                    { "Script", script.Name },
                                    { "Step", stepNumber },
                                    { "Message", messageType },
                                    { "Target", target },
                                    { "PLS", txtPayload },
                                    { "Response", response },
                                    { "ResponsePLS", response?.PLS },
                                })));

                                UpdateStorageList(script.Name, "Error: No Output", stepNumber, script, variablesSnapshot, replay);

                                if (step.DontRetryOnEmptyResponse != true && (remainingRetryCount < 0 || remainingRetryCount > 0))
                                {
                                    remainingRetryCount--;
                                    bDoRetry = true;
                                }
                                string retriesRemaining = bDoRetry ? (remainingRetryCount >= 0 ? $"{remainingRetryCount + 1}" : "infinite") : "none";
                                MyBaseThing.SetStatus(3, $"Error in script '{script?.Name}', step {stepNumber}: no outputs found in response. Retries remaining: {retriesRemaining}");
                            }
                        }
                        else
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(175005, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error Script step: timeout", eMsgLevel.l1_Error, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                                { "Script", script.Name },
                                { "Step", stepNumber },
                                { "Message", messageType },
                                { "Target", target },
                                { "PLS", txtPayload },
                                { "Response", response },
                            })));

                            UpdateStorageList(script.Name, "Error: Timeout", stepNumber, script, variablesSnapshot, replay);

                            //Retries infinitely unless count is specified
                            if (remainingRetryCount < 0 || remainingRetryCount > 0)
                            {
                                remainingRetryCount--;
                                bDoRetry = true;
                            }
                            string retriesRemaining = bDoRetry ? (remainingRetryCount >= 0 ? $"{remainingRetryCount + 1}" : "infinite") : "none";
                            MyBaseThing.SetStatus(3, $"Error in script '{script?.Name}', step {stepNumber}: timeout. Retries remaining: {retriesRemaining}");
                        }
                        if (bDoRetry)
                        {
                            await TheCommonUtils.TaskDelayOneEye(30000, 100).ConfigureAwait(false);
                        }
                    } while (bDoRetry && TheBaseAssets.MasterSwitch);
                }
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(175006, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error in script step", eMsgLevel.l1_Error, TheCommonUtils.SerializeObjectToJSONString(new Dictionary <String, object> {
                    { "Script", script.Name },
                    { "Exception", e.Message },
                })));
                MyBaseThing.SetStatus(3, $"Error in script '{script?.Name}': {e.Message}");
                //Save variables instead of snapshot in case of error
                UpdateStorageList(script.Name, $"Error: {e.Message}", stepNumber, script, variables, replay);
            }
        }
Пример #24
0
 public Task <MsgUnsubscribeFromThingsResponse> UnsubscribeFromThingsAsync(MsgUnsubscribeFromThings unsubscribeThingsRequest)
 {
     return(TheCommRequestResponse.PublishRequestJSonAsync <MsgUnsubscribeFromThings, MsgUnsubscribeFromThingsResponse>(this, unsubscribeThingsRequest));
 }