Exemple #1
0
        public bool PushEvent(AasEventMsgEnvelope ev)
        {
            // access
            if (ev == null)
            {
                return(false);
            }

            // internal?
            if (CheckPushedEventInternal(ev))
            {
                return(true);
            }

            // use enumerator
            var consume = false;

            foreach (var con in GetAllConnectors())
            {
                var br = con.PushEvent(ev);
                if (br)
                {
                    consume = true;
                    break;
                }
            }

            // done
            return(consume);
        }
Exemple #2
0
        //
        // Interface
        //

        /// <summary>
        /// PackageCentral pushes an AAS event message down to the connector.
        /// Return true, if the event shall be consumed and PackageCentral shall not
        /// push anything further.
        /// </summary>
        /// <param name="ev">The event message</param>
        /// <returns>True, if consume event</returns>
        public override bool PushEvent(AasEventMsgEnvelope ev)
        {
            // add
            if (_eventStore != null)
            {
                lock (_eventStore)
                    _eventStore.Insert(0, ev);
            }

            // do not consume, just want to listen!
            return(false);
        }
Exemple #3
0
        //
        // Interface
        //

        /// <summary>
        /// PackageCentral pushes an AAS event message down to the connector.
        /// Return true, if the event shall be consumed and PackageCentral shall not
        /// push anything further.
        /// </summary>
        /// <param name="ev">The event message</param>
        /// <returns>True, if consume event</returns>
        public bool PushEvent(AasEventMsgEnvelope ev)
        {
            // add
            if (_eventStore != null)
            {
                lock (_eventStore)
                    _eventStore.Insert(0, ev);
            }

            // _autoTop?
            if (_autoTop)
            {
                DataGridMessages.SelectedIndex = 0;
            }

            // do not consume, just want to listen!
            return(false);
        }
Exemple #4
0
        private void PublishSingleValues_UpdateItem(
            AasEventMsgEnvelope ev,
            AdminShell.ReferableRootInfo ri,
            AdminShell.KeyList startPath,
            AasPayloadUpdateValueItem ui)
        {
            // trivial
            if (ev == null || ui == null || startPath == null || ui.Path == null)
            {
                return;
            }

            // value of the leaf
            var valStr = "" + ui.Value;

            // build a complete path of keys
            var path    = startPath + ui.Path;
            var pathStr = path.BuildIdShortPath();

            // publish
            if (_diaData.LogDebug)
            {
                _logger?.Info("Publish single value (update value)");
            }
            var message = new MqttApplicationMessageBuilder()
                          .WithTopic(GenerateTopic(
                                         _diaData.EventTopic, defaultIfNull: "SingleValue",
                                         aasIdShort: ri?.AAS?.idShort, aasId: ri?.AAS?.identification,
                                         smIdShort: ri?.Submodel?.idShort, smId: ri?.Submodel?.identification,
                                         path: pathStr))
                          .WithPayload(valStr)
                          .WithExactlyOnceQoS()
                          .WithRetainFlag(_diaData.MqttRetain)
                          .Build();

            // publish
            _mqttClient.PublishAsync(message).GetAwaiter().GetResult();
            LogStatus(incSingleValue: 1);
        }
Exemple #5
0
        public bool PushEvent(AasEventMsgEnvelope ev)
        {
            // access
            if (ev == null)
            {
                return(false);
            }
            var consume = false;

            // use enumerator
            foreach (var con in GetAllInstanceManageEvents())
            {
                var br = con.PushEvent(ev);
                if (br)
                {
                    consume = true;
                    break;
                }
            }

            // done
            return(consume);
        }
