More work on connector
This commit is contained in:
@@ -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.");
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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");
|
||||
|
||||
@@ -8,4 +8,4 @@ const broker = new MultiMessageBroker();
|
||||
broker.registerAAS({ aas, serverInterfaces: { serverInterface: HTTPInterfaceServer, config: { bindPort: 3000, bindAddress: "0.0.0.0" } } });
|
||||
|
||||
broker.prepare();
|
||||
broker.start();
|
||||
broker.start();
|
||||
@@ -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 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