@@ -238,9 +238,7 @@ class AssetInterfaceDescriptionUtilTest {
238238 . to . eql ( "modbus+tcp://192.168.178.146:502/1/40020?quantity=16" ) ;
239239 expect ( tdObj . properties . device_name . forms [ 0 ] ) . to . have . property ( "modv:function" ) . to . eql ( "readHoldingRegisters" ) ;
240240 expect ( tdObj . properties . device_name . forms [ 0 ] ) . to . have . property ( "modv:type" ) . to . eql ( "string" ) ;
241- expect ( tdObj . properties . device_name . forms [ 0 ] )
242- . to . have . property ( "contentType" )
243- . to . eql ( "application/octet-stream" ) ;
241+ expect ( tdObj . properties . device_name . forms [ 0 ] ) . to . have . property ( "contentType" ) . to . eql ( "text/plain" ) ;
244242 expect ( tdObj . properties . device_name . forms [ 0 ] ) . not . to . have . property ( "security" ) ;
245243
246244 // check property soc
@@ -400,6 +398,7 @@ class AssetInterfaceDescriptionUtilTest {
400398 let hasContentType = false ;
401399 let hasModbusFunction = false ;
402400 let hasModbusType = false ;
401+ let hasModbusMostSignificantByte = false ;
403402 for ( const formEntry of propProperty . value ) {
404403 if ( formEntry . idShort === "href" ) {
405404 hasHref = true ;
@@ -410,7 +409,9 @@ class AssetInterfaceDescriptionUtilTest {
410409 // expect(formEntry.value).to.equal("readproperty");
411410 } else if ( formEntry . idShort === "contentType" ) {
412411 hasContentType = true ;
413- expect ( formEntry . value ) . to . equal ( "application/octet-stream" ) ;
412+ // Note: It uses the global contentType (locally it was not set in the AID)
413+ expect ( formEntry . value ) . to . equal ( "text/plain" ) ;
414+ // expect(formEntry.value).to.equal("application/octet-stream");
414415 } else if ( formEntry . idShort === "modv_function" ) {
415416 // vs. "modv:function"
416417 hasModbusFunction = true ;
@@ -419,13 +420,18 @@ class AssetInterfaceDescriptionUtilTest {
419420 // vs. "modv:type"
420421 hasModbusType = true ;
421422 expect ( formEntry . value ) . to . equal ( "string" ) ;
423+ } else if ( formEntry . idShort === "modv_mostSignificantByte" ) {
424+ // vs. "modv:mostSignificantByte"
425+ hasModbusMostSignificantByte = true ;
426+ expect ( formEntry . value ) . to . equal ( "true" ) ;
422427 }
423428 }
424429 expect ( hasHref ) . to . equal ( true ) ;
425430 expect ( hasOp ) . to . equal ( false ) ;
426431 expect ( hasContentType ) . to . equal ( true ) ;
427432 expect ( hasModbusFunction ) . to . equal ( true ) ;
428433 expect ( hasModbusType ) . to . equal ( true ) ;
434+ expect ( hasModbusMostSignificantByte ) . to . equal ( true ) ; // global
429435 }
430436 }
431437 expect ( hasType ) . to . equal ( true ) ;
@@ -1045,6 +1051,201 @@ class AssetInterfaceDescriptionUtilTest {
10451051 expect ( hasInteractionMetadata , "No InteractionMetadata" ) . to . equal ( true ) ;
10461052 }
10471053
1054+ td3 : ThingDescription = {
1055+ "@context" : "https://www.w3.org/2022/wot/td/v1.1" ,
1056+ title : "ModbusTD" ,
1057+ securityDefinitions : {
1058+ nosec_sc : {
1059+ scheme : "nosec" ,
1060+ } ,
1061+ } ,
1062+ security : "nosec_sc" ,
1063+ base : "modbus+tcp://$$addr$$:502/$$unitid$$/" ,
1064+ properties : {
1065+ voltage : {
1066+ forms : [
1067+ {
1068+ href : "40001?quantity=2" ,
1069+ contentType : "application/octet-stream" ,
1070+ op : [ "readproperty" ] ,
1071+ "modv:function" : "readHoldingRegisters" ,
1072+ "modv:type" : "xsd:float" ,
1073+ "modv:mostSignificantByte" : true ,
1074+ "modv:mostSignificantWord" : true ,
1075+ } ,
1076+ ] ,
1077+ } ,
1078+ } ,
1079+ } ;
1080+
1081+ @test async "should correctly transform sample TD3 into AID submodel" ( ) {
1082+ const sm = this . assetInterfaceDescriptionUtil . transformTD2SM ( JSON . stringify ( this . td3 ) ) ;
1083+
1084+ const smObj = JSON . parse ( sm ) ;
1085+ // console.log("###\n\n" + JSON.stringify(smObj) + "\n\n###");
1086+ const isValid = this . validateAID ( smObj ) ;
1087+ expect ( isValid . valid , isValid . errors ) . to . equal ( true ) ;
1088+ expect ( smObj ) . to . have . property ( "idShort" ) . that . equals ( "AssetInterfacesDescription" ) ;
1089+ expect ( smObj ) . to . have . property ( "semanticId" ) ;
1090+ expect ( smObj ) . to . have . property ( "submodelElements" ) . to . be . an ( "array" ) . to . have . lengthOf . greaterThan ( 0 ) ;
1091+ const smInterface = smObj . submodelElements [ 0 ] ;
1092+ expect ( smInterface ) . to . have . property ( "idShort" ) . to . equal ( "InterfaceMODBUS_TCP" ) ; // AID does not allow "+" in idShort, see InterfaceMODBUS+TCP
1093+ expect ( smInterface ) . to . have . property ( "value" ) . to . be . an ( "array" ) . to . have . lengthOf . greaterThan ( 0 ) ;
1094+ expect ( smInterface )
1095+ . to . have . property ( "semanticId" )
1096+ . to . be . an ( "object" )
1097+ . with . property ( "keys" )
1098+ . to . be . an ( "array" )
1099+ . to . have . lengthOf . greaterThan ( 0 ) ;
1100+ expect ( smInterface )
1101+ . to . have . property ( "supplementalSemanticIds" )
1102+ . to . be . an ( "array" )
1103+ . to . have . lengthOf . greaterThan ( 1 ) ; // default WoT-TD and http
1104+ let hasThingTitle = false ;
1105+ let hasEndpointMetadata = false ;
1106+ for ( const smValue of smInterface . value ) {
1107+ if ( smValue . idShort === "title" ) {
1108+ hasThingTitle = true ;
1109+ expect ( smValue ) . to . have . property ( "value" ) . to . equal ( "ModbusTD" ) ;
1110+ } else if ( smValue . idShort === "EndpointMetadata" ) {
1111+ hasEndpointMetadata = true ;
1112+ const endpointMetadata = smValue ;
1113+ expect ( endpointMetadata ) . to . have . property ( "value" ) . to . be . an ( "array" ) . to . have . lengthOf . greaterThan ( 0 ) ;
1114+ let hasBase = false ;
1115+ let hasContentType = false ;
1116+ let hasSecurity = false ;
1117+ let hasSecurityDefinitions = false ;
1118+ for ( const endpointMetadataValue of endpointMetadata . value ) {
1119+ if ( endpointMetadataValue . idShort === "base" ) {
1120+ hasBase = true ;
1121+ expect ( endpointMetadataValue . value ) . to . equal ( "modbus+tcp://$$addr$$:502/$$unitid$$/" ) ;
1122+ } else if ( endpointMetadataValue . idShort === "contentType" ) {
1123+ hasContentType = true ;
1124+ } else if ( endpointMetadataValue . idShort === "security" ) {
1125+ hasSecurity = true ;
1126+ expect ( endpointMetadataValue )
1127+ . to . have . property ( "value" )
1128+ . to . be . an ( "array" )
1129+ . to . have . lengthOf . greaterThan ( 0 ) ;
1130+ expect ( endpointMetadataValue . value [ 0 ] ) . to . have . property ( "value" ) ;
1131+ const modelReferenceValue = endpointMetadataValue . value [ 0 ] . value ;
1132+ expect ( modelReferenceValue ) . to . have . property ( "type" ) . to . equal ( "ModelReference" ) ;
1133+ expect ( modelReferenceValue ) . to . have . property ( "keys" ) . to . be . an ( "array" ) . to . have . lengthOf ( 5 ) ;
1134+ expect ( modelReferenceValue . keys [ 4 ] ) . to . have . property ( "value" ) . to . equal ( "nosec_sc" ) ;
1135+ } else if ( endpointMetadataValue . idShort === "securityDefinitions" ) {
1136+ hasSecurityDefinitions = true ;
1137+ }
1138+ }
1139+ expect ( hasBase ) . to . equal ( true ) ; // AID requires base to exist
1140+ expect ( hasContentType ) . to . equal ( false ) ;
1141+ expect ( hasSecurity ) . to . equal ( true ) ;
1142+ expect ( hasSecurityDefinitions ) . to . equal ( true ) ;
1143+ }
1144+ }
1145+ expect ( hasThingTitle , "No thing title" ) . to . equal ( true ) ;
1146+ expect ( hasEndpointMetadata , "No EndpointMetadata" ) . to . equal ( true ) ;
1147+
1148+ // InteractionMetadata with properties etc
1149+ let hasInteractionMetadata = false ;
1150+ for ( const smValue of smInterface . value ) {
1151+ if ( smValue . idShort === "InteractionMetadata" ) {
1152+ hasInteractionMetadata = true ;
1153+ expect ( smValue ) . to . have . property ( "value" ) . to . be . an ( "array" ) . to . have . lengthOf . greaterThan ( 0 ) ;
1154+ let hasProperties = false ;
1155+ for ( const interactionValues of smValue . value ) {
1156+ if ( interactionValues . idShort === "properties" ) {
1157+ hasProperties = true ;
1158+ expect ( interactionValues )
1159+ . to . have . property ( "value" )
1160+ . to . be . an ( "array" )
1161+ . to . have . lengthOf . greaterThan ( 0 ) ;
1162+ let hasPropertyVoltage = false ;
1163+ for ( const propertyValue of interactionValues . value ) {
1164+ if ( propertyValue . idShort === "voltage" ) {
1165+ hasPropertyVoltage = true ;
1166+ expect ( propertyValue )
1167+ . to . have . property ( "value" )
1168+ . to . be . an ( "array" )
1169+ . to . have . lengthOf . greaterThan ( 0 ) ;
1170+ let hasType = false ;
1171+ let hasTitle = false ;
1172+ let hasObservable = false ;
1173+ let hasForms = false ;
1174+ for ( const propProperty of propertyValue . value ) {
1175+ if ( propProperty . idShort === "type" ) {
1176+ hasType = true ;
1177+ } else if ( propProperty . idShort === "title" ) {
1178+ hasTitle = true ;
1179+ } else if ( propProperty . idShort === "observable" ) {
1180+ hasObservable = true ;
1181+ } else if ( propProperty . idShort === "forms" ) {
1182+ hasForms = true ;
1183+ expect ( propProperty )
1184+ . to . have . property ( "value" )
1185+ . to . be . an ( "array" )
1186+ . to . have . lengthOf . greaterThan ( 0 ) ;
1187+ let hasHref = false ;
1188+ let hasContentType = false ;
1189+ let hasOp = false ;
1190+ let hasModbusFunction = false ;
1191+ let hasModbusType = false ;
1192+ let hasModbusMostSignificantByte = false ;
1193+ let hasModbusMostSignificantWord = false ;
1194+ for ( const formEntry of propProperty . value ) {
1195+ if ( formEntry . idShort === "href" ) {
1196+ hasHref = true ;
1197+ expect ( formEntry . value ) . to . be . oneOf ( [
1198+ "40001?quantity=2" ,
1199+ "modbus+tcp://$$addr$$:502/$$unitid$$/40001?quantity=2" ,
1200+ ] ) ; // absolute or relative
1201+ } else if ( formEntry . idShort === "contentType" ) {
1202+ hasContentType = true ;
1203+ expect ( formEntry . value ) . to . equal ( "application/octet-stream" ) ;
1204+ } else if ( formEntry . idShort === "op" ) {
1205+ hasOp = true ;
1206+ // Note: AID does not know "op"
1207+ // expect(formEntry.value).to.equal("readproperty");
1208+ } else if ( formEntry . idShort === "modv_function" ) {
1209+ hasModbusFunction = true ;
1210+ expect ( formEntry . value ) . to . equal ( "readHoldingRegisters" ) ;
1211+ } else if ( formEntry . idShort === "modv_type" ) {
1212+ hasModbusType = true ;
1213+ expect ( formEntry . value ) . to . equal ( "xsd:float" ) ;
1214+ expect ( formEntry . valueType ) . to . equal ( "xs:string" ) ;
1215+ } else if ( formEntry . idShort === "modv_mostSignificantByte" ) {
1216+ hasModbusMostSignificantByte = true ;
1217+ expect ( formEntry . value ) . to . equal ( "true" ) ;
1218+ expect ( formEntry . valueType ) . to . equal ( "xs:boolean" ) ;
1219+ } else if ( formEntry . idShort === "modv_mostSignificantWord" ) {
1220+ hasModbusMostSignificantWord = true ;
1221+ expect ( formEntry . value ) . to . equal ( "true" ) ;
1222+ expect ( formEntry . valueType ) . to . equal ( "xs:boolean" ) ;
1223+ }
1224+ }
1225+ expect ( hasHref ) . to . equal ( true ) ;
1226+ expect ( hasContentType ) . to . equal ( true ) ;
1227+ expect ( hasOp ) . to . equal ( false ) ;
1228+ expect ( hasModbusFunction ) . to . equal ( true ) ;
1229+ expect ( hasModbusType ) . to . equal ( true ) ;
1230+ expect ( hasModbusMostSignificantByte ) . to . equal ( true ) ;
1231+ expect ( hasModbusMostSignificantWord ) . to . equal ( true ) ;
1232+ }
1233+ }
1234+ expect ( hasType ) . to . equal ( false ) ;
1235+ expect ( hasTitle ) . to . equal ( false ) ;
1236+ expect ( hasObservable ) . to . equal ( false ) ;
1237+ expect ( hasForms ) . to . equal ( true ) ;
1238+ }
1239+ }
1240+ expect ( hasPropertyVoltage ) . to . equal ( true ) ;
1241+ }
1242+ }
1243+ expect ( hasProperties ) . to . equal ( true ) ;
1244+ }
1245+ }
1246+ expect ( hasInteractionMetadata , "No InteractionMetadata" ) . to . equal ( true ) ;
1247+ }
1248+
10481249 @test . skip async "should correctly transform counter TD into JSON AAS" ( ) {
10491250 // built-in fetch requires Node.js 18+
10501251 const response = await fetch ( "http://plugfest.thingweb.io:8083/counter" ) ;
0 commit comments