Documentation for example project
This commit is contained in:
@@ -3,11 +3,20 @@ import { MultiMessageBroker, FileImporter } from "aas-multimessagebroker";
|
|||||||
import HTTPInterfaceServer from "./modules/httpInterfaceServer";
|
import HTTPInterfaceServer from "./modules/httpInterfaceServer";
|
||||||
import MQTTConnector from "./modules/mqttConnector";
|
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");
|
const aas = FileImporter.readAASByPath("../owntest.json");
|
||||||
|
|
||||||
|
// Then we create a new broker instance
|
||||||
const broker = new MultiMessageBroker();
|
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 }})
|
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" } } });
|
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();
|
broker.prepare();
|
||||||
|
// Run the broker (this will start the servers)
|
||||||
broker.start();
|
broker.start();
|
||||||
@@ -1,34 +1,69 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import { AbstractInterfaceServer, Types, Traverser, AASCoreJsonization, AASCoreTypes } from "aas-multimessagebroker";
|
import { AbstractInterfaceServer, Types, Traverser, AASCoreJsonization, AASCoreTypes } from "aas-multimessagebroker";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the configuration interface for the HTTPInterfaceServer.
|
||||||
|
*/
|
||||||
export type Config = {
|
export type Config = {
|
||||||
bindAddress: string,
|
bindAddress: string,
|
||||||
bindPort: number,
|
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> {
|
export default class HTTPInterfaceServer extends AbstractInterfaceServer<Config> {
|
||||||
public static serverInterfaceName: string = "HTTPInterfaceServer";
|
public static serverInterfaceName: string = "HTTPInterfaceServer";
|
||||||
public static supportsSubscriptions: boolean = false; // TODO, longpolling?
|
public static supportsSubscriptions: boolean = false; // TODO, longpolling?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the {@link express#Express|express app}.
|
||||||
|
*/
|
||||||
private app: express.Express = express();
|
private app: express.Express = express();
|
||||||
|
/**
|
||||||
|
* The server instance
|
||||||
|
*/
|
||||||
private server: any = null;
|
private server: any = null;
|
||||||
|
/**
|
||||||
|
* List of observers, currently not used.
|
||||||
|
*/
|
||||||
private observers: any[] = [];
|
private observers: any[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the server, e.g. create routes.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* This is called before the server is started.
|
||||||
|
*/
|
||||||
public prepare(): void {
|
public prepare(): void {
|
||||||
this.app.use(express.json());
|
this.app.use(express.json());
|
||||||
this.createRoutes();
|
this.createRoutes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should start the server.
|
||||||
|
*/
|
||||||
public run(): void {
|
public run(): void {
|
||||||
this.server = this.app.listen(this.config.bindPort, this.config.bindAddress, () => {
|
this.server = this.app.listen(this.config.bindPort, this.config.bindAddress, () => {
|
||||||
console.log(`Listening on ${this.config.bindAddress}:${this.config.bindPort}`);
|
console.log(`Listening on ${this.config.bindAddress}:${this.config.bindPort}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should stop the server.
|
||||||
|
*/
|
||||||
public stop(): void {
|
public stop(): void {
|
||||||
if (this.server && this.server.close) this.server.close();
|
if (this.server && this.server.close) this.server.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should call notify all observers
|
||||||
|
*/
|
||||||
public notify(event: any): void {
|
public notify(event: any): void {
|
||||||
this.observers.forEach(observer => {
|
this.observers.forEach(observer => {
|
||||||
// TODO
|
// 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 {
|
private createRoutes(): void {
|
||||||
const NOT_IMPLEMENTED = (_req: express.Request, res: express.Response) => res.status(501).end();
|
const NOT_IMPLEMENTED = (_req: express.Request, res: express.Response) => res.status(501).end();
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,38 @@ import * as mqtt from "mqtt";
|
|||||||
import { AbstractConnectionObject } from "aas-multimessagebroker";
|
import { AbstractConnectionObject } from "aas-multimessagebroker";
|
||||||
import type { AASCoreTypes } 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> {
|
export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClientOptions> {
|
||||||
public static readonly connectorName: string = "MQTT Connector";
|
public static readonly connectorName: string = "MQTT Connector";
|
||||||
public static readonly uriProtocol: string[] = ["mqtt", "mqtts"];
|
public static readonly uriProtocol: string[] = ["mqtt", "mqtts"];
|
||||||
public static readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT";
|
public static readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT";
|
||||||
public static readonly supportsSubscriptions: boolean = true;
|
public static readonly supportsSubscriptions: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link mqtt#MqttClient|MQTT client object}.
|
||||||
|
*/
|
||||||
private client: mqtt.MqttClient|null = null;
|
private client: mqtt.MqttClient|null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store where the messages are temporally stored for requests.
|
||||||
|
*/
|
||||||
private readonly messageStore: Record<string, any> = {};
|
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 {
|
public connect(): boolean {
|
||||||
if (!this.client) this.client = mqtt.connect(this.endpointMetadata.base, this.connectionParameter);
|
if (!this.client) this.client = mqtt.connect(this.endpointMetadata.base, this.connectionParameter);
|
||||||
this.client.on("message", (topic, message) => {
|
this.client.on("message", (topic, message) => {
|
||||||
@@ -27,11 +49,23 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
|
|||||||
return this.client.connected;
|
return this.client.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should disconnect the Connector from the asset (if it even is connected).
|
||||||
|
*/
|
||||||
public disconnect(): void {
|
public disconnect(): void {
|
||||||
if (this.client) this.client.end();
|
if (this.client) this.client.end();
|
||||||
this.client = null;
|
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 {
|
public readProperty(prop: AASCoreTypes.Property): any {
|
||||||
const cc = this.mapper.get(prop);
|
const cc = this.mapper.get(prop);
|
||||||
if (cc === undefined) return null;
|
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 {
|
public writeProperty(prop: AASCoreTypes.Property, value: any): boolean {
|
||||||
const cc = this.mapper.get(prop);
|
const cc = this.mapper.get(prop);
|
||||||
if (cc === undefined || !this.client || !this.client.connected) return false;
|
if (cc === undefined || !this.client || !this.client.connected) return false;
|
||||||
@@ -67,6 +107,12 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
|
|||||||
return true;
|
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 {
|
public observeProperty(prop: AASCoreTypes.Property, callback: (value: any) => void): boolean {
|
||||||
const cc = this.mapper.get(prop);
|
const cc = this.mapper.get(prop);
|
||||||
if (cc === undefined || !cc.observable || !this.client || !this.client.connected) return false;
|
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;
|
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 {
|
public callActionSync(action: AASCoreTypes.Operation, args: Record<string, any>): any {
|
||||||
// TODO
|
// TODO
|
||||||
// Vorher mal ne ordentliche Mapping-Definition
|
// Vorher mal ne ordentliche Mapping-Definition
|
||||||
@@ -85,6 +138,13 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
|
|||||||
throw new Error("Method not implemented.");
|
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 {
|
public callActionAsync(action: AASCoreTypes.Operation, args: Record<string, any>): string | null {
|
||||||
// TODO
|
// TODO
|
||||||
// Vorher mal ne ordentliche Mapping-Definition
|
// Vorher mal ne ordentliche Mapping-Definition
|
||||||
@@ -92,6 +152,12 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
|
|||||||
throw new Error("Method not implemented.");
|
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 {
|
public subscribeEvent(event: AASCoreTypes.BasicEventElement, callback: (event: AASCoreTypes.BasicEventElement) => void): boolean {
|
||||||
// TODO
|
// TODO
|
||||||
// Vorher mal ne ordentliche Mapping-Definition
|
// Vorher mal ne ordentliche Mapping-Definition
|
||||||
@@ -99,6 +165,10 @@ export default class MQTTConnector extends AbstractConnectionObject<mqtt.IClient
|
|||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from an event.
|
||||||
|
* @param event Event
|
||||||
|
*/
|
||||||
public unsubscribeEvent(event: AASCoreTypes.BasicEventElement): void {
|
public unsubscribeEvent(event: AASCoreTypes.BasicEventElement): void {
|
||||||
// TODO
|
// TODO
|
||||||
// Vorher mal ne ordentliche Mapping-Definition
|
// Vorher mal ne ordentliche Mapping-Definition
|
||||||
|
|||||||
Reference in New Issue
Block a user