Exemple #6
0
        /// <summary>
        /// Tries to get an HTTP REST update value event and transforms this into an AAS event.
        /// </summary>
        /// <returns>True, if an event was emitted</returns>
        public async Task <bool> SimulateUpdateValuesEventByGetAsync(
            AdminShell.Submodel rootSubmodel,
            AdminShell.BasicEvent sourceEvent,
            AdminShell.Referable requestedElement,
            DateTime timestamp,
            string topic   = null,
            string subject = null)
        {
            // access
            if (!IsValid())
            {
                throw new PackageConnectorException("PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    "connection not valid!");
            }

            // first check (only allow two types of elements!)
            var reqSm  = requestedElement as AdminShell.Submodel;
            var reqSme = requestedElement as AdminShell.SubmodelElement;

            if (rootSubmodel == null || sourceEvent == null ||
                requestedElement == null || timestamp == null ||
                (reqSm == null && reqSme == null))
            {
                throw new PackageConnectorException("PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    "input arguments not valid!");
            }

            // need the parent info (even, if the calling app might have used this)
            rootSubmodel.SetAllParents();

            // get the reference of the sourceEvent and requestedElement
            var sourceReference    = sourceEvent.GetReference();
            var requestedReference = (reqSm != null) ? reqSm.GetReference() : reqSme.GetReference();

            // 2nd check
            if (sourceReference == null || requestedReference == null)
            {
                throw new PackageConnectorException("PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    "element references cannot be determined!");
            }

            //// try identify the original Observable
            //// var origObservable = AdminShell.SubmodelElementWrapper.FindReferableByReference(
            ////    rootSubmodel.submodelElements, sourceEvent.observed, keyIndex: 0);

            // basically, can query updates of Submodel or SubmodelElements
            string qst = null;

            if (reqSm != null && reqSm.idShort.HasContent())
            {
                // easy query
                qst = StartQuery("submodels", reqSm.idShort, "values");
            }
            else if (reqSme != null && reqSme.idShort.HasContent() &&
                     rootSubmodel.idShort.HasContent())
            {
                // TODO (all, 2021-01-30): check periodically for supported element types

                // the query prepared here will fail deterministically, if the reqSme element type is not supported
                // be the AAS server. Therefore, filter for element types, which are not expected to return a valid
                // response
                var reqSmeTypeSupported = reqSme is AdminShell.SubmodelElementCollection ||
                                          reqSme is AdminShell.Property;
                if (!reqSmeTypeSupported)
                {
                    return(false);
                }

                // build path
                var path = "" + reqSme.idShort;

                // Resharper disable once IteratorMethodResultIsIgnored
                reqSme.FindAllParents((x) =>
                {
                    path = x.idShort + "/" + path;
                    return(true);
                }, includeThis: false, includeSubmodel: false);

                // full query
                qst = StartQuery("submodels", rootSubmodel.idShort, "elements", path, "values");
            }

            // valid
            if (qst == null)
            {
                throw new PackageConnectorException("PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    "not enough data to build query path!");
            }

            // do the actual query
            var response = await _client.GetAsync(qst);

            if (!response.IsSuccessStatusCode)
            {
                throw new PackageConnectorException($"PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    $"server did not respond correctly on query {qst} !");
            }

            // prepare basic event message (without sending it)
            var pluv = new AasPayloadUpdateValue();
            var ev   = new AasEventMsgEnvelope(
                timestamp,
                source: sourceReference,
                sourceSemanticId: sourceEvent.semanticId,
                observableReference: requestedReference,
                observableSemanticId: (requestedElement as AdminShell.IGetSemanticId).GetSemanticId(),
                topic: topic, subject: subject,
                payload: pluv);

            // goals (1) form the event content from response
            //       (2) directyl update the associated AAS

            // in order to serve goal (2), a wrapper-root is required from the observableReference,
            // that is: requestedElement!
            var wrappers = ((requestedElement as AdminShell.IEnumerateChildren)?.EnumerateChildren())?.ToList();

            // parse dynamic response object
            // Note: currently only updating Properties
            // TODO (MIHO, 2021-01-03): check to handle more SMEs for AasEventMsgUpdateValue
            // TODO (MIHO, 2021-01-04): ValueIds still missing ..
            var frame = Newtonsoft.Json.Linq.JObject.Parse(await response.Content.ReadAsStringAsync());

            if (frame.ContainsKey("values"))
            {
                // populate
                // Resharper disable once PossibleNullReferenceException
                dynamic vallist = JsonConvert.DeserializeObject(frame["values"].ToString());
                if (vallist != null)
                {
                    foreach (var tuple in vallist)
                    {
                        if (tuple.path != null)
                        {
                            // KeyList from path
                            var kl = AdminShell.KeyList.CreateNew(AdminShell.Key.SubmodelElement, false,
                                                                  AdminShell.Key.IdShort, tuple.path.ToObject <string[]>());
                            // goal (1)
                            pluv.Values.Add(
                                new AasPayloadUpdateValueItem(kl, "" + tuple.value));

                            // goal (2)
                            if (wrappers != null)
                            {
                                var x = AdminShell.SubmodelElementWrapper.FindReferableByReference(
                                    wrappers, AdminShell.Reference.CreateNew(kl), keyIndex: 0);
                                if (x is AdminShell.Property prop)
                                {
                                    if (tuple.value != null)
                                    {
                                        prop.value = tuple.value;
                                    }
                                }
                                pluv.IsAlreadyUpdatedToAAS = true;
                            }
                        }
                    }
                }
            }
            else if (frame.ContainsKey("value"))
            {
                // access response
                var val = frame["value"]?.ToString();

                // goal (1)
                pluv.Values.Add(
                    new AasPayloadUpdateValueItem(path: null, value: "" + val));

                // goal (2)
                if (reqSme is AdminShell.Property prop)
                {
                    if (val != null)
                    {
                        prop.value = val;
                    }
                    pluv.IsAlreadyUpdatedToAAS = true;
                }
            }
            else
            {
                throw new PackageConnectorException($"PackageConnector::SimulateUpdateValuesEventByGetAsync() " +
                                                    $"cannot parse response!");
            }

            // try send (only, if there were updates)
            var res = false;

            if (pluv.Values.Count >= 1)
            {
                Container?.PackageCentral?.PushEvent(ev);
                res = true;
            }

            // ok
            return(res);
        }
Exemple #7
0
        //
        // Event management
        //

        private bool CheckPushedEventInternal(AasEventMsgEnvelope ev)
        {
            // access
            if (ev == null)
            {
                return(false);
            }

            // to be applicable, the event message Observable has to relate into this's environment
            var foundObservable = Env?.AasEnv?.FindReferableByReference(ev?.ObservableReference);

            if (foundObservable == null)
            {
                return(false);
            }

            //
            // Update value?
            //
            // Note: an update will only be executed, if NOT ALREADY marked as being updated in the
            //       event message. MOST LIKELY, the AAS update will be done in the connector, already!
            //
            foreach (var pluv in ev.GetPayloads <AasPayloadUpdateValue>())
            {
                if (pluv.Values != null &&
                    !pluv.IsAlreadyUpdatedToAAS &&
                    foundObservable is AdminShell.IEnumerateChildren &&
                    (foundObservable is AdminShell.Submodel || foundObservable is AdminShell.SubmodelElement))
                {
                    // will later access children ..
                    var wrappers         = ((foundObservable as AdminShell.IEnumerateChildren).EnumerateChildren())?.ToList();
                    var changedSomething = false;

                    // go thru all value updates
                    if (pluv.Values != null)
                    {
                        foreach (var vl in pluv.Values)
                        {
                            if (vl == null)
                            {
                                continue;
                            }

                            // Note: currently only updating Properties
                            // TODO (MIHO, 2021-01-03): check to handle more SMEs for AasEventMsgUpdateValue

                            AdminShell.SubmodelElement smeToModify = null;
                            if (vl.Path == null && foundObservable is AdminShell.Property fop)
                            {
                                smeToModify = fop;
                            }
                            else if (vl.Path != null && vl.Path.Count >= 1 && wrappers != null)
                            {
                                var x = AdminShell.SubmodelElementWrapper.FindReferableByReference(
                                    wrappers, AdminShell.Reference.CreateNew(vl.Path), keyIndex: 0);
                                if (x is AdminShell.Property fpp)
                                {
                                    smeToModify = fpp;
                                }
                            }

                            // something to modify?
                            if (smeToModify is AdminShell.Property prop)
                            {
                                if (vl.Value != null)
                                {
                                    prop.value = vl.Value;
                                }
                                if (vl.ValueId != null)
                                {
                                    prop.valueId = vl.ValueId;
                                }
                                changedSomething = true;
                            }
                        }
                    }

                    // if something was changed, the event messages is to be consumed
                    if (changedSomething)
                    {
                        return(true);
                    }
                }
            }

            // no
            return(false);
        }
        //
        // Event handling
        //

        /// <summary>
        /// PackageCentral pushes an AAS event message down to the connector.
        /// Return true, if the event shall be consumed and PackageCentral shall not
        /// push anything further.
        /// </summary>
        /// <param name="ev">The event message</param>
        /// <returns>True, if consume event</returns>
        public virtual bool PushEvent(AasEventMsgEnvelope ev)
        {
            return(false);
        }
Exemple #9
0
 public void PublishEvent(AasEventMsgEnvelope ev,
                          AdminShell.ReferableRootInfo ri = null)
 {
     PublishEventAsync(ev, ri);
 }
Exemple #10
0
        public void PublishEventAsync(AasEventMsgEnvelope ev,
                                      AdminShell.ReferableRootInfo ri = null)
        {
            // access
            if (ev == null || _mqttClient == null || !_mqttClient.IsConnected)
            {
                return;
            }

            // serialize the event
            var settings = AasxIntegrationBase.AasxPluginOptionSerialization.GetDefaultJsonSettings(
                new[] { typeof(AasEventMsgEnvelope) });

            settings.TypeNameHandling = TypeNameHandling.Auto;
            settings.Formatting       = Formatting.Indented;
            var json = JsonConvert.SerializeObject(ev, settings);

            // aas / sm already available in rootInfo, prepare idShortPath
            var sourcePathStr = "";
            var sourcePath    = new AdminShell.KeyList();

            if (ev.Source?.Keys != null && ri != null && ev.Source.Keys.Count > ri.NrOfRootKeys)
            {
                sourcePath    = ev.Source.Keys.SubList(ri.NrOfRootKeys);
                sourcePathStr = sourcePath.BuildIdShortPath();
            }

            var observablePath = new AdminShell.KeyList();

            if (ev.ObservableReference?.Keys != null && ri != null &&
                ev.ObservableReference.Keys.Count > ri.NrOfRootKeys)
            {
                observablePath = ev.ObservableReference.Keys.SubList(ri.NrOfRootKeys);
            }

            // publish the full event?
            if (_diaData.EnableEventPublish)
            {
                if (_diaData.LogDebug)
                {
                    _logger?.Info("Publish Event");
                }
                var message = new MqttApplicationMessageBuilder()
                              .WithTopic(GenerateTopic(
                                             _diaData.EventTopic, defaultIfNull: "Event",
                                             aasIdShort: ri?.AAS?.idShort, aasId: ri?.AAS?.identification,
                                             smIdShort: ri?.Submodel?.idShort, smId: ri?.Submodel?.identification,
                                             path: sourcePathStr))
                              .WithPayload(json)
                              .WithExactlyOnceQoS()
                              .WithRetainFlag(_diaData.MqttRetain)
                              .Build();

                // convert to synchronous behaviour
                _mqttClient.PublishAsync(message).GetAwaiter().GetResult();
                LogStatus(incEvent: 1);
            }

            // deconstruct the event into single units?
            if (_diaData.SingleValuePublish)
            {
                if (_diaData.LogDebug)
                {
                    _logger?.Info("Publish single values ..");
                }

                if (ev.Payloads != null)
                {
                    foreach (var epl in ev.Payloads)
                    {
                        if (epl is AasPayloadStructuralChange apsc && apsc.Changes != null)
                        {
                            foreach (var ci in apsc.Changes)
                            {
                                PublishSingleValues_ChangeItem(ev, ri, observablePath, ci);
                            }
                        }

                        if (epl is AasPayloadUpdateValue apuv && apuv.Values != null)
                        {
                            foreach (var ui in apuv.Values)
                            {
                                PublishSingleValues_UpdateItem(ev, ri, observablePath, ui);
                            }
                        }
                    }
                }
            }
        }
Exemple #11
0
        private void PublishSingleValues_ChangeItem(
            AasEventMsgEnvelope ev,
            AdminShell.ReferableRootInfo ri,
            AdminShell.KeyList startPath,
            AasPayloadStructuralChangeItem ci)
        {
            // trivial
            if (ev == null || ci == null || startPath == null)
            {
                return;
            }

            // only specific reasons
            if (!(ci.Reason == AasPayloadStructuralChangeItem.ChangeReason.Create ||
                  ci.Reason == AasPayloadStructuralChangeItem.ChangeReason.Modify))
            {
                return;
            }

            // need a payload
            if (ci.Path == null || ci.Data == null)
            {
                return;
            }

            var dataRef = ci.GetDataAsReferable();

            // give this to (recursive) function
            var messages = new List <MqttApplicationMessage>();

            if (dataRef is AdminShell.SubmodelElement dataSme)
            {
                var smwc = new AdminShell.SubmodelElementWrapperCollection(dataSme);
                smwc.RecurseOnSubmodelElements(null, null, (o, parents, sme) =>
                {
                    // assumption is, the sme is now "leaf" of a SME-hierarchy
                    if (sme is AdminShell.IEnumerateChildren)
                    {
                        return;
                    }

                    // value of the leaf
                    var valStr = sme.ValueAsText();

                    // build a complete path of keys
                    var path    = startPath + ci.Path + parents.ToKeyList() + sme?.ToKey();
                    var pathStr = path.BuildIdShortPath();

                    // publish
                    if (_diaData.LogDebug)
                    {
                        _logger?.Info("Publish single value (create/ update)");
                    }
                    messages.Add(
                        new MqttApplicationMessageBuilder()
                        .WithTopic(GenerateTopic(
                                       _diaData.EventTopic, defaultIfNull: "SingleValue",
                                       aasIdShort: ri?.AAS?.idShort, aasId: ri?.AAS?.identification,
                                       smIdShort: ri?.Submodel?.idShort, smId: ri?.Submodel?.identification,
                                       path: pathStr))
                        .WithPayload(valStr)
                        .WithExactlyOnceQoS()
                        .WithRetainFlag(_diaData.MqttRetain)
                        .Build());
                });
            }

            // publish these
            // convert to synchronous behaviour
            int count = 0;

            foreach (var msg in messages)
            {
                count++;
                _mqttClient.PublishAsync(msg).GetAwaiter().GetResult();
            }
            LogStatus(incSingleValue: count);
        }
 public static void PushEventIntoPlugins(AasEventMsgEnvelope ev)
 {
     // over all loaded plugins
     AllPluginsInvoke("push-aas-event", ev);
 }