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); }
// // 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); }
// // 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); }
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); }
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); }
/// <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); }
// // 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); }
public void PublishEvent(AasEventMsgEnvelope ev, AdminShell.ReferableRootInfo ri = null) { PublishEventAsync(ev, ri); }
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); } } } } } }
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); }