Skip to content

Don't switch on the off lights inside a group; compact the Status section - #4

Merged
ameesme merged 2 commits into
mainfrom
claude/group-aware-adaptation
Aug 2, 2026
Merged

Don't switch on the off lights inside a group; compact the Status section#4
ameesme merged 2 commits into
mainfrom
claude/group-aware-adaptation

Conversation

@ameesme

@ameesme ameesme commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Bumps the manifest to 2.2.1.

Adapting a group no longer turns on its dark members

A light group reports on as soon as any member is on, so a partly-lit group passed Sundial's is_on check and got adapted. Turning a group on lights every member, so that write switched on the lights that had deliberately been left off. Symptom: fixtures coming on with nothing in the logbook to explain them, and the group flipping state behind them.

_write_targets now reads the group's members and addresses only the ones already lit, falling back to the entity itself when there's nothing to narrow (all members on, or not an introspectable group):

base = {ATTR_ENTITY_ID: self._write_targets(entity_id), ...}

Side benefit: those members now change under Sundial's own context, so they can't be mistaken for someone adjusting the light by hand.

What this does not fix

Only groups that publish a member list can be recognised. Zigbee groups can't be — they're a radio-level construct with no members to read, and turning one on is a groupcast that necessarily lights everything in it. They're indistinguishable from an ordinary light from the integration's side.

I initially guessed at them via "no backing device in the entity registry", but that also catches helper entities, so it's out. The payload reports what it can prove rather than guessing. For Zigbee groups the only remedy is adding the individual lights instead — and groups we can see now carry a note saying exactly that.

Status section cut to five or six rows

From ~20 rows down to what a diagnosis actually turns on: whether Sundial is in control and why not, the target against what the light reports, what the last run did, and when the next one is.

rows
Light Control, Reason*, Back to automatic*, Target, Reports, Last run, Next run, Group*
Sun Adaptation, Sun, Sun now, Next run, Lights

* conditional

Removed rows were either static configuration already visible in the sheet above, or restated a neighbour. Merged: the light's on/off state now shows in place of its reported values, sunrise and sunset share one row, and the outcome carries its own timestamp.

Outcomes read as <what happened> — <why>, so a run that did nothing says which of the several reasons applied:

Updated because of schedule
Turned off because of schedule
Idle — Sundial is disabled
Idle — Manually controlled
Idle — Current status is correct
Idle — Light is off
Idle — Light not found

Verification

  • ruff check . clean, python -m pytest 33 passed, npm run build clean with the bundle committed.
  • Driven in the dev harness with a fake three-member group, one member lit: the Status section shows Group — 3 lights · 1 on and the note, an ordinary light shows neither, and every sheet renders in 5–6 rows.

Worth knowing

_already_at_target still reads the group's aggregate attributes when deciding whether a write is needed. For a partly-lit group those are an average across the lit members, so it can decide a write is warranted slightly more often than strictly necessary. It no longer turns anything on, so the effect is cosmetic — but it's why a group row may report "Updated because of schedule" more often than a plain fixture.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XdpAyEvqgNcBstA75dQ5wr


Generated by Claude Code

claude added 2 commits August 2, 2026 23:12
… off

A light group reports "on" as soon as any one member is on, so Sundial saw
a partly-lit group as a light it should adapt. Turning a group on lights
every member, so the write switched on the lights that were deliberately
left off — reported as fixtures coming on for no logged reason, and as the
group flipping state behind them.

_write_targets now reads the group's members and addresses only the ones
already lit, falling back to the entity itself when there is nothing to
narrow. As a side effect those members change under our own context, so
they can no longer be mistaken for someone adjusting the light by hand.

Only groups that publish a member list can be recognised. Zigbee groups are
a radio-level construct with no members to read and a groupcast that
necessarily lights everything, so they are indistinguishable from an
ordinary light here and cannot be narrowed; the status payload reports them
as such rather than guessing from the entity registry. Groups we can see
carry a note that adding the individual lights is the better arrangement.

The Status section is cut from around twenty rows to five or six. What
survives is what a diagnosis actually turns on: whether Sundial is in
control and why not, the target against what the light reports, what the
last run did, and when the next one is. Static configuration was already
visible in the sheet above it, and several rows restated their neighbours —
the light's on/off state now shows in place of its reported values, and the
outcome carries its own timestamp. Outcomes read as "<what happened> — <why>"
so a run that did nothing says which of the several reasons applied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XdpAyEvqgNcBstA75dQ5wr
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XdpAyEvqgNcBstA75dQ5wr
@ameesme
ameesme merged commit 6059b28 into main Aug 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants