WoT / NodeSet conversion

August 5, 2026 ยท View on GitHub

Opc.Ua.Wot.WotNodeSetConverter converts OPC UA NodeSet2 documents to WoT Thing Models / Thing Descriptions and materializes WoT documents back to NodeSet2. The converter preserves a byte-exact uav:nodeSet envelope when requested, uses the structured uav:nodes projection when the readable vocabulary is not complete, and otherwise synthesizes NodeSet2 from the readable WoT terms.

WoT to NodeSet defaults

The table below lists the defaults the current WoT-to-NodeSet materializer applies when the WoT input lacks information needed for a NodeSet2 projection. Rows marked Fails emit an error diagnostic and ToNodeSet throws. Rows marked Default substitute the listed value; warnings or informational diagnostics are noted where the code emits them.

Missing WoT inputBehaviourMaterialized value
Convertible content: no uav:nodeSet, no uav:nodes, and neither a Thing Model nor a Thing Description kindFailsNoConvertibleContent error; no NodeSet is returned.
Model namespace: root uav:id has no nsu=<NamespaceUri>;... part and document id is absentDefaultNamespaceUris = ["urn:opcua:wot:synthesized"] and Models[0].ModelUri = "urn:opcua:wot:synthesized". This is intentionally synthetic and should be replaced by an authored namespace in portable documents.
Root local name: root uav:browseName is absentDefaultSanitized title (letters, digits, _, -) when non-empty; otherwise Thing.
Root uav:idDefaultDeterministic NodeId ns=1;s=<rootLocal> and an informational GeneratedNodeId diagnostic.
Root uav:browseNameDefault1:<rootLocal>.
Root titleDefaultRoot DisplayName becomes <rootLocal>.
Thing Model root event annotation uav:eventTypeDefaultRoot is a non-abstract UAObjectType with inverse HasSubtype to BaseObjectType (i=58). If the event annotation is present, the default supertype is BaseEventType (i=2041).
Thing Description root type informationDefaultRoot is a UAObject with HasTypeDefinition to BaseObjectType (i=58).
Root descriptionDefaultNo Description field is materialized.
Property affordance uav:browseNameDefaultThe affordance map key is used as the local name and BrowseName 1:<key>.
Property affordance uav:idDefaultDeterministic NodeId ns=1;s=<rootLocal>/<propertyLocal>.
Property DataSchema type or an unrecognized typeDefaultOPC UA BaseDataType (i=24). type: object maps to BaseObjectType (i=22) and emits an unsupported-schema warning; type: array currently falls back to BaseDataType with the same warning, which is a deliberately conservative but coarse default.
Property readOnly and writeOnlyDefaultMissing flags mean read/write access (`CurrentRead
Property titleDefaultNo DisplayName field is materialized for the variable.
Property descriptionDefaultNo Description field is materialized for the variable.
Property type definitionDefaultHasTypeDefinition to BaseDataVariableType (i=63).
Action affordance uav:browseNameDefaultThe affordance map key is used as the local name and BrowseName 1:<key>.
Action affordance uav:idDefaultDeterministic NodeId ns=1;s=<rootLocal>/<actionLocal>.
Action titleDefaultNo DisplayName field is materialized for the method.
Event affordance uav:browseNameDefaultThe affordance map key is used as the local name and BrowseName 1:<key>.
Event affordance uav:idDefaultDeterministic NodeId ns=1;s=<rootLocal>/<eventLocal>.
Event titleDefaultNo DisplayName field is materialized for the event type.
Event type abstraction/supertypeDefaultEvent affordances materialize as non-abstract UAObjectType nodes with inverse HasSubtype to BaseEventType (i=2041) and a root GeneratesEvent reference.
uav:modellingRule on a property or actionDefaultNo HasModellingRule reference is materialized.
uav:hasComponent / uav:componentOf entry has no matching typed ReferenceType linkDefaultHasComponent is used for the component reference.
Binding link has no resolvable model-name relation and no uav:refIdDefaultuav:componentModel maps to HasComponent; other generic binding relations map to Organizes.
Reference link points to another Thing by URI and no resolver is supplied or the resolver cannot find uav:idDefaultThe reference is omitted and a warning diagnostic is emitted; no placeholder NodeId is generated.
Invalid namespace-qualified uav:id / uav:browseName syntax or unbound compact-name prefixFailsAn error diagnostic is emitted; ToNodeSet throws even though synthesis continues far enough to collect diagnostics.
Event affordance says @type: uav:eventType and uav:isEvent: falseFailsEventAnnotationConflict error; the two terms must not contradict each other.