Summary
The Autopilot widget (V2 API) stays off-line and shows no control panel (no ±1/±10, no mode selector — only Engage/Disengage) when the autopilot provider publishes state/engaged but not the optional mode field.
Details
apMode is fed only from the autopilotMode stream (the V2 mode field):
// startV2Subscriptions()
this.streams.observe('autopilotMode', newValue => {
if (newValue.data?.value) {
this.apMode.set(newValue.data.value);
} else {
this.apMode.set('off-line'); // <-- provider didn't publish `mode`
}
});
mode is optional in the Signal K Autopilot V2 API (it's meant for devices with distinct sub-modes). Many providers only report state (standby/auto/wind/route) — e.g. @signalk/signalk-autopilot for Raymarine doesn't publish mode. When mode is absent, apMode becomes off-line and the panel is effectively unusable.
Notably the V1 path already does the right thing — it maps the "mode" from state:
// startV1Subscriptions()
paths['autopilotMode'].path = API_PATHS.V1_MODE_PATH; // = 'self.steering.autopilot.state'
So V1 shows the panel while V2 doesn't, for the same physical autopilot.
Impact
Any V2 provider that doesn't publish the optional mode leaves the user with only Engage/Disengage, and — since the displayed mode reads off-line — no clear indication of the real state. (Engaging then shows no way to steer or, depending on state reporting, to disengage.)
Proposed fix
In V2, fall back to state when mode is absent, mirroring V1. For example, in the autopilotMode observer use this.apState() when newValue.data?.value is null, or derive apMode from mode ?? state.
References
src/app/widgets/widget-autopilot/widget-autopilot.component.ts — startV2Subscriptions() vs startV1Subscriptions() (V1_MODE_PATH), apMode, apGrid.
Happy to open a PR — wanted to confirm the preferred approach first (observer-level fallback vs. a computed effective-mode), since the signal ordering between the state and mode observers matters.
Summary
The Autopilot widget (V2 API) stays off-line and shows no control panel (no ±1/±10, no mode selector — only Engage/Disengage) when the autopilot provider publishes
state/engagedbut not the optionalmodefield.Details
apModeis fed only from theautopilotModestream (the V2modefield):modeis optional in the Signal K Autopilot V2 API (it's meant for devices with distinct sub-modes). Many providers only reportstate(standby/auto/wind/route) — e.g.@signalk/signalk-autopilotfor Raymarine doesn't publishmode. Whenmodeis absent,apModebecomesoff-lineand the panel is effectively unusable.Notably the V1 path already does the right thing — it maps the "mode" from
state:So V1 shows the panel while V2 doesn't, for the same physical autopilot.
Impact
Any V2 provider that doesn't publish the optional
modeleaves the user with only Engage/Disengage, and — since the displayed mode readsoff-line— no clear indication of the real state. (Engaging then shows no way to steer or, depending on state reporting, to disengage.)Proposed fix
In V2, fall back to
statewhenmodeis absent, mirroring V1. For example, in theautopilotModeobserver usethis.apState()whennewValue.data?.valueis null, or deriveapModefrommode ?? state.References
src/app/widgets/widget-autopilot/widget-autopilot.component.ts—startV2Subscriptions()vsstartV1Subscriptions()(V1_MODE_PATH),apMode,apGrid.Happy to open a PR — wanted to confirm the preferred approach first (observer-level fallback vs. a
computedeffective-mode), since the signal ordering between thestateandmodeobservers matters.