Fix all the bugs (it wörks now)

This commit is contained in:
Daniel Kluge
2023-11-01 20:39:30 +01:00
parent 7d21df351b
commit cab50cda6a
12 changed files with 104 additions and 79 deletions
+11 -5
View File
@@ -2,7 +2,7 @@ import type { Express } from "express";
import express from "express"; import express from "express";
import { jsonization, types } from "@aas-core-works/aas-core3.0-typescript"; import { jsonization, types } from "@aas-core-works/aas-core3.0-typescript";
import AASInterfaceServer from "../server"; import AASInterfaceServer from "../server";
import type { OnRequestCallback, Request } from "types/requests"; import type { OnRequestCallback, Request } from "../types/requests";
import Traverser from "../helper/traverser"; import Traverser from "../helper/traverser";
export type Config = { export type Config = {
@@ -11,8 +11,8 @@ export type Config = {
} }
export default class HTTPInterfaceServer extends AASInterfaceServer<Config> { export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
public readonly name: string = "HTTPInterfaceServer"; public static serverInterfaceName: string = "HTTPInterfaceServer";
public readonly supportsSubscriptions: boolean = false; // TODO, longpolling? public static supportsSubscriptions: boolean = false; // TODO, longpolling?
private app: Express = express(); private app: Express = express();
private server: any = null; private server: any = null;
@@ -62,6 +62,10 @@ export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
} }
} }
this.app.use("/*", (req, res, next) => {
console.log(req.originalUrl); next();
});
// /aas // /aas
this.app.get("/aas", (_, res) => res.json(jsonization.toJsonable(this.aas)).end()); this.app.get("/aas", (_, res) => res.json(jsonization.toJsonable(this.aas)).end());
this.app.put("/aas", NOT_IMPLEMENTED); this.app.put("/aas", NOT_IMPLEMENTED);
@@ -88,8 +92,10 @@ export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
this.app.put("/aas/submodels/:smId", NOT_IMPLEMENTED); this.app.put("/aas/submodels/:smId", NOT_IMPLEMENTED);
this.app.patch("/aas/submodels/:smId", NOT_IMPLEMENTED); this.app.patch("/aas/submodels/:smId", NOT_IMPLEMENTED);
this.app.delete("/aas/submodels/:smId", NOT_IMPLEMENTED); this.app.delete("/aas/submodels/:smId", NOT_IMPLEMENTED);
// /aas/submodels/:smId/submodel-elements // /aas/submodels/:smId/submodel-elements
this.app.use("/aas/submodels/:smId/submodel-elements", (req, res) => { this.app.use("/aas/submodels/:smId/submodel-elements", (req, res, next) => {
if (req.path !== "/") return next();
if (req.method !== "GET") return res.status(501).end(); if (req.method !== "GET") return res.status(501).end();
const sm = getSM(req.params.smId); const sm = getSM(req.params.smId);
@@ -101,7 +107,6 @@ export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
// Main function // Main function
this.app.use("/aas/submodels/:smId/submodel-elements/*", (req, res) => { this.app.use("/aas/submodels/:smId/submodel-elements/*", (req, res) => {
const idShortPathString = (req.params as any)[0]; const idShortPathString = (req.params as any)[0];
console.log(idShortPathString);
if (idShortPathString.endsWith("/")) res.status(400).end(); if (idShortPathString.endsWith("/")) res.status(400).end();
const sm = getSM(req.params.smId); const sm = getSM(req.params.smId);
@@ -126,6 +131,7 @@ export default class HTTPInterfaceServer extends AASInterfaceServer<Config> {
const idShortPath = endingMatch ? idShortPathString.replace(new RegExp(`${endingMatch}$`), "").split("/") : idShortPathString.split("/"); const idShortPath = endingMatch ? idShortPathString.replace(new RegExp(`${endingMatch}$`), "").split("/") : idShortPathString.split("/");
console.log(idShortPath, endingMatch)
switch (endingMatch) { switch (endingMatch) {
case undefined: { case undefined: {
+16 -11
View File
@@ -1,12 +1,12 @@
import * as mqtt from "mqtt"; import * as mqtt from "mqtt";
import InterfaceConnectionObject from "interfaceConnectionObject"; import InterfaceConnectionObject from "../interfaceConnectionObject";
import type { types } from "@aas-core-works/aas-core3.0-typescript"; import type { types } from "@aas-core-works/aas-core3.0-typescript";
export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClientOptions> { export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClientOptions> {
public readonly name: string = "MQTT Connector"; public static readonly connectorName: string = "MQTT Connector";
public readonly uriProtocol: string[] = ["mqtt", "mqtts"]; public static readonly uriProtocol: string[] = ["mqtt", "mqtts"];
public readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT"; public static readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT";
public readonly supportsSubscriptions: boolean = true; public static readonly supportsSubscriptions: boolean = true;
private client: mqtt.MqttClient|null = null; private client: mqtt.MqttClient|null = null;
@@ -15,6 +15,7 @@ export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClien
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) => {
//console.log(`${topic}: ${message.toString("utf-8")}`)
// If json is expected you could parse it here // If json is expected you could parse it here
this.messageStore[topic] = message.toString("utf-8"); this.messageStore[topic] = message.toString("utf-8");
// Notify observers // Notify observers
@@ -32,13 +33,18 @@ export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClien
} }
public readProperty(prop: types.Property): any { public readProperty(prop: types.Property): any {
console.log(prop);
const cc = this.mapper.get(prop); const cc = this.mapper.get(prop);
console.log(cc);
if (cc === undefined) return null; if (cc === undefined) return null;
const errorReturn = cc.default ?? null; const errorReturn = cc.default ?? null;
if (!this.client || !this.client.connected) return errorReturn; 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]; console.log(this.messageStore)
const value = this.messageStore[cc.forms.href.substring(1)];
console.log(value)
if (value === undefined) return errorReturn; if (value === undefined) return errorReturn;
switch (cc.type) { switch (cc.type) {
case "integer": case "integer":
@@ -58,7 +64,7 @@ export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClien
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;
const topic = cc.forms.map(f => f.href.substring(1))[0]; const topic = cc.forms.href.substring(1);
if (topic === undefined) return false; if (topic === undefined) return false;
this.client.publish(topic, value.toString()); this.client.publish(topic, value.toString());
@@ -70,10 +76,9 @@ export default class MQTTConnector extends InterfaceConnectionObject<mqtt.IClien
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;
cc.forms.map(f => f.href.substring(1)).forEach(topic => { const topic = cc.forms.href.substring(1);
if (this.observerStore[topic] === undefined) this.observerStore[topic] = [callback]; if (this.observerStore[topic] === undefined) this.observerStore[topic] = [callback];
else this.observerStore[topic].push(callback); else this.observerStore[topic].push(callback);
});
return true; return true;
} }
+1 -1
View File
@@ -1,7 +1,7 @@
import { types } from "@aas-core-works/aas-core3.0-typescript"; import { types } from "@aas-core-works/aas-core3.0-typescript";
import { RelationshipElement } from "@aas-core-works/aas-core3.0-typescript/dist/types/types"; import { RelationshipElement } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
import { ResolvedRelationshipElement } from "types/common"; import { ResolvedRelationshipElement } from "../types/common";
const GLOBALLY_IDENTIFIABLES = [types.KeyTypes.GlobalReference, types.KeyTypes.AssetAdministrationShell, types.KeyTypes.ConceptDescription, types.KeyTypes.Identifiable, types.KeyTypes.Submodel] const GLOBALLY_IDENTIFIABLES = [types.KeyTypes.GlobalReference, types.KeyTypes.AssetAdministrationShell, types.KeyTypes.ConceptDescription, types.KeyTypes.Identifiable, types.KeyTypes.Submodel]
+3 -1
View File
@@ -1,10 +1,12 @@
import MultiMessageBroker from "./multimessageBroker"; import MultiMessageBroker from "./multimessageBroker";
import HTTPInterfaceServer from "./example_modules/httpInterfaceServer"; import HTTPInterfaceServer from "./example_modules/httpInterfaceServer";
import FileImporter from "./helper/fileImporter"; import FileImporter from "./helper/fileImporter";
import MQTTConnector from "./example_modules/mqttConnector";
const aas = FileImporter.readAASByPath("../AID-AIMC-Full-Example-20230911T1608.json"); const aas = FileImporter.readAASByPath("../owntest.json");
const broker = new MultiMessageBroker(); const broker = new MultiMessageBroker();
broker.registerInterfaceConnection({ interfaceConnection: MQTTConnector, config: { reconnectPeriod: 1000 }})
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" } } });
broker.prepare(); broker.prepare();
+5 -5
View File
@@ -1,17 +1,17 @@
import type { types } from "@aas-core-works/aas-core3.0-typescript"; import type { types } from "@aas-core-works/aas-core3.0-typescript";
import AIMCMapper from "./parser/AIMCMapper"; import AIMCMapper from "./parser/AIMCMapper";
import { v4 } from "uuid"; import { v4 } from "uuid";
import type { EndpointMetadata } from "types/aidConf"; import type { EndpointMetadata } from "./types/aidConf";
type ConnectionType = "ON_DEMAND" | "PERMANENT"; type ConnectionType = "ON_DEMAND" | "PERMANENT";
export type OnEventCallback = (response: any) => void export type OnEventCallback = (response: any) => void
export default abstract class InterfaceConnectionObject<ConfigInterface> { export default abstract class InterfaceConnectionObject<ConfigInterface> {
public abstract readonly name: string; public static readonly connectorName: string;
public abstract readonly uriProtocol: string[]|string; public static readonly uriProtocol: string[]|string;
public abstract readonly connectionType: ConnectionType; public static readonly connectionType: ConnectionType;
public abstract readonly supportsSubscriptions: boolean; public static readonly supportsSubscriptions: boolean;
protected readonly observerStore: Record<any, ((value: any) => void)[]> = {}; protected readonly observerStore: Record<any, ((value: any) => void)[]> = {};
protected readonly eventSubStore: Record<any, ((value: any) => void)[]> = {}; protected readonly eventSubStore: Record<any, ((value: any) => void)[]> = {};
+18 -6
View File
@@ -1,9 +1,10 @@
import { types } from "@aas-core-works/aas-core3.0-typescript"; import { types } from "@aas-core-works/aas-core3.0-typescript";
import type AASInterfaceServer from "./server"; import type AASInterfaceServer from "./server";
import type { Request } from "types/requests"; import type { Request } from "./types/requests";
import type InterfaceConnectionObject from "interfaceConnectionObject"; import type InterfaceConnectionObject from "interfaceConnectionObject";
import AIMCMapper from "./parser/AIMCMapper"; import AIMCMapper from "./parser/AIMCMapper";
import AIDParser from "./parser/AIDParser"; import AIDParser from "./parser/AIDParser";
import { EndpointMetadata } from "types/aidConf";
type AASRegistration = { type AASRegistration = {
aas: types.Environment, aas: types.Environment,
@@ -55,7 +56,7 @@ export default class MultiMessageBroker {
registration.serverInstances = registration.serverInterfaces.map(serverInterface => { registration.serverInstances = registration.serverInterfaces.map(serverInterface => {
try { try {
// @ts-ignore // @ts-ignore
const server = new serverInterface.serverInterface<typeof serverInterface.config>(serverInterface.config, registration.aas, registration.mappingConfiguration, (req: Request) => this.onInterfaceRequest(req, registration)); const server = new serverInterface.serverInterface<typeof serverInterface.config>(serverInterface.config, registration.aas, (req: Request) => this.onInterfaceRequest(req, registration));
server.prepare(); server.prepare();
return server; return server;
} catch (e) { } catch (e) {
@@ -68,13 +69,23 @@ export default class MultiMessageBroker {
if (!interfaceDescription) continue; if (!interfaceDescription) continue;
const endpoints = Object.values(interfaceDescription).flatMap(idEntries => idEntries.map(entry => entry.EndPointMetadata)); const endpoints = Object.values(interfaceDescription).flatMap(idEntries => idEntries.map(entry => entry.EndPointMetadata));
const uniqueProtocols = [...new Set(endpoints.map(endpoint => new URL(endpoint.base).protocol))]; const uniqueProtocols: Record<string, EndpointMetadata[]> = {};
endpoints.forEach(endpoint => {
const pUrl = new URL(endpoint.base);
if (!uniqueProtocols[pUrl.protocol]) uniqueProtocols[pUrl.protocol] = [endpoint];
else uniqueProtocols[pUrl.protocol].push(endpoint);
});
for (const protocol of uniqueProtocols) { for (const [protocol, endpoints] of Object.entries(uniqueProtocols)) {
const connectorProto = this.interfaceConnections.find(connection => connection.interfaceConnection.prototype.uriProtocol.includes(protocol)) const connectorProto = this.interfaceConnections.find(connection => {
const protos = typeof connection.interfaceConnection.uriProtocol === "string" ? [connection.interfaceConnection.uriProtocol] : connection.interfaceConnection.uriProtocol;
return protos.map(proto => proto.endsWith(":") ? proto : proto + ":").includes(protocol.endsWith(":") ? protocol : protocol + ":");
});
if (connectorProto === undefined) continue; if (connectorProto === undefined) continue;
// @ts-ignore // @ts-ignore
registration.connectorInterfaces.push(new connectorProto.interfaceConnection(connectorProto.config, registration.mappingConfiguration, (response: any) => this.onConnectorEvent(response))); for (const ep of endpoints) registration.connectorInterfaces.push(new connectorProto.interfaceConnection(connectorProto.config, ep, registration.mappingConfiguration, (response: any) => this.onConnectorEvent(response)));
} }
} }
@@ -85,6 +96,7 @@ export default class MultiMessageBroker {
if (!this.prepared) this.prepare(); if (!this.prepared) this.prepare();
for (const registration of this.aasRegistrations) { for (const registration of this.aasRegistrations) {
registration.connectorInterfaces.forEach(connector => connector.connect());
registration.serverInstances?.forEach(server => server?.run()); registration.serverInstances?.forEach(server => server?.run());
} }
} }
+17 -25
View File
@@ -1,12 +1,12 @@
import * as aasCore from "@aas-core-works/aas-core3.0-typescript"; import * as aasCore from "@aas-core-works/aas-core3.0-typescript";
import type { AssetInterfacesDescription, EndpointMetadata, InterfaceDescription, InterfaceMetadata, InterfaceAction, InterfaceEvent, InterfaceProperty, InterfacePropertyForm } from "types/aidConf"; import type { AssetInterfacesDescription, EndpointMetadata, InterfaceDescription, InterfaceMetadata, InterfaceAction, InterfaceEvent, InterfaceProperty, InterfacePropertyForm } from "../types/aidConf";
import { AvailableEndpoint, endpointAvailable } from "../types/common"; import { AvailableEndpoint, endpointAvailable } from "../types/common";
import Traverser from "../helper/traverser"; import Traverser from "../helper/traverser";
export default class AIDParser { export default class AIDParser {
public static parse(env: aasCore.types.Environment): AssetInterfacesDescription | null { public static parse(env: aasCore.types.Environment): AssetInterfacesDescription | null {
const sm = Traverser.findSMByIdShort(env, "AssetInterfaceDescription"); const sm = Traverser.findSMByIdShort(env, "AssetInterfacesDescription");
if (sm === null || sm.submodelElements === null) return null; if (sm === null || sm.submodelElements === null) return null;
const parsed = {} as AssetInterfacesDescription; const parsed = {} as AssetInterfacesDescription;
@@ -28,11 +28,11 @@ export default class AIDParser {
} }
private static parseAIDEntry(entry: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceDescription | null { private static parseAIDEntry(entry: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceDescription | null {
const title = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "title"); const title = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "title");
const titleString = title !== null && aasCore.types.isProperty(title) && title.value ? title.value : ""; const titleString = title !== null && aasCore.types.isProperty(title) && title.value ? title.value : "";
const ep = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "endpointmetadata"); const ep = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "endpointmetadata");
const im = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "interfacemetadata"); const im = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "interfacemetadata");
if (ep === null || !aasCore.types.isSubmodelElementCollection(ep) || !ep.value || im === null || !aasCore.types.isSubmodelElementCollection(im) || !im.value) return null; if (ep === null || !aasCore.types.isSubmodelElementCollection(ep) || !ep.value || im === null || !aasCore.types.isSubmodelElementCollection(im) || !im.value) return null;
const parsedEp = AIDParser.parseEndpointMetaData(ep, endpointProtocol); const parsedEp = AIDParser.parseEndpointMetaData(ep, endpointProtocol);
@@ -53,7 +53,7 @@ export default class AIDParser {
const parsed = {} as EndpointMetadata; const parsed = {} as EndpointMetadata;
for (const key of ["base", "contentType"]) { for (const key of ["base", "contentType"]) {
const prop = Traverser.findElement(endpoint, element => (element as any).idShort.toLocaleLowerCase() === key.toLocaleLowerCase()); const prop = Traverser.findElement(endpoint, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) return null; // Mandatory if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) return null; // Mandatory
else parsed[key] = prop.value; else parsed[key] = prop.value;
} }
@@ -73,7 +73,7 @@ export default class AIDParser {
events: [] events: []
} as InterfaceMetadata; } as InterfaceMetadata;
const prop = Traverser.findElement(interfaceMeta, element => (element as any).idShort.toLocaleLowerCase() === "properties"); const prop = Traverser.findElement(interfaceMeta, element => (element as any).idShort?.toLocaleLowerCase() === "properties");
if (prop === null || !aasCore.types.isSubmodelElementList(prop) || !prop.value) return null; // Mandatory if (prop === null || !aasCore.types.isSubmodelElementList(prop) || !prop.value) return null; // Mandatory
for (const element of prop.overValueOrEmpty()) { for (const element of prop.overValueOrEmpty()) {
if (!aasCore.types.isSubmodelElementCollection(element)) continue; if (!aasCore.types.isSubmodelElementCollection(element)) continue;
@@ -82,7 +82,7 @@ export default class AIDParser {
parsed.properties.push(parsedProp); parsed.properties.push(parsedProp);
} }
const actions = Traverser.findElement(interfaceMeta, element => (element as any).idShort.toLocaleLowerCase() === "actions"); const actions = Traverser.findElement(interfaceMeta, element => (element as any).idShort?.toLocaleLowerCase() === "actions");
if (actions === null || !aasCore.types.isSubmodelElementList(actions) || !actions.value) return null; // Mandatory if (actions === null || !aasCore.types.isSubmodelElementList(actions) || !actions.value) return null; // Mandatory
for (const element of actions.overValueOrEmpty()) { for (const element of actions.overValueOrEmpty()) {
if (!aasCore.types.isSubmodelElementCollection(element)) continue; if (!aasCore.types.isSubmodelElementCollection(element)) continue;
@@ -95,32 +95,24 @@ export default class AIDParser {
} }
public static parseInterfaceMetadataProperty(prop: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceProperty | null { public static parseInterfaceMetadataProperty(prop: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceProperty | null {
if (!aasCore.types.isSubmodelElementCollection(prop) || !prop.value || prop.idShort?.toLocaleLowerCase() !== "properties") return null; if (!aasCore.types.isSubmodelElementCollection(prop) || !prop.value) return null;
const parsed = {} as InterfaceProperty; const parsed = {} as InterfaceProperty;
// This does not matter in any way for the interface // This does not matter in any way for the interface
/* for (const key of ["title", "observeable", "type"]) { /* for (const key of ["title", "observeable", "type"]) {
const prop = AASStore.findElement(prop, element => (element as any).idShort.toLocaleLowerCase() === key.toLocaleLowerCase()); const prop = AASStore.findElement(prop, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) continue; // Not mandatory if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) continue; // Not mandatory
else parsed[key] = prop.value; else parsed[key] = prop.value;
} */ } */;
const parsedForms = [] as InterfacePropertyForm[];
const forms = Traverser.findElement(prop, element => (element as any).idShort.toLocaleLowerCase() === "forms");
if (forms === null || !aasCore.types.isSubmodelElementList(forms) || !forms.value) return null; // Mandatory
for (const element of forms.overValueOrEmpty()) {
if (!aasCore.types.isSubmodelElementCollection(element)) continue;
const parsedForm = AIDParser.parseInterfaceMetadataPropertyForm(element, endpointProtocol);
if (parsedForm === null) continue;
parsedForms.push(parsedForm);
}
const forms = Traverser.findElement(prop, element => (element as any).idShort?.toLocaleLowerCase() === "forms");
if (forms === null || !aasCore.types.isSubmodelElementCollection(forms) || !forms.value) return null; // Mandatory
const parsedForm = AIDParser.parseInterfaceMetadataPropertyForm(forms, endpointProtocol);
if (parsedForm === null) return null;
// TODO // TODO
// Other values based on endpoint protocol // Other values based on endpoint protocol
return { ...parsed, forms: parsedForm } as InterfaceProperty;
return { ...parsed, forms: parsedForms } as InterfaceProperty;
} }
private static parseInterfaceMetadataPropertyForm(form: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | null { private static parseInterfaceMetadataPropertyForm(form: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | null {
@@ -129,7 +121,7 @@ export default class AIDParser {
const parsed = {} as any; const parsed = {} as any;
for (const key of ["href", "contentType"]) { for (const key of ["href", "contentType"]) {
const prop = Traverser.findElement(form, element => (element as any).idShort.toLocaleLowerCase() === key.toLocaleLowerCase()); const prop = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) return null; // Mandatory if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) return null; // Mandatory
else parsed[key] = prop.value; else parsed[key] = prop.value;
} }
+14 -6
View File
@@ -1,7 +1,7 @@
import { types } from "@aas-core-works/aas-core3.0-typescript"; import { types } from "@aas-core-works/aas-core3.0-typescript";
import { ConnectionConfiguration, AIMCMap } from "types/aimcConf"; import { ConnectionConfiguration, AIMCMap } from "../types/aimcConf";
import AIMCParser from "./AIMCParser"; import AIMCParser from "./AIMCParser";
import Traverser from "helper/traverser"; import Traverser from "../helper/traverser";
import AIDParser from "./AIDParser"; import AIDParser from "./AIDParser";
import { SubmodelElementCollection } from "@aas-core-works/aas-core3.0-typescript/dist/types/types"; import { SubmodelElementCollection } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
@@ -31,14 +31,22 @@ export default class AIMCMapper {
const resolved = Traverser.resolveRelationship(this.env, ssm); const resolved = Traverser.resolveRelationship(this.env, ssm);
if (resolved === null) continue; if (resolved === null) continue;
const parsedPropConf = AIDParser.parseInterfaceMetadataProperty(resolved.second as SubmodelElementCollection); let {first, second} = resolved;
let parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as SubmodelElementCollection);
if (parsedPropConf === null) {
// maybe the property is in the first element
[first, second] = [second, first];
parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as SubmodelElementCollection);
}
if (parsedPropConf === null) continue; if (parsedPropConf === null) continue;
this.map.set(resolved.first, { this.map.set(second, {
...ep, ...ep,
...parsedPropConf ...parsedPropConf
}); });
} }
console.log(this.map)
} }
} }
@@ -65,8 +73,8 @@ export default class AIMCMapper {
const result = []; const result = [];
for (const [e, cc] of this.map.entries()) { for (const [e, cc] of this.map.entries()) {
const paths = cc.forms.map(f => cc.base + f.href); const formsPath = cc.base + cc.forms.href;
if (paths.includes(path)) result.push(e); if (formsPath === path) result.push(e);
} }
return result; return result;
+13 -13
View File
@@ -1,12 +1,12 @@
import * as aasCore from "@aas-core-works/aas-core3.0-typescript"; import * as aasCore from "@aas-core-works/aas-core3.0-typescript";
import Traverser from "helper/traverser"; import Traverser from "../helper/traverser";
import { AssetInterfacesMappingConfiguration, MappingConfEntry, MappingConfiguration } from "types/aimcConf"; import { AssetInterfacesMappingConfiguration, MappingConfEntry, MappingConfiguration } from "../types/aimcConf";
import { endpointAvailable, ResolvedRelationshipElement } from "types/common"; import { endpointAvailable, ResolvedRelationshipElement } from "../types/common";
export default class AIMCParser { export default class AIMCParser {
public static parse(env: aasCore.types.Environment): AssetInterfacesMappingConfiguration | null { public static parse(env: aasCore.types.Environment): AssetInterfacesMappingConfiguration | null {
const sm = Traverser.findSMByIdShort(env, "AssetInterfaceMappingConfiguration"); const sm = Traverser.findSMByIdShort(env, "AssetInterfacesMappingConfiguration");
if (sm === null || sm.submodelElements === null) return null; if (sm === null || sm.submodelElements === null) return null;
const parsed = {} as AssetInterfacesMappingConfiguration; const parsed = {} as AssetInterfacesMappingConfiguration;
@@ -28,12 +28,12 @@ export default class AIMCParser {
} }
public static parseAIMCEntry(entry: aasCore.types.SubmodelElementCollection, environment: aasCore.types.Environment): MappingConfEntry | null { public static parseAIMCEntry(entry: aasCore.types.SubmodelElementCollection, environment: aasCore.types.Environment): MappingConfEntry | null {
const ep = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "endpointmetadatareference"); const ep = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "endpointmetadatareference");
const mc = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "mappingconfiguration"); const mc = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "mappingconfiguration");
if (ep === null || !aasCore.types.isReference(ep) || !ep.keys || !ep.keys[0] || !mc || !aasCore.types.isSubmodelElementList(mc) || !mc.value) return null; if (ep === null || !aasCore.types.isReferenceElement(ep) || !ep.value || !ep.value.keys || !ep.value.keys[0] || !mc || !aasCore.types.isSubmodelElementList(mc) || !mc.value) return null;
const resolvedEp = Traverser.resolveReference(environment, ep); const resolvedEp = Traverser.resolveReference(environment, ep.value);
if (resolvedEp === null || !aasCore.types.isSubmodelElementCollection(resolvedEp) || resolvedEp.idShort?.toLocaleLowerCase() !== "endpointmetadatareference") return null; if (resolvedEp === null || !aasCore.types.isSubmodelElementCollection(resolvedEp) || resolvedEp.idShort?.toLocaleLowerCase() !== "endpointmetadata") return null;
const parsedMc: (MappingConfiguration|null)[] = [] const parsedMc: (MappingConfiguration|null)[] = []
for (const conf of mc.overValueOrEmpty()) { for (const conf of mc.overValueOrEmpty()) {
@@ -57,13 +57,13 @@ export default class AIMCParser {
SourceSinkMappings: [] SourceSinkMappings: []
} as any; } as any;
const ifMetaRef = Traverser.findElement(conf, element => (element as any).idShort.toLocaleLowerCase() === "interfacemetadatareference"); const ifMetaRef = Traverser.findElement(conf, element => (element as any).idShort?.toLocaleLowerCase() === "interfacemetadatareference");
if (!ifMetaRef || !aasCore.types.isReference(ifMetaRef) || !ifMetaRef.keys) return null; if (!ifMetaRef || !aasCore.types.isReferenceElement(ifMetaRef) || !ifMetaRef.value || !ifMetaRef.value.keys || !ifMetaRef.value.keys[0]) return null;
const ifMeta = Traverser.resolveReference(env, ifMetaRef); const ifMeta = Traverser.resolveReference(env, ifMetaRef.value);
if (!ifMeta || !aasCore.types.isSubmodelElementCollection(ifMeta) || ifMeta.idShort?.toLocaleLowerCase() !== "interfacemetadata") return null; if (!ifMeta || !aasCore.types.isSubmodelElementCollection(ifMeta) || ifMeta.idShort?.toLocaleLowerCase() !== "interfacemetadata") return null;
parsed.InterfaceMetaDataReference = ifMeta; parsed.InterfaceMetaDataReference = ifMeta;
const sourceSinkMappings = Traverser.findElement(conf, element => (element as any).idShort.toLocaleLowerCase() === "sourcesinkmappings"); const sourceSinkMappings = Traverser.findElement(conf, element => (element as any).idShort?.toLocaleLowerCase() === "sourcesinkmappings");
if (!sourceSinkMappings || !aasCore.types.isSubmodelElementList(sourceSinkMappings) || !sourceSinkMappings.value) return null; if (!sourceSinkMappings || !aasCore.types.isSubmodelElementList(sourceSinkMappings) || !sourceSinkMappings.value) return null;
for (const ssm of sourceSinkMappings.overValueOrEmpty()) { for (const ssm of sourceSinkMappings.overValueOrEmpty()) {
+4 -4
View File
@@ -1,13 +1,13 @@
import { types } from "@aas-core-works/aas-core3.0-typescript"; import { types } from "@aas-core-works/aas-core3.0-typescript";
import type { Request, OnRequestCallback } from "types/requests"; import type { Request, OnRequestCallback } from "./types/requests";
export default abstract class AASInterfaceServer<ConfigInterface> { export default abstract class AASInterfaceServer<ConfigInterface> {
public abstract readonly name: string; public static readonly serverInterfaceName: string;
public abstract readonly supportsSubscriptions: boolean; public static readonly supportsSubscriptions: boolean;
constructor( constructor(
protected readonly config: ConfigInterface, protected readonly config: ConfigInterface,
protected readonly aas: types.Environment, protected readonly aas: types.Environment,
protected readonly onRequestCallback: OnRequestCallback) {} protected readonly onRequestCallback: OnRequestCallback) {}
public abstract prepare(): void; public abstract prepare(): void;
+1 -1
View File
@@ -30,7 +30,7 @@ export type InterfaceMetadata = {
export type InterfaceProperty = { export type InterfaceProperty = {
title?: string; title?: string;
observable?: boolean; observable?: boolean;
forms: InterfacePropertyForm[]; forms: InterfacePropertyForm;
type?: string; type?: string;
enum?: string[]; enum?: string[];
const?: any; const?: any;
+1 -1
View File
@@ -30,7 +30,7 @@
"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. */
"paths": { "paths": {
"types/*": ["types/*"] "types/*": ["types/*"],
}, /* Specify a set of entries that re-map imports to additional lookup locations. */ }, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */