junction/src/Junction.App/Junction.App.csproj
dtrentin 88dfa74ebe feat: OPC UA protocol plugin (v0.4)
Second protocol plugin proving multi-protocol architecture. New
Junction.Protocols.OpcUa (multi-target net48;net8.0 — SDK has no ns2.0):
- OpcuaDriverFactory: config validation (EndpointUrl/SecurityMode/Policy/
  AuthMode/Username/Password/NodeIds/BrowseRoot/TimeoutSeconds), CONFIG_* codes.
- OpcuaDriver: ReadCurrentAsync (read configured nodes) + ProbeAsync (browse
  address space), linked-CTS timeout, Result mapping, opt-in FilterToMonitored
  — mirrors MtconnectDriver.
- IUaClient seam (SDK-free) injected for testability; UaClient wraps OPC UA
  Session (non-obsolete async API), Directory PKI store, anon/user-pass auth.

SDK: OPCFoundation.NetStandard.Opc.Ua.Client 1.5.378.156 (MIT), pinned exact,
transitive closure copied per-TFM into plugins/opcua/ (CopyLocalLockFileAssemblies
+ CopyOpcuaPlugin target). Host: AutoGenerateBindingRedirects. Core untouched —
protocol auto-discovered by plugin loader.

Projects: +Junction.Protocols.OpcUa, Junction.App (wiring), Junction.sln,
Junction.Tests (+23 tests: 13 factory + 10 driver via Mock<IUaClient>). 171 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 07:44:23 +02:00

71 lines
4.1 KiB
XML

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- net48 = shipped fleet (Win7/8); net8.0 = Linux dev iteration (dotnet run -f net8.0). -->
<TargetFrameworks>net48;net8.0</TargetFrameworks>
<!-- WinExe: no console window on Windows; on Linux net8.0 still runs. -->
<OutputType>WinExe</OutputType>
<RootNamespace>Junction.App</RootNamespace>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<!-- net48 needs binding redirects for the M.E.Logging/System.* shims the OPC UA SDK drags in. -->
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<!-- Avalonia 11.3.x supports net48; Avalonia 12 DROPS net48. PIN 11.3.10 exact everywhere. -->
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.10" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.10" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.10" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.3.10" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.10" />
<!-- Dev tooling only: not shipped to net48 fleet. -->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.10"
Condition="'$(Configuration)'=='Debug' and '$(TargetFramework)'=='net8.0'" />
</ItemGroup>
<ItemGroup>
<!-- NLog config copied next to the app so runtime target paths (logs/junction.log) resolve. -->
<None Include="nlog.config" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<!-- Concrete logging provider (Core depends on Logging.Abstractions). -->
<PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.15" />
</ItemGroup>
<!-- Composition root: needs these types at compile time. -->
<ItemGroup>
<ProjectReference Include="..\Junction.Domain\Junction.Domain.csproj" />
<ProjectReference Include="..\Junction.Core\Junction.Core.csproj" />
<ProjectReference Include="..\Junction.Persistence\Junction.Persistence.csproj" />
<!-- Plugin = RUNTIME artifact, NOT a compile reference. Build-order-only so we can copy its output. -->
<ProjectReference Include="..\Junction.Protocols.MTConnect\Junction.Protocols.MTConnect.csproj"
ReferenceOutputAssembly="false" Private="false" />
<ProjectReference Include="..\Junction.Protocols.OpcUa\Junction.Protocols.OpcUa.csproj"
ReferenceOutputAssembly="false" Private="false" />
</ItemGroup>
<!-- Copy MTConnect plugin (dll + manifest) into OutDir/plugins/mtconnect/ after build. -->
<Target Name="CopyMtconnectPlugin" AfterTargets="Build">
<ItemGroup>
<MtconnectPluginFiles Include="$(MSBuildThisFileDirectory)..\Junction.Protocols.MTConnect\bin\$(Configuration)\netstandard2.0\Junction.Protocols.MTConnect.dll" />
<MtconnectPluginFiles Include="$(MSBuildThisFileDirectory)..\Junction.Protocols.MTConnect\bin\$(Configuration)\netstandard2.0\plugin.manifest.json" />
</ItemGroup>
<Copy SourceFiles="@(MtconnectPluginFiles)" DestinationFolder="$(OutDir)plugins\mtconnect\" SkipUnchangedFiles="true" />
</Target>
<!-- Copy OPC UA plugin (its dll + FULL transitive SDK closure + manifest) into OutDir/plugins/opcua/
after build. Host $(TargetFramework) is net48 or net8.0; the plugin multi-targets the same TFMs,
so copy the matching per-TFM output. -->
<Target Name="CopyOpcuaPlugin" AfterTargets="Build" Condition="'$(TargetFramework)' != ''">
<ItemGroup>
<OpcuaPluginFiles Include="$(MSBuildThisFileDirectory)..\Junction.Protocols.OpcUa\bin\$(Configuration)\$(TargetFramework)\*.dll" />
<OpcuaPluginFiles Include="$(MSBuildThisFileDirectory)..\Junction.Protocols.OpcUa\bin\$(Configuration)\$(TargetFramework)\plugin.manifest.json" />
</ItemGroup>
<Copy SourceFiles="@(OpcuaPluginFiles)" DestinationFolder="$(OutDir)plugins\opcua\" SkipUnchangedFiles="true" />
</Target>
</Project>