Even more documentation

This commit is contained in:
Daniel Kluge
2023-11-01 23:44:43 +01:00
parent 86dcd8d2f8
commit 591cf6662b
10 changed files with 506 additions and 8 deletions
+1
View File
@@ -1,2 +1,3 @@
node_modules
dist
docs
+1 -1
View File
@@ -8,7 +8,7 @@ import MQTTConnector from "./modules/mqttConnector";
const aas = FileImporter.readAASByPath("../owntest.json");
// Then we create a new broker instance
const broker = new MultiMessageBroker();
const broker = MultiMessageBroker.getInstance();
// We need to register the connector we want to use.
// These will be chosen later if needed.
broker.registerInterfaceConnection({ interfaceConnection: MQTTConnector, config: { reconnectPeriod: 1000 }})
+190
View File
@@ -15,6 +15,7 @@
"devDependencies": {
"@types/node": "^20.8.2",
"@types/uuid": "^9.0.6",
"typedoc": "^0.25.3",
"typescript": "^5.2.2"
}
},
@@ -35,6 +36,99 @@
"integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==",
"dev": true
},
"node_modules/ansi-sequence-parser": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
"integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
"dev": true
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/jsonc-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
"dev": true
},
"node_modules/lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true
},
"node_modules/marked": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
"dev": true,
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/shiki": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
"integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==",
"dev": true,
"dependencies": {
"ansi-sequence-parser": "^1.1.0",
"jsonc-parser": "^3.2.0",
"vscode-oniguruma": "^1.7.0",
"vscode-textmate": "^8.0.0"
}
},
"node_modules/typedoc": {
"version": "0.25.3",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz",
"integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==",
"dev": true,
"dependencies": {
"lunr": "^2.3.9",
"marked": "^4.3.0",
"minimatch": "^9.0.3",
"shiki": "^0.14.1"
},
"bin": {
"typedoc": "bin/typedoc"
},
"engines": {
"node": ">= 16"
},
"peerDependencies": {
"typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x"
}
},
"node_modules/typescript": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
@@ -59,6 +153,18 @@
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vscode-oniguruma": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
"integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
"dev": true
},
"node_modules/vscode-textmate": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
"dev": true
}
},
"dependencies": {
@@ -79,6 +185,78 @@
"integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==",
"dev": true
},
"ansi-sequence-parser": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
"integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
"dev": true
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0"
}
},
"jsonc-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
"dev": true
},
"lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true
},
"marked": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
"dev": true
},
"minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"requires": {
"brace-expansion": "^2.0.1"
}
},
"shiki": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
"integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==",
"dev": true,
"requires": {
"ansi-sequence-parser": "^1.1.0",
"jsonc-parser": "^3.2.0",
"vscode-oniguruma": "^1.7.0",
"vscode-textmate": "^8.0.0"
}
},
"typedoc": {
"version": "0.25.3",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz",
"integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==",
"dev": true,
"requires": {
"lunr": "^2.3.9",
"marked": "^4.3.0",
"minimatch": "^9.0.3",
"shiki": "^0.14.1"
}
},
"typescript": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
@@ -89,6 +267,18 @@
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
},
"vscode-oniguruma": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
"integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
"dev": true
},
"vscode-textmate": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
"dev": true
}
}
}
+1
View File
@@ -32,6 +32,7 @@
"devDependencies": {
"@types/node": "^20.8.2",
"@types/uuid": "^9.0.6",
"typedoc": "^0.25.3",
"typescript": "^5.2.2"
},
"dependencies": {
+35
View File
@@ -5,14 +5,29 @@ import Traverser from "./helper/traverser";
import AIDParser from "./parser/AIDParser";
import { SubmodelElementCollection } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
/**
* The AIMC Mapper.
* @remarks
* This class is used to map properties t endpoints.
*/
export default class AIMCMapper {
/**
* The map.
*/
private map: AIMCMap = new Map();
/**
* Creates the mapper.
* @param env The AAS Environment
*/
public constructor(private readonly env: types.Environment) {
this.generate();
}
/**
* Generates the map from the AAS Environment.
*/
private generate(): void {
const aimc = AIMCParser.parse(this.env);
if (aimc === null) return;
@@ -51,14 +66,29 @@ export default class AIMCMapper {
}
}
/**
*
* @returns The complete map
*/
public getMap(): AIMCMap {
return this.map;
}
/**
* Get endpoint for a specific Element
* @param element Element
* @returns Endpoint description or undefined if not found
*/
public get(element: types.Class): ConnectionConfiguration | undefined {
return this.map.get(element);
}
/**
* Returns all endpoints for a idShort
* Can return multiple as idShorts are not necessarily unique
* @param idShort idShort of the element
* @returns Endpoints descriptions of elements with that idShort
*/
public getByIdShort(idShort: string): ConnectionConfiguration[] {
const result = [];
for (const [e, cc] of this.map.entries()) {
@@ -67,6 +97,11 @@ export default class AIMCMapper {
return result;
}
/**
* Get an element by its endpoint
* @param path Absolute endpoint path
* @returns Elements that use that path
*/
public reverseGet(path: string): types.Class[] {
const result = [];
+21
View File
@@ -2,7 +2,18 @@
import { readdirSync, readFileSync } from "fs";
import { types, jsonization } from "@aas-core-works/aas-core3.0-typescript";
/**
* Helper class to import AAS-Environments from files.
*/
export default class FileImporter {
/**
* Read an AAS-Environment from a file.
* @param path Filepath
* @returns Environment
* @throws Error if file is not a JSON file
* @throws Any IO error on file read operation
*/
public static readAASByPath(path: string): types.Environment {
if (!path.endsWith(".json")) throw new Error("File must be a JSON file");
@@ -15,6 +26,11 @@ export default class FileImporter {
return aasJson.mustValue();
}
/**
* Import all AAS-Environments from a directory.
* @param path Directory path
* @returns Environments
*/
public static readAllAASFromPath(path: string): types.Environment[] {
return FileImporter.getAllAASFilePaths(path).map(file => {
@@ -27,6 +43,11 @@ export default class FileImporter {
}).filter(aas => aas !== null) as types.Environment[];
}
/**
* Get all JSON files from a directory.
* @param aasPath Directory path
* @returns Paths of the JSON files
*/
private static getAllAASFilePaths(aasPath: string): string[] {
const files = readdirSync(aasPath);
return files.filter(file => file.endsWith(".json")).map(file => `${aasPath}/${file}`);
+63 -2
View File
@@ -3,28 +3,58 @@ import { types } from "@aas-core-works/aas-core3.0-typescript";
import { RelationshipElement } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
import { ResolvedRelationshipElement } from "../types/common";
/**
* Keytypes which are globally identifiable.
*/
const GLOBALLY_IDENTIFIABLES = [types.KeyTypes.GlobalReference, types.KeyTypes.AssetAdministrationShell, types.KeyTypes.ConceptDescription, types.KeyTypes.Identifiable, types.KeyTypes.Submodel]
/**
* Helper to traverse the AAS-Environment.
*/
export default class Traverser {
/**
* Find an AAS by its ID.
* @param environment Environment to search in
* @param id ID
* @returns AAS or null if not found
*/
public static findAASById(environment: types.Environment, id: string): types.AssetAdministrationShell | null {
if (environment.assetAdministrationShells === null) return null;
return (environment.assetAdministrationShells.find(aas => aas.id === id)) ?? null;
}
/**
* Find a Submodel by its ID.
* @param environment Environment to search in
* @param id ID
* @returns Submodel or null if not found
*/
public static findSMById(environment: types.Environment, id: string): types.Submodel | null {
if (environment.submodels === null) return null;
return (environment.submodels.find(sm => sm.id === id)) ?? null;
}
/**
* Find Submodel by its idShort.
* @param environment Environment to search in
* @param id idShort
* @returns Submodel or null if not found
*/
public static findSMByIdShort(environment: types.Environment, id: string): types.Submodel | null {
if (environment.submodels === null) return null;
return (environment.submodels.find(sm => sm.idShort === id)) ?? null;
}
/**
* Resolve a reference to an element.
* @param env Environment to search in
* @param ref Reference
* @returns Element or null if not found
*/
public static resolveReference(env: types.Environment, ref: types.Reference): types.Class | null {
if (ref.type === types.ReferenceTypes.ExternalReference) return null; // Not implemented
@@ -42,6 +72,12 @@ export default class Traverser {
return current;
}
/**
* Resolve both references of a relationship element
* @param env Environment to search in
* @param relationship Relationship element
* @returns Resolved relationship element or null if not found
*/
public static resolveRelationship(env: types.Environment, relationship: RelationshipElement): ResolvedRelationshipElement | null {
const first = Traverser.resolveReference(env, relationship.first);
const second = Traverser.resolveReference(env, relationship.second);
@@ -50,9 +86,15 @@ export default class Traverser {
return { first, second };
}
public static traverseByShortIds(start: types.Class, shortIds: string[]): types.Class | null {
/**
* Traverse downwards from a start element by using idShorts.
* @param start Start element
* @param idShorts Array of idShorts to traverse by
* @returns Target element at the end of the path or null if not found
*/
public static traverseByShortIds(start: types.Class, idShorts: string[]): types.Class | null {
let current: types.Class | null = start;
for (const shortId of shortIds) {
for (const shortId of idShorts) {
if (current === null) break;
current = Traverser.findChildByIdShort(current, shortId);
@@ -61,12 +103,25 @@ export default class Traverser {
return current;
}
/**
* Get element by using idShorts from an submodel.
* @param env Environment to search in
* @param submodelOrIdShort Submodel element or Submodel idShort
* @param idShorts idShorts to traverse by
* @returns Target element at the end of the path or null if not found
*/
public static getElementByIdPath(env: types.Environment, submodelOrIdShort: string | types.Submodel, idShorts: string[]): types.Class | null {
const sm = typeof submodelOrIdShort === "string" ? Traverser.findSMByIdShort(env, submodelOrIdShort) : submodelOrIdShort;
if (sm === null) return null;
return Traverser.traverseByShortIds(sm, idShorts);
}
/**
* Find an element using a function to check.
* @param start Start element
* @param checkFunction Function to find the element. First element which evaluates to true using this function will be returned.
* @returns Element or null if not found
*/
public static findElement(start: types.Class, checkFunction: (element: types.Class) => boolean): types.Class | null {
for (const element of start.descend()) {
if (checkFunction(element)) return element;
@@ -75,6 +130,12 @@ export default class Traverser {
return null;
}
/**
* Find a child element by its idShort.
* @param start Start element
* @param idShort idShort to search for
* @returns Child element or null if not found
*/
public static findChildByIdShort(start: types.Class, idShort: string): types.Class | null {
for (const child of start.descendOnce()) {
if ((child as any).idShort === idShort) return child;
+99 -1
View File
@@ -7,48 +7,146 @@ type ConnectionType = "ON_DEMAND" | "PERMANENT";
export type OnEventCallback = (response: any) => void
/**
* Abstract class for an connector to an asset.
* This should be used as base class for your own connectors.
*/
export default abstract class InterfaceConnectionObject<ConfigInterface> {
/**
* A name for your connector.
* @remarks
* Currently not used.
*/
public static readonly connectorName: string;
/**
* Which protocols are supported by your connector.
* This is really important later so the AAS can decide which connector to use!
*/
public static readonly uriProtocol: string[]|string;
/**
* The type of connection your connector uses.
* @remarks
* Currently not used.
*/
public static readonly connectionType: ConnectionType;
/**
* Whether your connector supports subscriptions.
* @remarks
* Currently not used.
*/
public static readonly supportsSubscriptions: boolean;
/**
* A store for all observers and their callbacks.
*/
protected readonly observerStore: Record<any, ((value: any) => void)[]> = {};
/**
* A store for all event subscriptions and their callbacks.
*/
protected readonly eventSubStore: Record<any, ((value: any) => void)[]> = {};
/**
* A store for all async action handles and their results.
*/
protected readonly asyncActionStateStore: Record<any, {finished: boolean, result: any}> = {};
/**
* Creates the connector.
* @param connectionParameter Connection parameter for your connector.
* @param endpointMetadata {@link EndpointMetadata}
* @param mapper {@link AIMCMapper}
* @param onConnectorEvent Callback when an event is received.
*/
public constructor(
protected readonly connectionParameter: ConfigInterface,
public readonly endpointMetadata: EndpointMetadata,
protected readonly mapper: AIMCMapper,
protected readonly onConnectorEvent: OnEventCallback) {}
/**
* This should connect the Connector to the asset.
* @returns Whether the connection was successful.
*/
public abstract connect(): boolean;
/**
* This should disconnect the Connector from the asset (if it even is connected).
*/
public abstract disconnect(): void;
/**
* Read a property value from the asset.
* @param prop Property
* @returns Value of property casted to the type it says it should be.
*/
public abstract readProperty(prop: types.Property): void;
/**
* Write a property value to the asset.
* @param prop Property
* @param value Value to write.
*/
public abstract writeProperty(prop: types.Property, value: any): void;
/**
* Observe a property value from the asset.
* @param prop Property
* @param callback Callback to call when the property changes.
* @returns Whether the creation of an observer was successful.
*/
public abstract observeProperty(prop: types.Property, callback: (value: any) => void): boolean;
/**
* Call an action on the asset synchronously.
* @param action Action
* @param args Arguments
* @returns Return value of the action.
*/
public abstract callActionSync(action: types.Operation, args: Record<string, any>): any;
/**
* Call an action on the asset asynchronously.
* @param action Action
* @param args Arguments
* @returns Handle for the async action.
*/
public abstract callActionAsync(action: types.Operation, args: Record<string, any>): string | null;
public readAsyncActionState(handle: string): any {
/**
* Read the state of an async action.
* @param handle Handle of the async action.
* @returns Whether the async action is finished.
*/
public readAsyncActionState(handle: string): boolean {
return this.asyncActionStateStore[handle].finished;
}
/**
* Read the result of an async action.
* @param handle Handle of the async action.
* @returns Result of the async action.
*/
public readAsyncActionResponse(handle: string): any {
return this.asyncActionStateStore[handle].result;
};
/**
* Subscribe to an event.
* @param event Event
* @param callback Callback to call when the event occurs.
* @returns Whether the subscription was successful.
*/
public abstract subscribeEvent(event: types.BasicEventElement, callback: (event: types.BasicEventElement) => void): boolean;
/**
* Unsubscribe from an event.
* @param event Event
*/
public abstract unsubscribeEvent(event: types.BasicEventElement): void;
/**
* Generate a handle for an async action.
* @returns Handle
*/
protected generateAsyncHandle() {
const handle = v4();
this.asyncActionStateStore[handle] = {finished: false, result: null};
+56 -2
View File
@@ -27,15 +27,46 @@ type InterfaceConnectionEntry<ConfigInterface> = {
config: ConfigInterface
}
/**
* The core of the library.
* @remarks
* Here are all Interface Servers and Connectors are created and managed.
* Also every request is handled here.
*/
export default class MultiMessageBroker {
private static instance: MultiMessageBroker|null = null;
/**
* Whether the broker is prepared.
*/
private prepared: boolean = false;
/**
* All registered AASs.
*/
private aasRegistrations: AASRegistrationPrepared[] = [];
/**
* All registered Interface Connectors.
*/
private interfaceConnections: InterfaceConnectionEntry<any>[] = [];
public constructor() {}
private constructor() {}
public registerAAS<T>(registration: AASRegistration): void {
/**
* Get the singleton instance of the broker.
*/
public static getInstance(): MultiMessageBroker {
if (this.instance === null) this.instance = new MultiMessageBroker();
return this.instance;
}
/**
* Register an AAS.
* @remarks
* This will also create the {@link AIMCMapper} for the AAS
* @param registration AAS registration
*/
public registerAAS(registration: AASRegistration): void {
this.aasRegistrations.push({
...registration,
serverInstances: [],
@@ -44,10 +75,20 @@ export default class MultiMessageBroker {
});
}
/**
* Register an Interface Connector.
* @param interfaceConnectionEntry Interface connector registration
* @typeParam T - The config interface for your interface connector.
*/
public registerInterfaceConnection<T>(interfaceConnectionEntry: InterfaceConnectionEntry<T>): void {
this.interfaceConnections.push(interfaceConnectionEntry);
}
/**
* Prepare the broker.
* @remarks
* This will create instances of the {@link AASInterfaceServer} and {@link InterfaceConnectionObject} classes.
*/
public prepare(): void {
for (const registration of this.aasRegistrations) {
@@ -92,6 +133,9 @@ export default class MultiMessageBroker {
this.prepared = true;
}
/**
* Start the broker.
*/
public start(): void {
if (!this.prepared) this.prepare();
@@ -101,6 +145,12 @@ export default class MultiMessageBroker {
}
}
/**
* Callback on an server request
* @param request Request
* @param registration AAS Registration
* @returns Value or success state or nothing based on the request type
*/
private onInterfaceRequest(request: Request, registration: AASRegistrationPrepared): any {
const getConnector = (target: types.Class) => {
@@ -162,6 +212,10 @@ export default class MultiMessageBroker {
}
}
/**
* Callback on a connector event.
* @param response
*/
private onConnectorEvent(response: any) {
for (const aas of this.aasRegistrations) {
for (const server of aas.serverInstances ?? []) {
+38 -1
View File
@@ -1,18 +1,55 @@
import { types } from "@aas-core-works/aas-core3.0-typescript";
import type { Request, OnRequestCallback } from "./types/requests";
import type { OnRequestCallback } from "./types/requests";
/**
* Abstract class for an interface server.
* This should be used as base class for your own interface servers!
*
* @typeParam ConfigInterface - The config interface for your interface server.
*/
export default abstract class AASInterfaceServer<ConfigInterface> {
/**
* A name for your interface server.
* @remarks
* Currently unused
*/
public static readonly serverInterfaceName: string;
/**
* Whether your interface server supports subscriptions.
* @remarks
* Currently unused
*/
public static readonly supportsSubscriptions: boolean;
/**
* Crate the interface server.
* @param config Interface server config
* @param aas AAS Environment for the server
* @param onRequestCallback Callback when a request is received and parsed
*/
constructor(
protected readonly config: ConfigInterface,
protected readonly aas: types.Environment,
protected readonly onRequestCallback: OnRequestCallback) {}
/**
* Prepare the interface server.
* @remarks
* Here you can create routes, listeners, callbacks,...
*/
public abstract prepare(): void;
/**
* Run the interface server.
*/
public abstract run(): void;
/**
* Stop the interface server.
*/
public abstract stop(): void;
/**
* Notify observers/subscribers about an event.
* @param event Event to notify the interface server about
*/
public abstract notify(event: any): void;
}