[SourceGeneration] Improve NodeSet to ModelDesign conversion and generated node state - #4132
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR improves OPC UA NodeSet → ModelDesign conversion and downstream code generation to better handle multi-namespace/combined NodeSets, method argument naming collisions, and correct runtime decoding/registration of generated nodes.
Changes:
- Added canonical C# identifier generation and improved string-literal escaping for generated code.
- Improved NodeSet import to better match ModelCompiler conventions (placeholder browse names, method declarations, DataTypeEncoding parenting).
- Updated generators (NodeState/ObjectType proxies/Fluent builders/NodeManager templates) to use stable method-argument symbol allocation and correct decoding contexts; added/expanded regression tests and fixtures.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/Opc.Ua.SourceGeneration.Core/Shared/SourceGenerationUtils.cs | Adds ToCSharpIdentifier and improves literal escaping for generated code. |
| tools/Opc.Ua.SourceGeneration.Core/Schema/NodeSetToModelDesign.cs | Fixes placeholder symbolic-name mapping, method argument naming, method-type reuse, and DataTypeEncoding parenting. |
| tools/Opc.Ua.SourceGeneration.Core/Schema/ModelDesignValidator.cs | Ensures generated method-argument code names are assigned during import/validation. |
| tools/Opc.Ua.SourceGeneration.Core/Schema/ModelDesignExtensions.cs | Introduces scoped, collision-aware generated names for method arguments (non-serialized). |
| tools/Opc.Ua.SourceGeneration.Core/Generators/ObjectTypeProxyGenerator.cs | Uses scoped argument identifiers and correct message context for decoding structured outputs. |
| tools/Opc.Ua.SourceGeneration.Core/Generators/NodeStateGenerator.cs | Uses scoped argument identifiers, correct decoding context, and handles argument value materialization from model parameters. |
| tools/Opc.Ua.SourceGeneration.Core/Generators/NodeManagerTemplates.cs | Adds __FindByDataTypeId to support VariableFromDataTypeId(...) in fluent APIs. |
| tools/Opc.Ua.SourceGeneration.Core/Generators/MethodDesignArgumentResolver.cs | Refactors argument resolution and assigns generated argument names as a side effect. |
| tools/Opc.Ua.SourceGeneration.Core/Generators/FluentBuilderGenerator.cs | Adds pass-through VariableFromDataTypeId overloads and minor doc formatting. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Shared/SourceGenerationUtilsTests.cs | Adds unit tests for new identifier/literal escaping helpers. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Schema/NodeSetToModelDesignTests.cs | Adds regression test covering preservation of runtime argument names. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Schema/ModelDesignExtensionsTests.cs | Adds tests for scoped method-argument name allocation and serialization behavior. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Resources/SameNamespaceEncoding.NodeSet2.xml | Adds fixture covering DataTypeEncoding nodes with same-namespace ParentNodeId. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Resources/SameNamedMethodArguments.NodeSet2.xml | Adds fixture covering argument naming/pathological characters and collisions. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Resources/MethodArgumentNamespace.NodeSet2.xml | Adds fixture covering method-argument datatype namespace resolution at runtime. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Generators/ObjectTypeProxyGeneratorTests.cs | Adds regression test for structured output decode using session message context. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Generators/NodeStateGeneratorTests.cs | Adds generator-level regressions for encoding nodes and argument symbol stability. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/Generators/FluentBuilderGeneratorTests.cs | Updates assertions to match new codegen behaviors and file names. |
| tests/Opc.Ua.SourceGeneration.Core.Tests/CompilerUtils.cs | Adds helpers to create in-memory AdditionalText and collect generator diagnostics. |
| src/Opc.Ua.ISA95/Design/Common/Opc.ISA95.NodeIds.csv | Regenerates NodeIds to reflect placeholder symbolic-name mapping changes. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4132 +/- ##
==========================================
- Coverage 80.23% 79.92% -0.32%
==========================================
Files 1515 1524 +9
Lines 209980 210992 +1012
Branches 36213 36387 +174
==========================================
+ Hits 168479 168627 +148
- Misses 28867 29693 +826
- Partials 12634 12672 +38
🚀 New features to boost your workflow:
|
|
Fixed the net10.0 solution build failure on this PR. The A generator change and the API it emits against have to land together, so the builder Also brings the eight Verified locally:
|
Adds three runnable samples: two flat OPC UA tag servers and an aggregation server that materializes them into a DI/Machinery/Pumps model through the WoT registry, plus an aggregation client that drives the result. The AggregationServer also ships a memory protocol binding, which doubles as the worked example for the binding contributor guide. Documents the WoT Connectivity surface end to end: a new protocol bindings guide, the expanded WoT Connectivity overview covering the registry, materialization and runtime projection, and the shadow-reload and shared byte-store sections for the runtime NodeSet and xRegistry guides. Registers the sample and test projects in the solution so they are built and run by CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Brings across the binder registry, codec, planner and target-mapping tests, the custom-binder sample test, the combined-model preservation tests and the aggregation document tests, closing the last coverage gap against the integration branch. The custom-binder sample needed updating: WotEndpointPolicy now fails closed on unknown URI schemes, so a binding that introduces its own scheme has to opt it in. That is exactly the situation every custom binding author hits, so the sample now shows it and the contributor guide documents the policy, the failure it produces and the checklist item. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
TransferServicesExtensions.BindToTransferService already ships but had no tests. Adds argument validation, required-method-children and routing coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
The transfer rollback, abandoned-claim and publish-queue requeue paths carried no tests, which is where a partial transfer would actually be observable: a failure part way through must leave the source session holding every subscription it started with. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
The registry client's fault handling, result validation and dependency-injection configuration branches carried no tests, which is where a misbehaving or unreachable registry would actually be observable to a client application. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
…ourcegen # Conflicts: # tests/Opc.Ua.SourceGeneration.Core.Tests/Schema/NodeSetToModelDesignTests.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/FluentBuilderGenerator.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/MethodDesignArgumentResolver.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/ObjectTypeProxyGenerator.cs # tools/Opc.Ua.SourceGeneration.Core/Schema/ModelDesignValidator.cs # tools/Opc.Ua.SourceGeneration.Core/Schema/NodeSetToModelDesign.cs
…scription-transfer
…-wotcon-model # Conflicts: # tests/Opc.Ua.SourceGeneration.Core.Tests/Schema/NodeSetToModelDesignTests.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/FluentBuilderGenerator.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/MethodDesignArgumentResolver.cs # tools/Opc.Ua.SourceGeneration.Core/Generators/ObjectTypeProxyGenerator.cs # tools/Opc.Ua.SourceGeneration.Core/Schema/ModelDesignValidator.cs # tools/Opc.Ua.SourceGeneration.Core/Schema/NodeSetToModelDesign.cs
…arcschier/wot-14-materialization
…n' into marcschier/wot-16-samples
## Summary - add optional WoT Connectivity asset TD mirroring into the WoT xRegistry - add DI opt-in via AddWotRegistryBridge and direct WotConnectivityServerOptions.RegistryBridge fallback - document default-off, best-effort failure policy and usage - add NUnit/Moq coverage for create, update, delete, disabled and failure paths ## Validation - dotnet build src\\Opc.Ua.WotCon.Server\\Opc.Ua.WotCon.Server.csproj -c Release -v:m (all TFMs, 0 warnings/errors) - dotnet test tests\\Opc.Ua.WotCon.Tests\\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 (0 failed / 983 passed) --------- Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
…o marcschier/wot-02-sourcegen
…o marcschier/wot-04-generator-wot
… into marcschier/wot-05-lifecycle
…o marcschier/wot-07-subscription-transfer
…ransfer' into marcschier/wot-09-xregistry-client
…nt' into marcschier/wot-10-wotcon-model
…into marcschier/wot-11-bindings-core
… into marcschier/wot-12-executors
…o marcschier/wot-13-registry
… marcschier/wot-15-client
…arcschier/wot-14-materialization
…n' into marcschier/wot-16-samples
…marcschier/wot-16-samples
…ion (#4156) Adds the runnable WoT Connectivity samples and completes the documentation. This is **PR 16 of a stack** splitting #4093, and the last one. ## Samples Three projects under `samples/WotCon/`: * **FlatTagServer** — a plain OPC UA server exposing flat tags, used as an aggregation source. * **AggregationServer** — registers Thing Descriptions with the WoT registry and materializes two flat sources into a runtime-loaded DI/Machinery/Pumps Pump model. It also ships a small in-memory protocol binding, which is the worked example the binding contributor guide walks through. * **AggregationClient** — drives the aggregated model: commands, `Refresh`, monitoring, and generation replacement. ## Documentation * New `docs/WotBindings.md` — the bindings that ship today (planner/executor architecture, bundled vs separate packages, operation coverage, target mapping, lazy channels, generation lifetime) plus the contributor guide for adding your own, with diagnostics, tests, packaging, TFM, trimming and NativeAOT guidance. * Expanded `docs/WoTConnectivity.md` covering the registry, dependency-closure materialization and runtime NodeSet projection. * `docs/RuntimeNodeSets.md` gains the shadow-reload section and `docs/XRegistry.md` the shared byte-store section. Both document APIs introduced earlier in the stack; they are collected here because this is the documentation PR. * `docs/README.md` links the new pages. ## Solution registration Registers the three samples and `Opc.Ua.WotCon.Samples.Tests` in `UA.slnx` so CI actually builds and runs them. ## Stack position Sits on top of **#4154** (materialization) and additionally merges **#4142** (registry client) and **#4144** (protocol executors), because the samples exercise the whole stack — `AggregationServer` needs the OPC UA executor and the client sample needs the registry client. Its diff therefore shows their content until they land. It also carries `WotRegistryProjectionLiveTests.cs`, which #4154 deliberately left out: those tests need both the materialization runtime *and* the registry client, so this is the first branch where they compile. ## Validation * All three samples build clean on every target framework. * `Opc.Ua.WotCon.Tests`: **830 passed**, 0 failed (769 from #4154 plus 61 from the live projection tests). * `Opc.Ua.WotCon.Samples.Tests`: 6 of 7 pass locally; the remaining one fails with `CryptographicException: The system cannot find the path specified`, a known certificate-store problem on this machine that was previously reproduced against a clean baseline worktree and is not related to this change. CI will confirm. * 0 warnings, 0 errors. One fix was needed while bringing the sample across: its memory binding called `ResolveCodec` with the pre-`out WotPayloadDescriptor` signature. The API gained the payload out-parameter and a `bool` result during review of the binding PRs, so the sample now follows the same `if (!ResolveCodec(...)) return Unsupported(...)` pattern as the shipped planners. Integration PR: #4093.
…pace (#4154) PR 14 of the stacked series splitting the large WoT Connectivity integration PR #4093. This PR adds the server-side materialization runtime that turns WoT Thing Description resources from the xRegistry snapshot into OPC UA address-space projections. The coordinator builds the dependency closure for each resource, plans binding metadata, activates binding channels, and publishes the resulting projection through the registry NodeManager so refresh, retire, and reload operations remain observable and deterministic. Projection intentionally goes through the NodeManager lifecycle reload API instead of mutating live nodes directly. That keeps complex type reload, runtime NodeSet publication, shadow reload, immediate reload, and retirement on the same lifecycle path as other dynamic server address-space changes. This branch has a triple dependency. It is based on #4146 (registry), and additionally needs #4147 (lifecycle reload API) and #4128 (2-argument TryGetStructure). Both #4147 and #4128 are merged into this branch, so this PR's diff will show their content until those dependencies land. Validation performed: - dotnet build src\Opc.Ua.WotCon.Server\Opc.Ua.WotCon.Server.csproj -c Release -f net10.0 -v:m - dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m - dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build - dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net48 -v:m - dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net48 --no-build - dotnet build tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m - dotnet test tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build (one known inherited failure: LiveNodeManagerAddRefreshesTheClientNamespaceTable)
PR 15 of a stacked split of integration PR #4093 into independently reviewable pieces. This branch is stacked on #4139 (`marcschier/wot-10-wotcon-model`) and additionally has #4128 (`marcschier/wot-01-core-types`) and #4130 (`marcschier/wot-09-xregistry-client`) merged in so this client slice can build. Those extra dependencies are intentional: - Without #4130: `WotRegistryClient.cs:83` — `error CS1729: 'XRegistryClient' does not contain a constructor that takes 4 arguments`. - Without #4128: `WotRegistryClient.cs:346,375` and `WotRegistryResourceClient.cs:144` — `error CS1501: No overload for method 'TryGetStructure' takes 2 arguments`. The extra diff from #4128 and #4130 disappears once those PRs land. This PR adds the WoT Connectivity registry client surface for browsing and reading registry groups, resources and versions, uploading documents through FileTransfer, invoking registry methods, and registering the client through DI/builder helpers.
Adds the WoT Connectivity registry service and stores for Thing Description and Thing Model documents. This is PR 13 of the stacked split of integration PR #4093 and is stacked on #4140 (`marcschier/wot-11-bindings-core`). The materialization runtime that consumes this registry follows separately. The registry has no dependency on the binding runtime or the NodeManager lifecycle; the stacking is only because this change shares the WoT Connectivity server project file with the preceding PRs. Validation: - `dotnet build src\Opc.Ua.WotCon.Server\Opc.Ua.WotCon.Server.csproj -c Release -f net10.0 -v:m` - `dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m` - `dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build -v:q` - `dotnet build src\Opc.Ua.WotCon.Server\Opc.Ua.WotCon.Server.csproj -c Release -v:m`
## Summary - Adds the concrete WoT binding transport executors for HTTP, Modbus TCP, OPC UA and MQTT. - Includes executor/channel tests and in-process HTTP, Modbus, MQTT and OPC UA harness coverage. - Leaves CoAP, BACnet, PROFINET and LoRaWAN planner-only because this stack split intentionally lands validation/planning before executable transports. ## Stack context This is PR 12 of the stacked split of integration PR #4093. It is stacked on #4140, where the protocol-agnostic planner layer landed separately, so this PR is limited to the concrete transport implementations. ## Validation - `dotnet build tests\Opc.Ua.WotCon.Bindings.Tests\Opc.Ua.WotCon.Bindings.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m` - `dotnet test tests\Opc.Ua.WotCon.Bindings.Tests\Opc.Ua.WotCon.Bindings.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build` (512 passed) - `dotnet build src\Opc.Ua.WotCon.Bindings\Opc.Ua.WotCon.Bindings.csproj -c Release -v:m` - `dotnet build src\Opc.Ua.WotCon.Bindings.Mqtt\Opc.Ua.WotCon.Bindings.Mqtt.csproj -c Release -v:m`
## Summary PR 11 of the stacked split for integration PR #4093. This adds the protocol-agnostic core of `Opc.Ua.WotCon.Bindings`: binder, planner, executor and channel-factory contracts; payload codec and credential provider seams; the binding plan model; polling subscriptions for forms without native observation; and DI/builder registration helpers. This PR is stacked on #4139, which itself depends on #4132 and #4134. ## Scope The included planners validate forms and produce binding plans without transport I/O: - HTTP planner and validation only; the concrete HTTP executor follows in the next PR. - MQTT planner and validation only; the separate MQTT executor package follows in the next PR. - Modbus TCP planner and shared Modbus type/limit definitions only; the Modbus executor and TCP client follow in the next PR. - OPC UA planner and validation only; the concrete OPC UA executor follows in the next PR. - CoAP, BACnet, PROFINET and LoRaWAN are planner/validation-only in this split. Keeping concrete transport executors out of this PR makes the abstractions and planning layer reviewable without a network stack. ## Validation - `dotnet build tests\Opc.Ua.WotCon.Bindings.Tests\Opc.Ua.WotCon.Bindings.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m` - `dotnet test tests\Opc.Ua.WotCon.Bindings.Tests\Opc.Ua.WotCon.Bindings.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build` - `dotnet build src\Opc.Ua.WotCon.Bindings\Opc.Ua.WotCon.Bindings.csproj -c Release -v:m`
This is PR 10 of the stacked split of integration PR #4093 into independently reviewable pieces. Stack/dependency shape: - This branch is stacked on #4134 (`marcschier/wot-04-generator-wot`). - It also requires #4132 (`marcschier/wot-02-sourcegen`), which is merged into this branch so the model can build. The #4132 dependency is functional, not cosmetic. Without #4132, building the WoT Connectivity model on #4134 alone fails with duplicate generated declarations, for example: ```text CS0102: The type 'Methods' already contains a definition for 'CreateAssetMethodType' ``` That occurs because the combined WoT-Con NodeSet ships the 1.02 `CreateAssetMethodType` node explicitly; without #4132's NodeSet-to-ModelDesign fix, the generator synthesizes a second declaration with the same name. Once #4132 and #4134 land, the extra diff from those dependencies disappears and this PR reduces to the three WoT Connectivity model files: - `src\Opc.Ua.WotCon\Design\Opc.Ua.WotCon.NodeSet2.xml` - `src\Opc.Ua.WotCon\Design\Opc.Ua.WotCon.NodeSet2.csv` - `src\Opc.Ua.WotCon\Opc.Ua.WotCon.csproj` The generated C# is produced from the pinned NodeSet2 at build time. I verified it builds from clean after deleting the WotCon `bin`/`obj`, the source-generation tool `bin`/`obj` directories, and shutting down dotnet build servers.
This extracts the xRegistry client generalisation from #4093 as PR 9 of the stacked split into independently reviewable pieces. The change lets the xRegistry client base accept an explicit registry root NodeId while preserving the existing well-known-root default. GenericXRegistryClient exposes the same explicit-root path so callers can drive registries whose root Object is discovered separately, and the tests cover the supplied-root and fallback behavior across the lifecycle helpers. This PR is independent of the other stack PRs and contains no WoT registry implementation or Opc.Ua.WotCon.* references. A later PR adds the WoT registry client on top of this general xRegistry client surface.
…4150) This is PR 7 of the stacked series splitting integration PR #4093, stacked on #4147 (`marcschier/wot-05-lifecycle`). This PR makes subscription transfer between sessions transactional: subscriptions are prepared before any ownership move, publish-queue transfer claims block stale source-session publishing, and rollback restores monitored-item resend-data trigger state. `ServerInternalData` also gains asynchronous disposal so the asynchronously disposable subscription manager is shut down without blocking, with sync and async dispose paths guarded so repeated disposal is a no-op. It also brings the transfer-focused coverage for subscription transfer, publish-queue transfer claims, and `ServerInternalData` async/double-disposal behavior. The immediate monitored-item retirement mechanism present in #4093 is deliberately excluded per maintainer decision. `IRetirableMonitoredItem` and `INodeManagerMonitoredItemRetirementTracker` do not appear in this PR.
## Summary Adds PR 5 of the stack splitting #4093 into independently reviewable pieces, targeting `master` directly. This PR extends the NodeManager lifecycle with live shadow reload support and RuntimeNodeSet lifecycle helpers. `ShadowReloadAsync` stages a replacement generation and routes new service requests to it while monitored items already owned by the retired generation continue there until subscriptions drain. `ImmediateReloadAsync` keeps the immediate policy but implements it on the existing detach machinery at the maintainer's request: affected non-durable monitored items are detached/marked deleted with `IDetachableMonitoredItem`, queue `BadNodeIdUnknown`, and are not migrated to the replacement generation. The prior NodeManager generation is disposed before `ImmediateReloadAsync` returns in the covered lifecycle path. The bespoke permanent retirement-error path is intentionally removed, so follow-up operations use the existing detached-item semantics rather than a separate retirement state. ## Validation - `dotnet build src\Opc.Ua.Server\Opc.Ua.Server.csproj -c Release -f net10.0 -v:m` - `dotnet build tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m` - `dotnet test tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build` — 3914 passed, 9 skipped, 0 failed - `dotnet build tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net48 -v:m` - `dotnet test tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c Release -p:CustomTestTarget=net48 --no-build` — full run hit local durable queue file-lock flake; the failed test passed in isolation. Full run otherwise reported 3913 passed, 9 skipped, 1 failed.
…files (#4134) ## Summary - Adds WoT Thing Description and Thing Model AdditionalFiles support to Opc.Ua.SourceGeneration for .tm.json, .td.json, .tm.jsonld, .td.jsonld, and explicitly opted-in .jsonld inputs. - Converts WoT inputs to an in-memory UANodeSet and reuses the existing NodeSet generation pipeline for constants, node states, and proxies. - Reports parsing, conversion, and virtual path collision failures as MODELGEN030 through MODELGEN034 diagnostics instead of generator exceptions. ## Stack context This is PR 4 of the stacked split of integration PR #4093. It is stacked on #4131 (`marcschier/wot-03-converter`) and should be reviewed and merged after that PR. The source-generation entry-point project is included whole in this PR because its final state is irreducibly WoT-coupled. The genuinely generic generator work lives in the separate PR 2 branch. ## Notes Roslyn source generators must run synchronously. This PR drives WoT conversion through the converter's synchronous entry point and does not use the asynchronous resolver contracts from generator code. ## Validation - `dotnet build tools\Opc.Ua.SourceGeneration\Opc.Ua.SourceGeneration.csproj -c Release -v:m` - `dotnet build tests\Opc.Ua.SourceGeneration.Tests\Opc.Ua.SourceGeneration.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m` - `dotnet test tests\Opc.Ua.SourceGeneration.Tests\Opc.Ua.SourceGeneration.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build` - `dotnet build tests\Opc.Ua.SourceGeneration.Tests\Opc.Ua.SourceGeneration.Tests.csproj -c Release -p:CustomTestTarget=net48 -v:m` - `dotnet test tests\Opc.Ua.SourceGeneration.Tests\Opc.Ua.SourceGeneration.Tests.csproj -c Release -p:CustomTestTarget=net48 --no-build`
…ation, Server and xRegistry work it builds on (#4128) ## Summary Adds OPC UA WoT Connectivity 1.1 to the stack, together with the Types, source generation, Server and xRegistry work it is built on. This branch is the merge point for the fourteen-PR stack that replaced integration PR #4093; every constituent PR was reviewed and approved separately and is listed below. 414 files changed, +108,936 / -3,199. Roughly 46k added lines of product code, 57k of tests, plus samples, tools and documentation. ## Types - Complete `ExtensionObject` raw-body decoding for binary, XML and JSON bodies by resolving the concrete type through the message context's encodeable factory, and simplify the `Variant` structure helpers by delegating to it (#4128). - Add `IAtomicFileReplace` as an optional `IFileSystem` capability so existing external implementations keep working, with atomic publish for `LocalFileSystem` via `File.Replace`/`File.Move` and for `VirtualFileSystem` by re-keying the in-memory entry (#4128). - Add lossless conversion between WoT documents and NodeSet2 (`Opc.Ua.Wot.WotNodeSetConverter`). A byte-exact `uav:nodeSet` envelope is preserved when requested, the structured `uav:nodes` projection is used when the readable vocabulary is incomplete, and NodeSet2 is otherwise synthesized from readable WoT terms. Unmapped JSON members survive a round trip as pointer-addressed residue (#4131). ## Source generation - Improve the NodeSet to ModelDesign conversion and the generated node state (#4132). - Generate OPC UA models directly from WoT Thing Description files (#4134). ## Server - Add live NodeManager shadow and immediate reload. A reload materializes a new generation beside the active one and switches atomically; the superseded generation is retired gracefully so existing MonitoredItems keep being served until they drain, or immediately when the caller asks for it. Includes the request admission and drain machinery that lets an orderly shutdown wait for admitted requests instead of tearing down underneath them (#4147). - Make subscription transfer between sessions transactional, so a failed transfer leaves neither session holding a partially moved subscription (#4150). ## xRegistry - Allow clients to use explicit registry roots rather than assuming a well-known location (#4130). ## WoT Connectivity - Add the WoT Connectivity 1.1 information model: a registry-first revision layered on the abstract xRegistry base model, incorporating the complete published OPC 10100-1 v1.02 surface as deprecated nodes in the same namespace so existing 1.02 clients keep working (#4139). - Add the protocol binding abstractions and planners that compile WoT forms into executable plans (#4140). - Add the HTTP, Modbus, OPC UA and MQTT binding executors (#4144). - Add the registry and its stores, including document versioning, validation, dependency resolution and refresh (#4146). - Add the registry client (#4142). - Materialize WoT Thing Descriptions into the server address space, deriving types from Thing Models and instances from Thing Descriptions (#4154). - Restore the WoT asset registry bridge so the deprecated 1.02 asset surface is backed by the registry (#4171). - Add the WoT Connectivity samples and complete the documentation (#4156), and restore the remaining coverage and docs (#4172). ## New projects `src/Opc.Ua.WotCon.Bindings`, `src/Opc.Ua.WotCon.Bindings.Mqtt`, `tests/Opc.Ua.WotCon.Bindings.Tests`, `tests/Opc.Ua.WotCon.Samples.Tests`, and the `samples/WotCon` AggregationServer, AggregationClient and FlatTagServer samples. ## Constituent pull requests Merged into this branch top-down, each independently approved: | PR | Title | | --- | --- | | #4128 | [Types] Complete ExtensionObject decoding and add an atomic file replace capability | | #4131 | [Types] Add lossless conversion between WoT documents and NodeSet2 | | #4132 | [SourceGeneration] Improve NodeSet to ModelDesign conversion and generated node state | | #4134 | [SourceGeneration] Generate OPC UA models from WoT Thing Description files | | #4147 | [Server] Add live NodeManager shadow and immediate reload | | #4150 | [Server] Make subscription transfer between sessions transactional | | #4130 | [XRegistry] Allow clients to use explicit registry roots | | #4139 | [WotCon] Add the WoT Connectivity 1.1 information model | | #4140 | [WotCon] Add the WoT protocol binding abstractions and planners | | #4144 | [WotCon] Add the HTTP, Modbus, OPC UA and MQTT binding executors | | #4146 | [WotCon] Add the WoT Connectivity registry and its stores | | #4142 | [WotCon] Add the WoT Connectivity registry client | | #4154 | [WotCon] Materialize WoT Thing Descriptions into the server address space | | #4156 | [WotCon] Add the WoT Connectivity samples and complete the documentation | | #4171 | Restore WoT asset registry bridge | | #4172 | Restore WoT coverage and docs | Supersedes #4093. ## Follow-up The WoT Connectivity and WoT Binding drafts have moved to 1.1-draft2 since this work was authored. Aligning with that revision - the removed group vocabulary, the new projection/View construct, the remaining model vocabulary terms and the two new portable-identity validation rules - is tracked separately and will follow in its own pull request. ## Validation Built for every target framework with zero warnings and zero errors, and validated at the tip of the stack with `Opc.Ua.WotCon.Tests` at 999 passed / 0 failed and `Opc.Ua.Server.Tests` at 4024 passed / 0 failed. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Summary
Stack context
This is PR 2 of a stacked split of integration PR #4093 into independently reviewable pieces. This PR is independent of the other stack PRs and contains no WoT content.
Validation
dotnet build tests\Opc.Ua.SourceGeneration.Core.Tests\Opc.Ua.SourceGeneration.Core.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:mdotnet test tests\Opc.Ua.SourceGeneration.Core.Tests\Opc.Ua.SourceGeneration.Core.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-builddotnet build tests\Opc.Ua.SourceGeneration.Core.Tests\Opc.Ua.SourceGeneration.Core.Tests.csproj -c Release -p:CustomTestTarget=net48 -v:mdotnet test tests\Opc.Ua.SourceGeneration.Core.Tests\Opc.Ua.SourceGeneration.Core.Tests.csproj -c Release -p:CustomTestTarget=net48 --no-builddotnet build src\Opc.Ua.ISA95\Opc.Ua.ISA95.csproj -c Release -f net10.0 -v:msrc\Opc.Ua.ISA95\Design\Common\Opc.ISA95.NodeIds.csvwith no unstaged regeneration diff.