feat(modbus): block-read coalescing on by default; coils/DI/BitInRegister/String fold
U2: MaxReadGap defaults to 8 and 0 now means adjacent-only rather than off; a new DisableReadCoalescing switch (factory DTO + AdminUI form) turns it off entirely. The planner also merges Coils/DiscreteInputs (FC01/FC02, gap in bits), String scalars and BitInRegister tags - sixteen bit tags on one status word are one FC03 instead of sixteen. Auto-prohibition and its re-probe / bisection use the region's own function code (a coil range was re-probed with FC04). Refs #741 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
@@ -30,6 +30,13 @@ internal sealed class ScriptedTransport : IModbusTransport
|
||||
|
||||
public int TotalSends => _sendsByUnit.Values.Sum();
|
||||
|
||||
/// <summary>Every PDU sent, in order.</summary>
|
||||
public ConcurrentQueue<(byte Unit, byte[] Pdu)> Sent { get; } = new();
|
||||
|
||||
/// <summary>The (function code, start, quantity) of every sent request with that function code.</summary>
|
||||
public List<(byte Fc, ushort Start, ushort Qty)> Requests(byte fc) =>
|
||||
[.. Sent.Where(s => s.Pdu[0] == fc).Select(s => (s.Pdu[0], (ushort)((s.Pdu[1] << 8) | s.Pdu[2]), (ushort)((s.Pdu[3] << 8) | s.Pdu[4])))];
|
||||
|
||||
public async Task ConnectAsync(CancellationToken ct)
|
||||
{
|
||||
ConnectEntered.TrySetResult();
|
||||
@@ -39,6 +46,7 @@ internal sealed class ScriptedTransport : IModbusTransport
|
||||
public Task<byte[]> SendAsync(byte unitId, byte[] pdu, CancellationToken ct)
|
||||
{
|
||||
_sendsByUnit.AddOrUpdate(unitId, 1, (_, n) => n + 1);
|
||||
Sent.Enqueue((unitId, pdu));
|
||||
var scripted = Handler?.Invoke(unitId, pdu, ct);
|
||||
return scripted ?? Bank.SendAsync(unitId, pdu, ct);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user