import * as aasCore from "@aas-core-works/aas-core3.0-typescript"; import type { AssetInterfaceDescription, EndpointMetadata, InterfaceDescription, InterfaceMetadata, InterfaceAction, InterfaceEvent, InterfaceProperty, InterfacePropertyForm } from "types/aidConf"; import { AvailableEndpoint, endpointAvailable } from "../types/common"; import Traverser from "../helper/traverser"; export default class AIDParser { public static parse(env: aasCore.types.Environment): AssetInterfaceDescription | null { const sm = Traverser.findSMByIdShort(env, "AssetInterfaceDescription"); if (sm === null || sm.submodelElements === null) return null; const parsed = {} as AssetInterfaceDescription; sm.submodelElements.forEach(e => { if (!aasCore.types.isSubmodelElementList(e) || !e.idShort || !e.value) return; const endpointProto = endpointAvailable(e.idShort); if (!endpointProto) return; parsed[endpointProto] = e.value.map(element => { if (!aasCore.types.isSubmodelElementCollection(element)) return null; return AIDParser.parseAIDEntry(element, endpointProto); }).filter(e => e !== null) as InterfaceDescription[]; }); return parsed; } private static parseAIDEntry(entry: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceDescription | null { 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 ep = Traverser.findElement(entry, element => (element as any).idShort.toLocaleLowerCase() === "endpointmetadata"); 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; const parsedEp = AIDParser.parseEndpointMetaData(ep, endpointProtocol); const parsedIm = AIDParser.parseInterfaceMetaData(im, endpointProtocol); if (parsedEp === null || parsedIm === null) return null; return { title: titleString, EndPointMetadata: parsedEp, InterfaceMetadata: parsedIm } as InterfaceDescription; } public static parseEndpointMetaData(endpoint: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): EndpointMetadata | null { if (!endpoint.value || endpoint.idShort?.toLocaleLowerCase() !== "endpointmetadata") return null; const parsed = {} as EndpointMetadata; for (const key of ["base", "contentType"]) { 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 else parsed[key] = prop.value; } // TODO // Other values based on endpoint protocol return parsed; } public static parseInterfaceMetaData(interfaceMeta: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceMetadata | null { if (!interfaceMeta.value || interfaceMeta.idShort?.toLocaleLowerCase() !== "interfacemetadata") return null; const parsed = { properties: [], actions: [], events: [] } as InterfaceMetadata; const prop = Traverser.findElement(interfaceMeta, element => (element as any).idShort.toLocaleLowerCase() === "properties"); if (prop === null || !aasCore.types.isSubmodelElementList(prop) || !prop.value) return null; // Mandatory for (const element of prop.value) { if (!aasCore.types.isSubmodelElementCollection(element)) continue; const parsedProp = AIDParser.parseInterfaceMetadataProperty(element, endpointProtocol); if (parsedProp === null) continue; parsed.properties.push(parsedProp); } const actions = Traverser.findElement(interfaceMeta, element => (element as any).idShort.toLocaleLowerCase() === "actions"); if (actions === null || !aasCore.types.isSubmodelElementList(actions) || !actions.value) return null; // Mandatory for (const element of actions.value) { if (!aasCore.types.isSubmodelElementCollection(element)) continue; const parsedAction = AIDParser.parseInterfaceMetadataProperty(element, endpointProtocol); if (parsedAction === null) continue; parsed.actions.push(parsedAction); } return parsed as InterfaceMetadata; } public static parseInterfaceMetadataProperty(prop: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceProperty | null { if (!prop.value || prop.idShort?.toLocaleLowerCase() !== "properties") return null; const parsed = {} as InterfaceProperty; // This does not matter in any way for the interface /* for (const key of ["title", "observeable", "type"]) { 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 else parsed[key] = prop.value; } */ 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.value) { if (!aasCore.types.isSubmodelElementCollection(element)) continue; const parsedForm = AIDParser.parseInterfaceMetadataPropertyForm(element, endpointProtocol); if (parsedForm === null) continue; parsed.forms.push(parsedForm); } // TODO // Other values based on endpoint protocol return parsed; } private static parseInterfaceMetadataPropertyForm(form: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | null { if (!form.value) return null; const parsed = {} as any; for (const key of ["href", "contentType"]) { 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 else parsed[key] = prop.value; } // TODO // Other values based on endpoint protocol return parsed as InterfacePropertyForm; } public static parseInterfaceMetadataAction(action: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceAction | null { // TODO return null; } public static parseInterfaceMetadataEvent(event: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceAction | null { // TODO return null; } }