Files
lmxopcua/src/Server/ZB.MOM.WW.OtOpcUa.Admin/Components/Pages/Modbus/ModbusAddressPreview.razor
T
Joseph Doherty 866dc03fac style(ui): align admin styling with ScadaLink master conventions
- Move CSS into wwwroot/css/ (theme.css, site.css); sidebar 218 -> 220px
- Add hamburger + Bootstrap collapse for <lg viewports
- Add Components/Shared/ with LoadingSpinner, ToastNotification, StatusBadge
- Replace .page-title with flex + <h4 class="mb-0"> across 20 pages
- Convert NewCluster + IdentificationFields forms to card + h6 subsection pattern
2026-05-26 01:12:57 -04:00

96 lines
4.1 KiB
Plaintext

@page "/modbus/address-preview"
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@using Microsoft.AspNetCore.Components.Web
@using ZB.MOM.WW.OtOpcUa.Driver.Modbus
@rendermode RenderMode.InteractiveServer
@*
#149 — standalone preview / sanity-check tool for Modbus address strings. The Admin UI
doesn't yet have a per-tag CRUD surface (tags are seeded via SQL or arrive at runtime
through ITagDiscovery), so the ModbusAddressEditor component shipped in #145 needs a
page where operators can paste an address string and confirm it parses to what they
expect before committing it to a config row.
Doubles as a "did the parser ship correctly" smoke target for QA + a copy-pasteable
grammar reference for users skimming the docs.
*@
<PageTitle>Modbus address preview</PageTitle>
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="mb-0">Modbus address preview</h4>
</div>
<p class="text-muted">
Paste an address string and watch the parser break it down field by field. Useful for
sanity-checking a tag spreadsheet row before adding it to a driver's <span class="mono">DriverConfig</span>.
Full grammar: <a href="https://github.com/" target="_blank">docs/v2/modbus-addressing.md</a>.
</p>
<section class="panel rise" style="animation-delay:.02s">
<div class="panel-head">Family</div>
<div style="padding:.75rem 1rem">
<div class="row g-3">
<div class="col-md-4">
<label class="form-label">PLC family hint (drives the family-native branch)</label>
<select class="form-select form-select-sm" @bind="_family">
@foreach (var f in Enum.GetValues<ModbusFamily>())
{
<option value="@f">@f</option>
}
</select>
</div>
@if (_family == ModbusFamily.MELSEC)
{
<div class="col-md-4">
<label class="form-label">MELSEC sub-family</label>
<select class="form-select form-select-sm" @bind="_melsecSubFamily">
@foreach (var f in Enum.GetValues<MelsecFamily>())
{
<option value="@f">@f</option>
}
</select>
</div>
}
</div>
<div class="mt-3">
<ModbusAddressEditor @bind-AddressString="_address"
Family="_family"
MelsecSubFamily="_melsecSubFamily"/>
</div>
</div>
</section>
<section class="panel rise" style="animation-delay:.08s">
<div class="panel-head">Quick-reference grammar</div>
<pre class="small" style="padding:1rem;margin:0;overflow-x:auto">@_grammarReference</pre>
</section>
@code {
private string? _address;
private ModbusFamily _family = ModbusFamily.Generic;
private MelsecFamily _melsecSubFamily = MelsecFamily.Q_L_iQR;
// Held as a const string rather than inline markup so the Razor parser doesn't try to
// interpret the angle-bracket grammar tokens as element open/close.
private const string _grammarReference = @"<region><offset>[.<bit>][:<type>[<len>]][:<order>][:<count>]
Examples (post-#146 type codes):
40001 HoldingRegisters[0], Int16
400001 same, 6-digit form
40001:F Float32 (HR[0..1])
40001:F:CDAB Float32 word-swapped
40001:STR20 20-char ASCII string
40001:S:5 Int16[5] array (3-field shorthand)
40001:I:CDAB:10 Int32[10] word-swapped (4-field strict)
40001.5 bit 5 of HR[0]
HR1:I Int32 via mnemonic region (matches Wonderware)
C100 Coil 100 (mnemonic, 1-based)
V2000:F:CDAB DL205 V-memory at PDU 1024 (Family=DL205)
D100:I MELSEC D-register 100, Int32 (Family=MELSEC)
Type codes: BOOL, S (Int16), US (UInt16), I (Int32), UI (UInt32),
I_64 (Int64), UI_64 (UInt64), F, D, BCD, BCD_32, STR<n>
Byte order: ABCD (BE default), CDAB (word-swap), BADC (byte-swap), DCBA (full reverse)";
}