Skip to content

Add cover-capability detection if cover hardware variants diverge #572

Description

@ng

Context

src/hardware/pods.ts (PodCapabilities) describes OS-level capability per pod generation (iptables path, python version, DAC socket, package manager). It is keyed by PodVersion (H00 = Pod 3, I00 = Pod 4, J00 = Pod 5).

There is currently no equivalent for cover hardware — cover vibration motor, capSense version, Pillow accessory, etc. The code paths that depend on these implicitly assume the cover variant we've observed in production (Pod 5 J55, cover-only).

Why this hasn't been needed yet

Per docs/adr/0021-alarm-solo-trigger.md, the cover-vibration wire format (ALARM_LEFT/ALARM_RIGHT cmd 5/6 + hex-CBOR) fires the cover motor on both cover-only and Pillow-equipped Pod 5 firmware — the cover motor write runs unconditionally in Sensor.cpp:1221 triggerVibrationAlarm before the pillow path is consulted. So one code path covers every J55 variant we've seen.

We also don't have a known shipped Pod 5 SKU that lacks a cover motor. Every J55 in the wild has one.

When this becomes load-bearing

Add a cover-capability layer the first time one of these appears:

  • Pillow accessory exposure — pillow motor is a distinct UART/LSP path. Surfacing Pillow as a controllable accessory (UI, HomeKit) requires runtime detection
  • capSense v1 vs v2 sensor parsing — already a real divergence (docs/hardware/sensor-profiles.md); currently handled implicitly in parsers. Promoting to caps.coverSenseVersion would make intent clearer
  • HomeKit accessory advertisement — avoid exposing a "vibration switch" accessory if hardware doesn't have one
  • Alarm UI gating — hide intensity slider on a hypothetical coverless variant
  • A new cover SKU that doesn't fit the J55 assumptions baked into the alarm code path

Proposed shape (when triggered)

Extend PodCapabilities (or add a sibling CoverCapabilities) with:

interface CoverCapabilities {
  hasCoverMotor: boolean
  hasPillow: boolean
  pillowMotorTransport?: 'uart' | 'lsp'
  coverSenseVersion: 1 | 2
}

Detection probably keys off /persistent/deviceinfo/sensor-label + a small DAC probe (frame-shape signature). Source of truth: existing fingerprints in docs/hardware/sensor-profiles.md.

Acceptance (when picked up)

  • New CoverCapabilities type + detection function with unit tests against captured sensor-label fixtures
  • One real consumer wired up (Pillow exposure OR capSense version branch) — not just a matrix with one row
  • ADR documenting the detection strategy and known variant fingerprints
  • Existing alarm path remains variant-agnostic unless a real branch case justifies splitting

Why deferring is correct right now

A capability matrix with one row is premature abstraction. File this so it isn't forgotten, but don't build it until the first real branch appears.

Refs

  • ADR 0021 (docs/adr/0021-alarm-solo-trigger.md) — cover motor write semantics on J55
  • docs/hardware/sensor-profiles.md — capSense v1/v2 variant fingerprints
  • src/hardware/pods.ts — current OS-level capability model

Metadata

Metadata

Assignees

No one assigned

    Labels

    code-reviewFindings from codebase auditenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions