feat(adminui): Build-address pickers in the protocol-driver Tag editors
This commit is contained in:
+28
-2
@@ -1,23 +1,43 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.AbCip
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><label class="form-label">Device host</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.DeviceHostAddress" placeholder="ab://gateway[:port]/cip-path" @onchange="@(e => Update(() => _m.DeviceHostAddress = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5"><label class="form-label">Tag path</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.TagPath" placeholder="e.g. Motor1.Speed" @onchange="@(e => Update(() => _m.TagPath = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Tag path</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-sm mono" value="@_m.TagPath" placeholder="e.g. Motor1.Speed" @onchange="@(e => Update(() => _m.TagPath = e.Value?.ToString() ?? string.Empty))" />
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, AbCipDataType.DInt)))">
|
||||
@foreach (var v in Enum.GetValues<AbCipDataType>()) { <option value="@v">@v</option> }
|
||||
</select></div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="AB CIP address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<AbCipAddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private AbCipTagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -37,4 +57,10 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
await Update(() => _m.TagPath = address);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -1,23 +1,43 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><label class="form-label">Device host</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.DeviceHostAddress" placeholder="ab://host" @onchange="@(e => Update(() => _m.DeviceHostAddress = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5"><label class="form-label">Address</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. N7:0, B3:0/0" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Address</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. N7:0, B3:0/0" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" />
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, AbLegacyDataType.Int)))">
|
||||
@foreach (var v in Enum.GetValues<AbLegacyDataType>()) { <option value="@v">@v</option> }
|
||||
</select></div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="AB Legacy address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<AbLegacyAddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private AbLegacyTagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -37,4 +57,10 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
await Update(() => _m.Address = address);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -1,23 +1,43 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.FOCAS
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><label class="form-label">Device host</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.DeviceHostAddress" placeholder="host[:port]" @onchange="@(e => Update(() => _m.DeviceHostAddress = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5"><label class="form-label">Address</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. X0.0, R100, PARAM:1815/0, MACRO:500" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Address</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. X0.0, R100, PARAM:1815/0, MACRO:500" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" />
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, FocasDataType.Int32)))">
|
||||
@foreach (var v in Enum.GetValues<FocasDataType>()) { <option value="@v">@v</option> }
|
||||
</select></div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="FOCAS address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<FOCASAddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private FocasTagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -37,4 +57,10 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
await Update(() => _m.Address = address);
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -1,5 +1,7 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.Modbus
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><label class="form-label">Region</label>
|
||||
@@ -20,14 +22,30 @@
|
||||
<input type="number" class="form-control form-control-sm" value="@_m.BitIndex" @onchange="@(e => Update(() => _m.BitIndex = ParseInt(e.Value)))" /></div>
|
||||
<div class="col-md-2"><label class="form-label">String len</label>
|
||||
<input type="number" class="form-control form-control-sm" value="@_m.StringLength" @onchange="@(e => Update(() => _m.StringLength = ParseInt(e.Value)))" /></div>
|
||||
<div class="col-12 mt-1">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build address</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="Modbus address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<ModbusAddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private ModbusTagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -49,4 +67,22 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
// Parse the builder string (e.g. "4x00001-1") back into Region + Address fields.
|
||||
// Format: {prefix}{offset:00000}-{length} where prefix is 0x/1x/3x/4x.
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(address)) return;
|
||||
var region = address.StartsWith("0x") ? ModbusRegion.Coils
|
||||
: address.StartsWith("1x") ? ModbusRegion.DiscreteInputs
|
||||
: address.StartsWith("3x") ? ModbusRegion.InputRegisters
|
||||
: ModbusRegion.HoldingRegisters;
|
||||
var rest = address.Length > 2 ? address[2..] : address;
|
||||
var dashIdx = rest.IndexOf('-');
|
||||
var offsetStr = dashIdx >= 0 ? rest[..dashIdx] : rest;
|
||||
if (int.TryParse(offsetStr, out var offset))
|
||||
{
|
||||
await Update(() => { _m.Region = region; _m.Address = offset; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -1,9 +1,16 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.S7
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-5"><label class="form-label">Address</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. DB1.DBW0, M0.0, I0.0, QD4" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Address</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-sm mono" value="@_m.Address" placeholder="e.g. DB1.DBW0, M0.0, I0.0, QD4" @onchange="@(e => Update(() => _m.Address = e.Value?.ToString() ?? string.Empty))" />
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, S7DataType.Int16)))">
|
||||
@foreach (var v in Enum.GetValues<S7DataType>()) { <option value="@v">@v</option> }
|
||||
@@ -12,12 +19,25 @@
|
||||
<input type="number" class="form-control form-control-sm" value="@_m.StringLength" @onchange="@(e => Update(() => _m.StringLength = ParseInt(e.Value)))" /></div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="S7 address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<S7AddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private S7TagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -39,4 +59,10 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
await Update(() => _m.Address = address);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -1,23 +1,43 @@
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors
|
||||
@using ZB.MOM.WW.OtOpcUa.Driver.TwinCAT
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><label class="form-label">Device host</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.DeviceHostAddress" placeholder="AmsNetId[:port]" @onchange="@(e => Update(() => _m.DeviceHostAddress = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5"><label class="form-label">Symbol path</label>
|
||||
<input class="form-control form-control-sm mono" value="@_m.SymbolPath" placeholder="e.g. MAIN.bStart, GVL.Counter" @onchange="@(e => Update(() => _m.SymbolPath = e.Value?.ToString() ?? string.Empty))" /></div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Symbol path</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-sm mono" value="@_m.SymbolPath" placeholder="e.g. MAIN.bStart, GVL.Counter" @onchange="@(e => Update(() => _m.SymbolPath = e.Value?.ToString() ?? string.Empty))" />
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="@(() => _showPicker = true)">Build</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3"><label class="form-label">Data type</label>
|
||||
<select class="form-select form-select-sm" value="@_m.DataType" @onchange="@(e => Update(() => _m.DataType = ParseEnum(e.Value, TwinCATDataType.DInt)))">
|
||||
@foreach (var v in Enum.GetValues<TwinCATDataType>()) { <option value="@v">@v</option> }
|
||||
</select></div>
|
||||
</div>
|
||||
|
||||
@if (_showPicker)
|
||||
{
|
||||
<DriverTagPicker @bind-Visible="_showPicker"
|
||||
Title="TwinCAT address builder"
|
||||
CurrentAddress="@_pickerAddress"
|
||||
OnPickAddress="@OnAddressPicked">
|
||||
<TwinCATAddressPickerBody CurrentAddress="@_pickerAddress"
|
||||
CurrentAddressChanged="@((s) => _pickerAddress = s)" />
|
||||
</DriverTagPicker>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ConfigJson { get; set; }
|
||||
[Parameter] public EventCallback<string> ConfigJsonChanged { get; set; }
|
||||
|
||||
private TwinCATTagConfigModel _m = new();
|
||||
private string? _lastConfigJson;
|
||||
private bool _showPicker;
|
||||
private string _pickerAddress = "";
|
||||
|
||||
// Re-parse only when the incoming JSON actually changes, so an unrelated parent re-render
|
||||
// (Blazor Server live-status pushes do this) can't reset the user's in-progress edits.
|
||||
@@ -37,4 +57,10 @@
|
||||
apply();
|
||||
await ConfigJsonChanged.InvokeAsync(_m.ToJson());
|
||||
}
|
||||
|
||||
private async Task OnAddressPicked(string address)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
await Update(() => _m.SymbolPath = address);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user