diff --git a/Submodel_AssetInterfacesDescription.json b/Submodel_AssetInterfacesDescription.json new file mode 100644 index 0000000..f047e34 --- /dev/null +++ b/Submodel_AssetInterfacesDescription.json @@ -0,0 +1,428 @@ +{ + "idShort": "AssetInterfacesDescription", + "id": "www.example.com/ids/sm/7142_2140_7032_7989", + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MQTT", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "EndpointMetadata", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "titles", + "value": [ + { + "language": "en", + "text": "AID and AIMC Test" + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "idShort": "base", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883", + "modelType": "Property" + }, + { + "idShort": "mqv:version", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "5.0", + "modelType": "Property" + }, + { + "idShort": "contentType", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "securityDefinitions", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "basic", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "in", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "header", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "AssetsReservedClientName", + "valueType": "xs:string", + "value": "thisandthat", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "InterfaceMetadata", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "Properties", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "title", + "valueType": "xs:string", + "value": "TestingParameter01", + "modelType": "Property" + }, + { + "idShort": "observable", + "valueType": "xs:boolean", + "value": "true", + "modelType": "Property" + }, + { + "idShort": "type", + "valueType": "xs:string", + "value": "integer", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testparam1", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "readProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-01", + "value": [ + { + "idShort": "title", + "valueType": "xs:string", + "value": "TestingParameter02", + "modelType": "Property" + }, + { + "idShort": "observable", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "type", + "valueType": "xs:string", + "value": "boolean", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883/testtopic/testparam2", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "readProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883/testtopic/testparam2/write", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "writeProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + }, + { + "idShort": "Actions", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation1", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-01", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation2", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-02", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation3", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + }, + { + "idShort": "Events", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "Submodel" +} diff --git a/Submodel_AssetInterfacesMappingConfiguration.json b/Submodel_AssetInterfacesMappingConfiguration.json new file mode 100644 index 0000000..34045be --- /dev/null +++ b/Submodel_AssetInterfacesMappingConfiguration.json @@ -0,0 +1,341 @@ +{ + "idShort": "AssetInterfacesMappingConfiguration", + "id": "https://example.com/ids/sm/4342_8060_7032_0872", + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MQTT", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "EndpointMetaDataReference", + "value": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "EndpointMetadata" + } + ] + }, + "modelType": "ReferenceElement" + }, + { + "idShort": "MappingConfiguration", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "InterfaceMetaDataReference", + "value": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + } + ] + }, + "modelType": "ReferenceElement" + }, + { + "idShort": "SourceSinkMappings", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Properties" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Params" + }, + { + "type": "Property", + "value": "TestParam1" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-01", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Properties" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-01" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Params" + }, + { + "type": "Property", + "value": "TestParam2" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-02", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation1" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-03", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-01" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation2" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-04", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-02" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation3" + } + ] + }, + "modelType": "RelationshipElement" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "Submodel" +} diff --git a/Submodel_OperationalData.json b/Submodel_OperationalData.json new file mode 100644 index 0000000..3ed09b5 --- /dev/null +++ b/Submodel_OperationalData.json @@ -0,0 +1,86 @@ +{ + "idShort": "OperationalData", + "id": "https://example.com/ids/sm/8055_9060_7032_0793", + "submodelElements": [ + { + "idShort": "Params", + "value": [ + { + "idShort": "TestParam1", + "valueType": "xs:string", + "modelType": "Property" + }, + { + "idShort": "TestParam2", + "valueType": "xs:string", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "Operations", + "value": [ + { + "idShort": "TestOperation1", + "description": [ + { + "language": "de", + "text": "Operation, sync mit keinem In/Out" + } + ], + "modelType": "Operation" + }, + { + "idShort": "TestOperation2", + "description": [ + { + "language": "de", + "text": "Operation, sync mit einem Input" + } + ], + "inputVariables": [ + { + "value": { + "idShort": "TestInput", + "valueType": "xs:string", + "modelType": "Property" + } + } + ], + "modelType": "Operation" + }, + { + "idShort": "TestOperation3", + "description": [ + { + "language": "de", + "text": "Operation, sync mit einem Input und einem Output" + } + ], + "inputVariables": [ + { + "value": { + "idShort": "TestInput", + "valueType": "xs:int", + "modelType": "Property" + } + } + ], + "outputVariables": [ + { + "value": { + "idShort": "TestOutput", + "valueType": "xs:float", + "modelType": "Property" + } + } + ], + "modelType": "Operation" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "Submodel" +} diff --git a/example/src/modules/httpInterfaceServer.ts b/example/src/modules/httpInterfaceServer.ts index 3fa2fec..302bd83 100644 --- a/example/src/modules/httpInterfaceServer.ts +++ b/example/src/modules/httpInterfaceServer.ts @@ -198,7 +198,7 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer const prop = Traverser.getElementByIdPath(this.aas, sm, idShortPath); if (prop === null || !AASCoreTypes.isProperty(prop)) return res.status(404).end(); - const request: Types.RequestTypes.Request = req.method === "GET" ? { type: "READ", target: prop } : { type: "WRITE", target: prop, extraData: { value: req.body } }; + const request: Types.RequestTypes.Request = req.method === "GET" ? { type: "readProperty", target: prop } : { type: "writeProperty", target: prop, extraData: { value: req.body } }; const value = this.onRequestCallback(request); @@ -215,7 +215,7 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer // TODO // Parameter? - const success = this.onRequestCallback({ type: "CALL", target: op, extraData: { args: req.body } }); + const success = this.onRequestCallback({ type: "invokeAction", target: op, extraData: { args: req.body, async: false } }); return res.send(success ? 204 : 500).end(); } @@ -226,7 +226,7 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer // TODO // Invoke operation and get handle - const request: Types.RequestTypes.Request = { type: "CALL-ASYNC", target: op, extraData: { args: req.body } }; + const request: Types.RequestTypes.Request = { type: "invokeAction", target: op, extraData: { args: req.body, async: true } }; const handle = this.onRequestCallback(request); @@ -241,7 +241,7 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer case "operation-status": { if (req.method !== "GET") return res.status(405).end(); - const state = this.onRequestCallback({ type: "GET-OP-STATE", target: handle }); + const state = this.onRequestCallback({ type: "xAsyncActionState", target: handle }); if (state === undefined) return res.status(404).end(); @@ -253,7 +253,7 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer case "operation-result": { if (req.method !== "GET") return res.status(405).end(); - const result = this.onRequestCallback({ type: "GET-OP-RESULT", target: handle }); + const result = this.onRequestCallback({ type: "xAsyncActionResult", target: handle }); if (result === null) return res.status(404).end(); return res.json({ diff --git a/example/src/modules/mqttConnector.ts b/example/src/modules/mqttConnector.ts index 6b14d9c..a10b698 100644 --- a/example/src/modules/mqttConnector.ts +++ b/example/src/modules/mqttConnector.ts @@ -1,6 +1,7 @@ import * as mqtt from "mqtt"; import { AbstractConnectionObject } from "aas-multimessagebroker"; -import type { AASCoreTypes } from "aas-multimessagebroker"; +import { AASCoreTypes, Types } from "aas-multimessagebroker"; +import { MMBEvent } from "aas-multimessagebroker/dist/types/requests"; /** * This is an example module for the asset connection object. @@ -70,7 +71,10 @@ export default class MQTTConnector extends AbstractConnectionObject cb(message.toString("utf-8"))); + this.observerStore[topic].forEach(sub => sub.cb({ type: "event", value: message.toString("utf-8"), target: sub.target})); + } + if (this.eventSubStore[topic] !== undefined) { + this.eventSubStore[topic].forEach(sub => sub.cb({ type: "event", value: message.toString("utf-8"), target: sub.target})); } }); this.client.subscribe("#"); @@ -87,6 +91,10 @@ export default class MQTTConnector extends AbstractConnectionObject void): boolean { - const cc = this.mapper.get(prop); - if (cc === undefined || !cc.observable || !this.client || !this.client.connected) return false; + public observeProperty(target: AASCoreTypes.Property, mapping: Types.RequestTypes.ConnectionConfiguration, cb: (value: Types.RequestTypes.MMBEvent) => void): boolean { + if (!mapping.observable || !this.client || !this.client.connected) return false; - const topic = cc.forms.href.substring(1); - if (this.observerStore[topic] === undefined) this.observerStore[topic] = [callback]; - else this.observerStore[topic].push(callback); + const topic = mapping.forms[0].href.substring(1); + if (this.observerStore[topic] === undefined) this.observerStore[topic] = [{ target, cb }]; + else this.observerStore[topic].push({ target, cb }); return true; } + public unobserveProperty(target: AASCoreTypes.Property, mapping: Types.RequestTypes.ConnectionConfiguration): void { + const topic = mapping.forms[0].href.substring(1); + this.observerStore[topic]; + //! TODO + } + /** * Calls an action synchronously. * @param action Action @@ -168,13 +177,22 @@ export default class MQTTConnector extends AbstractConnectionObject): any { - // TODO - // Vorher mal ne ordentliche Mapping-Definition + public callActionSync(_target: AASCoreTypes.Operation, mapping: Types.RequestTypes.ConnectionConfiguration, args: Record): any { + this.assertConnected(); - throw new Error("Method not implemented."); + const form: Types.AIDTypes.InterfaceFormMQTTAction = mapping.forms[0]; + const topic = form.href.substring(1); + if (topic === undefined || !mapping.forms) throw new Error("Mapping invalid."); + + const message = JSON.stringify(args); + this.execute(form.mqv_controlPacketValue ?? "PUBLISH", topic, message); + + // There is currently no way to get the result of an action + // Not because we cannot wait but because we don't know where the result is sent! + + return; } /** @@ -187,11 +205,17 @@ export default class MQTTConnector extends AbstractConnectionObject): string | null { - // TODO - // Vorher mal ne ordentliche Mapping-Definition + public callActionAsync(_target: AASCoreTypes.Operation, mapping: Types.RequestTypes.ConnectionConfiguration, args: Record): string { + this.assertConnected(); - throw new Error("Method not implemented."); + const form: Types.AIDTypes.InterfaceFormMQTTAction = mapping.forms[0]; + const topic = form.href.substring(1); + if (topic === undefined || !mapping.forms) throw new Error("Mapping invalid."); + + const message = JSON.stringify(args); + this.execute(form.mqv_controlPacketValue ?? "PUBLISH", topic, message); + + return this.generateAsyncHandle(); } /** @@ -203,11 +227,14 @@ export default class MQTTConnector extends AbstractConnectionObject void): boolean { - // TODO - // Vorher mal ne ordentliche Mapping-Definition + public subscribeEvent(target: AASCoreTypes.Class, mapping: Types.RequestTypes.ConnectionConfiguration, cb: (event: Types.RequestTypes.MMBEvent) => void): boolean { + if (!mapping.observable || !this.client || !this.client.connected) return false; - throw new Error("Method not implemented."); + const topic = mapping.forms[0].href.substring(1); + if (this.eventSubStore[topic] === undefined) this.eventSubStore[topic] = [{ target, cb }]; + else this.eventSubStore[topic].push({ target, cb }); + + return true; } /** @@ -217,11 +244,20 @@ export default class MQTTConnector extends AbstractConnectionObject { * A store for all observers and their callbacks. * @sealed */ - protected readonly observerStore: Record void)[]> = {}; + protected readonly observerStore: Record void) }[]> = {}; /** * A store for all event subscriptions and their callbacks. * @sealed */ - protected readonly eventSubStore: Record void)[]> = {}; + protected readonly eventSubStore: Record void) }[]> = {}; /** * A store for all async action handles and their results. * @sealed @@ -100,7 +100,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract readProperty(mapping: ConnectionConfiguration): void; + public abstract readProperty(target: types.Property, mapping: ConnectionConfiguration): void; /** * Write a property value to the asset. @@ -109,7 +109,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract writeProperty(mapping: ConnectionConfiguration, value: any): void; + public abstract writeProperty(target: types.Property, mapping: ConnectionConfiguration, value: any): void; /** * Observe a property value from the asset. @@ -119,7 +119,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract observeProperty(mapping: ConnectionConfiguration, callback: (value: any) => void): boolean; + public abstract observeProperty(target: types.Property, mapping: ConnectionConfiguration, callback: (value: any) => void): boolean; /** * Unobserve a property value from the asset. @@ -127,7 +127,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract unobserveProperty(mapping: ConnectionConfiguration): void; + public abstract unobserveProperty(target: types.Property, mapping: ConnectionConfiguration): void; /** * Call an action on the asset synchronously. @@ -137,7 +137,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract callActionSync(mapping: ConnectionConfiguration, args: Record): any; + public abstract callActionSync(target: types.Operation, mapping: ConnectionConfiguration, args: Record): any; /** * Call an action on the asset asynchronously. @@ -147,7 +147,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract callActionAsync(mapping: ConnectionConfiguration, args: Record): string | null; + public abstract callActionAsync(target: types.Operation, mapping: ConnectionConfiguration, args: Record): string | null; /** * Read the state of an async action. @@ -179,7 +179,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract subscribeEvent(mapping: ConnectionConfiguration, callback: (event: types.BasicEventElement) => void): boolean; + public abstract subscribeEvent(target: types.Class, mapping: ConnectionConfiguration, callback: (event: MMBEvent) => void): boolean; /** * Unsubscribe from an event. @@ -187,7 +187,7 @@ export default abstract class AbstractConnectionObject { * @public * @virtual */ - public abstract unsubscribeEvent(mapping: ConnectionConfiguration): void; + public abstract unsubscribeEvent(target: types.Class, mapping: ConnectionConfiguration): void; /** * Generate a handle for an async action. @@ -199,8 +199,4 @@ export default abstract class AbstractConnectionObject { this.asyncActionStateStore[handle] = {finished: false, result: null}; return handle; } - - protected static findValidForms(mapping: ConnectionConfiguration, op: FormOp): (InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm)[] { - return mapping.forms.filter((form: InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm) => form.op === op); - } } \ No newline at end of file diff --git a/lib/src/multimessageBroker.ts b/lib/src/multimessageBroker.ts index 53726fa..8d6a35c 100644 --- a/lib/src/multimessageBroker.ts +++ b/lib/src/multimessageBroker.ts @@ -4,8 +4,8 @@ import type { Request } from "./types/requests"; import type AbstractConnectionObject from "./abstractConnectionObject"; import AIMCMapper from "./AIMCMapper"; import AIDParser from "./parser/AIDParser"; -import type { EndpointMetadata, InterfaceActionForm, InterfaceEventForm, InterfacePropertyForm } from "./types/aidConf"; -import type { ConnectionConfiguration } from "./types/aimcConf"; +import type { EndpointMetadata, InterfaceActionForm, InterfaceEventForm, InterfaceForm, InterfacePropertyForm } from "./types/aidConf"; +import type { ConnectionConfiguration } from "./types/requests"; type AASRegistration = { aas: types.Environment, @@ -192,16 +192,24 @@ export default class MultiMessageBroker { } else { const mapping = getMapping(request.target); + mapping.forms = mapping.forms.filter((form: InterfaceForm) => form.op.toLocaleLowerCase() === request.type.toLocaleLowerCase()); + + if (mapping.forms.length === 0) throw new ReferenceError(`No form found for ${(request.target as any).idShort} with operation ${request.type}`); + const connector = getConnector(mapping); switch (request.type) { - case "readProperty": return connector.readProperty(mapping); - case "writeProperty": return connector.writeProperty(mapping, request.extraData.value); - case "observeProperty": return connector.observeProperty(mapping, request.extraData.callback); - case "unobserveProperty": return connector.unobserveProperty(mapping); - case "subscribeEvent": return connector.subscribeEvent(mapping, request.extraData.callback); - case "unsubscribeEvent": return connector.unsubscribeEvent(mapping); - case "invokeAction": return request.extraData.async ? connector.callActionAsync(mapping, request.extraData.args) : connector.callActionSync(mapping, request.extraData.args); + case "readProperty": return connector.readProperty(request.target, mapping); + case "writeProperty": return connector.writeProperty(request.target, mapping, request.extraData.value); + case "observeProperty": return connector.observeProperty(request.target, mapping, request.extraData.callback); + case "unobserveProperty": return connector.unobserveProperty(request.target, mapping); + case "subscribeEvent": { + return connector.subscribeEvent(request.target, mapping, request.extraData.callback); + } + case "unsubscribeEvent": { + return connector.unsubscribeEvent(request.target, mapping); + } + case "invokeAction": return request.extraData.async ? connector.callActionAsync(request.target, mapping, request.extraData.args) : connector.callActionSync(request.target, mapping, request.extraData.args); } } } diff --git a/lib/src/parser/AIDParser.ts b/lib/src/parser/AIDParser.ts index d7ed443..e087076 100644 --- a/lib/src/parser/AIDParser.ts +++ b/lib/src/parser/AIDParser.ts @@ -2,7 +2,6 @@ import * as aasCore from "@aas-core-works/aas-core3.0-typescript"; import type { AssetInterfacesDescription, EndpointMetadata, InterfaceDescription, InterfaceMetadata, InterfaceAction, InterfaceEvent, InterfaceProperty, InterfacePropertyForm, InterfaceActionForm, InterfaceFormBase, InterfaceFormBaseHTTP, InterfaceEventForm } from "../types/aidConf"; import { AvailableEndpoint, endpointAvailable } from "../types/common"; import Traverser from "../helper/traverser"; -import { Property } from "@aas-core-works/aas-core3.0-typescript/dist/types/types"; /** * Class for static methods to parse the AssetInterfacesDescription Submodel @@ -285,7 +284,7 @@ export default class AIDParser { if (!endpoint) return true; - return validOperations[endpoint][element].includes(operation); + return validOperations[endpoint][element].includes(operation.toLocaleLowerCase()); } private static parseAdditionalFormProperties(form: aasCore.types.SubmodelElementCollection, currentlyParsed: any, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm { @@ -297,21 +296,21 @@ export default class AIDParser { // If method is set and it's a valid HTTP method we take it, else we use the default // setting for read/write const methodName = ["GET", "PUT", "POST", "DELETE", "PATCH"].includes(method.value?.toLocaleUpperCase() ?? "") ? method.value?.toLocaleUpperCase() : AIDParser.getDefaultMethod(currentlyParsed.op) ?? "GET"; - currentlyParsed["htv:methodName"] = methodName; + currentlyParsed.htv_methodName = methodName; } const headers = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "htv:headers"); if (headers !== null && aasCore.types.isSubmodelElementList(headers)) { - const parsedHeaders: { "htv:fieldName": string, "htv:fieldValue": string }[] = []; + const parsedHeaders: { htv_fieldName: string, htv_fieldValue: string }[] = []; for (const header of headers.overValueOrEmpty()) { if (!aasCore.types.isSubmodelElementCollection(header) || !header.value) continue; const fieldName = Traverser.findElement(header, element => (element as any).idShort?.toLocaleLowerCase() === "htv:fieldname"); const fieldValue = Traverser.findElement(header, element => (element as any).idShort?.toLocaleLowerCase() === "htv:fieldvalue"); if (fieldName === null || !aasCore.types.isProperty(fieldName) || !fieldName.value || fieldValue === null || !aasCore.types.isProperty(fieldValue) || !fieldValue.value) continue; - parsedHeaders.push({ "htv:fieldName": fieldName.value, "htv:fieldValue": fieldValue.value }); + parsedHeaders.push({ htv_fieldName: fieldName.value, htv_fieldValue: fieldValue.value }); } - currentlyParsed["htv:headers"] = parsedHeaders; + currentlyParsed.htv_headers = parsedHeaders; } break; } @@ -322,12 +321,12 @@ export default class AIDParser { // If controlPacket is set and it's a valid MQTT control packet we take it, else we use the default // setting for read/write const controlPacketValue = ["PUBLISH", "SUBSCRIBE", "UNSUBSCRIBE"].includes(controlPacket.value?.toLocaleUpperCase() ?? "") ? controlPacket.value?.toLocaleUpperCase() : AIDParser.getDefaultMethod(currentlyParsed.op); - currentlyParsed["mqv:controlPacketValue"] = controlPacketValue; + currentlyParsed.mqv_controlPacketValue = controlPacketValue; } const options = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:options"); if (options !== null && aasCore.types.isSubmodelElementList(options)) { - const parsedOptions: ({ "mqv:optionName": string, "mqv:optionValue": number | boolean })[] = []; + const parsedOptions: ({ mqv_optionName: string, mqv_optionValue: number | boolean })[] = []; for (const option of options.overValueOrEmpty()) { if (!aasCore.types.isSubmodelElementCollection(option) || !option.value) continue; @@ -335,9 +334,9 @@ export default class AIDParser { const optionValue = Traverser.findElement(option, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:optionvalue"); if (optionName === null || !aasCore.types.isProperty(optionName) || !optionName.value || optionValue === null || !aasCore.types.isProperty(optionValue) || !optionValue.value) continue; const value = Number.isNaN(Number.parseInt(optionValue.value)) ? optionValue.value === "true" : Number.parseInt(optionValue.value); - parsedOptions.push({ "mqv:optionName": optionName.value, "mqv:optionValue": value }); + parsedOptions.push({ mqv_optionName: optionName.value, mqv_optionValue: value }); } - currentlyParsed["mqv:options"] = parsedOptions; + currentlyParsed.mqv_options = parsedOptions; } break; diff --git a/lib/src/types/aidConf.ts b/lib/src/types/aidConf.ts index b8934b3..158ac66 100644 --- a/lib/src/types/aidConf.ts +++ b/lib/src/types/aidConf.ts @@ -48,25 +48,25 @@ It should be pretty easy to extend this. So let's derive some of this from the WoT and see what we can achieve. */ -export type FormOp = "readproperty" | -"writeproperty" | -"observeproperty" | -"unobserveproperty" | -"invokeaction" | -"subscribeevent" | -"unsubscribeevent"; +export type FormOp = "readProperty" | +"writeProperty" | +"observeProperty" | +"unobserveProperty" | +"invokeAction" | +"subscribeEvent" | +"unsubscribeEvent"; // The following are defined in WoT but not useful in our case //"readallproperties" | //"writeallproperties" | //"readmultipleproperties" | //"writemultipleproperties"; -type FormOpHTTPProp = "readproperty" | "writeproperty"; -type FormOpHTTPAction = "invokeaction"; +type FormOpHTTPProp = "readProperty" | "writeProperty"; +type FormOpHTTPAction = "invokeAction"; -type FormOpMQTTProp = "readproperty" | "writeproperty" | "observeproperty" | "unobserveproperty"; -type FormOpMQTTAction = "invokeaction"; -type FormOpMQTTEvent = "subscribeevent" | "unsubscribeevent"; +type FormOpMQTTProp = "readProperty" | "writeProperty" | "observeProperty" | "unobserveProperty"; +type FormOpMQTTAction = "invokeAction"; +type FormOpMQTTEvent = "subscribeEvent" | "unsubscribeEvent"; export type InterfaceFormBase = { href: string; @@ -75,50 +75,51 @@ export type InterfaceFormBase = { } export type InterfaceFormBaseHTTP = InterfaceFormBase & { - "htv:methodName": "GET" | "PUT" | "POST" | "DELETE" | "PATCH"; - "htv:headers": { - "htv:fieldName": string; - "htv:fieldValue": string; + htv_methodName?: "GET" | "PUT" | "POST" | "DELETE" | "PATCH"; + htv_headers?: { + htv_fieldName: string; + htv_fieldValue: string; }[]; op: FormOpHTTPProp | FormOpHTTPAction; } -type IFormHTTPProp = InterfaceFormBaseHTTP & { +export type InterfaceFormHTTPProp = InterfaceFormBaseHTTP & { op: FormOpHTTPProp; } -type IFormHTTPAction = InterfaceFormBaseHTTP & { +export type InterfaceFormHTTPAction = InterfaceFormBaseHTTP & { op: FormOpHTTPAction; } export type InterfaceFormBaseMQTT = InterfaceFormBase & { - "mqv:controlPacketValue": "PUBLISH" | "SUBSCRIBE" | "UNSUBSCRIBE"; - "mqv:options": ({ - "mqv:optionName": "qos"; - "mqv:optionValue": 0 | 1 | 2; + mqv_controlPacketValue?: "PUBLISH" | "SUBSCRIBE" | "UNSUBSCRIBE"; + mqv_options?: ({ + mqv_optionName: "qos"; + mqv_optionValue: 0 | 1 | 2; } | { - "mqv:optionName": "retain" | "dup"; - "mqv:optionValue": boolean; + mqv_optionName: "retain" | "dup"; + mqv_optionValue: boolean; })[]; op: FormOpMQTTProp | FormOpMQTTAction | FormOpMQTTEvent; } -type IFormMQTTProp = InterfaceFormBaseMQTT & { +export type InterfaceFormMQTTProp = InterfaceFormBaseMQTT & { op: FormOpMQTTProp; } -type IFormMQTTAction = InterfaceFormBaseMQTT & { +export type InterfaceFormMQTTAction = InterfaceFormBaseMQTT & { op: FormOpMQTTAction; } -type IFormMQTTEvent = InterfaceFormBaseMQTT & { +export type InterfaceFormMQTTEvent = InterfaceFormBaseMQTT & { op: FormOpMQTTEvent; } -export type InterfacePropertyForm = IFormHTTPProp | IFormMQTTProp; -export type InterfaceActionForm = IFormHTTPAction | IFormMQTTAction; -export type InterfaceEventForm = IFormMQTTEvent; +export type InterfacePropertyForm = InterfaceFormHTTPProp | InterfaceFormMQTTProp; +export type InterfaceActionForm = InterfaceFormHTTPAction | InterfaceFormMQTTAction; +export type InterfaceEventForm = InterfaceFormMQTTEvent; +export type InterfaceForm = InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm; export type InterfaceProperty = { title?: string; @@ -139,20 +140,11 @@ export type InterfaceProperty = { } /** @beta */ -export type InterfaceAction = InterfaceActionSync | InterfaceActionAsync; - -type InterfaceActionBase = { +export type InterfaceAction = { title?: string; - type: string; + type?: string; forms: InterfaceActionForm[]; -} - -type InterfaceActionSync = InterfaceActionBase & { - async: false; -} - -type InterfaceActionAsync = { - async: true; + async: boolean; } /** @beta */ diff --git a/lib/src/types/aimcConf.ts b/lib/src/types/aimcConf.ts index daab155..be88dff 100644 --- a/lib/src/types/aimcConf.ts +++ b/lib/src/types/aimcConf.ts @@ -1,6 +1,6 @@ import type { types } from "@aas-core-works/aas-core3.0-typescript"; import type { AvailableEndpoint } from "./common"; -import type { EndpointMetadata, InterfaceAction, InterfaceEvent, InterfaceProperty } from "./aidConf"; +import type { ConnectionConfiguration } from "./requests"; export type AssetInterfacesMappingConfiguration = Record; @@ -14,7 +14,4 @@ export type MappingConfiguration = { SourceSinkMappings: types.RelationshipElement[]; } -export type AIMCMap = Map; - -type InterfaceElement = InterfaceProperty | InterfaceAction | InterfaceEvent; -export type ConnectionConfiguration = EndpointMetadata & InterfaceElement; // Wenn Transformationen implementiert werden, dann hier anpassen \ No newline at end of file +export type AIMCMap = Map; \ No newline at end of file diff --git a/lib/src/types/requests.ts b/lib/src/types/requests.ts index 50f19eb..1e68e3e 100644 --- a/lib/src/types/requests.ts +++ b/lib/src/types/requests.ts @@ -1,4 +1,5 @@ import type { types } from "@aas-core-works/aas-core3.0-typescript"; +import type { EndpointMetadata, InterfaceForm } from "./aidConf"; /** * Read Property Request @@ -36,7 +37,7 @@ type ObserveRequest = { type: "observeProperty"; target: types.Property; extraData: { - callback: (value: any) => void; + callback: (event: MMBEvent) => void; } } @@ -52,7 +53,7 @@ type UnobserveRequest = { type: "unobserveProperty"; target: types.Property; extraData: { - callback: (value: any) => void; + callback: (event: MMBEvent) => void; } } @@ -66,9 +67,9 @@ type UnobserveRequestCallback = (request: ObserveRequest) => boolean; */ type SubscribeRequest = { type: "subscribeEvent"; - target: types.BasicEventElement; + target: types.Class; extraData: { - callback: (value: any) => void; + callback: (event: MMBEvent) => void; } } @@ -82,7 +83,7 @@ type SubscribeRequestCallback = (request: SubscribeRequest) => boolean; */ type UnsubscribeRequest = { type: "unsubscribeEvent"; - target: types.BasicEventElement; + target: types.Class; } /** @@ -142,3 +143,11 @@ export type Request = GetRequest | WriteRequest | ObserveRequest | UnobserveRequ * Combined Request Callback Type */ export type OnRequestCallback = (request: Request) => any & GetRequestCallback & WriteRequestCallback & ObserveRequestCallback & UnobserveRequestCallback & CallRequestCallback & AsyncStateRequestCallback & AsyncResultRequestCallback & SubscribeRequestCallback & UnsubscribeRequestCallback; + +export type ConnectionConfiguration = EndpointMetadata & InterfaceForm; // Wenn Transformationen implementiert werden, dann hier anpassen + +export type MMBEvent = { + type: "changed" | "event"; + target: types.Class; + value: any; +} \ No newline at end of file diff --git a/owntest.json b/owntest.json index ba10c15..54961b5 100644 --- a/owntest.json +++ b/owntest.json @@ -1 +1,957 @@ -{"assetAdministrationShells":[{"idShort":"AASwithAIDandAIMC","id":"https://example.com/ids/sm/6560_0160_7032_0896","assetInformation":{"assetKind":"Instance","globalAssetId":"draft"},"submodels":[{"type":"ExternalReference","keys":[{"type":"Submodel","value":"www.example.com/ids/sm/7142_2140_7032_7989"}]},{"type":"ModelReference","keys":[{"type":"Submodel","value":"https://example.com/ids/sm/4342_8060_7032_0872"}]},{"type":"ModelReference","keys":[{"type":"Submodel","value":"https://example.com/ids/sm/8055_9060_7032_0793"}]}],"modelType":"AssetAdministrationShell"}],"submodels":[{"idShort":"AssetInterfacesDescription","id":"www.example.com/ids/sm/7142_2140_7032_7989","submodelElements":[{"idShort":"MQTT","typeValueListElement":"SubmodelElement","value":[{"idShort":"DEL-00","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"value":[{"idShort":"EndpointMetadata","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"value":[{"idShort":"titles","value":[{"language":"en","text":"AID and AIMC Test"}],"modelType":"MultiLanguageProperty"},{"idShort":"base","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"valueType":"xs:string","value":"mqtt://127.0.0.1:1883","modelType":"Property"},{"idShort":"mqv:version","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"valueType":"xs:string","value":"5.0","modelType":"Property"},{"idShort":"contentType","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"valueType":"xs:string","value":"application/json","modelType":"Property"},{"idShort":"securityDefinitions","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"value":[{"idShort":"basic","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"value":[{"idShort":"in","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"valueType":"xs:string","value":"header","modelType":"Property"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementCollection"},{"idShort":"AssetsReservedClientName","valueType":"xs:string","value":"thisandthat","modelType":"Property"}],"modelType":"SubmodelElementCollection"},{"idShort":"InterfaceMetadata","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"value":[{"idShort":"Properties","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"typeValueListElement":"SubmodelElement","value":[{"idShort":"DEL-00","value":[{"idShort":"title","valueType":"xs:string","value":"TestingParameter01","modelType":"Property"},{"idShort":"observable","valueType":"xs:boolean","value":"true","modelType":"Property"},{"idShort":"forms","value":[{"idShort":"href","valueType":"xs:string","value":"/testtopic/testparam1","modelType":"Property"},{"idShort":"contentType","valueType":"xs:string","value":"application/json","modelType":"Property"}],"modelType":"SubmodelElementCollection"},{"idShort":"type","valueType":"xs:string","value":"integer","modelType":"Property"}],"modelType":"SubmodelElementCollection"},{"idShort":"DEL-01","value":[{"idShort":"title","valueType":"xs:string","value":"TestingParameter02","modelType":"Property"},{"idShort":"observable","valueType":"xs:boolean","value":"false","modelType":"Property"},{"idShort":"forms","value":[{"idShort":"href","valueType":"xs:string","value":"mqtt://127.0.0.1:1883/testtopic/testparam2","modelType":"Property"},{"idShort":"contentType","valueType":"xs:string","value":"application/json","modelType":"Property"}],"modelType":"SubmodelElementCollection"},{"idShort":"type","valueType":"xs:string","value":"boolean","modelType":"Property"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementList"},{"idShort":"Actions","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"typeValueListElement":"SubmodelElement","value":[],"modelType":"SubmodelElementList"},{"idShort":"Events","semanticId":{"type":"ExternalReference","keys":[]},"embeddedDataSpecifications":[],"typeValueListElement":"SubmodelElement","value":[],"modelType":"SubmodelElementList"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementList"}],"modelType":"Submodel"},{"idShort":"AssetInterfacesMappingConfiguration","id":"https://example.com/ids/sm/4342_8060_7032_0872","submodelElements":[{"idShort":"MQTT","typeValueListElement":"SubmodelElement","value":[{"idShort":"DEL-00","value":[{"idShort":"EndpointMetaDataReference","value":{"type":"ModelReference","keys":[{"type":"Submodel","value":"www.example.com/ids/sm/7142_2140_7032_7989"},{"type":"SubmodelElementList","value":"MQTT"},{"type":"SubmodelElementCollection","value":"DEL-00"},{"type":"SubmodelElementCollection","value":"EndpointMetadata"}]},"modelType":"ReferenceElement"},{"idShort":"MappingConfiguration","typeValueListElement":"SubmodelElement","value":[{"idShort":"DEL-00","value":[{"idShort":"InterfaceMetaDataReference","value":{"type":"ModelReference","keys":[{"type":"Submodel","value":"www.example.com/ids/sm/7142_2140_7032_7989"},{"type":"SubmodelElementList","value":"MQTT"},{"type":"SubmodelElementCollection","value":"DEL-00"},{"type":"SubmodelElementCollection","value":"InterfaceMetadata"}]},"modelType":"ReferenceElement"},{"idShort":"SourceSinkMappings","typeValueListElement":"SubmodelElement","value":[{"idShort":"DEL-00","first":{"type":"ModelReference","keys":[{"type":"Submodel","value":"www.example.com/ids/sm/7142_2140_7032_7989"},{"type":"SubmodelElementList","value":"MQTT"},{"type":"SubmodelElementCollection","value":"DEL-00"},{"type":"SubmodelElementCollection","value":"InterfaceMetadata"},{"type":"SubmodelElementList","value":"Properties"},{"type":"SubmodelElementCollection","value":"DEL-00"}]},"second":{"type":"ModelReference","keys":[{"type":"Submodel","value":"https://example.com/ids/sm/8055_9060_7032_0793"},{"type":"SubmodelElementCollection","value":"Params"},{"type":"Property","value":"TestParam1"}]},"modelType":"RelationshipElement"},{"idShort":"DEL-01","first":{"type":"ModelReference","keys":[{"type":"Submodel","value":"www.example.com/ids/sm/7142_2140_7032_7989"},{"type":"SubmodelElementList","value":"MQTT"},{"type":"SubmodelElementCollection","value":"DEL-00"},{"type":"SubmodelElementCollection","value":"InterfaceMetadata"},{"type":"SubmodelElementList","value":"Properties"},{"type":"SubmodelElementCollection","value":"DEL-01"}]},"second":{"type":"ModelReference","keys":[{"type":"Submodel","value":"https://example.com/ids/sm/8055_9060_7032_0793"},{"type":"SubmodelElementCollection","value":"Params"},{"type":"Property","value":"TestParam2"}]},"modelType":"RelationshipElement"}],"modelType":"SubmodelElementList"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementList"}],"modelType":"SubmodelElementCollection"}],"modelType":"SubmodelElementList"}],"modelType":"Submodel"},{"idShort":"OperationalData","id":"https://example.com/ids/sm/8055_9060_7032_0793","submodelElements":[{"idShort":"Params","value":[{"idShort":"TestParam1","valueType":"xs:string","modelType":"Property"},{"idShort":"TestParam2","valueType":"xs:string","modelType":"Property"}],"modelType":"SubmodelElementCollection"}],"modelType":"Submodel"},{"idShort":"Control","id":"https://example.com/ids/sm/6560_0160_7032_5896","submodelElements":[{"idShort":"OperationMode","value":[{"idShort":"Value","valueType":"xs:string","modelType":"Property"},{"idShort":"Timestamp","valueType":"xs:string","modelType":"Property"}],"modelType":"SubmodelElementCollection"}],"modelType":"Submodel"}],"conceptDescriptions":[{"id":"https://example.com/ids/cd/3505_8080_9032_2713","embeddedDataSpecifications":[{"dataSpecification":{"type":"ExternalReference","keys":[{"type":"GlobalReference","value":"http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0"}]},"dataSpecificationContent":{"preferredName":[{"language":"en?","text":""}],"unit":"Watt","symbol":"W","dataType":"INTEGER_MEASURE","modelType":"DataSpecificationIec61360"}}],"modelType":"ConceptDescription"},{"id":"https://example.com/ids/cd/9285_8080_9032_4909","embeddedDataSpecifications":[{"dataSpecification":{"type":"ExternalReference","keys":[{"type":"GlobalReference","value":"http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0"}]},"dataSpecificationContent":{"preferredName":[{"language":"en?","text":""}],"unit":"Datetime ISO 8601","modelType":"DataSpecificationIec61360"}}],"modelType":"ConceptDescription"}]} \ No newline at end of file +{ + "assetAdministrationShells": [ + { + "idShort": "AASwithAIDandAIMC", + "id": "https://example.com/ids/sm/6560_0160_7032_0896", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": "draft" + }, + "submodels": [ + { + "type": "ExternalReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/4342_8060_7032_0872" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + } + ] + } + ], + "modelType": "AssetAdministrationShell" + } + ], + "submodels": [ + { + "idShort": "AssetInterfacesDescription", + "id": "www.example.com/ids/sm/7142_2140_7032_7989", + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MQTT", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "EndpointMetadata", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "titles", + "value": [ + { + "language": "en", + "text": "AID and AIMC Test" + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "idShort": "base", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883", + "modelType": "Property" + }, + { + "idShort": "mqv:version", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "5.0", + "modelType": "Property" + }, + { + "idShort": "contentType", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "securityDefinitions", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "basic", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "in", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "valueType": "xs:string", + "value": "header", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "AssetsReservedClientName", + "valueType": "xs:string", + "value": "thisandthat", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "InterfaceMetadata", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "value": [ + { + "idShort": "Properties", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "title", + "valueType": "xs:string", + "value": "TestingParameter01", + "modelType": "Property" + }, + { + "idShort": "observable", + "valueType": "xs:boolean", + "value": "true", + "modelType": "Property" + }, + { + "idShort": "type", + "valueType": "xs:string", + "value": "integer", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testparam1", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "readProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-01", + "value": [ + { + "idShort": "title", + "valueType": "xs:string", + "value": "TestingParameter02", + "modelType": "Property" + }, + { + "idShort": "observable", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "type", + "valueType": "xs:string", + "value": "boolean", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883/testtopic/testparam2", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "readProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "mqtt://127.0.0.1:1883/testtopic/testparam2/write", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "writeProperty", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + }, + { + "idShort": "Actions", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation1", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-01", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation2", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "DEL-02", + "value": [ + { + "idShort": "async", + "valueType": "xs:boolean", + "value": "false", + "modelType": "Property" + }, + { + "idShort": "forms", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "", + "value": [ + { + "idShort": "href", + "valueType": "xs:string", + "value": "/testtopic/testoperation3", + "modelType": "Property" + }, + { + "idShort": "contentType", + "valueType": "xs:string", + "value": "application/json", + "modelType": "Property" + }, + { + "idShort": "op", + "valueType": "xs:string", + "value": "invokeAction", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + }, + { + "idShort": "Events", + "semanticId": { + "type": "ExternalReference", + "keys": [] + }, + "embeddedDataSpecifications": [], + "typeValueListElement": "SubmodelElementCollection", + "value": [], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "Submodel" + }, + { + "idShort": "AssetInterfacesMappingConfiguration", + "id": "https://example.com/ids/sm/4342_8060_7032_0872", + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MQTT", + "typeValueListElement": "SubmodelElementCollection", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "EndpointMetaDataReference", + "value": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "EndpointMetadata" + } + ] + }, + "modelType": "ReferenceElement" + }, + { + "idShort": "MappingConfiguration", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "value": [ + { + "idShort": "InterfaceMetaDataReference", + "value": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + } + ] + }, + "modelType": "ReferenceElement" + }, + { + "idShort": "SourceSinkMappings", + "typeValueListElement": "SubmodelElement", + "value": [ + { + "idShort": "DEL-00", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Properties" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Params" + }, + { + "type": "Property", + "value": "TestParam1" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-01", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Properties" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-01" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Params" + }, + { + "type": "Property", + "value": "TestParam2" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-02", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation1" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-03", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-01" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation2" + } + ] + }, + "modelType": "RelationshipElement" + }, + { + "idShort": "DEL-04", + "first": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "www.example.com/ids/sm/7142_2140_7032_7989" + }, + { + "type": "SubmodelElementList", + "value": "MQTT" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-00" + }, + { + "type": "SubmodelElementCollection", + "value": "InterfaceMetadata" + }, + { + "type": "SubmodelElementList", + "value": "Actions" + }, + { + "type": "SubmodelElementCollection", + "value": "DEL-02" + } + ] + }, + "second": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://example.com/ids/sm/8055_9060_7032_0793" + }, + { + "type": "SubmodelElementCollection", + "value": "Operations" + }, + { + "type": "Operation", + "value": "TestOperation3" + } + ] + }, + "modelType": "RelationshipElement" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementList" + } + ], + "modelType": "Submodel" + }, + { + "idShort": "OperationalData", + "id": "https://example.com/ids/sm/8055_9060_7032_0793", + "submodelElements": [ + { + "idShort": "Params", + "value": [ + { + "idShort": "TestParam1", + "valueType": "xs:string", + "modelType": "Property" + }, + { + "idShort": "TestParam2", + "valueType": "xs:string", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "Operations", + "value": [ + { + "idShort": "TestOperation1", + "description": [ + { + "language": "de", + "text": "Operation, sync mit keinem In/Out" + } + ], + "modelType": "Operation" + }, + { + "idShort": "TestOperation2", + "description": [ + { + "language": "de", + "text": "Operation, sync mit einem Input" + } + ], + "inputVariables": [ + { + "value": { + "idShort": "TestInput", + "valueType": "xs:string", + "modelType": "Property" + } + } + ], + "modelType": "Operation" + }, + { + "idShort": "TestOperation3", + "description": [ + { + "language": "de", + "text": "Operation, sync mit einem Input und einem Output" + } + ], + "inputVariables": [ + { + "value": { + "idShort": "TestInput", + "valueType": "xs:int", + "modelType": "Property" + } + } + ], + "outputVariables": [ + { + "value": { + "idShort": "TestOutput", + "valueType": "xs:float", + "modelType": "Property" + } + } + ], + "modelType": "Operation" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "Submodel" + } + ], + "conceptDescriptions": [ + { + "id": "https://example.com/ids/cd/3505_8080_9032_2713", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "en?", + "text": "" + } + ], + "unit": "Watt", + "symbol": "W", + "dataType": "INTEGER_MEASURE", + "modelType": "DataSpecificationIec61360" + } + } + ], + "modelType": "ConceptDescription" + }, + { + "id": "https://example.com/ids/cd/9285_8080_9032_4909", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "en?", + "text": "" + } + ], + "unit": "Datetime ISO 8601", + "modelType": "DataSpecificationIec61360" + } + } + ], + "modelType": "ConceptDescription" + } + ] +} \ No newline at end of file