Documentation for example project

This commit is contained in:
Daniel Kluge
2023-11-01 22:58:12 +01:00
parent 09484a0d62
commit 86dcd8d2f8
3 changed files with 121 additions and 0 deletions
+9
View File
@@ -3,11 +3,20 @@ import { MultiMessageBroker, FileImporter } from "aas-multimessagebroker";
import HTTPInterfaceServer from "./modules/httpInterfaceServer";
import MQTTConnector from "./modules/mqttConnector";
// First we need to import the AAS Package
// It was created using the aasx-package-explorer (https://github.com/admin-shell-io/aasx-package-explorer)
const aas = FileImporter.readAASByPath("../owntest.json");
// Then we create a new broker instance
const broker = new MultiMessageBroker();
// We need to register the connector we want to use.
// These will be chosen later if needed.
broker.registerInterfaceConnection({ interfaceConnection: MQTTConnector, config: { reconnectPeriod: 1000 }})
// Also we need to register the aas and the server interfaces it should use.
// Multiple server interfaces can be used for the same AAS (by making "serverInterfaces" an array).
broker.registerAAS({ aas, serverInterfaces: { serverInterface: HTTPInterfaceServer, config: { bindPort: 3000, bindAddress: "0.0.0.0" } } });
// Prepare the broker (this will create instances of the interfaces and connectors)
broker.prepare();
// Run the broker (this will start the servers)
broker.start();
@@ -1,34 +1,69 @@
import express from "express";
import { AbstractInterfaceServer, Types, Traverser, AASCoreJsonization, AASCoreTypes } from "aas-multimessagebroker";
/**
* This is the configuration interface for the HTTPInterfaceServer.
*/
export type Config = {
bindAddress: string,
bindPort: number,
}
/**
* This is an example module for the interface server.
*
* @remarks
* It _must_ extend the {@link aas-multimessagebroker#AbstractInterfaceServer|AbstractInterfaceServer} class!
*
* @see {@link aas-multimessagebroker#AbstractInterfaceServer|AbstractInterfaceServer}
*/
export default class HTTPInterfaceServer extends AbstractInterfaceServer<Config> {
public static serverInterfaceName: string = "HTTPInterfaceServer";
public static supportsSubscriptions: boolean = false; // TODO, longpolling?
/**
* This is the {@link express#Express|express app}.
*/
private app: express.Express = express();
/**
* The server instance
*/
private server: any = null;
/**
* List of observers, currently not used.
*/
private observers: any[] = [];
/**
* Prepare the server, e.g. create routes.
*
* @remarks
* This is called before the server is started.
*/
public prepare(): void {
this.app.use(express.json());
this.createRoutes();
}
/**
* This should start the server.
*/
public run(): void {
this.server = this.app.listen(this.config.bindPort, this.config.bindAddress, () => {
console.log(`Listening on ${this.config.bindAddress}:${this.config.bindPort}`);
});
}
/**
* This should stop the server.
*/
public stop(): void {
if (this.server && this.server.close) this.server.close();
}
/**
* This should call notify all observers
*/
public notify(event: any): void {
this.observers.forEach(observer => {
// TODO
@@ -36,6 +71,13 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer<Config>
});
}
/**
* Here we create all the routes for the express server.
*
* @remarks
* Most of it is _not_ using the specification nor even implemented.
* This is more of a PoC
*/
private createRoutes(): void {
const NOT_IMPLEMENTED = (_req: express.Request, res: express.Response) => res.status(501).end();
+70
View File
@@ -2,16 +2,38 @@ import * as mqtt from "mqtt";
import { AbstractConnectionObject } from "aas-multimessagebroker";
import type { AASCoreTypes } from "aas-multimessagebroker";
/**
* This is an example module for the asset connection object.
*
* @remarks
* It _must_ extend the {@link aas-multimessagebroker#AbstractConnectionObject|AbstractConnectionObject} class!
*
* @see {@link aas-multimessagebroker#AbstractConnectionObject|AbstractConnectionObject}
*/
export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClientOptions> {
public static readonly connectorName: string = "MQTT Connector";
public static readonly uriProtocol: string[] = ["mqtt", "mqtts"];
public static readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT";
public static readonly supportsSubscriptions: boolean = true;
/**
* The {@link mqtt#MqttClient|MQTT client object}.
*/
private client: mqtt.MqttClient|null = null;
/**
* Store where the messages are temporally stored for requests.
*/
private readonly messageStore: Record<string, any> = {};
/**
* This should connect the Connector to the asset.
*
* @remarks For async connections like HTTP you can just return true and do the connection on demand.
*
* @returns Whether the connection was successful.
*/
public connect(): boolean {
if (!this.client) this.client = mqtt.connect(this.endpointMetadata.base, this.connectionParameter);
this.client.on("message", (topic, message) => {
@@ -27,11 +49,23 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
return this.client.connected;
}
/**
* This should disconnect the Connector from the asset (if it even is connected).
*/
public disconnect(): void {
if (this.client) this.client.end();
this.client = null;
}
/**
* Read a property value from the asset.
*
* @remarks
* As we have our message store no connection is needed here.
*
* @param prop Property
* @returns Value of property casted to the type it says it should be.
*/
public readProperty(prop: AASCoreTypes.Property): any {
const cc = this.mapper.get(prop);
if (cc === undefined) return null;
@@ -55,6 +89,12 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
}
/**
* Write a property value to the asset.
* @param prop Property
* @param value Value
* @returns Whether the write was successful.
*/
public writeProperty(prop: AASCoreTypes.Property, value: any): boolean {
const cc = this.mapper.get(prop);
if (cc === undefined || !this.client || !this.client.connected) return false;
@@ -67,6 +107,12 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
return true;
}
/**
* Creates an observer for a property.
* @param prop Property
* @param callback Callback on change
* @returns Whether the observer was created successfully.
*/
public observeProperty(prop: AASCoreTypes.Property, callback: (value: any) => void): boolean {
const cc = this.mapper.get(prop);
if (cc === undefined || !cc.observable || !this.client || !this.client.connected) return false;
@@ -78,6 +124,13 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
return true;
}
/**
* Calls an action synchronously.
* @param action Action
* @param args Arguments
*
* @returns Return value of action.
*/
public callActionSync(action: AASCoreTypes.Operation, args: Record<string, any>): any {
// TODO
// Vorher mal ne ordentliche Mapping-Definition
@@ -85,6 +138,13 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
throw new Error("Method not implemented.");
}
/**
* Calls an action synchronously.
* @param action Action
* @param args Arguments
*
* @returns Handle (uuid) for the result or null if it fails.
*/
public callActionAsync(action: AASCoreTypes.Operation, args: Record<string, any>): string | null {
// TODO
// Vorher mal ne ordentliche Mapping-Definition
@@ -92,6 +152,12 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
throw new Error("Method not implemented.");
}
/**
* Subscribe to an event.
* @param event Event
* @param callback Callback onEvent
* @returns Whether the subscription was successful.
*/
public subscribeEvent(event: AASCoreTypes.BasicEventElement, callback: (event: AASCoreTypes.BasicEventElement) => void): boolean {
// TODO
// Vorher mal ne ordentliche Mapping-Definition
@@ -99,6 +165,10 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
throw new Error("Method not implemented.");
}
/**
* Unsubscribe from an event.
* @param event Event
*/
public unsubscribeEvent(event: AASCoreTypes.BasicEventElement): void {
// TODO
// Vorher mal ne ordentliche Mapping-Definition