Files
wwtools/mbproxy/src/Mbproxy/Mbproxy.csproj
T
Joseph Doherty e719dd51c1 mbproxy: replace status page with a live SignalR web dashboard
The single auto-refreshing zero-JS status page gave operators a 25-column
wall and no way to drill into one connection. This adds a Bootstrap fleet
dashboard (filterable/sortable KPI table) and a per-PLC detail page with a
real-time debug view of raw PLC-side BCD vs. decoded client-side values,
streamed live over a SignalR feed. The debug view is fed by an on-demand
per-tag value capture, armed only while a detail page is open. All assets
(Bootstrap, SignalR client, fonts) are embedded so the UI works unchanged
on firewalled networks; GET /status.json is untouched for scrapers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 10:41:02 -04:00

97 lines
5.1 KiB
XML

<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<RootNamespace>Mbproxy</RootNamespace>
<AssemblyName>Mbproxy</AssemblyName>
<!-- Assembly version. CI can override via /p:InformationalVersion=... -->
<InformationalVersion>1.0.0</InformationalVersion>
</PropertyGroup>
<!-- Single-file publish settings — apply only to a Release publish with an explicit RID.
Publishing with -r <rid> produces a single-file binary, self-contained by default
(bundles the .NET 10 + ASP.NET Core runtime, ~100 MB) so no .NET install is needed on
the target. Override with -p:SelfContained=false for a framework-dependent build
(~1.6 MB) when the target already has the .NET 10 + ASP.NET Core runtime.
The RID is supplied per publish (win-x64, linux-x64, ...) and is deliberately NOT
hardcoded here — see install/publish.ps1 / install/publish.sh. The
'$(RuntimeIdentifier)' != '' guard means a plain `dotnet build -c Release` with no RID
stays an ordinary framework build (SelfContained without a RID is an SDK error). -->
<PropertyGroup Condition="'$(Configuration)' == 'Release' and '$(RuntimeIdentifier)' != ''">
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
<ItemGroup>
<!-- ASP.NET Core for the Kestrel-hosted admin endpoint. -->
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<!-- Microsoft.Extensions.Hosting is already included transitively via
Microsoft.AspNetCore.App — do not re-add it explicitly.
The two init-system integration packages are both portable: each is
safe to reference and call on any OS (the helper self-detects its host
and no-ops otherwise), so no conditional reference is needed. -->
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="10.0.8" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<!-- Local-syslog sink for the Linux diagnostic bridge (Error+ events).
Serilog.Sinks.SyslogMessages is the maintained IonxSolutions package. -->
<PackageReference Include="Serilog.Sinks.SyslogMessages" Version="4.1.0" />
<!-- Polly: backend-connect retry pipeline (PolicyFactory.BuildBackendConnect) and
listener-recovery pipeline (PolicyFactory.BuildListenerRecovery). -->
<PackageReference Include="Polly" Version="8.6.6" />
</ItemGroup>
<ItemGroup>
<!-- Allow test project to access internal types (HeartbeatWorker, HostingExtensions, etc.) -->
<InternalsVisibleTo Include="Mbproxy.Tests" />
</ItemGroup>
<ItemGroup>
<!-- Admin web-UI assets — Bootstrap, the SignalR JS client, vendored fonts, and the
dashboard's own HTML/CSS/JS. Embedded into the assembly so the single-file binary
serves the whole UI with no CDN dependency (firewalled networks). Resource names
are Mbproxy.Admin.wwwroot.<filename>; AdminEndpointHost streams them on
GET /assets/<filename>. The directory is intentionally flat to keep the
resource-name → request-path mapping trivial. -->
<EmbeddedResource Include="Admin\wwwroot\*.*" />
</ItemGroup>
<!-- Link the platform-appropriate install template as the published appsettings.json so
the binary ships with a fully-commented, usable example config (PLCs, BCD tags, all
sections present) instead of an empty stub. The .NET configuration loader supports
JSONC (comments) under the default Host.CreateApplicationBuilder path, so the comments
in the template are valid at runtime.
The two templates differ only in OS-specific paths (log directory) and platform
notes. A `dotnet publish -r linux-*` (or any non-win RID) ships the Linux template;
win-* and a plain RID-less dev build ship the Windows one. -->
<ItemGroup>
<None Remove="appsettings.json" />
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == '' or $(RuntimeIdentifier.StartsWith('win'))">
<Content Include="..\..\install\mbproxy.config.template.json"
Link="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' != '' and !$(RuntimeIdentifier.StartsWith('win'))">
<Content Include="..\..\install\mbproxy.linux.config.template.json"
Link="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>