docs(focas): retire stale 'wire backend returns no figures' comments after cnc_getfigure shipped

This commit is contained in:
Joseph Doherty
2026-06-18 12:32:55 -04:00
parent feddc2b80e
commit e5f568d01f
3 changed files with 13 additions and 12 deletions
@@ -657,7 +657,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// Per-axis decimal-place figures (cnc_getfigure), fetched once. Auto figures win // Per-axis decimal-place figures (cnc_getfigure), fetched once. Auto figures win
// over the manual PositionDecimalPlaces config at the publish seam; an empty list // over the manual PositionDecimalPlaces config at the publish seam; an empty list
// (the managed wire backend today) makes every axis fall back to the config knob. // (or a failed/empty figure read) makes every axis fall back to the config knob.
// Defensive: a figure-read failure must NOT fault device init — default to empty. // Defensive: a figure-read failure must NOT fault device init — default to empty.
state.PositionFigures = await SafeProbe(() => client.GetPositionFiguresAsync(ct), []); state.PositionFigures = await SafeProbe(() => client.GetPositionFiguresAsync(ct), []);
@@ -830,9 +830,8 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// an auto cnc_getfigure figure WINS, and the configured PositionDecimalPlaces is the // an auto cnc_getfigure figure WINS, and the configured PositionDecimalPlaces is the
// fallback when the CNC didn't report one for that axis (see AxisFactor). A figure of // fallback when the CNC didn't report one for that axis (see AxisFactor). A figure of
// 0 yields factor 1.0 — i.e. the integer widened to double, byte-identical to legacy // 0 yields factor 1.0 — i.e. the integer widened to double, byte-identical to legacy
// behaviour (12345 / 1.0 == 12345.0). CAVEAT: the managed WireFocasClient returns no // behaviour (12345 / 1.0 == 12345.0). The managed WireFocasClient fetches figures live
// figures today, so the REAL backend always uses the manual fallback; live auto-fetch // via ReadPositionFiguresAsync; the config knob is the per-axis fallback only. FeedRate /
// lands when a FocasWireClient cnc_getfigure wire command is added. FeedRate /
// SpindleSpeed (rate snapshot) and ServoLoad are NOT position-scaled (published elsewhere). // SpindleSpeed (rate snapshot) and ServoLoad are NOT position-scaled (published elsewhere).
var factor = AxisFactor(state, axisIndex); var factor = AxisFactor(state, axisIndex);
state.LastFixedSnapshots[FixedTreeReference(host, $"Axes/{axis.Display}/AbsolutePosition")] = snap.AbsolutePosition / factor; state.LastFixedSnapshots[FixedTreeReference(host, $"Axes/{axis.Display}/AbsolutePosition")] = snap.AbsolutePosition / factor;
@@ -845,8 +844,9 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
/// Resolve the position-scale factor (10^figure) for a single axis. Auto /// Resolve the position-scale factor (10^figure) for a single axis. Auto
/// (<c>cnc_getfigure</c>) wins per-axis; manual <c>PositionDecimalPlaces</c> is the /// (<c>cnc_getfigure</c>) wins per-axis; manual <c>PositionDecimalPlaces</c> is the
/// fallback when the CNC didn't report a figure for that axis. Both clamp non-negative; /// fallback when the CNC didn't report a figure for that axis. Both clamp non-negative;
/// 0 ⇒ factor 1.0 (legacy byte-identical). The managed wire backend returns no figures /// 0 ⇒ factor 1.0 (legacy byte-identical). The managed wire backend fetches figures live
/// today, so the real backend always takes the manual-fallback branch. /// via <c>ReadPositionFiguresAsync</c>; the fallback branch fires only when the CNC
/// reports no figure for a given axis (or the figure read returns empty).
/// </summary> /// </summary>
private static double AxisFactor(DeviceState state, int axisIndex) private static double AxisFactor(DeviceState state, int axisIndex)
{ {
@@ -1202,8 +1202,8 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
/// <summary> /// <summary>
/// Gets or sets the per-axis position decimal-place figures fetched once at init via /// Gets or sets the per-axis position decimal-place figures fetched once at init via
/// <c>cnc_getfigure</c> (parallel to the axis-name list; index = axis). An auto figure /// <c>cnc_getfigure</c> (parallel to the axis-name list; index = axis). An auto figure
/// for an axis WINS over the configured <c>PositionDecimalPlaces</c>; an empty list (the /// for an axis WINS over the configured <c>PositionDecimalPlaces</c>; an empty list (or
/// managed wire backend's behaviour today) makes every axis fall back to that config knob. /// a failed/empty figure read) makes every axis fall back to that config knob.
/// </summary> /// </summary>
public IReadOnlyList<int> PositionFigures { get; set; } = []; public IReadOnlyList<int> PositionFigures { get; set; } = [];
@@ -9,8 +9,8 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
/// per-axis position decimal-place figures at init and applies them at the /// per-axis position decimal-place figures at init and applies them at the
/// <see cref="FocasDriver"/> publish seam. Precedence: an auto figure for an axis WINS; /// <see cref="FocasDriver"/> publish seam. Precedence: an auto figure for an axis WINS;
/// the configured <c>PositionDecimalPlaces</c> is the per-axis fallback when the CNC did /// the configured <c>PositionDecimalPlaces</c> is the per-axis fallback when the CNC did
/// not report a figure for that axis. (The managed wire backend returns no figures today, /// not report a figure for that axis. These tests drive the Fake to exercise the driver's
/// so the real backend always uses the manual fallback — these tests drive the Fake.) /// auto-scale-vs-fallback logic independently of the wire path.
/// </summary> /// </summary>
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public sealed class FocasPositionAutoScaleTests public sealed class FocasPositionAutoScaleTests
@@ -8,8 +8,9 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
/// Phase 4 data-type tier — axis-position scaling. <c>cnc_rddynamic2</c> returns /// Phase 4 data-type tier — axis-position scaling. <c>cnc_rddynamic2</c> returns
/// positions as scaled integers; the driver applies a <c>10^PositionDecimalPlaces</c> /// positions as scaled integers; the driver applies a <c>10^PositionDecimalPlaces</c>
/// divide at the <see cref="FocasDriver"/> publish seam so positions surface in /// divide at the <see cref="FocasDriver"/> publish seam so positions surface in
/// engineering units on the Float64 axis nodes. DecimalPlaces is config-supplied /// engineering units on the Float64 axis nodes. The managed wire backend fetches per-axis
/// (auto-fetch via <c>cnc_getfigure</c> is deferred — wire-gated). /// figures live via <c>cnc_getfigure</c>; the config knob is the per-axis fallback used
/// when the CNC reports no figure for an axis. These tests cover the config-supplied path.
/// </summary> /// </summary>
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public sealed class FocasPositionScalingTests public sealed class FocasPositionScalingTests