@@ -287,6 +287,52 @@ internal sealed class FwlibFocasClient : IFocasClient
|
||||
return Task.FromResult<FocasWorkOffsetsInfo?>(new FocasWorkOffsetsInfo(slots));
|
||||
}
|
||||
|
||||
public Task<FocasOperatorMessagesInfo?> GetOperatorMessagesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_connected) return Task.FromResult<FocasOperatorMessagesInfo?>(null);
|
||||
// type 0..3 = OPMSG / MACRO / EXTERN / REJ-EXT (issue #261). Single-slot read
|
||||
// (length 4 + 256 = 260) returns the most-recent message in each class — best-
|
||||
// effort: a single-class failure leaves that class out of the snapshot rather
|
||||
// than failing the whole call, mirroring GetProductionAsync's policy.
|
||||
var list = new List<FocasOperatorMessage>(4);
|
||||
string[] classNames = ["OPMSG", "MACRO", "EXTERN", "REJ-EXT"];
|
||||
for (short t = 0; t < 4; t++)
|
||||
{
|
||||
var buf = new FwlibNative.OPMSG3 { Data = new byte[256] };
|
||||
var ret = FwlibNative.RdOpMsg3(_handle, t, length: 4 + 256, ref buf);
|
||||
if (ret != 0) continue;
|
||||
var text = TrimAnsiPadding(buf.Data);
|
||||
if (string.IsNullOrEmpty(text)) continue;
|
||||
list.Add(new FocasOperatorMessage(buf.Datano, classNames[t], text));
|
||||
}
|
||||
return Task.FromResult<FocasOperatorMessagesInfo?>(new FocasOperatorMessagesInfo(list));
|
||||
}
|
||||
|
||||
public Task<FocasCurrentBlockInfo?> GetCurrentBlockAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_connected) return Task.FromResult<FocasCurrentBlockInfo?>(null);
|
||||
var buf = new FwlibNative.ODBACTPT { Data = new byte[256] };
|
||||
var ret = FwlibNative.RdActPt(_handle, ref buf);
|
||||
if (ret != 0) return Task.FromResult<FocasCurrentBlockInfo?>(null);
|
||||
return Task.FromResult<FocasCurrentBlockInfo?>(
|
||||
new FocasCurrentBlockInfo(TrimAnsiPadding(buf.Data)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode + trim a Fanuc ANSI byte buffer. The CNC right-pads block text + opmsg
|
||||
/// bodies with nulls or spaces; trim them so the round-trip through the OPC UA
|
||||
/// address space stays stable (issue #261). Stops at the first NUL so any wire
|
||||
/// buffer that gets reused doesn't leak old bytes.
|
||||
/// </summary>
|
||||
internal static string TrimAnsiPadding(byte[] data)
|
||||
{
|
||||
if (data is null) return string.Empty;
|
||||
var len = 0;
|
||||
for (; len < data.Length; len++)
|
||||
if (data[len] == 0) break;
|
||||
return System.Text.Encoding.ASCII.GetString(data, 0, len).TrimEnd(' ', '\0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode one OFSB axis block from a <c>cnc_rdzofs</c> data buffer. Each axis
|
||||
/// occupies 10 bytes per <c>fwlib32.h</c>: <c>int data</c> + <c>short dec</c> +
|
||||
|
||||
Reference in New Issue
Block a user