Skip to content

Commit cc46531

Browse files
refactor(AID): reflect latest security representation (#1150)
using list of References
1 parent e25cbd9 commit cc46531

4 files changed

Lines changed: 135 additions & 22 deletions

File tree

packages/td-tools/src/util/asset-interface-description.ts

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ export class AssetInterfaceDescriptionUtil {
140140
const submdelElements = [];
141141
for (const protocol of protocols) {
142142
// use protocol binding prefix like "http" for name
143-
const submodelElementIdShort = protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase();
143+
const submodelElementIdShort = this.sanitizeIdShort(
144+
protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase()
145+
);
144146

145147
const supplementalSemanticIds = [this.createSemanticId("https://www.w3.org/2019/wot/td")];
146148
if (protocol !== undefined) {
@@ -159,7 +161,7 @@ export class AssetInterfaceDescriptionUtil {
159161
}
160162

161163
const submdelElement = {
162-
idShort: this.sanitizeIdShort(submodelElementIdShort),
164+
idShort: submodelElementIdShort,
163165
semanticId: this.createSemanticId(
164166
"https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface"
165167
),
@@ -174,7 +176,7 @@ export class AssetInterfaceDescriptionUtil {
174176
semanticId: this.createSemanticId("https://www.w3.org/2019/wot/td#title"),
175177
},
176178
// created, modified, support ?
177-
this.createEndpointMetadata(td), // EndpointMetadata like base, security and securityDefinitions
179+
this.createEndpointMetadata(td, aidID, submodelElementIdShort), // EndpointMetadata like base, security and securityDefinitions
178180
this.createInterfaceMetadata(td, protocol), // InterfaceMetadata like properties, actions and events
179181
{
180182
idShort: "ExternalDescriptor",
@@ -382,8 +384,16 @@ export class AssetInterfaceDescriptionUtil {
382384
} else if (v.idShort === "security") {
383385
if (v.value instanceof Array) {
384386
for (const securityValue of v.value) {
385-
if (securityValue.value != null) {
386-
security.push(securityValue.value);
387+
if (securityValue.value != null && securityValue.value.keys instanceof Array) {
388+
// e.g.,
389+
// {
390+
// "type": "SubmodelElementCollection",
391+
// "value": "nosec_sc"
392+
// }
393+
const key = securityValue.value.keys[securityValue.value.keys.length - 1]; // last path
394+
if (key.value != null) {
395+
security.push(key.value);
396+
}
387397
}
388398
}
389399
}
@@ -822,7 +832,11 @@ export class AssetInterfaceDescriptionUtil {
822832
return JSON.stringify(thing);
823833
}
824834

825-
private createEndpointMetadata(td: ThingDescription): Record<string, unknown> {
835+
private createEndpointMetadata(
836+
td: ThingDescription,
837+
submodelIdShort: string,
838+
submodelElementIdShort: string
839+
): Record<string, unknown> {
826840
const values: Array<unknown> = [];
827841

828842
// base ?
@@ -851,9 +865,31 @@ export class AssetInterfaceDescriptionUtil {
851865
if (td.security != null) {
852866
for (const secKey of td.security) {
853867
securityValues.push({
854-
valueType: "xs:string",
855-
value: secKey,
856-
modelType: "Property",
868+
value: {
869+
type: "ModelReference",
870+
keys: [
871+
{
872+
type: "Submodel",
873+
value: submodelIdShort,
874+
},
875+
{
876+
type: "SubmodelElementCollection",
877+
value: submodelElementIdShort,
878+
},
879+
{
880+
type: "SubmodelElementCollection",
881+
value: "EndpointMetadata",
882+
},
883+
{
884+
type: "SubmodelElementCollection",
885+
value: "securityDefinitions",
886+
},
887+
{
888+
type: "SubmodelElementCollection",
889+
value: secKey,
890+
},
891+
],
892+
},
857893
});
858894
}
859895
}

packages/td-tools/test/AssetInterfaceDescriptionTest.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,11 @@ class AssetInterfaceDescriptionUtilTest {
277277
.to.have.property("value")
278278
.to.be.an("array")
279279
.to.have.lengthOf.greaterThan(0);
280-
expect(endpointMetadataValue.value[0].value).to.equal("nosec_sc");
280+
expect(endpointMetadataValue.value[0]).to.have.property("value");
281+
const modelReferenceValue = endpointMetadataValue.value[0].value;
282+
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
283+
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
284+
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("nosec_sc");
281285
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
282286
hasSecurityDefinitions = true;
283287
expect(endpointMetadataValue)
@@ -472,6 +476,7 @@ class AssetInterfaceDescriptionUtilTest {
472476
td1: ThingDescription = {
473477
"@context": "https://www.w3.org/2022/wot/td/v1.1",
474478
title: "testTD",
479+
id: "urn:uuid:0804d572-cce8-422a-bb7c-4412fcd56f03",
475480
securityDefinitions: {
476481
basic_sc: {
477482
scheme: "basic",
@@ -517,9 +522,11 @@ class AssetInterfaceDescriptionUtilTest {
517522

518523
const smObj = JSON.parse(sm);
519524
expect(smObj).to.have.property("idShort").that.equals("AssetInterfacesDescription");
525+
expect(smObj).to.have.property("id");
520526
expect(smObj).to.have.property("semanticId");
521527
expect(smObj).to.have.property("submodelElements").to.be.an("array").to.have.lengthOf.greaterThan(0);
522528
const smInterface = smObj.submodelElements[0];
529+
expect(smInterface).to.have.property("idShort");
523530
expect(smInterface).to.have.property("value").to.be.an("array").to.have.lengthOf.greaterThan(0);
524531
expect(smInterface)
525532
.to.have.property("semanticId")
@@ -557,7 +564,28 @@ class AssetInterfaceDescriptionUtilTest {
557564
.to.have.property("value")
558565
.to.be.an("array")
559566
.to.have.lengthOf.greaterThan(0);
560-
expect(endpointMetadataValue.value[0].value).to.equal("basic_sc");
567+
expect(endpointMetadataValue.value[0]).to.have.property("value");
568+
const modelReferenceValue = endpointMetadataValue.value[0].value;
569+
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
570+
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
571+
expect(modelReferenceValue.keys[0]).to.have.property("type").to.equal("Submodel");
572+
expect(modelReferenceValue.keys[0]).to.have.property("value").to.equal(smObj.id);
573+
expect(modelReferenceValue.keys[1])
574+
.to.have.property("type")
575+
.to.equal("SubmodelElementCollection");
576+
expect(modelReferenceValue.keys[1]).to.have.property("value").to.equal(smInterface.idShort);
577+
expect(modelReferenceValue.keys[2])
578+
.to.have.property("type")
579+
.to.equal("SubmodelElementCollection");
580+
expect(modelReferenceValue.keys[2]).to.have.property("value").to.equal("EndpointMetadata");
581+
expect(modelReferenceValue.keys[3])
582+
.to.have.property("type")
583+
.to.equal("SubmodelElementCollection");
584+
expect(modelReferenceValue.keys[3]).to.have.property("value").to.equal("securityDefinitions");
585+
expect(modelReferenceValue.keys[4])
586+
.to.have.property("type")
587+
.to.equal("SubmodelElementCollection");
588+
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("basic_sc");
561589
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
562590
hasSecurityDefinitions = true;
563591
expect(endpointMetadataValue)
@@ -725,11 +753,9 @@ class AssetInterfaceDescriptionUtilTest {
725753
expect(hasInterfaceMetadata, "No InterfaceMetadata").to.equal(true);
726754

727755
// Test to use all possible prefixes -> in this case it is only https
756+
// Note: id is autogenerated (if not present) -> needs to be exluded/removed/set in TD
728757
const sm2 = this.assetInterfaceDescriptionUtil.transformTD2SM(JSON.stringify(this.td1));
729758
const sm2Obj = JSON.parse(sm2);
730-
// Note: id is autogenerated and needs to be exluded/removed
731-
delete smObj.id;
732-
delete sm2Obj.id;
733759
expect(smObj).to.eql(sm2Obj);
734760
}
735761

@@ -837,7 +863,11 @@ class AssetInterfaceDescriptionUtilTest {
837863
.to.have.property("value")
838864
.to.be.an("array")
839865
.to.have.lengthOf.greaterThan(0);
840-
expect(endpointMetadataValue.value[0].value).to.equal("nosec_sc");
866+
expect(endpointMetadataValue.value[0]).to.have.property("value");
867+
const modelReferenceValue = endpointMetadataValue.value[0].value;
868+
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
869+
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
870+
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("nosec_sc");
841871
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
842872
hasSecurityDefinitions = true;
843873
}

packages/td-tools/test/util/counterHTTP.json

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,32 @@
102102
"typeValueListElement": "SubmodelElement",
103103
"value": [
104104
{
105-
"valueType": "xs:string",
106-
"value": "nosec_sc",
107-
"modelType": "Property"
105+
"value": {
106+
"type": "ModelReference",
107+
"keys": [
108+
{
109+
"type": "Submodel",
110+
"value": "https://example.com/ids/sm/4333_9041_7022_4184"
111+
},
112+
{
113+
"type": "SubmodelElementCollection",
114+
"value": "InterfaceHTTP"
115+
},
116+
{
117+
"type": "SubmodelElementCollection",
118+
"value": "EndpointMetadata"
119+
},
120+
{
121+
"type": "SubmodelElementCollection",
122+
"value": "securityDefinitions"
123+
},
124+
{
125+
"type": "SubmodelElementCollection",
126+
"value": "nosec_sc"
127+
}
128+
]
129+
},
130+
"modelType": "ReferenceElement"
108131
}
109132
],
110133
"modelType": "SubmodelElementList"

packages/td-tools/test/util/inverterModbus.json

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
],
3232
"submodelElements": [
3333
{
34-
"idShort": "InterfaceMODBUS+TCP",
34+
"idShort": "InterfaceMODBUS_TCP",
3535
"value": [
3636
{
3737
"idShort": "title",
@@ -50,11 +50,35 @@
5050
},
5151
{
5252
"idShort": "security",
53+
"typeValueListElement": "SubmodelElement",
5354
"value": [
5455
{
55-
"valueType": "xs:string",
56-
"value": "nosec_sc",
57-
"modelType": "Property"
56+
"value": {
57+
"type": "ModelReference",
58+
"keys": [
59+
{
60+
"type": "Submodel",
61+
"value": "uri:dev:inverter"
62+
},
63+
{
64+
"type": "SubmodelElementCollection",
65+
"value": "InterfaceMODBUS_TCP"
66+
},
67+
{
68+
"type": "SubmodelElementCollection",
69+
"value": "EndpointMetadata"
70+
},
71+
{
72+
"type": "SubmodelElementCollection",
73+
"value": "securityDefinitions"
74+
},
75+
{
76+
"type": "SubmodelElementCollection",
77+
"value": "nosec_sc"
78+
}
79+
]
80+
},
81+
"modelType": "ReferenceElement"
5882
}
5983
],
6084
"modelType": "SubmodelElementCollection"

0 commit comments

Comments
 (0)