Skip to content

Sensor endpoints with a display-toggle OnOff spawn a phantom 'Matter Relay' (IKEA ALPSTUGA) #64

Description

@simons-plugins

Found while assessing IKEA's new Matter-over-Thread range for support. Verified against the real handler registry, not yet against hardware (no ALPSTUGA in hand).

What happens

The IKEA ALPSTUGA air-quality sensor exposes, on one endpoint: AirQuality (0x005B), CO₂ (0x040D), PM2.5 (0x042A), Temperature (0x0402), Humidity (0x0405), OnOff (0x0006), plus node-scoped PowerSource. The OnOff cluster does not switch power — it toggles the sensor's front display (a "dead front" control).

Running an ALPSTUGA-shaped node through HandlerRegistry.handlers_for_endpoint yields:

['matterAirQualitySensor', 'matterCO2Sensor', 'matterHumiditySensor',
 'matterPM25Sensor', 'matterRelay', 'matterTemperatureSensor']

The five sensor devices are correct and wanted. The matterRelay is the wrinkleOnOffHandler.is_primary_for returns True because none of the lighting/ENDPOINT_OWNER_CLUSTERS are present, so a generic relay is created for the display toggle. It's not broken (the relay genuinely toggles the display), but it's an unexpected, generically-labelled extra device. Home Assistant has the same confusion — it mis-classifies ALPSTUGA as an Outlet (HA core #158943).

This is a cousin of #58 (the duplicate-device class): an OnOff that is a secondary control of a sensor, not the endpoint's primary purpose.

Why it's not auto-fixed (and the decision to make)

Suppressing OnOff "whenever sensors are present" would be wrong — legitimate sensor+switch combos could exist. The Matter-correct signals to distinguish a display toggle from a real switch are:

  1. OnOff FeatureMap (attr 0xFFFC) bit 2 = DeadFrontBehavior (DF). ALPSTUGA's display OnOff is expected to set this; a real plug/switch does not. This is the clean, spec-defined tell (and the one the HA issue points to).
  2. The endpoint's DeviceTypeList (Descriptor 0x001D) — an Air Quality Sensor device type (0x002C) means OnOff is auxiliary; an On/Off Plug-in Unit (0x010A) means it's primary.

Either requires data the pipeline doesn't currently consult (FeatureMap isn't parsed; device-type-driven dispatch is a larger change than cluster-driven). Deliberately not implemented blind — there's no ALPSTUGA on hand to verify the DF flag against, and a wrong suppression rule could break real combos.

Captured for now

tests/test_device_zoo.py gains an alpstuga entry that characterises current behaviour (expects the matterRelay), so the wrinkle is pinned and any future change is deliberate. When this is fixed (likely: OnOffHandler.is_primary_for returns False when the OnOff FeatureMap advertises DeadFront), the fix updates that expected-types list in the same change.

Refs

  • HA core #158943 — ALPSTUGA mis-classified as Outlet (DeadFrontBehavior is the tell)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdevice-supportNew Matter device class / cluster support

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions