Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@node-wot/td-tools

Package Overview
Dependencies
Maintainers
4
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@node-wot/td-tools - npm Package Compare versions

Comparing version 0.8.7 to 0.8.8

15

dist/util/asset-interface-description.d.ts
export declare class AssetInterfaceDescriptionUtil {
transformToTD(aid: string, template?: string, submodelRegex?: string): string;
transformAAS2TD(aas: string, template?: string, submodelRegex?: string): string;
transformSM2TD(aid: string, template?: string, submodelRegex?: string): string;
transformTD2AAS(td: string, protocols?: string[]): string;
transformTD2SM(tdAsString: string, protocols?: string[]): string;
private getProtocolPrefixes;
private updateProtocolPrefixes;
private getBaseFromEndpointMetadata;
private getContentTypeFromEndpointMetadata;
private getSecuritySchemesFromEndpointMetadata;
private getSecurityDefinitionsFromEndpointMetadata;
private getSecurityFromEndpointMetadata;
private createInteractionForm;

@@ -10,5 +18,4 @@ private processSubmodel;

private _transform;
transformToTD(aid: string, template?: string, submodelRegex?: string): string;
transformAAS2TD(aas: string, template?: string, submodelRegex?: string): string;
transformSM2TD(aid: string, template?: string, submodelRegex?: string): string;
private createEndpointMetadata;
private createInterfaceMetadata;
}
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -7,2 +30,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

exports.AssetInterfaceDescriptionUtil = void 0;
const TDParser = __importStar(require("../td-parser"));
const debug_1 = __importDefault(require("debug"));

@@ -12,5 +36,134 @@ const namespace = "node-wot:td-tools:asset-interface-description-util";

