More work on connector
This commit is contained in:
Generated
+32
-1
@@ -11,11 +11,13 @@
|
||||
"dependencies": {
|
||||
"@aas-core-works/aas-core3.0-typescript": "^1.0.0-rc.3",
|
||||
"express": "^4.18.2",
|
||||
"mqtt": "^5.1.2"
|
||||
"mqtt": "^5.1.2",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.19",
|
||||
"@types/node": "^20.8.2",
|
||||
"@types/uuid": "^9.0.6",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
@@ -193,6 +195,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz",
|
||||
"integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz",
|
||||
@@ -1358,6 +1366,18 @@
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
@@ -1577,6 +1597,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz",
|
||||
"integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "8.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz",
|
||||
@@ -2431,6 +2457,11 @@
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
|
||||
},
|
||||
"v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
|
||||
+3
-1
@@ -12,12 +12,14 @@
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.19",
|
||||
"@types/node": "^20.8.2",
|
||||
"@types/uuid": "^9.0.6",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aas-core-works/aas-core3.0-typescript": "^1.0.0-rc.3",
|
||||
"express": "^4.18.2",
|
||||
"mqtt": "^5.1.2"
|
||||
"mqtt": "^5.1.2",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as mqtt from "mqtt";
|
||||
import type { Property, Operation, OperationVariable, BasicEventElement } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
|
||||
import InterfaceConnectionObject from "interfaceConnectionObject";
|
||||
import type { types } from "@aas-core-works/aas-core3.0-typescript";
|
||||
|
||||
class MQTTConnector extends InterfaceConnectionObject<mqtt.IClientOptions> {
|
||||
protected name: string = "MQTT Connector";
|
||||
@@ -10,13 +11,17 @@ class MQTTConnector extends InterfaceConnectionObject<mqtt.IClientOptions> {
|
||||
|
||||
private client: mqtt.MqttClient|null = null;
|
||||
|
||||
private store: Record<string, any> = {};
|
||||
private messageStore: Record<string, any> = {};
|
||||
|
||||
public connect(): boolean {
|
||||
if (!this.client) this.client = mqtt.connect(this.connectionParameter);
|
||||
if (!this.client) this.client = mqtt.connect(this.endpointMetadata.base, this.connectionParameter);
|
||||
this.client.on("message", (topic, message) => {
|
||||
// If json is expected you could parse it here
|
||||
this.store[topic] = message.toString("utf-8");
|
||||
this.messageStore[topic] = message.toString("utf-8");
|
||||
// Notify observers
|
||||
if (this.observerStore[topic] !== undefined) {
|
||||
this.observerStore[topic].forEach(cb => cb(message.toString("utf-8")));
|
||||
}
|
||||
});
|
||||
this.client.subscribe("#");
|
||||
return this.client.connected;
|
||||
@@ -27,35 +32,85 @@ class MQTTConnector extends InterfaceConnectionObject<mqtt.IClientOptions> {
|
||||
this.client = null;
|
||||
}
|
||||
|
||||
public readProperty(prop: Property): void {
|
||||
public readProperty(prop: types.Property): any {
|
||||
const cc = this.mapper.get(prop);
|
||||
if (cc === undefined) return null;
|
||||
|
||||
const errorReturn = cc.default ?? null;
|
||||
if (!this.client || !this.client.connected) return errorReturn;
|
||||
|
||||
const value = cc.forms.map(f => this.messageStore[f.href.substring(1)]).filter(v => v !== undefined)[0];
|
||||
if (value === undefined) return errorReturn;
|
||||
switch (cc.type) {
|
||||
case "integer":
|
||||
return Number.parseInt(value);
|
||||
case "float":
|
||||
return Number.parseFloat(value);
|
||||
case "boolean":
|
||||
return !!value;
|
||||
case "string":
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public writeProperty(prop: types.Property, value: any): boolean {
|
||||
const cc = this.mapper.get(prop);
|
||||
if (cc === undefined || !this.client || !this.client.connected) return false;
|
||||
|
||||
const topic = cc.forms.map(f => f.href.substring(1))[0];
|
||||
if (topic === undefined) return false;
|
||||
|
||||
this.client.publish(topic, value.toString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public observeProperty(prop: types.Property, callback: (value: any) => void): boolean {
|
||||
const cc = this.mapper.get(prop);
|
||||
if (cc === undefined || !cc.observable || !this.client || !this.client.connected) return false;
|
||||
|
||||
cc.forms.map(f => f.href.substring(1)).forEach(topic => {
|
||||
if (this.observerStore[topic] === undefined) this.observerStore[topic] = [callback];
|
||||
else this.observerStore[topic].push(callback);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public callActionSync(action: types.Operation, args: OperationVariable[]): boolean {
|
||||
// TODO
|
||||
// Vorher mal ne ordentliche Mapping-Definition
|
||||
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public writeProperty(prop: Property, value: any): void {
|
||||
public callActionAsync(action: types.Operation, args: OperationVariable[]): string | null {
|
||||
// TODO
|
||||
// Vorher mal ne ordentliche Mapping-Definition
|
||||
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public observeProperty(prop: Property, callback: (value: any) => void): boolean {
|
||||
public readAsyncActionResponse(action: types.Operation): any {
|
||||
// TODO
|
||||
// Vorher mal ne ordentliche Mapping-Definition
|
||||
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public callActionSync(action: Operation, args: OperationVariable[]) {
|
||||
public subscribeEvent(event: types.BasicEventElement, callback: (event: BasicEventElement) => void): boolean {
|
||||
// TODO
|
||||
// Vorher mal ne ordentliche Mapping-Definition
|
||||
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public callActionAsync(action: Operation, args: OperationVariable[]): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
public unsubscribeEvent(event: types.BasicEventElement): void {
|
||||
// TODO
|
||||
// Vorher mal ne ordentliche Mapping-Definition
|
||||
|
||||
public readAsyncActionResponse(action: Operation): Promise<any> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public subscribeEvent(callback: (event: BasicEventElement) => void): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
public unsubscribeEvent(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import MultiMessageBroker from "./multimessageBroker";
|
||||
import HTTPInterfaceServer from "./example_modules/httpInterfaceServer";
|
||||
import FileImporter from "helper/fileImporter";
|
||||
import FileImporter from "./helper/fileImporter";
|
||||
|
||||
const aas = FileImporter.readAASByPath("../AID-AIMC-Full-Example-20230911T1608.json");
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { types } from "@aas-core-works/aas-core3.0-typescript";
|
||||
import { AIMCMapper } from "parser/AIMCMapper";
|
||||
import { v4 } from "uuid";
|
||||
import type { EndpointMetadata } from "types/aidConf";
|
||||
|
||||
type ConnectionType = "ON_DEMAND" | "PERMANENT";
|
||||
@@ -11,9 +13,14 @@ export default abstract class InterfaceConnectionObject<ConfigInterface> {
|
||||
protected abstract readonly connectionType: ConnectionType;
|
||||
protected abstract readonly supportsSubscriptions: boolean;
|
||||
|
||||
protected observerStore: Record<any, ((value: any) => void)[]> = {};
|
||||
protected eventSubStore: Record<any, ((value: any) => void)[]> = {};
|
||||
protected asyncActionStateStore: Record<any, {finished: boolean, result: any}> = {};
|
||||
|
||||
public constructor(
|
||||
protected readonly connectionParameter: ConfigInterface,
|
||||
protected readonly endpointMetadata: EndpointMetadata,
|
||||
protected readonly mapper: AIMCMapper,
|
||||
private readonly onResponseCallback: OnResponseCallback) {}
|
||||
|
||||
public abstract connect(): boolean;
|
||||
@@ -26,13 +33,19 @@ export default abstract class InterfaceConnectionObject<ConfigInterface> {
|
||||
|
||||
public abstract observeProperty(prop: types.Property, callback: (value: any) => void): boolean;
|
||||
|
||||
public abstract callActionSync(action: types.Operation, args: types.OperationVariable[]): any;
|
||||
public abstract callActionSync(action: types.Operation, args: types.OperationVariable[]): boolean;
|
||||
|
||||
public abstract callActionAsync(action: types.Operation, args: types.OperationVariable[]): Promise<boolean>;
|
||||
public abstract callActionAsync(action: types.Operation, args: types.OperationVariable[]): string | null;
|
||||
|
||||
public abstract readAsyncActionResponse(action: types.Operation): Promise<any>;
|
||||
public abstract readAsyncActionResponse(action: types.Operation): any;
|
||||
|
||||
public abstract subscribeEvent(callback: (event: types.BasicEventElement) => void): boolean;
|
||||
public abstract subscribeEvent(event: types.BasicEventElement, callback: (event: types.BasicEventElement) => void): boolean;
|
||||
|
||||
public abstract unsubscribeEvent(): void;
|
||||
public abstract unsubscribeEvent(event: types.BasicEventElement): void;
|
||||
|
||||
protected generateAsyncHandle() {
|
||||
const handle = v4();
|
||||
this.asyncActionStateStore[handle] = {finished: false, result: null};
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@ export type MappingConfiguration = {
|
||||
SourceSinkMappings: types.RelationshipElement[];
|
||||
}
|
||||
|
||||
export type ElementMap = Record<string, ConnectionConfiguration>;
|
||||
export type AIMCMap = Map<types.Class, ConnectionConfiguration>;
|
||||
|
||||
export type ConnectionConfiguration = EndpointMetadata & InterfaceProperty; // Wenn Transformationen implementiert werden, dann hier anpassen
|
||||
Reference in New Issue
Block a user