Restructured the AID parsing for the (hopefully) better
This commit is contained in:
+225
-38
@@ -1,7 +1,8 @@
|
|||||||
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, InterfaceActionForm, InterfaceFormBase, InterfaceFormBaseHTTP, InterfaceEventForm } 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";
|
||||||
|
import { Property } from "@aas-core-works/aas-core3.0-typescript/dist/types/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for static methods to parse the AssetInterfacesDescription Submodel
|
* Class for static methods to parse the AssetInterfacesDescription Submodel
|
||||||
@@ -118,11 +119,20 @@ export default class AIDParser {
|
|||||||
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;
|
||||||
const parsedAction = AIDParser.parseInterfaceMetadataProperty(element, endpointProtocol);
|
const parsedAction = AIDParser.parseInterfaceMetadataAction(element, endpointProtocol);
|
||||||
if (parsedAction === null) continue;
|
if (parsedAction === null) continue;
|
||||||
parsed.actions.push(parsedAction);
|
parsed.actions.push(parsedAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const events = Traverser.findElement(interfaceMeta, element => (element as any).idShort?.toLocaleLowerCase() === "events");
|
||||||
|
if (events === null || !aasCore.types.isSubmodelElementList(events) || !events.value) return null; // Mandatory
|
||||||
|
for (const element of events.overValueOrEmpty()) {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(element)) continue;
|
||||||
|
const parsedEvent = AIDParser.parseInterfaceMetadataEvent(element, endpointProtocol);
|
||||||
|
if (parsedEvent === null) continue;
|
||||||
|
parsed.events.push(parsedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
return parsed as InterfaceMetadata;
|
return parsed as InterfaceMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,22 +146,101 @@ 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) return null;
|
if (!aasCore.types.isSubmodelElementCollection(prop) || !prop.value) return null;
|
||||||
|
|
||||||
const parsed = {} as InterfaceProperty;
|
const parsed = {} as any;
|
||||||
|
|
||||||
// This does not matter in any way for the interface
|
// This does not really matter but...
|
||||||
/* 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 propProp = Traverser.findElement(prop, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
|
||||||
if (prop === null || !aasCore.types.isProperty(prop) || !prop.value) continue; // Not mandatory
|
if (propProp === null || !aasCore.types.isProperty(propProp) || !propProp.value) continue;
|
||||||
else parsed[key] = prop.value;
|
else parsed[key] = propProp.value;
|
||||||
} */;
|
};
|
||||||
|
|
||||||
|
const parsedForms: InterfacePropertyForm[] = [];
|
||||||
const forms = Traverser.findElement(prop, element => (element as any).idShort?.toLocaleLowerCase() === "forms");
|
const forms = Traverser.findElement(prop, element => (element as any).idShort?.toLocaleLowerCase() === "forms");
|
||||||
if (forms === null || !aasCore.types.isSubmodelElementCollection(forms) || !forms.value) return null; // Mandatory
|
if (forms === null || !aasCore.types.isSubmodelElementList(forms) || !forms.value) return null; // Mandatory
|
||||||
const parsedForm = AIDParser.parseInterfaceMetadataPropertyForm(forms, endpointProtocol);
|
for (const form of forms.overValueOrEmpty()) {
|
||||||
if (parsedForm === null) return null;
|
if (!aasCore.types.isSubmodelElementCollection(form)) continue;
|
||||||
// TODO
|
const parsedForm = AIDParser.parseInterfaceMetadataForm(form, "property", endpointProtocol) as InterfacePropertyForm;
|
||||||
// Other values based on endpoint protocol
|
if (parsedForm === null) continue;
|
||||||
return { ...parsed, forms: parsedForm } as InterfaceProperty;
|
parsedForms.push(parsedForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedForms.length === 0) return null;
|
||||||
|
|
||||||
|
return { ...parsed, forms: parsedForms } as InterfaceProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a single Action InterfaceMetadata
|
||||||
|
* @param prop SubmodelElementCollection of one Action
|
||||||
|
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
||||||
|
* @returns Parsed Action InterfaceMetadata or null if not parsable
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
public static parseInterfaceMetadataAction(action: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceAction | null {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(action) || !action.value) return null;
|
||||||
|
|
||||||
|
const parsed = {} as any;
|
||||||
|
|
||||||
|
// This does not really matter but...
|
||||||
|
for (const key of ["title", "type"]) {
|
||||||
|
const actionProp = Traverser.findElement(action, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
|
||||||
|
if (actionProp === null || !aasCore.types.isProperty(actionProp) || !actionProp.value) continue;
|
||||||
|
else parsed[key] = actionProp.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// But this is really important!
|
||||||
|
const asyncProp = Traverser.findElement(action, element => (element as any).idShort?.toLocaleLowerCase() === "async");
|
||||||
|
if (asyncProp === null || !aasCore.types.isProperty(asyncProp) || !asyncProp.value) {}
|
||||||
|
else parsed["async"] = asyncProp.value === "true";
|
||||||
|
|
||||||
|
const parsedForms: InterfaceActionForm[] = [];
|
||||||
|
const forms = Traverser.findElement(action, element => (element as any).idShort?.toLocaleLowerCase() === "forms");
|
||||||
|
if (forms === null || !aasCore.types.isSubmodelElementList(forms) || !forms.value) return null; // Mandatory
|
||||||
|
for (const form of forms.overValueOrEmpty()) {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(form)) continue;
|
||||||
|
const parsedForm = AIDParser.parseInterfaceMetadataForm(form, "action", endpointProtocol) as InterfaceActionForm;
|
||||||
|
if (parsedForm === null) continue;
|
||||||
|
parsedForms.push(parsedForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedForms.length === 0) return null;
|
||||||
|
|
||||||
|
return { ...parsed, forms: parsedForms } as InterfaceAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a single Event InterfaceMetadata
|
||||||
|
* @param prop SubmodelElementCollection of one Event
|
||||||
|
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
||||||
|
* @returns Parsed Event InterfaceMetadata or null if not parsable
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
public static parseInterfaceMetadataEvent(event: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceEvent | null {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(event) || !event.value) return null;
|
||||||
|
|
||||||
|
const parsed = {} as any;
|
||||||
|
|
||||||
|
// This does not really matter but...
|
||||||
|
for (const key of ["title", "type"]) {
|
||||||
|
const eventProp = Traverser.findElement(event, element => (element as any).idShort?.toLocaleLowerCase() === key.toLocaleLowerCase());
|
||||||
|
if (eventProp === null || !aasCore.types.isProperty(eventProp) || !eventProp.value) continue;
|
||||||
|
else parsed[key] = eventProp.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const parsedForms: InterfaceEventForm[] = [];
|
||||||
|
const forms = Traverser.findElement(event, element => (element as any).idShort?.toLocaleLowerCase() === "forms");
|
||||||
|
if (forms === null || !aasCore.types.isSubmodelElementList(forms) || !forms.value) return null; // Mandatory
|
||||||
|
for (const form of forms.overValueOrEmpty()) {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(form)) continue;
|
||||||
|
const parsedForm = AIDParser.parseInterfaceMetadataForm(form, "event", endpointProtocol) as InterfaceEventForm;
|
||||||
|
if (parsedForm === null) continue;
|
||||||
|
parsedForms.push(parsedForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedForms.length === 0) return null;
|
||||||
|
|
||||||
|
return { ...parsed, forms: parsedForms } as InterfaceEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,44 +249,142 @@ export default class AIDParser {
|
|||||||
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
||||||
* @returns Parsed Form or null if not parsable
|
* @returns Parsed Form or null if not parsable
|
||||||
*/
|
*/
|
||||||
private static parseInterfaceMetadataPropertyForm(form: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | null {
|
private static parseInterfaceMetadataForm(form: aasCore.types.SubmodelElementCollection, element: "property" | "action" | "event", endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm | null {
|
||||||
if (!form.value) return null;
|
if (!form.value) return null;
|
||||||
|
|
||||||
const parsed = {} as any;
|
const parsed = {} as any;
|
||||||
|
|
||||||
for (const key of ["href", "contentType"]) {
|
for (const key of ["href", "contentType", "op"]) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
if (!AIDParser.isValidFormOperation(parsed.op, element, endpointProtocol)) return null;
|
||||||
// Other values based on endpoint protocol
|
|
||||||
|
|
||||||
return parsed as InterfacePropertyForm;
|
switch (element) {
|
||||||
|
case "property": return AIDParser.parseAdditionalFormProperties(form, parsed, endpointProtocol) as InterfacePropertyForm;
|
||||||
|
case "action": return AIDParser.parseAdditionalFormProperties(form, parsed, endpointProtocol) as InterfaceActionForm;
|
||||||
|
case "event": return AIDParser.parseAdditionalFormProperties(form, parsed, endpointProtocol) as InterfaceEventForm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static isValidFormOperation(operation: string, element: "property" | "action" | "event", endpoint?: AvailableEndpoint) {
|
||||||
|
const validOperations: { [key in AvailableEndpoint]: { [key in "property" | "action" | "event"]: string[] } } = {
|
||||||
|
"HTTP": {
|
||||||
|
"property": ["readproperty", "writeproperty"],
|
||||||
|
"action": ["invokeaction"],
|
||||||
|
"event": []
|
||||||
|
},
|
||||||
|
"MQTT": {
|
||||||
|
"property": ["readproperty", "writeproperty", "observeproperty", "unobserveproperty"],
|
||||||
|
"action": ["invokeaction"],
|
||||||
|
"event": ["subscribeevent", "unsubscribeevent"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!endpoint) return true;
|
||||||
|
|
||||||
|
return validOperations[endpoint][element].includes(operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parseAdditionalFormProperties(form: aasCore.types.SubmodelElementCollection, currentlyParsed: any, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | InterfaceActionForm | InterfaceEventForm {
|
||||||
|
switch (endpointProtocol) {
|
||||||
|
case "HTTP": {
|
||||||
|
const method = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "htv:methodname");
|
||||||
|
if (method !== null && aasCore.types.isProperty(method)) {
|
||||||
|
// Next line is kinda long so heres a short explanation:
|
||||||
|
// If method is set and it's a valid HTTP method we take it, else we use the default
|
||||||
|
// setting for read/write
|
||||||
|
const methodName = ["GET", "PUT", "POST", "DELETE", "PATCH"].includes(method.value?.toLocaleUpperCase() ?? "") ? method.value?.toLocaleUpperCase() : AIDParser.getDefaultMethod(currentlyParsed.op) ?? "GET";
|
||||||
|
currentlyParsed["htv:methodName"] = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "htv:headers");
|
||||||
|
if (headers !== null && aasCore.types.isSubmodelElementList(headers)) {
|
||||||
|
const parsedHeaders: { "htv:fieldName": string, "htv:fieldValue": string }[] = [];
|
||||||
|
|
||||||
|
for (const header of headers.overValueOrEmpty()) {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(header) || !header.value) continue;
|
||||||
|
const fieldName = Traverser.findElement(header, element => (element as any).idShort?.toLocaleLowerCase() === "htv:fieldname");
|
||||||
|
const fieldValue = Traverser.findElement(header, element => (element as any).idShort?.toLocaleLowerCase() === "htv:fieldvalue");
|
||||||
|
if (fieldName === null || !aasCore.types.isProperty(fieldName) || !fieldName.value || fieldValue === null || !aasCore.types.isProperty(fieldValue) || !fieldValue.value) continue;
|
||||||
|
parsedHeaders.push({ "htv:fieldName": fieldName.value, "htv:fieldValue": fieldValue.value });
|
||||||
|
}
|
||||||
|
currentlyParsed["htv:headers"] = parsedHeaders;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "MQTT": {
|
||||||
|
const controlPacket = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:controlpacketvalue");
|
||||||
|
if (controlPacket !== null && aasCore.types.isProperty(controlPacket)) {
|
||||||
|
// Next line is kinda long so heres a short explanation:
|
||||||
|
// If controlPacket is set and it's a valid MQTT control packet we take it, else we use the default
|
||||||
|
// setting for read/write
|
||||||
|
const controlPacketValue = ["PUBLISH", "SUBSCRIBE", "UNSUBSCRIBE"].includes(controlPacket.value?.toLocaleUpperCase() ?? "") ? controlPacket.value?.toLocaleUpperCase() : AIDParser.getDefaultMethod(currentlyParsed.op);
|
||||||
|
currentlyParsed["mqv:controlPacketValue"] = controlPacketValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = Traverser.findElement(form, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:options");
|
||||||
|
if (options !== null && aasCore.types.isSubmodelElementList(options)) {
|
||||||
|
const parsedOptions: ({ "mqv:optionName": string, "mqv:optionValue": number | boolean })[] = [];
|
||||||
|
|
||||||
|
for (const option of options.overValueOrEmpty()) {
|
||||||
|
if (!aasCore.types.isSubmodelElementCollection(option) || !option.value) continue;
|
||||||
|
const optionName = Traverser.findElement(option, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:optionname");
|
||||||
|
const optionValue = Traverser.findElement(option, element => (element as any).idShort?.toLocaleLowerCase() === "mqv:optionvalue");
|
||||||
|
if (optionName === null || !aasCore.types.isProperty(optionName) || !optionName.value || optionValue === null || !aasCore.types.isProperty(optionValue) || !optionValue.value) continue;
|
||||||
|
const value = Number.isNaN(Number.parseInt(optionValue.value)) ? optionValue.value === "true" : Number.parseInt(optionValue.value);
|
||||||
|
parsedOptions.push({ "mqv:optionName": optionName.value, "mqv:optionValue": value });
|
||||||
|
}
|
||||||
|
currentlyParsed["mqv:options"] = parsedOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentlyParsed as InterfacePropertyForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a single Action InterfaceMetadata
|
* Get the default protocol method for an operation
|
||||||
* @param prop SubmodelElementCollection of one Action
|
* @param op Operation, e.g. "readproperty"
|
||||||
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
* @param endpoint
|
||||||
* @returns Parsed Action InterfaceMetadata or null if not parsable
|
* @returns
|
||||||
* @alpha
|
|
||||||
*/
|
*/
|
||||||
public static parseInterfaceMetadataAction(action: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceAction | null {
|
private static getDefaultMethod(op: string, endpoint?: AvailableEndpoint): string | undefined {
|
||||||
// TODO
|
const defaults: any = {
|
||||||
return null;
|
"readproperty": {
|
||||||
|
"HTTP": "GET",
|
||||||
|
"MQTT": "SUBSCRIBE"
|
||||||
|
},
|
||||||
|
"writeproperty": {
|
||||||
|
"HTTP": "PUT",
|
||||||
|
"MQTT": "PUBLISH"
|
||||||
|
},
|
||||||
|
"observeproperty": {
|
||||||
|
"MQTT": "SUBSCRIBE"
|
||||||
|
},
|
||||||
|
"unobserveproperty": {
|
||||||
|
"MQTT": "UNSUBSCRIBE"
|
||||||
|
},
|
||||||
|
"invokeaction": {
|
||||||
|
"HTTP": "POST",
|
||||||
|
"MQTT": "PUBLISH"
|
||||||
|
},
|
||||||
|
"subscribeevent": {
|
||||||
|
"MQTT": "SUBSCRIBE"
|
||||||
|
},
|
||||||
|
"unsubscribeevent": {
|
||||||
|
"MQTT": "UNSUBSCRIBE"
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
op = op.toLocaleLowerCase();
|
||||||
* Parse a single Event InterfaceMetadata
|
|
||||||
* @param prop SubmodelElementCollection of one Event
|
return defaults[op] === undefined ? defaults[op][endpoint ?? ""] ?? null : null;
|
||||||
* @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed
|
|
||||||
* @returns Parsed Event InterfaceMetadata or null if not parsable
|
|
||||||
* @alpha
|
|
||||||
*/
|
|
||||||
public static parseInterfaceMetadataEvent(event: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceEvent | null {
|
|
||||||
// TODO
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+85
-82
@@ -48,11 +48,83 @@ It should be pretty easy to extend this.
|
|||||||
So let's derive some of this from the WoT and see what we can achieve.
|
So let's derive some of this from the WoT and see what we can achieve.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type FormOp = "readproperty" |
|
||||||
|
"writeproperty" |
|
||||||
|
"observeproperty" |
|
||||||
|
"unobserveproperty" |
|
||||||
|
"invokeaction" |
|
||||||
|
"subscribeevent" |
|
||||||
|
"unsubscribeevent";
|
||||||
|
// The following are defined in WoT but not useful in our case
|
||||||
|
//"readallproperties" |
|
||||||
|
//"writeallproperties" |
|
||||||
|
//"readmultipleproperties" |
|
||||||
|
//"writemultipleproperties";
|
||||||
|
|
||||||
|
type FormOpHTTPProp = "readproperty" | "writeproperty";
|
||||||
|
type FormOpHTTPAction = "invokeaction";
|
||||||
|
|
||||||
|
type FormOpMQTTProp = "readproperty" | "writeproperty" | "observeproperty" | "unobserveproperty";
|
||||||
|
type FormOpMQTTAction = "invokeaction";
|
||||||
|
type FormOpMQTTEvent = "subscribeevent" | "unsubscribeevent";
|
||||||
|
|
||||||
|
export type InterfaceFormBase = {
|
||||||
|
href: string;
|
||||||
|
op: FormOp;
|
||||||
|
contentType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InterfaceFormBaseHTTP = InterfaceFormBase & {
|
||||||
|
"htv:methodName": "GET" | "PUT" | "POST" | "DELETE" | "PATCH";
|
||||||
|
"htv:headers": {
|
||||||
|
"htv:fieldName": string;
|
||||||
|
"htv:fieldValue": string;
|
||||||
|
}[];
|
||||||
|
op: FormOpHTTPProp | FormOpHTTPAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFormHTTPProp = InterfaceFormBaseHTTP & {
|
||||||
|
op: FormOpHTTPProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFormHTTPAction = InterfaceFormBaseHTTP & {
|
||||||
|
op: FormOpHTTPAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type InterfaceFormBaseMQTT = InterfaceFormBase & {
|
||||||
|
"mqv:controlPacketValue": "PUBLISH" | "SUBSCRIBE" | "UNSUBSCRIBE";
|
||||||
|
"mqv:options": ({
|
||||||
|
"mqv:optionName": "qos";
|
||||||
|
"mqv:optionValue": 0 | 1 | 2;
|
||||||
|
} | {
|
||||||
|
"mqv:optionName": "retain" | "dup";
|
||||||
|
"mqv:optionValue": boolean;
|
||||||
|
})[];
|
||||||
|
op: FormOpMQTTProp | FormOpMQTTAction | FormOpMQTTEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFormMQTTProp = InterfaceFormBaseMQTT & {
|
||||||
|
op: FormOpMQTTProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFormMQTTAction = InterfaceFormBaseMQTT & {
|
||||||
|
op: FormOpMQTTAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFormMQTTEvent = InterfaceFormBaseMQTT & {
|
||||||
|
op: FormOpMQTTEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InterfacePropertyForm = IFormHTTPProp | IFormMQTTProp;
|
||||||
|
export type InterfaceActionForm = IFormHTTPAction | IFormMQTTAction;
|
||||||
|
export type InterfaceEventForm = IFormMQTTEvent;
|
||||||
|
|
||||||
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;
|
||||||
default?: any;
|
default?: any;
|
||||||
@@ -66,95 +138,26 @@ export type InterfaceProperty = {
|
|||||||
// maxItems?: number;
|
// maxItems?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type FormOp = "readproperty" |
|
/** @beta */
|
||||||
"writeproperty" |
|
export type InterfaceAction = InterfaceActionSync | InterfaceActionAsync;
|
||||||
"observeproperty" |
|
|
||||||
"unobserveproperty" |
|
|
||||||
"invokeaction" |
|
|
||||||
"subscribeevent" |
|
|
||||||
"unsubscribeevent" |
|
|
||||||
"readallproperties" |
|
|
||||||
"writeallproperties" |
|
|
||||||
"readmultipleproperties" |
|
|
||||||
"writemultipleproperties";
|
|
||||||
|
|
||||||
type FormOpHTTP = "readproperty" |
|
|
||||||
"writeproperty" |
|
|
||||||
"invokeaction" |
|
|
||||||
"readallproperties" |
|
|
||||||
"writeallproperties" |
|
|
||||||
"readmultipleproperties" |
|
|
||||||
"writemultipleproperties";
|
|
||||||
|
|
||||||
type IForm = {
|
|
||||||
href: string;
|
|
||||||
op: FormOp;
|
|
||||||
contentType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type IFormHTTP = IForm & {
|
|
||||||
"htv:methodName": "GET" | "PUT" | "POST" | "DELETE" | "PATCH";
|
|
||||||
"htv:headers": {
|
|
||||||
"htv:fieldName": string;
|
|
||||||
"htv:fieldValue": string;
|
|
||||||
}[];
|
|
||||||
op: FormOpHTTP;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InterfacePropertyForm = InterfacePropertyFormHTTP | InterfacePropertyFormMQTT | InterfacePropertyFormModbus;
|
|
||||||
|
|
||||||
type InterfacePropertyFormBase = {
|
|
||||||
href: string;
|
|
||||||
contentType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type InterfacePropertyFormHTTP = InterfacePropertyFormBase & {
|
|
||||||
methodName: string;
|
|
||||||
headers?: Record<string, string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
type InterfacePropertyFormModbus = InterfacePropertyFormBase & {
|
|
||||||
function: "readCoil" |
|
|
||||||
"readDeviceIdentification" |
|
|
||||||
"readDiscreteInput" |
|
|
||||||
"readHoldingRegisters" |
|
|
||||||
"readInputRegisters" |
|
|
||||||
"writeMultipleCoils" |
|
|
||||||
"writeMultipleHoldingRegisters" |
|
|
||||||
"writeSingleCoil" |
|
|
||||||
"writeSingleHoldingRegister";
|
|
||||||
entity?: "Coil" | "DiscreteInput" | "HoldingRegister" | "InputRegister";
|
|
||||||
zeroBasedAddressing?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
type InterfacePropertyFormMQTT = InterfacePropertyFormBase & {
|
|
||||||
retain?: boolean;
|
|
||||||
controlPacket: "publish" | "subscribe" | "unsubscribe";
|
|
||||||
qos?: 0 | 1 | 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @alpha */
|
|
||||||
export type InterfaceAction = {
|
|
||||||
title: string;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type InterfaceActionBase = {
|
type InterfaceActionBase = {
|
||||||
title: string;
|
title?: string;
|
||||||
type: string;
|
type: string;
|
||||||
const?: boolean;
|
forms: InterfaceActionForm[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type InterfaceActionSync = {
|
type InterfaceActionSync = InterfaceActionBase & {
|
||||||
|
async: false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InterfaceActionAsync = {
|
type InterfaceActionAsync = {
|
||||||
|
async: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @alpha */
|
/** @beta */
|
||||||
export type InterfaceEvent = {
|
export type InterfaceEvent = {
|
||||||
// TODO
|
title?: string;
|
||||||
|
type: string;
|
||||||
|
forms: InterfaceEventForm[];
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { types } from "@aas-core-works/aas-core3.0-typescript";
|
import type { types } from "@aas-core-works/aas-core3.0-typescript";
|
||||||
|
|
||||||
export const availableEndpoints = ["HTTP", "MQTT", "Modbus"] as const;
|
export const availableEndpoints = ["HTTP", "MQTT"] as const;
|
||||||
export type AvailableEndpoint = typeof availableEndpoints[number];
|
export type AvailableEndpoint = typeof availableEndpoints[number];
|
||||||
|
|
||||||
export function endpointAvailable(endpoint: string): AvailableEndpoint | null {
|
export function endpointAvailable(endpoint: string): AvailableEndpoint | null {
|
||||||
|
|||||||
Reference in New Issue
Block a user