const logInfo = (0, debug_1.default)(`${namespace}:info`);
const noSecSS = { scheme: "nosec" };
const noSecName = 0 + "_sc";
const logError = (0, debug_1.default)(`${namespace}:error`);
class AssetInterfaceDescriptionUtil {
transformToTD(aid, template, submodelRegex) {
return this.transformAAS2TD(aid, template, submodelRegex);
}
transformAAS2TD(aas, template, submodelRegex) {
const smInformation = this.getSubmodelInformation(aas, submodelRegex);
return this._transform(smInformation, template);
}
transformSM2TD(aid, template, submodelRegex) {
const submodel = JSON.parse(aid);
const smInformation = {
actions: new Map(),
events: new Map(),
properties: new Map(),
endpointMetadataArray: [],
thing: new Map(),
};
this.processSubmodel(smInformation, submodel, submodelRegex);
return this._transform(smInformation, template);
}
transformTD2AAS(td, protocols) {
const submodel = this.transformTD2SM(td, protocols);
const submodelObj = JSON.parse(submodel);
const submodelId = submodelObj.id;
const aasName = "SampleAAS";
const aasId = "https://example.com/ids/aas/7474_9002_6022_1115";
const aas = {
assetAdministrationShells: [
{
idShort: aasName,
id: aasId,
assetInformation: {
assetKind: "Type",
},
submodels: [
{
type: "ModelReference",
keys: [
{
type: "Submodel",
value: submodelId,
},
],
},
],
modelType: "AssetAdministrationShell",
},
],
submodels: [submodelObj],
conceptDescriptions: [],
};
return JSON.stringify(aas);
}
transformTD2SM(tdAsString, protocols) {
const td = TDParser.parseTD(tdAsString);
const aidID = td.id ? td.id : "ID" + Math.random();
logInfo("TD " + td.title + " parsed...");
if (protocols === undefined || protocols.length === 0) {
protocols = this.getProtocolPrefixes(td);
}
const submdelElements = [];
for (const protocol of protocols) {
const submodelElementIdShort = protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase();
const submdelElement = {
idShort: submodelElementIdShort,
value: [
{
idShort: "title",
valueType: "xs:string",
value: td.title,
modelType: "Property",
},
this.createEndpointMetadata(td),
this.createInterfaceMetadata(td, protocol),
],
modelType: "SubmodelElementCollection",
};
submdelElements.push(submdelElement);
}
const aidObject = {
idShort: "AssetInterfacesDescription",
id: aidID,
kind: "Instance",
description: [
{
language: "en",
text: td.title,
},
],
submodelElements: submdelElements,
modelType: "Submodel",
};
return JSON.stringify(aidObject);
}
getProtocolPrefixes(td) {
const protocols = [];
if (td.properties) {
for (const propertyKey in td.properties) {
const property = td.properties[propertyKey];
this.updateProtocolPrefixes(property.forms, protocols);
}
}
if (td.actions) {
for (const actionKey in td.actions) {
const action = td.actions[actionKey];
this.updateProtocolPrefixes(action.forms, protocols);
}
}
if (td.events) {
for (const eventKey in td.events) {
const event = td.events[eventKey];
this.updateProtocolPrefixes(event.forms, protocols);
}
}
return protocols;
}
updateProtocolPrefixes(forms, protocols) {
if (forms) {
for (const interactionForm of forms) {
if (interactionForm.href) {
const positionColon = interactionForm.href.indexOf(":");
if (positionColon > 0) {
const prefix = interactionForm.href.substring(0, positionColon);
if (!protocols.includes(prefix)) {
protocols.push(prefix);
}
}
}
}
}
}
getBaseFromEndpointMetadata(endpointMetadata) {

@@ -36,15 +189,18 @@ if ((endpointMetadata === null || endpointMetadata === void 0 ? void 0 : endpointMetadata.value) && endpointMetadata.value instanceof Array) {

}
getSecuritySchemesFromEndpointMetadata(endpointMetadata) {
getSecurityDefinitionsFromEndpointMetadata(endpointMetadata) {
const securityDefinitions = {};
if ((endpointMetadata === null || endpointMetadata === void 0 ? void 0 : endpointMetadata.value) && endpointMetadata.value instanceof Array) {
for (const v of endpointMetadata.value) {
if (v.idShort === "securityDefinitions") {
const securitySchemes = [];
if (v.value && v.value instanceof Array) {
for (const secValue of v.value) {
const ss = { scheme: secValue.idShort };
securitySchemes.push(ss);
if (secValue.value && secValue.value instanceof Array) {
for (const v of secValue.value) {
if (v.idShort && typeof v.idShort === "string" && v.idShort.length > 0 && v.value) {
ss[v.idShort] = v.value;
for (const securityDefinitionsValues of v.value) {
if (securityDefinitionsValues.idShort) {
if (securityDefinitionsValues.value instanceof Array) {
for (const securityDefinitionsValue of securityDefinitionsValues.value) {
if (securityDefinitionsValue.idShort === "scheme") {
if (securityDefinitionsValue.value) {
const ss = { scheme: securityDefinitionsValue.value };
securityDefinitions[securityDefinitionsValues.idShort] = ss;
}
}
}

@@ -55,8 +211,24 @@ }

}
return securitySchemes;
}
}
}
return undefined;
return securityDefinitions;
}
getSecurityFromEndpointMetadata(endpointMetadata) {
const security = [];
if ((endpointMetadata === null || endpointMetadata === void 0 ? void 0 : endpointMetadata.value) && endpointMetadata.value instanceof Array) {
for (const v of endpointMetadata.value) {
if (v.idShort === "security") {
if (v.value && v.value instanceof Array) {
for (const securityValue of v.value) {
if (securityValue.value) {
security.push(securityValue.value);
}
}
}
}
}
}
return security;
}
createInteractionForm(vi, addSecurity) {

@@ -68,53 +240,51 @@ const form = {

if (addSecurity) {
const securitySchemes = this.getSecuritySchemesFromEndpointMetadata(vi.endpointMetadata);
if (securitySchemes === undefined) {
form.security = [noSecName];
}
else {
if (vi.secNamesForEndpoint) {
form.security = vi.secNamesForEndpoint;
}
}
logError("security at form level not added/present");
}
if (vi.interaction.value instanceof Array) {
for (const v of vi.interaction.value) {
if (v.idShort === "href") {
if (form.href && form.href.length > 0) {
form.href = form.href + v.value;
}
else {
form.href = v.value;
}
}
else if (typeof v.idShort === "string" && v.idShort.length > 0) {
if (v.value) {
form[v.idShort] = v.value;
if (v.valueType &&
v.valueType &&
v.valueType.dataObjectType &&
v.valueType.dataObjectType.name &&
typeof v.valueType.dataObjectType.name === "string") {
switch (v.valueType.dataObjectType.name) {
case "boolean":
form[v.idShort] = form[v.idShort] === "true";
break;
case "float":
case "double":
case "decimal":
case "integer":
case "nonPositiveInteger":
case "negativeInteger":
case "long":
case "int":
case "short":
case "byte":
case "nonNegativeInteger":
case "unsignedLong":
case "unsignedInt":
case "unsignedShort":
case "unsignedByte":
case "positiveInteger":
form[v.idShort] = Number(form[v.idShort]);
break;
for (const iv of vi.interaction.value) {
if (iv.idShort === "forms") {
if (iv.value instanceof Array) {
for (const v of iv.value) {
if (v.idShort === "href") {
if (form.href && form.href.length > 0) {
form.href = form.href + v.value;
}
else {
form.href = v.value;
}
}
else if (typeof v.idShort === "string" && v.idShort.length > 0) {
if (v.value) {
form[v.idShort] = v.value;
if (v.valueType &&
v.valueType &&
v.valueType.dataObjectType &&
v.valueType.dataObjectType.name &&
typeof v.valueType.dataObjectType.name === "string") {
switch (v.valueType.dataObjectType.name) {
case "boolean":
form[v.idShort] = form[v.idShort] === "true";
break;
case "float":
case "double":
case "decimal":
case "integer":
case "nonPositiveInteger":
case "negativeInteger":
case "long":
case "int":
case "short":
case "byte":
case "nonNegativeInteger":
case "unsignedLong":
case "unsignedInt":
case "unsignedShort":
case "unsignedByte":
case "positiveInteger":
form[v.idShort] = Number(form[v.idShort]);
break;
}
}
}
}
}

@@ -128,3 +298,3 @@ }

processSubmodel(smInformation, submodel, submodelRegex) {
if (submodel instanceof Object && submodel.idShort && submodel.idShort === "AssetInterfaceDescription") {
if (submodel instanceof Object && submodel.idShort && submodel.idShort === "AssetInterfacesDescription") {
if (submodel.submodelElements && submodel.submodelElements instanceof Array) {

@@ -158,2 +328,9 @@ for (const submodelElement of submodel.submodelElements) {

}
else if (smValue.idShort === "InterfaceMetadata") {
}
else if (smValue.idShort === "externalDescriptor") {
}
else {
smInformation.thing.set(smValue.idShort, smValue.value);
}
}

@@ -226,2 +403,3 @@ }

endpointMetadataArray: [],
thing: new Map(),
};

@@ -239,2 +417,9 @@ if (aidModel instanceof Object && aidModel.submodels) {

const thing = template ? JSON.parse(template) : {};
for (const [key, value] of smInformation.thing) {
if (typeof value === "string") {
thing[key] = value;
}
else {
}
}
if (!thing["@context"]) {

@@ -249,37 +434,16 @@ thing["@context"] = "https://www.w3.org/2022/wot/td/v1.1";

}
let cnt = 1;
const secSchemeNamesAll = new Array();
const secNamesForEndpointMetadata = new Map();
for (const endpointMetadata of smInformation.endpointMetadataArray) {
const secNames = [];
const securitySchemes = this.getSecuritySchemesFromEndpointMetadata(endpointMetadata);
if (securitySchemes === undefined) {
thing.securityDefinitions[noSecName] = noSecSS;
secSchemeNamesAll.push(noSecName);
secNames.push(noSecName);
thing.securityDefinitions = this.getSecurityDefinitionsFromEndpointMetadata(endpointMetadata);
thing.security = this.getSecurityFromEndpointMetadata(endpointMetadata);
for (const [key, value] of Object.entries(thing.securityDefinitions)) {
secNames.push(key);
}
else {
for (const secScheme of securitySchemes) {
const secName = cnt + "_sc";
thing.securityDefinitions[secName] = secScheme;
secSchemeNamesAll.push(secName);
secNames.push(secName);
cnt++;
}
}
secNamesForEndpointMetadata.set(endpointMetadata, secNames);
}
if (secSchemeNamesAll.length === 0) {
thing.securityDefinitions.nosec_sc = noSecSS;
thing.security = [noSecName];
}
else {
thing.security = secSchemeNamesAll;
}
logDebug("########### PROPERTIES (" + smInformation.properties.size + ")");
if (smInformation.properties.size > 0) {
thing.properties = {};
for (const entry of smInformation.properties.entries()) {
const key = entry[0];
const value = entry[1];
for (const [key, value] of smInformation.properties.entries()) {
logInfo("Property" + key + " = " + value);

@@ -289,12 +453,53 @@ thing.properties[key] = {};

for (const vi of value) {
if (vi.interaction.constraints && vi.interaction.constraints instanceof Array) {
for (const constraint of vi.interaction.constraints)
if (constraint.type === "valueType") {
if (constraint.value === "float") {
thing.properties[key].type = "number";
for (const keyInteraction in vi.interaction) {
if (keyInteraction === "description") {
const aasDescription = vi.interaction[keyInteraction];
const tdDescription = {};
if (aasDescription instanceof Array) {
for (const aasDescriptionEntry of aasDescription) {
if (aasDescriptionEntry.language && aasDescriptionEntry.text) {
const language = aasDescriptionEntry.language;
const text = aasDescriptionEntry.text;
tdDescription[language] = text;
}
}
else {
thing.properties[key].type = constraint.value;
}
}
thing.properties[key].descriptions = tdDescription;
}
else if (keyInteraction === "value") {
if (vi.interaction.value instanceof Array) {
for (const interactionValue of vi.interaction.value)
if (interactionValue.idShort === "type") {
if (interactionValue.value === "float") {
thing.properties[key].type = "number";
}
else {
thing.properties[key].type = interactionValue.value;
}
}
else if (interactionValue.idShort === "range") {
if (interactionValue.min) {
thing.properties[key].min = interactionValue.min;
}
if (interactionValue.max) {
thing.properties[key].max = interactionValue.max;
}
}
else if (interactionValue.idShort === "observable") {
thing.properties[key].observable = interactionValue.value === "true";
}
else if (interactionValue.idShort === "readOnly") {
thing.properties[key].readOnly = interactionValue.value === "true";
}
else if (interactionValue.idShort === "writeOnly") {
thing.properties[key].writeOnly = interactionValue.value === "true";
}
else if (interactionValue.idShort === "forms") {
}
else {
const key2 = interactionValue.idShort;
thing.properties[key][key2] = interactionValue.value;
}
}
}
}

@@ -312,5 +517,3 @@ if (vi.endpointMetadata) {

thing.actions = {};
for (const entry of smInformation.actions.entries()) {
const key = entry[0];
const value = entry[1];
for (const [key, value] of smInformation.actions.entries()) {
logInfo("Action" + key + " = " + value);

@@ -331,5 +534,3 @@ thing.actions[key] = {};

thing.events = {};
for (const entry of smInformation.events.entries()) {
const key = entry[0];
const value = entry[1];
for (const [key, value] of smInformation.events.entries()) {
logInfo("Event " + key + " = " + value);

@@ -349,19 +550,173 @@ thing.events[key] = {};

}
transformToTD(aid, template, submodelRegex) {
return this.transformAAS2TD(aid, submodelRegex);
createEndpointMetadata(td) {
const values = [];
if (td.base) {
values.push({
idShort: "base",
valueType: "xs:anyURI",
value: td.base,
modelType: "Property",
});
}
const securityValues = [];
if (td.security) {
for (const secKey of td.security) {
securityValues.push({
valueType: "xs:string",
value: secKey,
modelType: "Property",
});
}
}
values.push({
idShort: "security",
value: securityValues,
modelType: "SubmodelElementCollection",
});
const securityDefinitionsValues = [];
for (const secKey in td.securityDefinitions) {
const secValue = td.securityDefinitions[secKey];
securityDefinitionsValues.push({
idShort: secKey,
value: [
{
idShort: "scheme",
valueType: "xs:string",
value: secValue.scheme,
modelType: "Property",
},
],
modelType: "SubmodelElementCollection",
});
}
values.push({
idShort: "securityDefinitions",
value: securityDefinitionsValues,
modelType: "SubmodelElementCollection",
});
const endpointMetadata = {
idShort: "EndpointMetadata",
value: values,
modelType: "SubmodelElementCollection",
};
return endpointMetadata;
}
transformAAS2TD(aas, template, submodelRegex) {
const smInformation = this.getSubmodelInformation(aas, submodelRegex);
return this._transform(smInformation, template);
}
transformSM2TD(aid, template, submodelRegex) {
const submodel = JSON.parse(aid);
const smInformation = {
actions: new Map(),
events: new Map(),
properties: new Map(),
endpointMetadataArray: [],
createInterfaceMetadata(td, protocol) {
var _a;
const properties = [];
const actions = [];
const events = [];
if (protocol) {
if (td.properties) {
for (const propertyKey in td.properties) {
const propertyValue = td.properties[propertyKey];
let formElementPicked;
if (propertyValue.forms) {
for (const formElementProperty of propertyValue.forms) {
if ((_a = formElementProperty.href) === null || _a === void 0 ? void 0 : _a.startsWith(protocol)) {
formElementPicked = formElementProperty;
break;
}
}
}
if (formElementPicked === undefined) {
continue;
}
const propertyValues = [];
if (propertyValue.type) {
propertyValues.push({
idShort: "type",
valueType: "xs:string",
value: propertyValue.type,
modelType: "Property",
});
}
if (propertyValue.title) {
propertyValues.push({
idShort: "title",
valueType: "xs:string",
value: propertyValue.title,
modelType: "Property",
});
}
if (propertyValue.observable) {
propertyValues.push({
idShort: "observable",
valueType: "xs:boolean",
value: `${propertyValue.observable}`,
modelType: "Property",
});
}
if (formElementPicked) {
const propertyForm = [];
for (const formTerm in formElementPicked) {
const formValue = formElementPicked[formTerm];
if (typeof formValue === "string") {
propertyForm.push({
idShort: formTerm,
valueType: "xs:string",
value: formValue,
modelType: "Property",
});
}
}
propertyValues.push({
idShort: "forms",
value: propertyForm,
modelType: "SubmodelElementCollection",
});
}
let description;
if (propertyValue.descriptions) {
description = [];
for (const langKey in propertyValue.descriptions) {
const langValue = propertyValue.descriptions[langKey];
description.push({
language: langKey,
text: langValue,
});
}
}
else if (propertyValue.description) {
description = [];
description.push({
language: "en",
text: propertyValue.description,
});
}
properties.push({
idShort: propertyKey,
description: description,
value: propertyValues,
modelType: "SubmodelElementCollection",
});
}
}
if (td.actions) {
}
if (td.events) {
}
}
const values = [];
values.push({
idShort: "Properties",
value: properties,
modelType: "SubmodelElementCollection",
});
values.push({
idShort: "Actions",
value: actions,
modelType: "SubmodelElementCollection",
});
values.push({
idShort: "Events",
value: events,
modelType: "SubmodelElementCollection",
});
const interfaceMetadata = {
idShort: "InterfaceMetadata",
value: values,
modelType: "SubmodelElementCollection",
};
this.processSubmodel(smInformation, submodel, submodelRegex);
return this._transform(smInformation, template);
return interfaceMetadata;
}

@@ -368,0 +723,0 @@ }

{
"name": "@node-wot/td-tools",
"version": "0.8.7",
"version": "0.8.8",
"description": "W3C Web of Things (WoT) Thing Description parser, serializer, and other tools",

@@ -5,0 +5,0 @@ "author": "Eclipse Thingweb <thingweb-dev@eclipse.org> (https://thingweb.io/)",

# TD (Thing Description) tools of node-wot
Current Maintainer(s): [@danielpeintner](https://github.com/danielpeintner) [@relu91](https://github.com/relu91)
## Getting Started

@@ -4,0 +6,0 @@

@@ -19,42 +19,219 @@ /********************************************************************************

import { SecurityScheme } from "wot-thing-description-types";
import * as TDParser from "../td-parser";
import debug from "debug";
import { ThingDescription } from "wot-typescript-definitions";
import { FormElementBase, PropertyElement } from "wot-thing-model-types";
const namespace = "node-wot:td-tools:asset-interface-description-util";
const logDebug = debug(`${namespace}:debug`);
const logInfo = debug(`${namespace}:info`);
const logError = debug(`${namespace}:error`);
/** Utilities around Asset Interface Description
/**
* Utilities around Asset Interface Description
* https://github.com/admin-shell-io/submodel-templates/tree/main/development/Asset%20Interface%20Description/1/0
*
* e.g, transform to TD
* e.g, transform AAS (or AID submodel) to TD or vicerversa transform TD to AAS (or AID submodel)
*
*/
/*
* TODOs
* - what is the desired input/output? string, object, ... ?
* - what are options that would be desired? (context version, id, security, ...) -> template mechanism fine?
* - Fields like @context, id, .. etc representable in AID?
* - More test-data for action & events, data input and output, ...
*
*/
export class AssetInterfaceDescriptionUtil {
/** @deprecated use transformAAS2TD method instead */
public transformToTD(aid: string, template?: string, submodelRegex?: string): string {
return this.transformAAS2TD(aid, template, submodelRegex);
}
interface AASInteraction {
endpointMetadata?: Record<string, unknown>;
secNamesForEndpoint?: Array<string>;
interaction: Record<string, unknown>;
}
/**
* Transform AAS in JSON format to a WoT ThingDescription (TD)
*
* @param aas input AAS in JSON format
* @param template TD template with basic desired TD template
* @param submodelRegex allows to filter submodel elements based on regex expression (e.g, "HTTP*") or full text based on idShort (e.g., "InterfaceHTTP")
* @returns transformed TD
*/
public transformAAS2TD(aas: string, template?: string, submodelRegex?: string): string {
const smInformation = this.getSubmodelInformation(aas, submodelRegex);
return this._transform(smInformation, template);
}
interface SubmodelInformation {
properties: Map<string, Array<AASInteraction>>;
actions: Map<string, Array<AASInteraction>>;
events: Map<string, Array<AASInteraction>>;
/**
* Transform AID submodel definition in JSON format to a WoT ThingDescription (TD)
*
* @param aid input AID submodel in JSON format
* @param template TD template with basic desired TD template
* @param submodelRegex allows to filter submodel elements based on regex expression (e.g, "HTTP*") or full text based on idShort (e.g., "InterfaceHTTP")
* @returns transformed TD
*/
public transformSM2TD(aid: string, template?: string, submodelRegex?: string): string {
const submodel = JSON.parse(aid);
endpointMetadataArray: Array<Record<string, unknown>>;
}
const smInformation: SubmodelInformation = {
actions: new Map<string, Array<AASInteraction>>(),
events: new Map<string, Array<AASInteraction>>(),
properties: new Map<string, Array<AASInteraction>>(),
endpointMetadataArray: [],
thing: new Map<string, Record<string, unknown>>(),
};
const noSecSS: SecurityScheme = { scheme: "nosec" };
const noSecName = 0 + "_sc";
this.processSubmodel(smInformation, submodel, submodelRegex);
export class AssetInterfaceDescriptionUtil {
return this._transform(smInformation, template);
}
/**
* Transform WoT ThingDescription (TD) to AAS in JSON format
*
* @param td input TD
* @param protocols protocol prefixes of interest (e.g., ["http", "coap"]) or optional if all
* @returns transformed AAS in JSON format
*/
public transformTD2AAS(td: string, protocols?: string[]): string {
const submodel = this.transformTD2SM(td, protocols);
const submodelObj = JSON.parse(submodel);
const submodelId = submodelObj.id;
// configuration
const aasName = "SampleAAS";
const aasId = "https://example.com/ids/aas/7474_9002_6022_1115";
const aas = {
assetAdministrationShells: [
{
idShort: aasName,
id: aasId,
assetInformation: {
assetKind: "Type",
},
submodels: [
{
type: "ModelReference",
keys: [
{
type: "Submodel",
value: submodelId,
},
],
},
],
modelType: "AssetAdministrationShell",
},
],
submodels: [submodelObj],
conceptDescriptions: [],
};
return JSON.stringify(aas);
}
/**
* Transform WoT ThingDescription (TD) to AID submodel definition in JSON format
*
* @param td input TD
* @param protocols protocol prefixes of interest (e.g., ["http", "coap"]) or optional if all
* @returns transformed AID submodel definition in JSON format
*/
public transformTD2SM(tdAsString: string, protocols?: string[]): string {
const td: ThingDescription = TDParser.parseTD(tdAsString);
const aidID = td.id ? td.id : "ID" + Math.random();
logInfo("TD " + td.title + " parsed...");
// collect all possible prefixes
if (protocols === undefined || protocols.length === 0) {
protocols = this.getProtocolPrefixes(td);
}
const submdelElements = [];
for (const protocol of protocols) {
// use protocol binding prefix like "http" for name
const submodelElementIdShort = protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase();
const submdelElement = {
idShort: submodelElementIdShort,
// semanticId needed?
// embeddedDataSpecifications needed?
value: [
{
idShort: "title",
valueType: "xs:string",
value: td.title,
modelType: "Property",
},
// support and other?
this.createEndpointMetadata(td), // EndpointMetadata like base, security and securityDefinitions
this.createInterfaceMetadata(td, protocol), // InterfaceMetadata like properties, actions and events
// externalDescriptor ?
],
modelType: "SubmodelElementCollection",
};
submdelElements.push(submdelElement);
}
const aidObject = {
idShort: "AssetInterfacesDescription",
id: aidID,
kind: "Instance",
// semanticId needed?
description: [
// TODO does this need to be an array or can it simply be a value
{
language: "en",
text: td.title, // TODO should be description, where does title go to? later on in submodel?
},
],
submodelElements: submdelElements,
modelType: "Submodel",
};
return JSON.stringify(aidObject);
}
/*
* PRIVATE IMPLEMENTATION METHODS ARE FOLLOWING
*
*/
private getProtocolPrefixes(td: ThingDescription): string[] {
const protocols: string[] = [];
if (td.properties) {
for (const propertyKey in td.properties) {
const property = td.properties[propertyKey];
this.updateProtocolPrefixes(property.forms, protocols);
}
}
if (td.actions) {
for (const actionKey in td.actions) {
const action = td.actions[actionKey];
this.updateProtocolPrefixes(action.forms, protocols);
}
}
if (td.events) {
for (const eventKey in td.events) {
const event = td.events[eventKey];
this.updateProtocolPrefixes(event.forms, protocols);
}
}
return protocols;
}
private updateProtocolPrefixes(forms: [FormElementBase, ...FormElementBase[]], protocols: string[]): void {
if (forms) {
for (const interactionForm of forms) {
if (interactionForm.href) {
const positionColon = interactionForm.href.indexOf(":");
if (positionColon > 0) {
const prefix = interactionForm.href.substring(0, positionColon);
if (!protocols.includes(prefix)) {
protocols.push(prefix);
}
}
}
}
}
}
private getBaseFromEndpointMetadata(endpointMetadata?: Record<string, unknown>): string {

@@ -84,22 +261,25 @@ if (endpointMetadata?.value && endpointMetadata.value instanceof Array) {

private getSecuritySchemesFromEndpointMetadata(
endpointMetadata?: Record<string, unknown>
): Array<SecurityScheme> | undefined {
private getSecurityDefinitionsFromEndpointMetadata(endpointMetadata?: Record<string, unknown>): {
[k: string]: SecurityScheme;
} {
const securityDefinitions: {
[k: string]: SecurityScheme;
} = {};
if (endpointMetadata?.value && endpointMetadata.value instanceof Array) {
for (const v of endpointMetadata.value) {
if (v.idShort === "securityDefinitions") {
const securitySchemes: Array<SecurityScheme> = [];
// const securitySchemes: Array<SecurityScheme> = [];
if (v.value && v.value instanceof Array) {
for (const secValue of v.value) {
// allow all *other* security schemes like "uasec" as welll
const ss: SecurityScheme = { scheme: secValue.idShort };
securitySchemes.push(ss);
/* if (secValue.idShort === "nosec" || secValue.idShort === "auto" || secValue.idShort === "combo" || secValue.idShort === "basic" || secValue.idShort === "digest" || secValue.idShort === "apikey" || secValue.idShort === "bearer" || secValue.idShort === "psk" || secValue.idShort === "oauth2" ) {
const ss : SecurityScheme = { scheme: secValue.idShort};
securitySchemes.push(ss);
} */
if (secValue.value && secValue.value instanceof Array) {
for (const v of secValue.value) {
if (v.idShort && typeof v.idShort === "string" && v.idShort.length > 0 && v.value) {
ss[v.idShort] = v.value;
for (const securityDefinitionsValues of v.value) {
if (securityDefinitionsValues.idShort) {
// key
if (securityDefinitionsValues.value instanceof Array) {
for (const securityDefinitionsValue of securityDefinitionsValues.value) {
if (securityDefinitionsValue.idShort === "scheme") {
if (securityDefinitionsValue.value) {
const ss: SecurityScheme = { scheme: securityDefinitionsValue.value };
securityDefinitions[securityDefinitionsValues.idShort] = ss;
}
}
}

@@ -110,9 +290,29 @@ }

}
return securitySchemes;
}
}
}
return undefined;
return securityDefinitions;
}
private getSecurityFromEndpointMetadata(
endpointMetadata?: Record<string, unknown>
): string | [string, ...string[]] {
const security: string[] = [];
if (endpointMetadata?.value && endpointMetadata.value instanceof Array) {
for (const v of endpointMetadata.value) {
if (v.idShort === "security") {
if (v.value && v.value instanceof Array) {
for (const securityValue of v.value) {
if (securityValue.value) {
security.push(securityValue.value);
}
}
}
}
}
}
return security as string | [string, ...string[]];
}
private createInteractionForm(vi: AASInteraction, addSecurity: boolean): TD.Form {

@@ -123,7 +323,10 @@ const form: TD.Form = {

};
// need to add security at form level at all ?
if (addSecurity) {
const securitySchemes = this.getSecuritySchemesFromEndpointMetadata(vi.endpointMetadata);
// XXX need to add security at form level at all ?
logError("security at form level not added/present");
/*
const securitySchemes = this.getSecurityDefinitionsFromEndpointMetadata(vi.endpointMetadata);
if (securitySchemes === undefined) {
form.security = [noSecName];
form.security = [0 + "_sc"];
} else {

@@ -134,50 +337,58 @@ if (vi.secNamesForEndpoint) {

}
*/
}
if (vi.interaction.value instanceof Array) {
for (const v of vi.interaction.value) {
// Binding HTTP
if (v.idShort === "href") {
if (form.href && form.href.length > 0) {
form.href = form.href + v.value; // TODO handle leading/trailing slashes
} else {
form.href = v.value;
}
} else if (typeof v.idShort === "string" && v.idShort.length > 0) {
// pick *any* value (and possibly override, e.g, contentType)
// TODO Should we add all value's (e.g., dataMapping might be empty array) ?
// if (typeof v.value === "string" ||typeof v.value === "number" || typeof v.value === "boolean") {
if (v.value) {
form[v.idShort] = v.value;
// use valueType to convert the string value
if (
v.valueType &&
v.valueType &&
v.valueType.dataObjectType &&
v.valueType.dataObjectType.name &&
typeof v.valueType.dataObjectType.name === "string"
) {
// XSD schemaTypes, https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
switch (v.valueType.dataObjectType.name) {
case "boolean":
form[v.idShort] = form[v.idShort] === "true";
break;
case "float":
case "double":
case "decimal":
case "integer":
case "nonPositiveInteger":
case "negativeInteger":
case "long":
case "int":
case "short":
case "byte":
case "nonNegativeInteger":
case "unsignedLong":
case "unsignedInt":
case "unsignedShort":
case "unsignedByte":
case "positiveInteger":
form[v.idShort] = Number(form[v.idShort]);
break;
// TODO handle more XSD types ?
for (const iv of vi.interaction.value) {
if (iv.idShort === "forms") {
if (iv.value instanceof Array) {
for (const v of iv.value) {
// Binding
if (v.idShort === "href") {
if (form.href && form.href.length > 0) {
form.href = form.href + v.value; // TODO handle leading/trailing slashes
} else {
form.href = v.value;
}
} else if (typeof v.idShort === "string" && v.idShort.length > 0) {
// TODO is this still relevant?
// pick *any* value (and possibly override, e.g, contentType)
// TODO Should we add all value's (e.g., dataMapping might be empty array) ?
// if (typeof v.value === "string" ||typeof v.value === "number" || typeof v.value === "boolean") {
if (v.value) {
form[v.idShort] = v.value;
// use valueType to convert the string value
if (
v.valueType &&
v.valueType &&
v.valueType.dataObjectType &&
v.valueType.dataObjectType.name &&
typeof v.valueType.dataObjectType.name === "string"
) {
// XSD schemaTypes, https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
switch (v.valueType.dataObjectType.name) {
case "boolean":
form[v.idShort] = form[v.idShort] === "true";
break;
case "float":
case "double":
case "decimal":
case "integer":
case "nonPositiveInteger":
case "negativeInteger":
case "long":
case "int":
case "short":
case "byte":
case "nonNegativeInteger":
case "unsignedLong":
case "unsignedInt":
case "unsignedShort":
case "unsignedByte":
case "positiveInteger":
form[v.idShort] = Number(form[v.idShort]);
break;
// TODO handle more XSD types ?
}
}
}
}

@@ -197,3 +408,3 @@ }

): void {
if (submodel instanceof Object && submodel.idShort && submodel.idShort === "AssetInterfaceDescription") {
if (submodel instanceof Object && submodel.idShort && submodel.idShort === "AssetInterfacesDescription") {
if (submodel.submodelElements && submodel.submodelElements instanceof Array) {

@@ -230,2 +441,8 @@ for (const submodelElement of submodel.submodelElements) {

smInformation.endpointMetadataArray.push(endpointMetadata);
} else if (smValue.idShort === "InterfaceMetadata") {
// handled later
} else if (smValue.idShort === "externalDescriptor") {
// needed?
} else {
smInformation.thing.set(smValue.idShort, smValue.value);
}

@@ -300,2 +517,3 @@ }

endpointMetadataArray: [],
thing: new Map<string, Record<string, unknown>>(),
};

@@ -317,3 +535,12 @@

// TODO required fields possible in AID also?
// walk over thing information and set them
for (const [key, value] of smInformation.thing) {
if (typeof value === "string") {
thing[key] = value;
} else {
// TODO what to do with non-string values?
}
}
// required TD fields
if (!thing["@context"]) {

@@ -328,35 +555,20 @@ thing["@context"] = "https://www.w3.org/2022/wot/td/v1.1";

// add "securityDefinitions" globally and add them on form level if necessary
// Note: possible collisions for "security" names handled by cnt
// TODO: possible collisions for "security" names *could* be handled by cnt
if (!thing.securityDefinitions) {
thing.securityDefinitions = {};
}
let cnt = 1;
const secSchemeNamesAll = new Array<string>();
// let cnt = 1;
const secNamesForEndpointMetadata = new Map<Record<string, unknown>, string[]>();
for (const endpointMetadata of smInformation.endpointMetadataArray) {
const secNames: Array<string> = [];
const securitySchemes = this.getSecuritySchemesFromEndpointMetadata(endpointMetadata);
if (securitySchemes === undefined) {
// we need "nosec" scheme
thing.securityDefinitions[noSecName] = noSecSS;
secSchemeNamesAll.push(noSecName);
secNames.push(noSecName);
} else {
// iterate over securitySchemes
for (const secScheme of securitySchemes) {
const secName = cnt + "_sc";
thing.securityDefinitions[secName] = secScheme;
secSchemeNamesAll.push(secName);
secNames.push(secName);
cnt++;
}
thing.securityDefinitions = this.getSecurityDefinitionsFromEndpointMetadata(endpointMetadata);
thing.security = this.getSecurityFromEndpointMetadata(endpointMetadata);
// iterate over securitySchemes
// eslint-disable-next-line unused-imports/no-unused-vars
for (const [key, value] of Object.entries(thing.securityDefinitions)) {
// TODO we could change the name to avoid name collisions. Shall we do so?
secNames.push(key);
}
secNamesForEndpointMetadata.set(endpointMetadata, secNames);
}
if (secSchemeNamesAll.length === 0) {
thing.securityDefinitions.nosec_sc = noSecSS;
thing.security = [noSecName];
} else {
thing.security = secSchemeNamesAll as [string, ...string[]];
}

@@ -369,5 +581,3 @@ // add interactions

for (const entry of smInformation.properties.entries()) {
const key = entry[0];
const value: AASInteraction[] = entry[1];
for (const [key, value] of smInformation.properties.entries()) {
logInfo("Property" + key + " = " + value);

@@ -379,12 +589,61 @@

for (const vi of value) {
// The first block of if condition is expected to be temporary. will be adjusted or removed when a decision on how the datapoint's datatype would be modelled is made for AID.
if (vi.interaction.constraints && vi.interaction.constraints instanceof Array) {
for (const constraint of vi.interaction.constraints)
if (constraint.type === "valueType") {
if (constraint.value === "float") {
thing.properties[key].type = "number";
} else {
thing.properties[key].type = constraint.value;
for (const keyInteraction in vi.interaction) {
if (keyInteraction === "description") {
const aasDescription = vi.interaction[keyInteraction];
// convert
//
// [{
// "language": "en",
// "text": "Current counter value"
// },
// {
// "language": "de",
// "text": "Derzeitiger Zählerwert"
// }]
//
// to
//
// {"en": "Current counter value", "de": "Derzeitiger Zählerwert"}
const tdDescription: Record<string, string> = {};
if (aasDescription instanceof Array) {
for (const aasDescriptionEntry of aasDescription) {
if (aasDescriptionEntry.language && aasDescriptionEntry.text) {
const language: string = aasDescriptionEntry.language;
const text: string = aasDescriptionEntry.text;
tdDescription[language] = text;
}
}
}
thing.properties[key].descriptions = tdDescription;
} else if (keyInteraction === "value") {
if (vi.interaction.value instanceof Array) {
for (const interactionValue of vi.interaction.value)
if (interactionValue.idShort === "type") {
if (interactionValue.value === "float") {
thing.properties[key].type = "number";
} else {
thing.properties[key].type = interactionValue.value;
}
} else if (interactionValue.idShort === "range") {
if (interactionValue.min) {
thing.properties[key].min = interactionValue.min;
}
if (interactionValue.max) {
thing.properties[key].max = interactionValue.max;
}
} else if (interactionValue.idShort === "observable") {
thing.properties[key].observable = interactionValue.value === "true";
} else if (interactionValue.idShort === "readOnly") {
thing.properties[key].readOnly = interactionValue.value === "true";
} else if (interactionValue.idShort === "writeOnly") {
thing.properties[key].writeOnly = interactionValue.value === "true";
} else if (interactionValue.idShort === "forms") {
// will be handled below
} else {
// handle other terms specifically?
const key2 = interactionValue.idShort;
thing.properties[key][key2] = interactionValue.value;
}
}
}
}

@@ -406,5 +665,3 @@

for (const entry of smInformation.actions.entries()) {
const key = entry[0];
const value: AASInteraction[] = entry[1];
for (const [key, value] of smInformation.actions.entries()) {
logInfo("Action" + key + " = " + value);

@@ -430,5 +687,3 @@

for (const entry of smInformation.events.entries()) {
const key = entry[0];
const value: AASInteraction[] = entry[1];
for (const [key, value] of smInformation.events.entries()) {
logInfo("Event " + key + " = " + value);

@@ -452,42 +707,247 @@

/** @deprecated use transformAAS2TD method instead */
public transformToTD(aid: string, template?: string, submodelRegex?: string): string {
return this.transformAAS2TD(aid, submodelRegex);
}
private createEndpointMetadata(td: ThingDescription): Record<string, unknown> {
const values: Array<unknown> = [];
/**
* Transform AAS in JSON format to a WoT ThingDescription (TD)
*
* @param aas input AAS in JSON format
* @param template TD template with basic desired TD template
* @param submodelRegex allows to filter submodel elements based on regex expression (e.g, "HTTP*") or full text based on idShort (e.g., "InterfaceHTTP")
* @returns transformed TD
*/
public transformAAS2TD(aas: string, template?: string, submodelRegex?: string): string {
const smInformation = this.getSubmodelInformation(aas, submodelRegex);
return this._transform(smInformation, template);
// base ?
if (td.base) {
values.push({
idShort: "base",
valueType: "xs:anyURI",
value: td.base, // TODO
modelType: "Property",
});
}
// TODO wrong place.. not allowed in TD spec?
/*
{
idShort: "contentType",
valueType: "xs:string",
value: "application/json", // TODO
modelType: "Property",
},
*/
// security
const securityValues: Array<unknown> = [];
if (td.security) {
for (const secKey of td.security) {
securityValues.push({
valueType: "xs:string",
value: secKey,
modelType: "Property",
});
}
}
values.push({
idShort: "security",
value: securityValues,
modelType: "SubmodelElementCollection",
});
// securityDefinitions
const securityDefinitionsValues: Array<unknown> = [];
for (const secKey in td.securityDefinitions) {
const secValue: SecurityScheme = td.securityDefinitions[secKey];
securityDefinitionsValues.push({
idShort: secKey,
value: [
{
idShort: "scheme",
valueType: "xs:string",
value: secValue.scheme,
modelType: "Property",
},
],
modelType: "SubmodelElementCollection",
});
}
values.push({
idShort: "securityDefinitions",
value: securityDefinitionsValues,
modelType: "SubmodelElementCollection",
});
const endpointMetadata: Record<string, unknown> = {
idShort: "EndpointMetadata",
// semanticId ?
// embeddedDataSpecifications ?
value: values,
modelType: "SubmodelElementCollection",
};
return endpointMetadata;
}
/**
* Transform AID submodel definition in JSON format to a WoT ThingDescription (TD)
*
* @param aid input AID submodel in JSON format
* @param template TD template with basic desired TD template
* @param submodelRegex allows to filter submodel elements based on regex expression (e.g, "HTTP*") or full text based on idShort (e.g., "InterfaceHTTP")
* @returns transformed TD
*/
public transformSM2TD(aid: string, template?: string, submodelRegex?: string): string {
const submodel = JSON.parse(aid);
private createInterfaceMetadata(td: ThingDescription, protocol: string): Record<string, unknown> {
const properties: Array<unknown> = [];
const actions: Array<unknown> = [];
const events: Array<unknown> = [];
const smInformation: SubmodelInformation = {
actions: new Map<string, Array<AASInteraction>>(),
events: new Map<string, Array<AASInteraction>>(),
properties: new Map<string, Array<AASInteraction>>(),
endpointMetadataArray: [],
if (protocol) {
// Properties
if (td.properties) {
for (const propertyKey in td.properties) {
const propertyValue: PropertyElement = td.properties[propertyKey];
// check whether protocol prefix exists for a form
let formElementPicked: FormElementBase | undefined;
if (propertyValue.forms) {
for (const formElementProperty of propertyValue.forms) {
if (formElementProperty.href?.startsWith(protocol)) {
formElementPicked = formElementProperty;
// found matching form --> abort loop
break;
}
}
}
if (formElementPicked === undefined) {
// do not add this property, since there will be no href of interest
continue;
}
const propertyValues: Array<unknown> = [];
// type
if (propertyValue.type) {
propertyValues.push({
idShort: "type",
valueType: "xs:string",
value: propertyValue.type,
modelType: "Property",
});
}
// title
if (propertyValue.title) {
propertyValues.push({
idShort: "title",
valueType: "xs:string",
value: propertyValue.title,
modelType: "Property",
});
}
// observable
if (propertyValue.observable) {
propertyValues.push({
idShort: "observable",
valueType: "xs:boolean",
value: `${propertyValue.observable}`, // in AID represented as string
modelType: "Property",
});
}
// readOnly and writeOnly marked as EXTERNAL in AID spec
// range and others? Simply add them as is?
// forms
if (formElementPicked) {
const propertyForm: Array<unknown> = [];
// TODO AID for now supports just *one* href/form
// --> pick the first one that matches protocol (other means in future?)
// walk over string values like: "href", "contentType", "htv:methodName", ...
for (const formTerm in formElementPicked) {
const formValue = formElementPicked[formTerm];
if (typeof formValue === "string") {
propertyForm.push({
idShort: formTerm,
valueType: "xs:string",
value: formValue,
modelType: "Property",
});
}
}
// TODO terms that are not string-based, like op arrays?
propertyValues.push({
idShort: "forms",
value: propertyForm,
modelType: "SubmodelElementCollection",
});
}
let description;
if (propertyValue.descriptions) {
description = [];
for (const langKey in propertyValue.descriptions) {
const langValue = propertyValue.descriptions[langKey];
description.push({
language: langKey,
text: langValue,
});
}
} else if (propertyValue.description) {
// fallback
description = [];
description.push({
language: "en", // TODO where to get language identifier
text: propertyValue.description,
});
}
properties.push({
idShort: propertyKey,
description: description,
value: propertyValues,
modelType: "SubmodelElementCollection",
});
}
}
// Actions
if (td.actions) {
// TODO actions - TBD by AID
}
// Events
if (td.events) {
// TODO events - TBD by AID
}
}
const values: Array<unknown> = [];
// Properties
values.push({
idShort: "Properties",
value: properties,
modelType: "SubmodelElementCollection",
});
// Actions
values.push({
idShort: "Actions",
value: actions,
modelType: "SubmodelElementCollection",
});
// Events
values.push({
idShort: "Events",
value: events,
modelType: "SubmodelElementCollection",
});
const interfaceMetadata: Record<string, unknown> = {
idShort: "InterfaceMetadata",
// semanticId ?
// embeddedDataSpecifications ?
value: values,
modelType: "SubmodelElementCollection",
};
this.processSubmodel(smInformation, submodel, submodelRegex);
return this._transform(smInformation, template);
return interfaceMetadata;
}
}
interface AASInteraction {
endpointMetadata?: Record<string, unknown>;
secNamesForEndpoint?: Array<string>;
interaction: Record<string, unknown>;
}
interface SubmodelInformation {
properties: Map<string, Array<AASInteraction>>;
actions: Map<string, Array<AASInteraction>>;
events: Map<string, Array<AASInteraction>>;
thing: Map<string, Record<string, unknown>>;
endpointMetadataArray: Array<Record<string, unknown>>;
}

@@ -7,6 +7,4 @@ # Thing Description Utilities

### Sample Application
### Sample Applications
The file `AID_v03_counter.json` describes the counter sample in AID format. The `AssetInterfaceDescriptionUtil` utility class allows to transform the AID format to a valid WoT TD format which in the end can be properly consumed by node-wot.
#### Prerequisites

@@ -18,8 +16,10 @@

#### Sample Code
#### AAS/AID to WoT TD
The file `counterHTTP.json` describes the counter sample in AID format for http binding. The `AssetInterfaceDescriptionUtil` utility class allows to transform the AID format to a valid WoT TD format which in the end can be properly consumed by node-wot.
The example tries to load an AID file in AID format and transforms it to a regular WoT TD.
```js
// aid-client.js
// aid-to-td.js
const fs = require("fs/promises"); // to read JSON file in AID format

@@ -41,12 +41,12 @@

try {
const aid = await fs.readFile("AID_v03_counter.json", {
const aas = await fs.readFile("counterHTTP.json", {
encoding: "utf8",
});
// transform AID to WoT TD
let tdAID = assetInterfaceDescriptionUtil.transformToTD(aid, `{"title": "counter"}`);
// Note: transformToTD() may have up to 3 input parameters
// * aid (required): AID input
let tdAID = assetInterfaceDescriptionUtil.transformAAS2TD(aas, `{"title": "counter"}`);
// Note: transformAAS2TD() may have up to 3 input parameters
// * aas (required): AAS in JSON format
// * template (optional): Initial TD template
// * submodelRegex (optional): Submodel filter based on regular expression
// e.g., filtering HTTP only by calling transformToTD(aid, `{}`, "HTTP")
// e.g., filtering HTTP only by calling transformAAS2TD(aas, `{}`, "HTTP")

@@ -69,8 +69,37 @@ // do work as usual

#### Run the sample script
#### WoT TD to AAS/AID
`node aid-client.js`
The example tries to load online counter TD and converts it to AAS JSON format.
It will show the counter value retrieved from http://plugfest.thingweb.io:8083/counter/properties/count
```js
// td-to-aid.js
AssetInterfaceDescriptionUtil = require("@node-wot/td-tools").AssetInterfaceDescriptionUtil;
Note: make sure that the file `AID_v03_counter.json` is in the same folder as the script.
let assetInterfaceDescriptionUtil = new AssetInterfaceDescriptionUtil();
async function example() {
try {
const response = await fetch("http://plugfest.thingweb.io:8083/counter");
const counterTD = await response.json();
const sm = assetInterfaceDescriptionUtil.transformTD2AAS(JSON.stringify(counterTD), ["http", "coap"]);
// print JSON format of AAS
console.log(sm);
} catch (err) {
console.log(err);
}
}
// launch example
example();
```
#### Run the sample scripts
`node aid-to-td.js`
... will show the counter value retrieved from http://plugfest.thingweb.io:8083/counter/properties/count
Note: make sure that the file `counterHTTP.json` is in the same folder as the script.
`node td-to-aid.js`
... will show the online counter im AAS/AID JSON format (usable by AASX Package Explorer 2023-08-01.alpha).

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc