More setup and an example componente
This commit is contained in:
Generated
+1486
-1
File diff suppressed because it is too large
Load Diff
+5
-2
@@ -2,7 +2,7 @@
|
|||||||
"name": "prototyp",
|
"name": "prototyp",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
@@ -10,10 +10,13 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.19",
|
||||||
"@types/node": "^20.8.2",
|
"@types/node": "^20.8.2",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aas-core-works/aas-core3.0rc02-typescript": "^1.0.0-rc.6"
|
"@aas-core-works/aas-core3.0rc02-typescript": "^1.0.0-rc.6",
|
||||||
|
"express": "^4.18.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-17
@@ -1,8 +1,10 @@
|
|||||||
import { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
|
||||||
|
|
||||||
export class AASStore {
|
import { readdirSync, readFileSync } from "fs";
|
||||||
|
import { types, jsonization } from "@aas-core-works/aas-core3.0rc02-typescript";
|
||||||
|
|
||||||
|
export default class AASStore {
|
||||||
private static instance: AASStore;
|
private static instance: AASStore;
|
||||||
private shells: Array<types.AssetAdministrationShell> = [];
|
private shells: Array<types.Environment> = [];
|
||||||
|
|
||||||
private constructor() { }
|
private constructor() { }
|
||||||
|
|
||||||
@@ -14,23 +16,58 @@ export class AASStore {
|
|||||||
return AASStore.instance;
|
return AASStore.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addAAS(aas: types.AssetAdministrationShell | types.Environment): void {
|
public addAAS(aas: types.Environment): void {
|
||||||
if (aas instanceof types.Environment) {
|
|
||||||
if (aas.assetAdministrationShells) this.shells = this.shells.concat(aas.assetAdministrationShells);
|
|
||||||
} else {
|
|
||||||
this.shells.push(aas);
|
this.shells.push(aas);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public getAAS(id: string): types.AssetAdministrationShell | undefined {
|
public getAll(): Array<types.Environment> {
|
||||||
return this.shells.find((aas) => aas.id === id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeAAS(id: string): void {
|
|
||||||
this.shells = this.shells.filter((aas) => aas.id !== id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getAll(): Array<types.AssetAdministrationShell> {
|
|
||||||
return this.shells;
|
return this.shells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addAASByPath(path: string): void {
|
||||||
|
if (!path.endsWith(".json")) throw new Error("File must be a JSON file");
|
||||||
|
|
||||||
|
const file = getAASFileContent(path);
|
||||||
|
|
||||||
|
const aas = JSON.parse(file);
|
||||||
|
const aasJson = jsonization.environmentFromJsonable(aas);
|
||||||
|
if (aasJson.error) throw aasJson.error;
|
||||||
|
|
||||||
|
this.addAAS(aasJson.mustValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public addAllAASFromPath(path: string): void {
|
||||||
|
const errors: any[] = [];
|
||||||
|
|
||||||
|
getAllAASFiles(path).forEach(file => {
|
||||||
|
try {
|
||||||
|
this.addAASByPath(file);
|
||||||
|
} catch (e) {
|
||||||
|
errors.push(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAllAASFiles(aasPath: string): string[] {
|
||||||
|
const files = readdirSync(aasPath);
|
||||||
|
return files.filter(file => file.endsWith(".json")).map(file => `${aasPath}/${file}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAASFileContent(aasPath: string): string {
|
||||||
|
const content = readFileSync(aasPath, { encoding: "utf-8" });
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAllAASFileContents(aasPath: string): string[] {
|
||||||
|
const files = getAllAASFiles(aasPath)
|
||||||
|
const content = [];
|
||||||
|
for (const file of files) {
|
||||||
|
content.push(getAASFileContent(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type { Express } from "express";
|
||||||
|
import express from "express";
|
||||||
|
import { jsonization, types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
||||||
|
import AASInterfaceServer from "../server";
|
||||||
|
import type { OnRequestCallback } from "../server";
|
||||||
|
import AASStore from "../aasStore";
|
||||||
|
|
||||||
|
type Config = {
|
||||||
|
bindName: string,
|
||||||
|
bindPort: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
|
||||||
|
public name: string = "HTTPInterfaceServer";
|
||||||
|
|
||||||
|
private app: Express = express();
|
||||||
|
private server: any = null;
|
||||||
|
private observers: any[] = [];
|
||||||
|
|
||||||
|
public constructor(config: Config, aas: types.Environment, onRequestCallback: OnRequestCallback) {
|
||||||
|
super(config, aas, onRequestCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public prepare(): void {
|
||||||
|
const aas = AASStore.getInstance().getAll()[0];
|
||||||
|
this.app.use(express.json());
|
||||||
|
this.app.get("/aas", (_, res) => {
|
||||||
|
res.json(jsonization.toJsonable(aas));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public run(): void {
|
||||||
|
this.server = this.app.listen(this.config.bindPort, this.config.bindName, () => {
|
||||||
|
console.log(`Listening on ${this.config.bindName}:${this.config.bindPort}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop(): void {
|
||||||
|
if (this.server && this.server.close) this.server.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public notify(event: any): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected findElementByRequest(request: string): any | null {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,10 +2,20 @@ import type { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
|||||||
|
|
||||||
type ConnectionType = "ON_DEMAND" | "PERMANENT";
|
type ConnectionType = "ON_DEMAND" | "PERMANENT";
|
||||||
|
|
||||||
export abstract class InterfaceConnectionObject {
|
export type OnResponseCallback = (response: any) => void
|
||||||
public abstract readonly name: string;
|
|
||||||
public abstract readonly connectionType: ConnectionType;
|
export default abstract class InterfaceConnectionObject<ConfigInterface> {
|
||||||
public abstract readonly supportsSubscriptions: boolean;
|
protected abstract readonly name: string;
|
||||||
|
protected abstract readonly connectionType: ConnectionType;
|
||||||
|
protected abstract readonly supportsSubscriptions: boolean;
|
||||||
|
|
||||||
|
protected config: ConfigInterface;
|
||||||
|
private onResponseCallback: OnResponseCallback;
|
||||||
|
|
||||||
|
constructor(config: ConfigInterface, onResponseCallback: OnResponseCallback) {
|
||||||
|
this.config = config;
|
||||||
|
this.onResponseCallback = onResponseCallback;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract connect(): boolean;
|
public abstract connect(): boolean;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
||||||
|
import type AASInterfaceServer from "server";
|
||||||
|
import type { PossibleRequests } from "server";
|
||||||
|
import type InterfaceConnectionObject from "interfaceConnectionObject";
|
||||||
|
import AASStore from "aasStore";
|
||||||
|
|
||||||
|
class MultiMessageBroker {
|
||||||
|
private store = AASStore.getInstance();
|
||||||
|
|
||||||
|
private serverInterfaces: Array<typeof AASInterfaceServer> = [];
|
||||||
|
private serverInterfaceConfigs: Array<any> = [];
|
||||||
|
private serverInstances: Array<AASInterfaceServer<any>|null> = [];
|
||||||
|
|
||||||
|
private connectorInterfaces: Array<typeof InterfaceConnectionObject> = [];
|
||||||
|
private connectorConfigs: Array<any> = [];
|
||||||
|
private connectorInstances: Array<InterfaceConnectionObject<any>|null> = [];
|
||||||
|
|
||||||
|
public constructor() {}
|
||||||
|
|
||||||
|
public registerServerInterface(serverInterface: typeof AASInterfaceServer, config: any): void {
|
||||||
|
this.serverInterfaces.push(serverInterface);
|
||||||
|
this.serverInterfaceConfigs.push(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerConnectorInterface(connectorInterface: typeof InterfaceConnectionObject, config: any): void {
|
||||||
|
this.connectorInterfaces.push(connectorInterface);
|
||||||
|
this.connectorConfigs.push(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createServerInstances(aas: types.Environment): void {
|
||||||
|
this.serverInstances = this.serverInterfaces.map((serverInterface, index) => {
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
return new serverInterface(this.serverInterfaceConfigs[index], aas, this.onInterfaceRequest);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Error while creating server instance for ${serverInterface.name}: ${e}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createConnectorInstances(): void {
|
||||||
|
this.connectorInstances = this.connectorInterfaces.map((connectorInterface, index) => {
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
return new connectorInterface(this.connectorConfigs[index], this.onConnectorEvent);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Error while creating connector instance for ${connectorInterface.name}: ${e}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private onInterfaceRequest(request: PossibleRequests) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private onConnectorEvent(response: any) {
|
||||||
|
this.serverInstances.forEach(server => {
|
||||||
|
if (server) server.notify(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import type { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
|
||||||
|
|
||||||
type AASParsingType = types.Environment | types.AssetAdministrationShell | types.Submodel;
|
|
||||||
|
|
||||||
export interface Parser<T extends AASParsingType> {
|
|
||||||
parse(): T | T[];
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { readdir, readFile } from "fs/promises";
|
|
||||||
|
|
||||||
export async function getAllAASFiles(aasPath: string): Promise<string[]> {
|
|
||||||
const files = await readdir(aasPath);
|
|
||||||
return files.filter(file => file.endsWith(".json")).map(file => `${aasPath}/${file}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getAASFileContent(aasPath: string): Promise<string> {
|
|
||||||
const content = await readFile(aasPath, { encoding: "utf-8" });
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getAllAASFileContents(aasPath: string): Promise<string[]> {
|
|
||||||
const files = await getAllAASFiles(aasPath)
|
|
||||||
const content = [];
|
|
||||||
for (const file of files) {
|
|
||||||
content.push(await getAASFileContent(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
|
||||||
|
|
||||||
type AASRequestType = types.Environment | types.Submodel;
|
|
||||||
type AASResponseType = types.BasicEventElement | types.ValueList;
|
|
||||||
|
|
||||||
interface RequestTransformer<T extends AASRequestType, U> {
|
|
||||||
transform(request: T): U;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NorthboundResponseTransformer<T, U extends AASResponseType> {
|
|
||||||
transform(response: T): U;
|
|
||||||
}
|
|
||||||
+18
-7
@@ -1,12 +1,23 @@
|
|||||||
type ServerConfig = {
|
import { types } from "@aas-core-works/aas-core3.0rc02-typescript";
|
||||||
bindName: string;
|
|
||||||
bindPort: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class AASInterfaceServer {
|
export type PossibleRequests = "TODO";
|
||||||
public abstract readonly name: string;
|
|
||||||
public abstract config: ServerConfig;
|
export type OnRequestCallback = (request: PossibleRequests) => void
|
||||||
|
|
||||||
|
export default abstract class AASInterfaceServer<ConfigInterface> {
|
||||||
|
protected abstract readonly name: string;
|
||||||
|
protected config: ConfigInterface;
|
||||||
|
private onRequestCallback: OnRequestCallback;
|
||||||
|
|
||||||
|
constructor(config: ConfigInterface, aas: types.Environment, onRequestCallback: OnRequestCallback) {
|
||||||
|
this.config = config;
|
||||||
|
this.onRequestCallback = onRequestCallback;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract prepare(): void;
|
public abstract prepare(): void;
|
||||||
public abstract run(): void;
|
public abstract run(): void;
|
||||||
|
public abstract stop(): void;
|
||||||
|
public abstract notify(event: any): void;
|
||||||
|
|
||||||
|
protected abstract findElementByRequest(request: PossibleRequests): any | null;
|
||||||
}
|
}
|
||||||
+2
-2
@@ -11,7 +11,7 @@
|
|||||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
/* Language and Environment */
|
/* Language and Environment */
|
||||||
"target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
|
||||||
/* Modules */
|
/* Modules */
|
||||||
"module": "es2022", /* Specify what module code is generated. */
|
"module": "commonjs", /* Specify what module code is generated. */
|
||||||
"rootDir": "./src", /* Specify the root folder within your source files. */
|
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
"baseUrl": "src", /* Specify the base directory to resolve non-relative module names. */
|
"baseUrl": "src", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
|||||||
Reference in New Issue
Block a user