Auto: focas-f1c — Modal codes + overrides
Closes #259 Adds Modal/ + Override/ fixed-tree subfolders per FOCAS device, mirroring the pattern established by Status/ (#257) and Production/ (#258): cached snapshots refreshed on the probe tick, served from cache on read, no extra wire traffic on top of user-driven tag reads. Modal/ surfaces the four universally-present aux modal codes M/S/T/B from cnc_modal(type=100..103) as Int16. **G-group decoding (groups 1..21) is deferred to a follow-up** — the FWLIB ODBMDL union differs per series + group and the issue body explicitly permits this scoping. Adds the cnc_modal P/Invoke + ODBMDL struct + a generic int16 cnc_rdparam helper so the follow-up can add G-groups without further wire-level scaffolding. Override/ surfaces Feed/Rapid/Spindle/Jog from cnc_rdparam at MTB-specific parameter numbers (FocasDeviceOptions.OverrideParameters; defaults to 30i: 6010/6011/6014/6015). Per-field nullable params let a deployment hide overrides their MTB doesn't wire up; passing OverrideParameters=null suppresses the entire Override/ subfolder for that device. 6 unit tests cover discovery shape, omitted Override folder when unconfigured, partial Override field selection, cached-snapshot reads (Modal + Override), BadCommunicationError before first refresh, and the FwlibFocasClient disconnected short-circuit.
This commit is contained in:
@@ -70,6 +70,27 @@ public interface IFocasClient : IDisposable
|
||||
/// </summary>
|
||||
Task<FocasProductionInfo?> GetProductionAsync(CancellationToken cancellationToken)
|
||||
=> Task.FromResult<FocasProductionInfo?>(null);
|
||||
|
||||
/// <summary>
|
||||
/// Read the active modal M/S/T/B codes via <c>cnc_modal</c>. G-group decoding is
|
||||
/// deferred — the FWLIB <c>ODBMDL</c> union differs per series + group and the
|
||||
/// issue body permits surfacing only the universally-present M/S/T/B fields in
|
||||
/// the first cut (issue #259). Returns <c>null</c> when the wire client cannot
|
||||
/// supply the snapshot.
|
||||
/// </summary>
|
||||
Task<FocasModalInfo?> GetModalAsync(CancellationToken cancellationToken)
|
||||
=> Task.FromResult<FocasModalInfo?>(null);
|
||||
|
||||
/// <summary>
|
||||
/// Read the four operator override values (feed / rapid / spindle / jog) via
|
||||
/// <c>cnc_rdparam</c>. The parameter numbers are MTB-specific so the caller passes
|
||||
/// them in via <paramref name="parameters"/>; a <c>null</c> entry suppresses that
|
||||
/// field's read (the corresponding node is also omitted from the address space).
|
||||
/// Returns <c>null</c> when the wire client cannot supply the snapshot (issue #259).
|
||||
/// </summary>
|
||||
Task<FocasOverrideInfo?> GetOverrideAsync(
|
||||
FocasOverrideParameters parameters, CancellationToken cancellationToken)
|
||||
=> Task.FromResult<FocasOverrideInfo?>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -102,6 +123,47 @@ public sealed record FocasProductionInfo(
|
||||
int PartsTotal,
|
||||
int CycleTimeSeconds);
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the active modal M/S/T/B codes (issue #259). G-group decoding is a
|
||||
/// deferred follow-up — the FWLIB <c>ODBMDL</c> union differs per series + group, and
|
||||
/// the issue body permits the first cut to surface only the universally-present
|
||||
/// M/S/T/B fields. <c>short</c> matches the FWLIB <c>aux_data</c> width.
|
||||
/// </summary>
|
||||
public sealed record FocasModalInfo(
|
||||
short MCode,
|
||||
short SCode,
|
||||
short TCode,
|
||||
short BCode);
|
||||
|
||||
/// <summary>
|
||||
/// MTB-specific FOCAS parameter numbers for the four operator overrides (issue #259).
|
||||
/// Defaults match Fanuc 30i — Feed=6010, Rapid=6011, Spindle=6014, Jog=6015. A
|
||||
/// <c>null</c> entry suppresses that field's read on the wire and removes the matching
|
||||
/// node from the address space; this lets a deployment hide overrides their MTB doesn't
|
||||
/// wire up rather than always serving Bad.
|
||||
/// </summary>
|
||||
public sealed record FocasOverrideParameters(
|
||||
ushort? FeedParam,
|
||||
ushort? RapidParam,
|
||||
ushort? SpindleParam,
|
||||
ushort? JogParam)
|
||||
{
|
||||
/// <summary>Stock 30i defaults — Feed=6010, Rapid=6011, Spindle=6014, Jog=6015.</summary>
|
||||
public static FocasOverrideParameters Default { get; } = new(6010, 6011, 6014, 6015);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the four operator overrides (issue #259). Each value is a percentage
|
||||
/// surfaced as <c>Int16</c>; a value of <c>null</c> means the corresponding parameter
|
||||
/// was not configured (suppressed at <see cref="FocasOverrideParameters"/>). All four
|
||||
/// fields nullable so the driver can omit nodes whose MTB parameter is unset.
|
||||
/// </summary>
|
||||
public sealed record FocasOverrideInfo(
|
||||
short? Feed,
|
||||
short? Rapid,
|
||||
short? Spindle,
|
||||
short? Jog);
|
||||
|
||||
/// <summary>Factory for <see cref="IFocasClient"/>s. One client per configured device.</summary>
|
||||
public interface IFocasClientFactory
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user