Phase 0 — mechanical rename ZB.MOM.WW.LmxOpcUa.* → ZB.MOM.WW.OtOpcUa.*

Renames all 11 projects (5 src + 6 tests), the .slnx solution file, all source-file namespaces, all axaml namespace references, and all v1 documentation references in CLAUDE.md and docs/*.md (excluding docs/v2/ which is already in OtOpcUa form). Also updates the TopShelf service registration name from "LmxOpcUa" to "OtOpcUa" per Phase 0 Task 0.6.

Preserves runtime identifiers per Phase 0 Out-of-Scope rules to avoid breaking v1/v2 client trust during coexistence: OPC UA `ApplicationUri` defaults (`urn:{GalaxyName}:LmxOpcUa`), server `EndpointPath` (`/LmxOpcUa`), `ServerName` default (feeds cert subject CN), `MxAccessConfiguration.ClientName` default (defensive — stays "LmxOpcUa" for MxAccess audit-trail consistency), client OPC UA identifiers (`ApplicationName = "LmxOpcUaClient"`, `ApplicationUri = "urn:localhost:LmxOpcUaClient"`, cert directory `%LocalAppData%\LmxOpcUaClient\pki\`), and the `LmxOpcUaServer` class name (class rename out of Phase 0 scope per Task 0.5 sed pattern; happens in Phase 1 alongside `LmxNodeManager → GenericDriverNodeManager` Core extraction). 23 LmxOpcUa references retained, all enumerated and justified in `docs/v2/implementation/exit-gate-phase-0.md`.

Build clean: 0 errors, 30 warnings (lower than baseline 167). Tests at strict improvement over baseline: 821 passing / 1 failing vs baseline 820 / 2 (one flaky pre-existing failure passed this run; the other still fails — both pre-existing and unrelated to the rename). `Client.UI.Tests`, `Historian.Aveva.Tests`, `Client.Shared.Tests`, `IntegrationTests` all match baseline exactly. Exit gate compliance results recorded in `docs/v2/implementation/exit-gate-phase-0.md` with all 7 checks PASS or DEFERRED-to-PR-review (#7 service install verification needs Windows service permissions on the reviewer's box).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-04-17 13:57:47 -04:00
parent 5b8d708c58
commit 3b2defd94f
293 changed files with 841 additions and 722 deletions

View File

@@ -63,11 +63,11 @@ Key tables: `gobject` (hierarchy/deployment), `template_definition` (object cate
## Build Commands ## Build Commands
```bash ```bash
dotnet restore ZB.MOM.WW.LmxOpcUa.slnx dotnet restore ZB.MOM.WW.OtOpcUa.slnx
dotnet build ZB.MOM.WW.LmxOpcUa.slnx dotnet build ZB.MOM.WW.OtOpcUa.slnx
dotnet test ZB.MOM.WW.LmxOpcUa.slnx # all tests dotnet test ZB.MOM.WW.OtOpcUa.slnx # all tests
dotnet test tests/ZB.MOM.WW.LmxOpcUa.Tests # unit tests only dotnet test tests/ZB.MOM.WW.OtOpcUa.Tests # unit tests only
dotnet test tests/ZB.MOM.WW.LmxOpcUa.IntegrationTests # integration tests only dotnet test tests/ZB.MOM.WW.OtOpcUa.IntegrationTests # integration tests only
dotnet test --filter "FullyQualifiedName~MyTestClass.MyMethod" # single test dotnet test --filter "FullyQualifiedName~MyTestClass.MyMethod" # single test
``` ```
@@ -102,11 +102,11 @@ Use the DeepWiki MCP (`mcp__deepwiki`) to query documentation for the OPC UA .NE
## Testing ## Testing
Use the Client CLI at `src/ZB.MOM.WW.LmxOpcUa.Client.CLI/` for manual testing against the running OPC UA server. Supports connect, read, write, browse, subscribe, historyread, alarms, and redundancy commands. See `docs/Client.CLI.md` for full documentation. Use the Client CLI at `src/ZB.MOM.WW.OtOpcUa.Client.CLI/` for manual testing against the running OPC UA server. Supports connect, read, write, browse, subscribe, historyread, alarms, and redundancy commands. See `docs/Client.CLI.md` for full documentation.
```bash ```bash
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840 dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- browse -u opc.tcp://localhost:4840 -r -d 3 dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- browse -u opc.tcp://localhost:4840 -r -d 3
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- read -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- read -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode"
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" -i 500 dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" -i 500
``` ```

View File

@@ -1,17 +0,0 @@
<Solution>
<Folder Name="/src/">
<Project Path="src/ZB.MOM.WW.LmxOpcUa.Host/ZB.MOM.WW.LmxOpcUa.Host.csproj"/>
<Project Path="src/ZB.MOM.WW.LmxOpcUa.Historian.Aveva/ZB.MOM.WW.LmxOpcUa.Historian.Aveva.csproj"/>
<Project Path="src/ZB.MOM.WW.LmxOpcUa.Client.Shared/ZB.MOM.WW.LmxOpcUa.Client.Shared.csproj"/>
<Project Path="src/ZB.MOM.WW.LmxOpcUa.Client.CLI/ZB.MOM.WW.LmxOpcUa.Client.CLI.csproj"/>
<Project Path="src/ZB.MOM.WW.LmxOpcUa.Client.UI/ZB.MOM.WW.LmxOpcUa.Client.UI.csproj"/>
</Folder>
<Folder Name="/tests/">
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.Tests/ZB.MOM.WW.LmxOpcUa.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.Historian.Aveva.Tests/ZB.MOM.WW.LmxOpcUa.Historian.Aveva.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.IntegrationTests/ZB.MOM.WW.LmxOpcUa.IntegrationTests.csproj"/>
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.Client.Shared.Tests/ZB.MOM.WW.LmxOpcUa.Client.Shared.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.Client.CLI.Tests/ZB.MOM.WW.LmxOpcUa.Client.CLI.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.LmxOpcUa.Client.UI.Tests/ZB.MOM.WW.LmxOpcUa.Client.UI.Tests.csproj"/>
</Folder>
</Solution>

17
ZB.MOM.WW.OtOpcUa.slnx Normal file
View File

@@ -0,0 +1,17 @@
<Solution>
<Folder Name="/src/">
<Project Path="src/ZB.MOM.WW.OtOpcUa.Host/ZB.MOM.WW.OtOpcUa.Host.csproj"/>
<Project Path="src/ZB.MOM.WW.OtOpcUa.Historian.Aveva/ZB.MOM.WW.OtOpcUa.Historian.Aveva.csproj"/>
<Project Path="src/ZB.MOM.WW.OtOpcUa.Client.Shared/ZB.MOM.WW.OtOpcUa.Client.Shared.csproj"/>
<Project Path="src/ZB.MOM.WW.OtOpcUa.Client.CLI/ZB.MOM.WW.OtOpcUa.Client.CLI.csproj"/>
<Project Path="src/ZB.MOM.WW.OtOpcUa.Client.UI/ZB.MOM.WW.OtOpcUa.Client.UI.csproj"/>
</Folder>
<Folder Name="/tests/">
<Project Path="tests/ZB.MOM.WW.OtOpcUa.Tests/ZB.MOM.WW.OtOpcUa.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.OtOpcUa.Historian.Aveva.Tests/ZB.MOM.WW.OtOpcUa.Historian.Aveva.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.OtOpcUa.IntegrationTests/ZB.MOM.WW.OtOpcUa.IntegrationTests.csproj"/>
<Project Path="tests/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.csproj"/>
<Project Path="tests/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/ZB.MOM.WW.OtOpcUa.Client.UI.Tests.csproj"/>
</Folder>
</Solution>

View File

@@ -78,5 +78,5 @@ If no previous state is cached (first build), the full `BuildAddressSpace` path
## Key source files ## Key source files
- `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/LmxNodeManager.cs` -- Node manager with `BuildAddressSpace`, `SyncAddressSpace`, and `TopologicalSort` - `src/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LmxNodeManager.cs` -- Node manager with `BuildAddressSpace`, `SyncAddressSpace`, and `TopologicalSort`
- `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/AddressSpaceBuilder.cs` -- Testable in-memory model builder - `src/ZB.MOM.WW.OtOpcUa.Host/OpcUa/AddressSpaceBuilder.cs` -- Testable in-memory model builder

View File

@@ -2,14 +2,14 @@
## Overview ## Overview
`ZB.MOM.WW.LmxOpcUa.Client.CLI` is a cross-platform command-line client for the LmxOpcUa OPC UA server. It targets .NET 10 and uses the shared `IOpcUaClientService` from `Client.Shared` for all OPC UA operations. Commands are routed and parsed by [CliFx](https://github.com/Tyrrrz/CliFx). `ZB.MOM.WW.OtOpcUa.Client.CLI` is a cross-platform command-line client for the LmxOpcUa OPC UA server. It targets .NET 10 and uses the shared `IOpcUaClientService` from `Client.Shared` for all OPC UA operations. Commands are routed and parsed by [CliFx](https://github.com/Tyrrrz/CliFx).
The CLI is the primary tool for operators and developers to test and interact with the server from a terminal. It supports all core operations: connectivity testing, browsing, reading, writing, subscriptions, alarm monitoring, history reads, and redundancy queries. The CLI is the primary tool for operators and developers to test and interact with the server from a terminal. It supports all core operations: connectivity testing, browsing, reading, writing, subscriptions, alarm monitoring, history reads, and redundancy queries.
## Build and Run ## Build and Run
```bash ```bash
cd src/ZB.MOM.WW.LmxOpcUa.Client.CLI cd src/ZB.MOM.WW.OtOpcUa.Client.CLI
dotnet build dotnet build
dotnet run -- <command> [options] dotnet run -- <command> [options]
``` ```
@@ -240,5 +240,5 @@ Application URI: urn:localhost:LmxOpcUa:instance1
The Client CLI has 52 unit tests covering option parsing, service invocation, output formatting, and cleanup behavior: The Client CLI has 52 unit tests covering option parsing, service invocation, output formatting, and cleanup behavior:
```bash ```bash
dotnet test tests/ZB.MOM.WW.LmxOpcUa.Client.CLI.Tests dotnet test tests/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests
``` ```

View File

@@ -2,14 +2,14 @@
## Overview ## Overview
`ZB.MOM.WW.LmxOpcUa.Client.UI` is a cross-platform Avalonia desktop application for connecting to and interacting with the LmxOpcUa OPC UA server. It targets .NET 10 and uses the shared `IOpcUaClientService` from `Client.Shared` for all OPC UA operations. `ZB.MOM.WW.OtOpcUa.Client.UI` is a cross-platform Avalonia desktop application for connecting to and interacting with the LmxOpcUa OPC UA server. It targets .NET 10 and uses the shared `IOpcUaClientService` from `Client.Shared` for all OPC UA operations.
The UI provides a single-window interface for browsing the address space, reading and writing values, monitoring live subscriptions, managing alarms, and querying historical data. The UI provides a single-window interface for browsing the address space, reading and writing values, monitoring live subscriptions, managing alarms, and querying historical data.
## Build and Run ## Build and Run
```bash ```bash
cd src/ZB.MOM.WW.LmxOpcUa.Client.UI cd src/ZB.MOM.WW.OtOpcUa.Client.UI
dotnet build dotnet build
dotnet run dotnet run
``` ```
@@ -254,7 +254,7 @@ All service event handlers (data changes, alarm events, connection state changes
The UI has 102 unit tests covering ViewModel logic and headless rendering: The UI has 102 unit tests covering ViewModel logic and headless rendering:
```bash ```bash
dotnet test tests/ZB.MOM.WW.LmxOpcUa.Client.UI.Tests dotnet test tests/ZB.MOM.WW.OtOpcUa.Client.UI.Tests
``` ```
Tests use: Tests use:

View File

@@ -242,7 +242,7 @@ Three boolean properties act as feature flags that control optional subsystems:
- **`OpcUa.AlarmTrackingEnabled`** -- When `true`, the node manager creates `AlarmConditionState` nodes for alarm attributes and monitors `InAlarm` transitions. Disabled by default because alarm tracking adds per-attribute overhead. - **`OpcUa.AlarmTrackingEnabled`** -- When `true`, the node manager creates `AlarmConditionState` nodes for alarm attributes and monitors `InAlarm` transitions. Disabled by default because alarm tracking adds per-attribute overhead.
- **`OpcUa.AlarmFilter.ObjectFilters`** -- List of wildcard template-name patterns that scope alarm tracking to matching objects and their descendants. An empty list preserves the current unfiltered behavior; a non-empty list includes an object only when any name in its template derivation chain matches any pattern, then propagates the inclusion to every descendant in the containment hierarchy. `*` is the only wildcard, matching is case-insensitive, and the Galaxy `$` prefix on template names is normalized so operators can write `TestMachine*` instead of `$TestMachine*`. Each list entry may itself contain comma-separated patterns (`"TestMachine*, Pump_*"`) for convenience. When the list is non-empty but `AlarmTrackingEnabled` is `false`, the validator emits a warning because the filter has no effect. See [Alarm Tracking](AlarmTracking.md#template-based-alarm-object-filter) for the full matching algorithm and telemetry. - **`OpcUa.AlarmFilter.ObjectFilters`** -- List of wildcard template-name patterns that scope alarm tracking to matching objects and their descendants. An empty list preserves the current unfiltered behavior; a non-empty list includes an object only when any name in its template derivation chain matches any pattern, then propagates the inclusion to every descendant in the containment hierarchy. `*` is the only wildcard, matching is case-insensitive, and the Galaxy `$` prefix on template names is normalized so operators can write `TestMachine*` instead of `$TestMachine*`. Each list entry may itself contain comma-separated patterns (`"TestMachine*, Pump_*"`) for convenience. When the list is non-empty but `AlarmTrackingEnabled` is `false`, the validator emits a warning because the filter has no effect. See [Alarm Tracking](AlarmTracking.md#template-based-alarm-object-filter) for the full matching algorithm and telemetry.
- **`Historian.Enabled`** -- When `true`, the service calls `HistorianPluginLoader.TryLoad(config)` to load the `ZB.MOM.WW.LmxOpcUa.Historian.Aveva` plugin from the `Historian/` subfolder next to the host exe and registers the resulting `IHistorianDataSource` with the OPC UA server host. Disabled by default because not all deployments have a Historian instance -- when disabled the plugin is not probed and the Wonderware SDK DLLs are not required on the host. If the flag is `true` but the plugin or its SDK dependencies cannot be loaded, the server still starts and every history read returns `BadHistoryOperationUnsupported` with a warning in the log. - **`Historian.Enabled`** -- When `true`, the service calls `HistorianPluginLoader.TryLoad(config)` to load the `ZB.MOM.WW.OtOpcUa.Historian.Aveva` plugin from the `Historian/` subfolder next to the host exe and registers the resulting `IHistorianDataSource` with the OPC UA server host. Disabled by default because not all deployments have a Historian instance -- when disabled the plugin is not probed and the Wonderware SDK DLLs are not required on the host. If the flag is `true` but the plugin or its SDK dependencies cannot be loaded, the server still starts and every history read returns `BadHistoryOperationUnsupported` with a warning in the log.
- **`GalaxyRepository.ExtendedAttributes`** -- When `true`, the repository loads additional Galaxy attribute metadata beyond the core set needed for the address space. Disabled by default to minimize startup query time. - **`GalaxyRepository.ExtendedAttributes`** -- When `true`, the repository loads additional Galaxy attribute metadata beyond the core set needed for the address space. Disabled by default to minimize startup query time.
- **`GalaxyRepository.Scope`** -- When set to `LocalPlatform`, the repository filters the hierarchy and attributes to only include objects hosted by the platform whose `node_name` matches this machine (or the explicit `PlatformName` override). Ancestor areas are retained to keep the browse tree connected. Default is `Galaxy` (load everything). See [Galaxy Repository — Platform Scope Filter](GalaxyRepository.md#platform-scope-filter). - **`GalaxyRepository.Scope`** -- When set to `LocalPlatform`, the repository filters the hierarchy and attributes to only include objects hosted by the platform whose `node_name` matches this machine (or the explicit `PlatformName` override). Ancestor areas are retained to keep the browse tree connected. Default is `Galaxy` (load everything). See [Galaxy Repository — Platform Scope Filter](GalaxyRepository.md#platform-scope-filter).

View File

@@ -79,6 +79,6 @@ For historized attributes, `AccessLevels.HistoryRead` is added to the access lev
## Key source files ## Key source files
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/MxDataTypeMapper.cs` -- Type and CLR mapping - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/MxDataTypeMapper.cs` -- Type and CLR mapping
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/SecurityClassificationMapper.cs` -- Write access mapping - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/SecurityClassificationMapper.cs` -- Write access mapping
- `gr/data_type_mapping.md` -- Reference documentation for the full mapping table - `gr/data_type_mapping.md` -- Reference documentation for the full mapping table

View File

@@ -136,8 +136,8 @@ The polling approach is used because the Galaxy Repository database does not pro
## Key source files ## Key source files
- `src/ZB.MOM.WW.LmxOpcUa.Host/GalaxyRepository/GalaxyRepositoryService.cs` -- SQL queries and data access - `src/ZB.MOM.WW.OtOpcUa.Host/GalaxyRepository/GalaxyRepositoryService.cs` -- SQL queries and data access
- `src/ZB.MOM.WW.LmxOpcUa.Host/GalaxyRepository/PlatformScopeFilter.cs` -- Platform-based hierarchy and attribute filtering - `src/ZB.MOM.WW.OtOpcUa.Host/GalaxyRepository/PlatformScopeFilter.cs` -- Platform-based hierarchy and attribute filtering
- `src/ZB.MOM.WW.LmxOpcUa.Host/GalaxyRepository/ChangeDetectionService.cs` -- Deploy timestamp polling loop - `src/ZB.MOM.WW.OtOpcUa.Host/GalaxyRepository/ChangeDetectionService.cs` -- Deploy timestamp polling loop
- `src/ZB.MOM.WW.LmxOpcUa.Host/Configuration/GalaxyRepositoryConfiguration.cs` -- Connection, polling, and scope settings - `src/ZB.MOM.WW.OtOpcUa.Host/Configuration/GalaxyRepositoryConfiguration.cs` -- Connection, polling, and scope settings
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/PlatformInfo.cs` -- Platform-to-hostname DTO - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/PlatformInfo.cs` -- Platform-to-hostname DTO

View File

@@ -1,29 +1,29 @@
# Historical Data Access # Historical Data Access
`LmxNodeManager` exposes OPC UA historical data access (HDA) through an abstract `IHistorianDataSource` interface (`Historian/IHistorianDataSource.cs`). The Wonderware Historian implementation lives in a separate assembly, `ZB.MOM.WW.LmxOpcUa.Historian.Aveva`, which is loaded at runtime only when `Historian.Enabled=true`. This keeps the `aahClientManaged` SDK out of the core Host so deployments that do not need history do not need the SDK installed. `LmxNodeManager` exposes OPC UA historical data access (HDA) through an abstract `IHistorianDataSource` interface (`Historian/IHistorianDataSource.cs`). The Wonderware Historian implementation lives in a separate assembly, `ZB.MOM.WW.OtOpcUa.Historian.Aveva`, which is loaded at runtime only when `Historian.Enabled=true`. This keeps the `aahClientManaged` SDK out of the core Host so deployments that do not need history do not need the SDK installed.
## Plugin Architecture ## Plugin Architecture
The historian surface is split across two assemblies: The historian surface is split across two assemblies:
- **`ZB.MOM.WW.LmxOpcUa.Host`** (core) owns only OPC UA / BCL types: - **`ZB.MOM.WW.OtOpcUa.Host`** (core) owns only OPC UA / BCL types:
- `IHistorianDataSource` -- the interface `LmxNodeManager` depends on - `IHistorianDataSource` -- the interface `LmxNodeManager` depends on
- `HistorianEventDto` -- SDK-free representation of a historian event record - `HistorianEventDto` -- SDK-free representation of a historian event record
- `HistorianAggregateMap` -- maps OPC UA aggregate NodeIds to AnalogSummary column names - `HistorianAggregateMap` -- maps OPC UA aggregate NodeIds to AnalogSummary column names
- `HistorianPluginLoader` -- loads the plugin via `Assembly.LoadFrom` at startup - `HistorianPluginLoader` -- loads the plugin via `Assembly.LoadFrom` at startup
- `HistoryContinuationPointManager` -- paginates HistoryRead results - `HistoryContinuationPointManager` -- paginates HistoryRead results
- **`ZB.MOM.WW.LmxOpcUa.Historian.Aveva`** (plugin) owns everything SDK-bound: - **`ZB.MOM.WW.OtOpcUa.Historian.Aveva`** (plugin) owns everything SDK-bound:
- `HistorianDataSource` -- implements `IHistorianDataSource`, wraps `aahClientManaged` - `HistorianDataSource` -- implements `IHistorianDataSource`, wraps `aahClientManaged`
- `IHistorianConnectionFactory` / `SdkHistorianConnectionFactory` -- opens and polls `ArchestrA.HistorianAccess` connections - `IHistorianConnectionFactory` / `SdkHistorianConnectionFactory` -- opens and polls `ArchestrA.HistorianAccess` connections
- `AvevaHistorianPluginEntry.Create(HistorianConfiguration)` -- the static factory invoked by the loader - `AvevaHistorianPluginEntry.Create(HistorianConfiguration)` -- the static factory invoked by the loader
The plugin assembly and its SDK dependencies (`aahClientManaged.dll`, `aahClient.dll`, `aahClientCommon.dll`, `Historian.CBE.dll`, `Historian.DPAPI.dll`, `ArchestrA.CloudHistorian.Contract.dll`) deploy to a `Historian/` subfolder next to `ZB.MOM.WW.LmxOpcUa.Host.exe`. See [Service Hosting](ServiceHosting.md#required-runtime-assemblies) for the full layout and deployment matrix. The plugin assembly and its SDK dependencies (`aahClientManaged.dll`, `aahClient.dll`, `aahClientCommon.dll`, `Historian.CBE.dll`, `Historian.DPAPI.dll`, `ArchestrA.CloudHistorian.Contract.dll`) deploy to a `Historian/` subfolder next to `ZB.MOM.WW.OtOpcUa.Host.exe`. See [Service Hosting](ServiceHosting.md#required-runtime-assemblies) for the full layout and deployment matrix.
## Plugin Loading ## Plugin Loading
When the service starts with `Historian.Enabled=true`, `OpcUaService` calls `HistorianPluginLoader.TryLoad(config)`. The loader: When the service starts with `Historian.Enabled=true`, `OpcUaService` calls `HistorianPluginLoader.TryLoad(config)`. The loader:
1. Probes `AppDomain.CurrentDomain.BaseDirectory\Historian\ZB.MOM.WW.LmxOpcUa.Historian.Aveva.dll`. 1. Probes `AppDomain.CurrentDomain.BaseDirectory\Historian\ZB.MOM.WW.OtOpcUa.Historian.Aveva.dll`.
2. Installs a one-shot `AppDomain.AssemblyResolve` handler that redirects any `aahClientManaged`/`aahClientCommon`/`Historian.*` lookups to the same subfolder, so the CLR can resolve SDK dependencies when the plugin first JITs. 2. Installs a one-shot `AppDomain.AssemblyResolve` handler that redirects any `aahClientManaged`/`aahClientCommon`/`Historian.*` lookups to the same subfolder, so the CLR can resolve SDK dependencies when the plugin first JITs.
3. Calls the plugin's `AvevaHistorianPluginEntry.Create(HistorianConfiguration)` via reflection and returns the resulting `IHistorianDataSource`. 3. Calls the plugin's `AvevaHistorianPluginEntry.Create(HistorianConfiguration)` via reflection and returns the resulting `IHistorianDataSource`.
4. On any failure (plugin missing, entry type not found, SDK assembly unresolvable, bad image), logs a warning with the expected plugin path and returns `null`. The server starts normally and `LmxNodeManager` returns `BadHistoryOperationUnsupported` for every history call. 4. On any failure (plugin missing, entry type not found, SDK assembly unresolvable, bad image), logs a warning with the expected plugin path and returns `null`. The server starts normally and `LmxNodeManager` returns `BadHistoryOperationUnsupported` for every history call.
@@ -35,7 +35,7 @@ The plugin uses the AVEVA Historian managed SDK (`aahClientManaged.dll`) to quer
- **`HistoryQuery`** -- Raw historical samples with timestamp, value (numeric or string), and OPC quality. - **`HistoryQuery`** -- Raw historical samples with timestamp, value (numeric or string), and OPC quality.
- **`AnalogSummaryQuery`** -- Pre-computed aggregates with properties for Average, Minimum, Maximum, ValueCount, First, Last, StdDev, and more. - **`AnalogSummaryQuery`** -- Pre-computed aggregates with properties for Average, Minimum, Maximum, ValueCount, First, Last, StdDev, and more.
The SDK DLLs are located in `lib/` and originate from `C:\Program Files (x86)\Wonderware\Historian\`. Only the plugin project (`src/ZB.MOM.WW.LmxOpcUa.Historian.Aveva/`) references them at build time; the core Host project does not. The SDK DLLs are located in `lib/` and originate from `C:\Program Files (x86)\Wonderware\Historian\`. Only the plugin project (`src/ZB.MOM.WW.OtOpcUa.Historian.Aveva/`) references them at build time; the core Host project does not.
## Configuration ## Configuration

View File

@@ -152,15 +152,15 @@ The .NET runtime's garbage collector releases COM references non-deterministical
## Key source files ## Key source files
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/StaComThread.cs` -- STA thread and Win32 message pump - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/StaComThread.cs` -- STA thread and Win32 message pump
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.cs` -- Core client class (partial) - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.cs` -- Core client class (partial)
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.Connection.cs` -- Connect, disconnect, reconnect - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.Connection.cs` -- Connect, disconnect, reconnect
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.Subscription.cs` -- Subscribe, unsubscribe, replay - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.Subscription.cs` -- Subscribe, unsubscribe, replay
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.ReadWrite.cs` -- Read and write operations - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.ReadWrite.cs` -- Read and write operations
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.EventHandlers.cs` -- OnDataChange and OnWriteComplete handlers - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.EventHandlers.cs` -- OnDataChange and OnWriteComplete handlers
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxAccessClient.Monitor.cs` -- Background health monitor - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxAccessClient.Monitor.cs` -- Background health monitor
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/MxProxyAdapter.cs` -- COM object wrapper - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/MxProxyAdapter.cs` -- COM object wrapper
- `src/ZB.MOM.WW.LmxOpcUa.Host/MxAccess/GalaxyRuntimeProbeManager.cs` -- Per-host `ScanState` probes, state machine, `IsHostStopped` lookup - `src/ZB.MOM.WW.OtOpcUa.Host/MxAccess/GalaxyRuntimeProbeManager.cs` -- Per-host `ScanState` probes, state machine, `IsHostStopped` lookup
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/GalaxyRuntimeStatus.cs` -- Per-host DTO - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/GalaxyRuntimeStatus.cs` -- Per-host DTO
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/GalaxyRuntimeState.cs` -- `Unknown` / `Running` / `Stopped` enum - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/GalaxyRuntimeState.cs` -- `Unknown` / `Running` / `Stopped` enum
- `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/IMxAccessClient.cs` -- Client interface - `src/ZB.MOM.WW.OtOpcUa.Host/Domain/IMxAccessClient.cs` -- Client interface

View File

@@ -130,8 +130,8 @@ On startup, `OpcUaServerHost.StartAsync` calls `CheckApplicationInstanceCertific
## Key source files ## Key source files
- `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/OpcUaServerHost.cs` -- Application lifecycle and programmatic configuration - `src/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OpcUaServerHost.cs` -- Application lifecycle and programmatic configuration
- `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/LmxOpcUaServer.cs` -- StandardServer subclass and node manager creation - `src/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LmxOpcUaServer.cs` -- StandardServer subclass and node manager creation
- `src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/SecurityProfileResolver.cs` -- Profile-name to ServerSecurityPolicy mapping - `src/ZB.MOM.WW.OtOpcUa.Host/OpcUa/SecurityProfileResolver.cs` -- Profile-name to ServerSecurityPolicy mapping
- `src/ZB.MOM.WW.LmxOpcUa.Host/Configuration/OpcUaConfiguration.cs` -- Configuration POCO - `src/ZB.MOM.WW.OtOpcUa.Host/Configuration/OpcUaConfiguration.cs` -- Configuration POCO
- `src/ZB.MOM.WW.LmxOpcUa.Host/Configuration/SecurityProfileConfiguration.cs` -- Security configuration POCO - `src/ZB.MOM.WW.OtOpcUa.Host/Configuration/SecurityProfileConfiguration.cs` -- Security configuration POCO

View File

@@ -138,8 +138,8 @@ When deploying a redundant pair, the following configuration properties must dif
The Client CLI includes a `redundancy` command that reads the redundancy state from a running server. The Client CLI includes a `redundancy` command that reads the redundancy state from a running server.
```bash ```bash
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- redundancy -u opc.tcp://localhost:4840/LmxOpcUa dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- redundancy -u opc.tcp://localhost:4840/LmxOpcUa
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- redundancy -u opc.tcp://localhost:4841/LmxOpcUa dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- redundancy -u opc.tcp://localhost:4841/LmxOpcUa
``` ```
The command reads the following standard OPC UA nodes and displays their values: The command reads the following standard OPC UA nodes and displays their values:

View File

@@ -32,11 +32,11 @@ TopShelf provides these deployment modes from the same executable:
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `LmxOpcUa.Host.exe` | Run as a console application (foreground) | | `OtOpcUa.Host.exe` | Run as a console application (foreground) |
| `LmxOpcUa.Host.exe install` | Install as a Windows service | | `OtOpcUa.Host.exe install` | Install as a Windows service |
| `LmxOpcUa.Host.exe uninstall` | Remove the Windows service | | `OtOpcUa.Host.exe uninstall` | Remove the Windows service |
| `LmxOpcUa.Host.exe start` | Start the installed service | | `OtOpcUa.Host.exe start` | Start the installed service |
| `LmxOpcUa.Host.exe stop` | Stop the installed service | | `OtOpcUa.Host.exe stop` | Stop the installed service |
The service is configured to run as `LocalSystem` and start automatically on boot. The service is configured to run as `LocalSystem` and start automatically on boot.
@@ -146,26 +146,26 @@ Install additional instances using TopShelf's `-servicename` flag:
```bash ```bash
cd C:\publish\lmxopcua\instance2 cd C:\publish\lmxopcua\instance2
ZB.MOM.WW.LmxOpcUa.Host.exe install -servicename "LmxOpcUa2" -displayname "LMX OPC UA Server (Instance 2)" ZB.MOM.WW.OtOpcUa.Host.exe install -servicename "LmxOpcUa2" -displayname "LMX OPC UA Server (Instance 2)"
``` ```
See [Redundancy Guide](Redundancy.md) for full deployment details. See [Redundancy Guide](Redundancy.md) for full deployment details.
## Required Runtime Assemblies ## Required Runtime Assemblies
The build uses Costura.Fody to embed all NuGet dependencies into the single `ZB.MOM.WW.LmxOpcUa.Host.exe`. The only native dependency that must sit alongside the executable in every deployment is the MXAccess COM toolkit: The build uses Costura.Fody to embed all NuGet dependencies into the single `ZB.MOM.WW.OtOpcUa.Host.exe`. The only native dependency that must sit alongside the executable in every deployment is the MXAccess COM toolkit:
| Assembly | Purpose | | Assembly | Purpose |
|----------|---------| |----------|---------|
| `ArchestrA.MxAccess.dll` | MXAccess COM interop — runtime data access to Galaxy tags | | `ArchestrA.MxAccess.dll` | MXAccess COM interop — runtime data access to Galaxy tags |
The Wonderware Historian SDK is packaged as a **runtime-loaded plugin** so hosts that will not use historical data access do not need the SDK installed. The plugin lives in a `Historian/` subfolder next to `ZB.MOM.WW.LmxOpcUa.Host.exe`: The Wonderware Historian SDK is packaged as a **runtime-loaded plugin** so hosts that will not use historical data access do not need the SDK installed. The plugin lives in a `Historian/` subfolder next to `ZB.MOM.WW.OtOpcUa.Host.exe`:
``` ```
ZB.MOM.WW.LmxOpcUa.Host.exe ZB.MOM.WW.OtOpcUa.Host.exe
ArchestrA.MxAccess.dll ArchestrA.MxAccess.dll
Historian/ Historian/
ZB.MOM.WW.LmxOpcUa.Historian.Aveva.dll ZB.MOM.WW.OtOpcUa.Historian.Aveva.dll
aahClientManaged.dll aahClientManaged.dll
aahClientCommon.dll aahClientCommon.dll
aahClient.dll aahClient.dll
@@ -174,7 +174,7 @@ Historian/
ArchestrA.CloudHistorian.Contract.dll ArchestrA.CloudHistorian.Contract.dll
``` ```
At startup, if `Historian.Enabled=true` in `appsettings.json`, `HistorianPluginLoader` probes `Historian/ZB.MOM.WW.LmxOpcUa.Historian.Aveva.dll` via `Assembly.LoadFrom` and instantiates the plugin's entry point. An `AppDomain.AssemblyResolve` handler redirects the SDK assembly lookups (`aahClientManaged`, `aahClientCommon`, …) to the same subfolder so the CLR can resolve them when the plugin first JITs. If the plugin directory is absent or any SDK dependency fails to load, the loader logs a warning and the server continues to run with history support disabled — `LmxNodeManager` returns `BadHistoryOperationUnsupported` for every history call. At startup, if `Historian.Enabled=true` in `appsettings.json`, `HistorianPluginLoader` probes `Historian/ZB.MOM.WW.OtOpcUa.Historian.Aveva.dll` via `Assembly.LoadFrom` and instantiates the plugin's entry point. An `AppDomain.AssemblyResolve` handler redirects the SDK assembly lookups (`aahClientManaged`, `aahClientCommon`, …) to the same subfolder so the CLR can resolve them when the plugin first JITs. If the plugin directory is absent or any SDK dependency fails to load, the loader logs a warning and the server continues to run with history support disabled — `LmxNodeManager` returns `BadHistoryOperationUnsupported` for every history call.
Deployment matrix: Deployment matrix:

View File

@@ -8,12 +8,12 @@ Three new .NET 10 cross-platform projects providing a shared OPC UA client libra
| Project | Type | Purpose | | Project | Type | Purpose |
|---------|------|---------| |---------|------|---------|
| `ZB.MOM.WW.LmxOpcUa.Client.Shared` | Class library | Core OPC UA client, models, interfaces | | `ZB.MOM.WW.OtOpcUa.Client.Shared` | Class library | Core OPC UA client, models, interfaces |
| `ZB.MOM.WW.LmxOpcUa.Client.CLI` | Console app | Command-line interface using CliFx | | `ZB.MOM.WW.OtOpcUa.Client.CLI` | Console app | Command-line interface using CliFx |
| `ZB.MOM.WW.LmxOpcUa.Client.UI` | Avalonia app | Desktop UI with tree browser, subscriptions, alarms | | `ZB.MOM.WW.OtOpcUa.Client.UI` | Avalonia app | Desktop UI with tree browser, subscriptions, alarms |
| `ZB.MOM.WW.LmxOpcUa.Client.Shared.Tests` | Test project | Unit tests for shared library | | `ZB.MOM.WW.OtOpcUa.Client.Shared.Tests` | Test project | Unit tests for shared library |
| `ZB.MOM.WW.LmxOpcUa.Client.CLI.Tests` | Test project | Unit tests for CLI commands | | `ZB.MOM.WW.OtOpcUa.Client.CLI.Tests` | Test project | Unit tests for CLI commands |
| `ZB.MOM.WW.LmxOpcUa.Client.UI.Tests` | Test project | Unit tests for UI view models | | `ZB.MOM.WW.OtOpcUa.Client.UI.Tests` | Test project | Unit tests for UI view models |
## Technology Stack ## Technology Stack

View File

@@ -9,8 +9,8 @@ The application shall use TopShelf for Windows service lifecycle (install, unins
### Acceptance Criteria ### Acceptance Criteria
- TopShelf HostFactory configures the service with name `LmxOpcUa`, display name `LMX OPC UA Server`. - TopShelf HostFactory configures the service with name `LmxOpcUa`, display name `LMX OPC UA Server`.
- Service installs via command line: `ZB.MOM.WW.LmxOpcUa.Host.exe install`. - Service installs via command line: `ZB.MOM.WW.OtOpcUa.Host.exe install`.
- Service uninstalls via: `ZB.MOM.WW.LmxOpcUa.Host.exe uninstall`. - Service uninstalls via: `ZB.MOM.WW.OtOpcUa.Host.exe uninstall`.
- Service runs as LocalSystem account (needed for MXAccess COM access and Windows Auth to SQL Server). - Service runs as LocalSystem account (needed for MXAccess COM access and Windows Auth to SQL Server).
- Interactive console mode (exe with no args) works for development/debugging. - Interactive console mode (exe with no args) works for development/debugging.
- `StartAutomatically` is set for Windows service registration. - `StartAutomatically` is set for Windows service registration.

View File

@@ -110,7 +110,7 @@ The dashboard shall display a footer with last-updated time and service identifi
### Acceptance Criteria ### Acceptance Criteria
- Format: "Last updated: {timestamp} UTC | Service: ZB.MOM.WW.LmxOpcUa.Host v{version}". - Format: "Last updated: {timestamp} UTC | Service: ZB.MOM.WW.OtOpcUa.Host v{version}".
- Timestamp is the server-side UTC time when the HTML was generated. - Timestamp is the server-side UTC time when the HTML was generated.
- Version is read from the assembly version (`Assembly.GetExecutingAssembly().GetName().Version`). - Version is read from the assembly version (`Assembly.GetExecutingAssembly().GetName().Version`).

View File

@@ -211,19 +211,19 @@ The Client CLI supports the `-S` (or `--security`) flag to select the transport
### Connect with no security ### Connect with no security
```bash ```bash
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S none dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S none
``` ```
### Connect with signing ### Connect with signing
```bash ```bash
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S sign dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S sign
``` ```
### Connect with signing and encryption ### Connect with signing and encryption
```bash ```bash
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S encrypt dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840/LmxOpcUa -S encrypt
``` ```
### Browse with encryption and authentication ### Browse with encryption and authentication

View File

@@ -0,0 +1,119 @@
# Phase 0 — Exit Gate Record
**Phase**: 0 — Rename + .NET 10 cleanup
**Branch**: `phase-0-rename`
**Date**: 2026-04-17
**Implementation lead**: Claude (executing on behalf of dohertj2)
**Reviewer**: pending — PR review required before merge
## Compliance check results
### 1. No stale `LmxOpcUa` references (with allowlist)
Total `LmxOpcUa` references in `src/` + `tests/` (excluding `bin/`, `obj/`, `publish_temp/`, `docs/v2/`): **23**.
All 23 are **allowlisted retentions** per Phase 0 Out-of-Scope rules:
| File / line | Reference | Reason for retention |
|-------------|-----------|----------------------|
| `Client.CLI/Program.cs:13` | `"LmxOpcUa CLI - command-line client for the LmxOpcUa OPC UA server"` | CLI `--help` description; cosmetic, references the runtime server name which stays `LmxOpcUa` |
| `Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs:21,22,63` | `ApplicationName = "LmxOpcUaClient"`, `ApplicationUri = "urn:localhost:LmxOpcUaClient"` | OPC UA client identity. Per Phase 0 out-of-scope rule: `ApplicationUri` defaults stay to preserve v1/v2 client trust |
| `Client.Shared/Models/ConnectionSettings.cs:48` | `"LmxOpcUaClient", "pki"` | Client cert directory name `%LocalAppData%\LmxOpcUaClient\pki\`. Changing it would re-trigger trust handshake with all v1 servers |
| `Client.Shared/OpcUaClientService.cs:428` | `CreateSessionAsync(..., "LmxOpcUaClient", ...)` | OPC UA client session name |
| `Client.UI/Services/JsonSettingsService.cs:12` | `"LmxOpcUaClient"` | Client UI app-data folder; same rationale as cert path |
| `Client.UI/ViewModels/MainWindowViewModel.cs:26` | `"LmxOpcUaClient", "pki"` | Same cert path |
| `Client.UI/Views/MainWindow.axaml:81` | `Watermark="(default: AppData/LmxOpcUaClient/pki)"` | UI hint text reflecting the actual default cert path |
| `Host/appsettings.json:5` | `"EndpointPath": "/LmxOpcUa"` | OPC UA endpoint path; clients connect to `opc.tcp://host:port/LmxOpcUa`. Changing breaks v1 client connections |
| `Host/appsettings.json:6` | `"ServerName": "LmxOpcUa"` | Server's OPC UA `ApplicationName` and cert subject CN. Changing changes cert CN on regen, breaks v1 client trust |
| `Host/appsettings.json:17` | `"ClientName": "LmxOpcUa"` | OUR registration name to MxAccess. Defensive retention for audit trail consistency during v1/v2 coexistence |
| `Host/Configuration/MxAccessConfiguration.cs:11` | `ClientName default = "LmxOpcUa"` | Code default matching appsettings |
| `Host/Configuration/OpcUaConfiguration.cs:22` | `EndpointPath default = "/LmxOpcUa"` | Code default matching appsettings |
| `Host/Configuration/OpcUaConfiguration.cs:27` | `ServerName default = "LmxOpcUa"` | Code default matching appsettings |
| `Host/Configuration/OpcUaConfiguration.cs:36` | XML doc comment referencing `urn:{GalaxyName}:LmxOpcUa` ApplicationUri default | Documentation of behavior; the behavior itself is intentionally retained |
| `Host/OpcUa/LmxOpcUaServer.cs:17,19,45` | Class name `LmxOpcUaServer` | Class rename out of Phase 0 scope. Phase 0 Task 0.5 patterns rename only `ZB\.MOM\.WW\.LmxOpcUa` namespace prefix; bare class names stay. Class rename happens in Phase 1's `LmxNodeManager → GenericDriverNodeManager` work alongside the rest of the Core extraction |
| `Host/OpcUa/LmxOpcUaServer.cs:101,520` | `namespaceUri = $"urn:{_galaxyName}:LmxOpcUa"`, `ProductUri = $"urn:{_galaxyName}:LmxOpcUa"` | OPC UA `ApplicationUri` default derivation per Phase 0 out-of-scope rule |
| `Host/OpcUa/LmxOpcUaServer.cs:519` | `ProductName = "LmxOpcUa Server"` | OPC UA server identity string |
| `Host/OpcUa/OpcUaServerHost.cs:33,144,247` | References to `LmxOpcUaServer` class + `urn:{GalaxyName}:LmxOpcUa` URI | Same class-rename + URI-default rules |
**No unauthorized stale references.** Result: ✅ PASS
### 2. Build succeeds
```
dotnet build ZB.MOM.WW.OtOpcUa.slnx
```
Result: **0 errors, 30 warnings.** Warning count is *lower* than baseline (167) — the rename did not introduce new warnings; the baseline included repeated emissions across multiple build passes that cleared on the rename build. ✅ PASS
### 3. All tests pass at or above baseline
| Test project | Baseline (pass / fail) | Phase 0 result | Verdict |
|--------------|------------------------|----------------|---------|
| `Client.UI.Tests` | 98 / 0 | 98 / 0 | ✅ |
| `Client.CLI.Tests` | 51 / 1 | 51 / 1 | ✅ same baseline failure |
| `Historian.Aveva.Tests` | 41 / 0 | 41 / 0 | ✅ |
| `Client.Shared.Tests` | 131 / 0 | 131 / 0 | ✅ |
| `IntegrationTests` | 6 / 0 | 6 / 0 | ✅ |
| `Tests` (main) | 493 / 1 | **494 / 0** | ✅ improvement (one flaky baseline failure passed this run) |
| **Total** | **820 / 2** | **821 / 1** | ✅ strict improvement |
Phase 0 exit-gate adapted requirement was: failure count = baseline (2); pass count ≥ baseline (820). Actual: failure count 1 (≤ 2), pass count 821 (≥ 820). ✅ PASS
### 4. Solution structure matches plan
`ls src/`: 5 entries, all `ZB.MOM.WW.OtOpcUa.*` — matches plan §5 expected v1-renamed surface (no new projects added; those land in Phase 1)
`ls tests/`: 6 entries, all `ZB.MOM.WW.OtOpcUa.*` — matches
`ZB.MOM.WW.OtOpcUa.slnx` exists; previous `ZB.MOM.WW.LmxOpcUa.slnx` removed
✅ PASS
### 5. .NET targets unchanged
| Project type | Expected | Actual | Verdict |
|--------------|----------|--------|---------|
| Client.CLI | net10.0 | net10.0 | ✅ |
| Client.Shared | net10.0 | net10.0 | ✅ |
| Client.UI | net10.0 | net10.0 | ✅ |
| Historian.Aveva | net48 | net48 | ✅ Phase 2 splits this |
| Host | net48 | net48 | ✅ Phase 2 splits this |
| All test projects | match SUT | match SUT | ✅ |
✅ PASS
### 6. Decision compliance
This phase implements decision #9 (Rename to OtOpcUa as step 1). Citation in `entry-gate-phase-0.md` "Decision #9 confirmed" line. ✅ PASS
### 7. Service registration
Not separately tested in this run (would require Windows service install on the build machine). The TopShelf `SetServiceName("OtOpcUa")` change is in `src/ZB.MOM.WW.OtOpcUa.Host/Program.cs:37` (verified by grep). Manual service install/uninstall verification is **deferred to the deployment-side reviewer** as part of PR review. ⚠️ DEFERRED
### Branch-naming convention deviation
Original Phase 0 doc specified branch name `v2/phase-0-rename`. Git rejected this because `v2` is itself a branch and `v2/...` would create a path conflict. Convention updated in `implementation/overview.md` and `phase-0-rename-and-net10.md` to use `phase-0-rename` (no `v2/` prefix). All future phase branches follow the same pattern. ⚠️ DEVIATION DOCUMENTED
## Summary
| Check | Status |
|-------|--------|
| 1. No stale references (with allowlist) | ✅ PASS |
| 2. Build succeeds | ✅ PASS |
| 3. Tests at or above baseline | ✅ PASS (strict improvement: 821/1 vs baseline 820/2) |
| 4. Solution structure matches plan | ✅ PASS |
| 5. .NET targets unchanged | ✅ PASS |
| 6. Decision compliance | ✅ PASS |
| 7. Service registration | ⚠️ DEFERRED to PR review |
**Exit gate status: READY FOR PR REVIEW.**
## Deviations from Phase 0 doc
1. **Pre-existing test failures preserved as baseline** (documented at entry gate)
2. **Branch name** `phase-0-rename` instead of `v2/phase-0-rename` (git path conflict with existing `v2` branch — convention updated in overview.md)
3. **Service install verification deferred** to PR reviewer (requires Windows service install permissions on the test box)
None of these deviations affect the rename's correctness; all are documented in this record per the gate rules in `implementation/overview.md`.
## Signoff
Implementation lead: Claude (Opus 4.7) — 2026-04-17
Reviewer: pending — PR review required before merge to `v2`

View File

@@ -2,11 +2,11 @@ using CliFx;
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using Serilog; using Serilog;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; using ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI; namespace ZB.MOM.WW.OtOpcUa.Client.CLI;
/// <summary> /// <summary>
/// Abstract base class for all CLI commands providing common connection options and helpers. /// Abstract base class for all CLI commands providing common connection options and helpers.

View File

@@ -1,9 +1,9 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("alarms", Description = "Subscribe to alarm events")] [Command("alarms", Description = "Subscribe to alarm events")]
public class AlarmsCommand : CommandBase public class AlarmsCommand : CommandBase

View File

@@ -1,10 +1,10 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("browse", Description = "Browse the OPC UA address space")] [Command("browse", Description = "Browse the OPC UA address space")]
public class BrowseCommand : CommandBase public class BrowseCommand : CommandBase

View File

@@ -1,8 +1,8 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("connect", Description = "Test connection to an OPC UA server")] [Command("connect", Description = "Test connection to an OPC UA server")]
public class ConnectCommand : CommandBase public class ConnectCommand : CommandBase

View File

@@ -1,11 +1,11 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("historyread", Description = "Read historical data from a node")] [Command("historyread", Description = "Read historical data from a node")]
public class HistoryReadCommand : CommandBase public class HistoryReadCommand : CommandBase

View File

@@ -1,9 +1,9 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("read", Description = "Read a value from a node")] [Command("read", Description = "Read a value from a node")]
public class ReadCommand : CommandBase public class ReadCommand : CommandBase

View File

@@ -1,8 +1,8 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("redundancy", Description = "Read redundancy state from an OPC UA server")] [Command("redundancy", Description = "Read redundancy state from an OPC UA server")]
public class RedundancyCommand : CommandBase public class RedundancyCommand : CommandBase

View File

@@ -2,10 +2,10 @@ using System.Collections.Concurrent;
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("subscribe", Description = "Monitor a node for value changes")] [Command("subscribe", Description = "Monitor a node for value changes")]
public class SubscribeCommand : CommandBase public class SubscribeCommand : CommandBase

View File

@@ -1,11 +1,11 @@
using CliFx.Attributes; using CliFx.Attributes;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; using ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; using ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Commands; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
[Command("write", Description = "Write a value to a node")] [Command("write", Description = "Write a value to a node")]
public class WriteCommand : CommandBase public class WriteCommand : CommandBase

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.CLI.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Helpers;
/// <summary> /// <summary>
/// Parses node ID strings into OPC UA <see cref="NodeId" /> objects. /// Parses node ID strings into OPC UA <see cref="NodeId" /> objects.

View File

@@ -1,5 +1,5 @@
using CliFx; using CliFx;
using ZB.MOM.WW.LmxOpcUa.Client.CLI; using ZB.MOM.WW.OtOpcUa.Client.CLI;
return await new CliApplicationBuilder() return await new CliApplicationBuilder()
.AddCommandsFromThisAssembly() .AddCommandsFromThisAssembly()

View File

@@ -5,7 +5,7 @@
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>ZB.MOM.WW.LmxOpcUa.Client.CLI</RootNamespace> <RootNamespace>ZB.MOM.WW.OtOpcUa.Client.CLI</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -15,7 +15,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ZB.MOM.WW.LmxOpcUa.Client.Shared\ZB.MOM.WW.LmxOpcUa.Client.Shared.csproj"/> <ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Client.Shared\ZB.MOM.WW.OtOpcUa.Client.Shared.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,9 +1,9 @@
using Opc.Ua; using Opc.Ua;
using Opc.Ua.Configuration; using Opc.Ua.Configuration;
using Serilog; using Serilog;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Production implementation that builds a real OPC UA ApplicationConfiguration. /// Production implementation that builds a real OPC UA ApplicationConfiguration.

View File

@@ -2,7 +2,7 @@ using Opc.Ua;
using Opc.Ua.Client; using Opc.Ua.Client;
using Serilog; using Serilog;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Production endpoint discovery that queries the real server. /// Production endpoint discovery that queries the real server.

View File

@@ -2,7 +2,7 @@ using Opc.Ua;
using Opc.Ua.Client; using Opc.Ua.Client;
using Serilog; using Serilog;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Production session adapter wrapping a real OPC UA Session. /// Production session adapter wrapping a real OPC UA Session.

View File

@@ -2,7 +2,7 @@ using Opc.Ua;
using Opc.Ua.Client; using Opc.Ua.Client;
using Serilog; using Serilog;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Production session factory that creates real OPC UA sessions. /// Production session factory that creates real OPC UA sessions.

View File

@@ -2,7 +2,7 @@ using Opc.Ua;
using Opc.Ua.Client; using Opc.Ua.Client;
using Serilog; using Serilog;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Production subscription adapter wrapping a real OPC UA Subscription. /// Production subscription adapter wrapping a real OPC UA Subscription.

View File

@@ -1,7 +1,7 @@
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Creates and configures an OPC UA ApplicationConfiguration. /// Creates and configures an OPC UA ApplicationConfiguration.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Abstracts OPC UA endpoint discovery for testability. /// Abstracts OPC UA endpoint discovery for testability.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Abstracts the OPC UA session for read, write, browse, history, and subscription operations. /// Abstracts the OPC UA session for read, write, browse, history, and subscription operations.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Creates OPC UA sessions from a configured endpoint. /// Creates OPC UA sessions from a configured endpoint.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary> /// <summary>
/// Abstracts OPC UA subscription and monitored item management. /// Abstracts OPC UA subscription and monitored item management.

View File

@@ -1,7 +1,7 @@
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
/// <summary> /// <summary>
/// Maps the library's AggregateType enum to OPC UA aggregate function NodeIds. /// Maps the library's AggregateType enum to OPC UA aggregate function NodeIds.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
/// <summary> /// <summary>
/// Parses and normalizes failover URL sets for redundant OPC UA connections. /// Parses and normalizes failover URL sets for redundant OPC UA connections.

View File

@@ -1,7 +1,7 @@
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
/// <summary> /// <summary>
/// Maps between the library's SecurityMode enum and OPC UA SDK MessageSecurityMode. /// Maps between the library's SecurityMode enum and OPC UA SDK MessageSecurityMode.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
/// <summary> /// <summary>
/// Converts raw string values into typed values based on the current value's runtime type. /// Converts raw string values into typed values based on the current value's runtime type.

View File

@@ -1,8 +1,8 @@
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using BrowseResult = ZB.MOM.WW.LmxOpcUa.Client.Shared.Models.BrowseResult; using BrowseResult = ZB.MOM.WW.OtOpcUa.Client.Shared.Models.BrowseResult;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared; namespace ZB.MOM.WW.OtOpcUa.Client.Shared;
/// <summary> /// <summary>
/// Shared OPC UA client service contract for CLI and UI consumers. /// Shared OPC UA client service contract for CLI and UI consumers.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared; namespace ZB.MOM.WW.OtOpcUa.Client.Shared;
/// <summary> /// <summary>
/// Factory for creating <see cref="IOpcUaClientService" /> instances. /// Factory for creating <see cref="IOpcUaClientService" /> instances.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Aggregate functions for processed history reads. /// Aggregate functions for processed history reads.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Event data for an alarm or condition notification from the OPC UA server. /// Event data for an alarm or condition notification from the OPC UA server.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Represents a single node in the browse result set. /// Represents a single node in the browse result set.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Information about the current OPC UA session. /// Information about the current OPC UA session.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Settings for establishing an OPC UA client connection. /// Settings for establishing an OPC UA client connection.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Represents the current state of the OPC UA client connection. /// Represents the current state of the OPC UA client connection.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Event data raised when the client connection state changes. /// Event data raised when the client connection state changes.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Event data for a monitored data value change. /// Event data for a monitored data value change.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Redundancy information read from the server. /// Redundancy information read from the server.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
/// <summary> /// <summary>
/// Transport security mode for the OPC UA connection. /// Transport security mode for the OPC UA connection.

View File

@@ -1,12 +1,12 @@
using System.Text; using System.Text;
using Opc.Ua; using Opc.Ua;
using Serilog; using Serilog;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters; using ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Helpers; using ZB.MOM.WW.OtOpcUa.Client.Shared.Helpers;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using BrowseResult = ZB.MOM.WW.LmxOpcUa.Client.Shared.Models.BrowseResult; using BrowseResult = ZB.MOM.WW.OtOpcUa.Client.Shared.Models.BrowseResult;
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared; namespace ZB.MOM.WW.OtOpcUa.Client.Shared;
/// <summary> /// <summary>
/// Full implementation of <see cref="IOpcUaClientService" /> using adapter abstractions for testability. /// Full implementation of <see cref="IOpcUaClientService" /> using adapter abstractions for testability.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.Shared; namespace ZB.MOM.WW.OtOpcUa.Client.Shared;
/// <summary> /// <summary>
/// Default factory that creates <see cref="OpcUaClientService" /> instances with production adapters. /// Default factory that creates <see cref="OpcUaClientService" /> instances with production adapters.

View File

@@ -4,7 +4,7 @@
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>ZB.MOM.WW.LmxOpcUa.Client.Shared</RootNamespace> <RootNamespace>ZB.MOM.WW.OtOpcUa.Client.Shared</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -13,7 +13,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<InternalsVisibleTo Include="ZB.MOM.WW.LmxOpcUa.Client.Shared.Tests"/> <InternalsVisibleTo Include="ZB.MOM.WW.OtOpcUa.Client.Shared.Tests"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,6 +1,6 @@
<Application xmlns="https://github.com/avaloniaui" <Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.App" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.App"
RequestedThemeVariant="Light"> RequestedThemeVariant="Light">
<Application.Styles> <Application.Styles>
<FluentTheme /> <FluentTheme />

View File

@@ -1,12 +1,12 @@
using Avalonia; using Avalonia;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Views; using ZB.MOM.WW.OtOpcUa.Client.UI.Views;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI; namespace ZB.MOM.WW.OtOpcUa.Client.UI;
public class App : Application public class App : Application
{ {

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,6 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Controls.DateTimeRangePicker"> x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Controls.DateTimeRangePicker">
<StackPanel Orientation="Horizontal" Spacing="8"> <StackPanel Orientation="Horizontal" Spacing="8">
<StackPanel Spacing="2"> <StackPanel Spacing="2">
<TextBlock Text="Start (UTC)" FontSize="11" Foreground="Gray" /> <TextBlock Text="Start (UTC)" FontSize="11" Foreground="Gray" />

View File

@@ -5,7 +5,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Controls; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Controls;
/// <summary> /// <summary>
/// A date/time range picker using formatted text boxes and preset duration buttons. /// A date/time range picker using formatted text boxes and preset duration buttons.

View File

@@ -1,6 +1,6 @@
using Opc.Ua; using Opc.Ua;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Helpers;
/// <summary> /// <summary>
/// Formats OPC UA status codes as "0xHEX (description)". /// Formats OPC UA status codes as "0xHEX (description)".

View File

@@ -1,6 +1,6 @@
using System.Collections; using System.Collections;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Helpers; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Helpers;
/// <summary> /// <summary>
/// Formats OPC UA values for display, with array support. /// Formats OPC UA values for display, with array support.

View File

@@ -1,6 +1,6 @@
using Avalonia; using Avalonia;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI; namespace ZB.MOM.WW.OtOpcUa.Client.UI;
public class Program public class Program
{ {

View File

@@ -1,6 +1,6 @@
using Avalonia.Threading; using Avalonia.Threading;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Dispatches actions to the Avalonia UI thread. /// Dispatches actions to the Avalonia UI thread.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Loads and saves user settings. /// Loads and saves user settings.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Abstraction for dispatching actions to the UI thread. /// Abstraction for dispatching actions to the UI thread.

View File

@@ -1,6 +1,6 @@
using System.Text.Json; using System.Text.Json;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Persists user settings to a JSON file under LocalApplicationData. /// Persists user settings to a JSON file under LocalApplicationData.

View File

@@ -1,4 +1,4 @@
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Dispatcher that executes actions synchronously on the calling thread. /// Dispatcher that executes actions synchronously on the calling thread.

View File

@@ -1,6 +1,6 @@
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
/// <summary> /// <summary>
/// Persisted user connection settings. /// Persisted user connection settings.

View File

@@ -1,6 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// Represents a single alarm event row. /// Represents a single alarm event row.

View File

@@ -2,11 +2,11 @@ using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// ViewModel for the alarms panel. /// ViewModel for the alarms panel.

View File

@@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// ViewModel for the OPC UA browse tree panel. /// ViewModel for the OPC UA browse tree panel.

View File

@@ -1,6 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// Represents a single historical value row. /// Represents a single historical value row.

View File

@@ -2,11 +2,11 @@ using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// ViewModel for the history panel. /// ViewModel for the history panel.

View File

@@ -1,11 +1,11 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// Main window ViewModel coordinating all panels. /// Main window ViewModel coordinating all panels.

View File

@@ -1,10 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// ViewModel for the read/write panel. /// ViewModel for the read/write panel.

View File

@@ -1,6 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// Represents a single active subscription row. /// Represents a single active subscription row.

View File

@@ -2,11 +2,11 @@ using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Opc.Ua; using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// ViewModel for the subscriptions panel. /// ViewModel for the subscriptions panel.

View File

@@ -1,9 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; using ZB.MOM.WW.OtOpcUa.Client.UI.Services;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
/// <summary> /// <summary>
/// Represents a single node in the OPC UA browse tree with lazy-load support. /// Represents a single node in the OPC UA browse tree with lazy-load support.

View File

@@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui" <Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.AckAlarmWindow" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.AckAlarmWindow"
Title="Acknowledge Alarm" Title="Acknowledge Alarm"
Width="420" Width="420"
SizeToContent="Height" SizeToContent="Height"

View File

@@ -1,9 +1,9 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class AckAlarmWindow : Window public partial class AckAlarmWindow : Window
{ {

View File

@@ -1,7 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.AlarmsView" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.AlarmsView"
x:DataType="vm:AlarmsViewModel"> x:DataType="vm:AlarmsViewModel">
<DockPanel Margin="8"> <DockPanel Margin="8">
<!-- Controls --> <!-- Controls -->

View File

@@ -3,9 +3,9 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class AlarmsView : UserControl public partial class AlarmsView : UserControl
{ {

View File

@@ -1,7 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.BrowseTreeView" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.BrowseTreeView"
x:DataType="vm:BrowseTreeViewModel"> x:DataType="vm:BrowseTreeViewModel">
<TreeView ItemsSource="{Binding RootNodes}" <TreeView ItemsSource="{Binding RootNodes}"
Name="BrowseTree" Name="BrowseTree"

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class BrowseTreeView : UserControl public partial class BrowseTreeView : UserControl
{ {

View File

@@ -1,8 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
xmlns:controls="using:ZB.MOM.WW.LmxOpcUa.Client.UI.Controls" xmlns:controls="using:ZB.MOM.WW.OtOpcUa.Client.UI.Controls"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.HistoryView" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.HistoryView"
x:DataType="vm:HistoryViewModel"> x:DataType="vm:HistoryViewModel">
<DockPanel Margin="8"> <DockPanel Margin="8">
<!-- Controls --> <!-- Controls -->

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class HistoryView : UserControl public partial class HistoryView : UserControl
{ {

View File

@@ -1,8 +1,8 @@
<Window xmlns="https://github.com/avaloniaui" <Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
xmlns:views="using:ZB.MOM.WW.LmxOpcUa.Client.UI.Views" xmlns:views="using:ZB.MOM.WW.OtOpcUa.Client.UI.Views"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.MainWindow" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.MainWindow"
x:DataType="vm:MainWindowViewModel" x:DataType="vm:MainWindowViewModel"
Title="OPC UA Client" Title="OPC UA Client"
Width="1200" Width="1200"

View File

@@ -4,9 +4,9 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using SkiaSharp; using SkiaSharp;
using Svg.Skia; using Svg.Skia;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
@@ -21,7 +21,7 @@ public partial class MainWindow : Window
try try
{ {
var assembly = Assembly.GetExecutingAssembly(); var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream("ZB.MOM.WW.LmxOpcUa.Client.UI.Assets.app-icon.svg"); using var stream = assembly.GetManifestResourceStream("ZB.MOM.WW.OtOpcUa.Client.UI.Assets.app-icon.svg");
if (stream == null) return; if (stream == null) return;
using var svg = new SKSvg(); using var svg = new SKSvg();

View File

@@ -1,7 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.ReadWriteView" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.ReadWriteView"
x:DataType="vm:ReadWriteViewModel"> x:DataType="vm:ReadWriteViewModel">
<StackPanel Spacing="8" Margin="8"> <StackPanel Spacing="8" Margin="8">
<!-- Selected Node --> <!-- Selected Node -->

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class ReadWriteView : UserControl public partial class ReadWriteView : UserControl
{ {

View File

@@ -1,7 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels" xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.SubscriptionsView" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.SubscriptionsView"
x:DataType="vm:SubscriptionsViewModel"> x:DataType="vm:SubscriptionsViewModel">
<DockPanel Margin="8"> <DockPanel Margin="8">
<!-- Add/Remove Controls --> <!-- Add/Remove Controls -->

View File

@@ -2,9 +2,9 @@ using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class SubscriptionsView : UserControl public partial class SubscriptionsView : UserControl
{ {

View File

@@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui" <Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ZB.MOM.WW.LmxOpcUa.Client.UI.Views.WriteValueWindow" x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.WriteValueWindow"
Title="Write Value" Title="Write Value"
Width="420" Width="420"
SizeToContent="Height" SizeToContent="Height"

View File

@@ -1,9 +1,9 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Views; namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
public partial class WriteValueWindow : Window public partial class WriteValueWindow : Window
{ {

Some files were not shown because too many files have changed in this diff Show More