Skip to content

fix: RGB LED stays on during deep sleep#55

Closed
bharvey88 wants to merge 4 commits intobetafrom
fix/rgb-led-deep-sleep
Closed

fix: RGB LED stays on during deep sleep#55
bharvey88 wants to merge 4 commits intobetafrom
fix/rgb-led-deep-sleep

Conversation

@bharvey88
Copy link
Contributor

@bharvey88 bharvey88 commented Mar 8, 2026

Summary

  • The WS2812 RGB LED was staying faintly on after entering deep sleep despite on_shutdown containing light.turn_off: rgb_light
  • Root cause: addressable lights (RMT-based) schedule their state update for the next main loop iteration, but the loop stops running during shutdown before the signal is transmitted to the LED
  • Fix: explicitly specify transition_length: 0ms on all light.turn_off calls in on_shutdown hooks — this bypasses the loop-based timing mechanism so the off command is sent immediately

Confirmed fix per ESPHome issue #6800.

Files changed

All 7 YAML variants updated: TEMP-1, TEMP-1B, TEMP-1_Minimal, TEMP-1B_Minimal, TEMP-1_BLE, TEMP-1B_BLE, TEMP-1_Beta

Test plan

  • Flash device
  • Turn RGB LED on via Home Assistant
  • Wait for device to enter deep sleep
  • Confirm LED turns fully off with no faint glow

Summary by CodeRabbit

  • Chores

    • Standardized explicit immediate RGB light shutdown (zero transition) during shutdown and sleep paths.
    • Added accessory power switch-off in shutdown sequences where applicable.
  • Bug Fixes

    • Inserted an explicit light-off followed by a 200ms delay before deep sleep and after client disconnects to ensure LEDs extinguish reliably.

…nt RGB LED staying on during deep sleep

The WS2812 LED was staying slightly on after entering deep sleep despite
on_shutdown containing light.turn_off. Root cause: addressable lights
schedule their state update for the next main loop iteration, but the
loop stops running during shutdown before the RMT signal is transmitted.

Explicitly specifying transition_length: 0ms bypasses the loop-based
timing mechanism, ensuring the off command is sent synchronously.

Fix applied to all 7 YAML variants.

Ref: esphome/issues#6800
@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

Walkthrough

Multiple ESPHome YAMLs standardize shutdown light calls to an explicit mapping, add an explicit RGB light turn-off plus a 200ms delay before entering deep sleep in various on_boot / OTA / client-connected paths, and add accessory power switch turn-offs in some shutdown sequences.

Changes

Cohort / File(s) Summary
Shutdown action standardized
Integrations/ESPHome/TEMP-1.yaml, Integrations/ESPHome/TEMP-1B.yaml, Integrations/ESPHome/TEMP-1B_BLE.yaml, Integrations/ESPHome/TEMP-1B_Minimal.yaml, Integrations/ESPHome/TEMP-1_BLE.yaml, Integrations/ESPHome/TEMP-1_Beta.yaml, Integrations/ESPHome/TEMP-1_Minimal.yaml
Replaced shorthand - light.turn_off: rgb_light with explicit mapping - light.turn_off:\n id: rgb_light\n transition_length: 0ms in on_shutdown blocks across files.
Pre-sleep explicit turn-off + 200ms delay
Integrations/ESPHome/TEMP-1.yaml, Integrations/ESPHome/TEMP-1B.yaml, Integrations/ESPHome/TEMP-1B_BLE.yaml, Integrations/ESPHome/TEMP-1B_Minimal.yaml, Integrations/ESPHome/TEMP-1_BLE.yaml, Integrations/ESPHome/TEMP-1_Beta.yaml, Integrations/ESPHome/TEMP-1_Minimal.yaml
Inserted - light.turn_off: id: rgb_light, transition_length: 0ms followed by - delay: 200ms immediately before deep_sleep.enter in relevant on_boot / OTA-prevent-sleep / client-connected else branches.
Accessory power shutdown
Integrations/ESPHome/TEMP-1B.yaml, Integrations/ESPHome/TEMP-1B_BLE.yaml, Integrations/ESPHome/TEMP-1B_Minimal.yaml, Integrations/ESPHome/TEMP-1_BLE.yaml, Integrations/ESPHome/TEMP-1_Minimal.yaml
Added - switch.turn_off: accessory_power to on_shutdown sequences alongside the explicit light.turn_off mapping.
Core pre-sleep insertion
Integrations/ESPHome/Core.yaml
Inserted light.turn_off (id: rgb_light, transition_length: 0ms) and delay: 200ms after id(reportAllValues).execute() and before deep_sleep.enter.
Client-connected flow adjustment
Integrations/ESPHome/TEMP-1_Beta.yaml
Added the same explicit light.turn_off + 200ms delay in the api.on_client_connected branch that sleeps after connecting.

Sequence Diagram(s)

sequenceDiagram
    participant Boot as on_boot / flow
    participant API as api.on_client_connected
    participant Light as RGB Light
    participant Switch as Accessory Power
    participant Deep as Deep Sleep

    Boot->>Light: light.turn_off (id: rgb_light, transition_length: 0ms)
    Light-->>Boot: ack
    Boot->>Boot: delay 200ms
    alt shutdown includes accessory power
        Boot->>Switch: switch.turn_off (accessory_power)
        Switch-->>Boot: ack
    end
    Boot->>Deep: deep_sleep.enter
    Deep-->>Boot: entering sleep
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nudge the LEDs, then softly sigh,
I count two hundred milliseconds and eyes go dry.
Lights dim, switches rest, the circuits hum low—
A rabbit's hush: blink, delay, and go.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: RGB LED stays on during deep sleep' accurately and specifically describes the main problem being addressed across all seven YAML configuration files in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/rgb-led-deep-sleep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…uring sleep

The previous fix (transition_length: 0ms in on_shutdown) did not work
because on_shutdown runs after the main loop has stopped, so the RMT
peripheral never actually transmits the off signal.

This fix adds light.turn_off + 50ms delay immediately before every
deep_sleep.enter action call, while the main loop is still running and
can complete the RMT transmission before sleep is entered.

Affects Core.yaml (primary HA-connected path) and all 7 variant files.
- binary_sensor.is_off: ota_mode
- switch.is_off: prevent_sleep
then:
- light.turn_off: rgb_light
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed if it is already in the on_shutdown?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed if it is already in the on_shutdown?

this is a work in progress i'm submitting the PR then testing - so far neither commit is working.

Attempt 2 used the light.turn_off shorthand which may not respect
default_transition_length, leaving a ~1s fade active while only
waiting 50ms. This combines explicit transition_length: 0ms with a
200ms delay (ample time for RMT transmission to complete) while the
main loop is still running.

Also reverts on_shutdown back to simple shorthand since that hook
runs after the loop has stopped and cannot reliably transmit the
RMT signal regardless of transition settings.
…tdown

Test whether cutting accessory power on shutdown prevents the dim LED glow
during deep sleep, in addition to forcing zero-length light transition.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
Integrations/ESPHome/Core.yaml (1)

46-50: Consider extracting this sleep preamble into a shared script.

This exact light.turn_off -> delay -> deep_sleep.enter sequence is now duplicated in Integrations/ESPHome/Core.yaml and multiple variants. Centralizing it in one script would make future timing or target-id changes much safer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Integrations/ESPHome/Core.yaml` around lines 46 - 50, Extract the repeated
sequence (light.turn_off with id: rgb_light, transition_length: 0ms -> delay
200ms -> deep_sleep.enter) into a single reusable script (e.g., script:
sleep_preamble) and replace the inline sequence with a single call to that
script (e.g., script.execute: sleep_preamble) wherever it appears; centralize
the transition_length and delay values inside that script so future timing or
target-id changes are made in one place and ensure the script name and target
(rgb_light) match the existing usage.
Integrations/ESPHome/TEMP-1B_BLE.yaml (1)

73-78: Review the indentation convention under the then: block.

The sequence items (light.turn_off, delay, deep_sleep.enter) should be indented further than the then: key to follow YAML and ESPHome conventions. While the file parses, proper indentation improves readability and consistency with the rest of the configuration.

Suggested fix
                      then:
-                      - light.turn_off:
-                          id: rgb_light
-                          transition_length: 0ms
-                      - delay: 200ms
-                      - deep_sleep.enter:
-                          id: deep_sleep_1
+                        - light.turn_off:
+                            id: rgb_light
+                            transition_length: 0ms
+                        - delay: 200ms
+                        - deep_sleep.enter:
+                            id: deep_sleep_1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Integrations/ESPHome/TEMP-1B_BLE.yaml` around lines 73 - 78, The sequence
under the then: key is not indented to the same level as other action lists;
re-indent the action sequence so each item (light.turn_off with id: rgb_light,
delay, deep_sleep.enter with id: deep_sleep_1) is nested one level deeper than
then: to follow YAML/ESPHome conventions and match the rest of the file's action
lists.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Integrations/ESPHome/TEMP-1_BLE.yaml`:
- Around line 73-78: The YAML's then: action list uses a different indentation
style than the on_shutdown: block; update the then: block so each list item is
indented two spaces under the parent key to match the file style—adjust the
lines containing the actions light.turn_off (id: rgb_light), delay: 200ms, and
deep_sleep.enter (id: deep_sleep_1) so their leading hyphens and nested keys
follow the same 2-space indentation pattern as the on_shutdown: block.

---

Nitpick comments:
In `@Integrations/ESPHome/Core.yaml`:
- Around line 46-50: Extract the repeated sequence (light.turn_off with id:
rgb_light, transition_length: 0ms -> delay 200ms -> deep_sleep.enter) into a
single reusable script (e.g., script: sleep_preamble) and replace the inline
sequence with a single call to that script (e.g., script.execute:
sleep_preamble) wherever it appears; centralize the transition_length and delay
values inside that script so future timing or target-id changes are made in one
place and ensure the script name and target (rgb_light) match the existing
usage.

In `@Integrations/ESPHome/TEMP-1B_BLE.yaml`:
- Around line 73-78: The sequence under the then: key is not indented to the
same level as other action lists; re-indent the action sequence so each item
(light.turn_off with id: rgb_light, delay, deep_sleep.enter with id:
deep_sleep_1) is nested one level deeper than then: to follow YAML/ESPHome
conventions and match the rest of the file's action lists.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 294d8c1d-c3b1-4c85-bf44-a8e40005d198

📥 Commits

Reviewing files that changed from the base of the PR and between 7cbf1a8 and 485b027.

📒 Files selected for processing (8)
  • Integrations/ESPHome/Core.yaml
  • Integrations/ESPHome/TEMP-1.yaml
  • Integrations/ESPHome/TEMP-1B.yaml
  • Integrations/ESPHome/TEMP-1B_BLE.yaml
  • Integrations/ESPHome/TEMP-1B_Minimal.yaml
  • Integrations/ESPHome/TEMP-1_BLE.yaml
  • Integrations/ESPHome/TEMP-1_Beta.yaml
  • Integrations/ESPHome/TEMP-1_Minimal.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • Integrations/ESPHome/TEMP-1.yaml
  • Integrations/ESPHome/TEMP-1_Beta.yaml
  • Integrations/ESPHome/TEMP-1_Minimal.yaml

Comment on lines +73 to 78
- light.turn_off:
id: rgb_light
transition_length: 0ms
- delay: 200ms
- deep_sleep.enter:
id: deep_sleep_1
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python -c 'import yaml' 2>/dev/null || pip install --quiet pyyaml
python - <<'PY'
from pathlib import Path
import yaml

class Loader(yaml.SafeLoader):
    pass

def unknown(loader, tag_suffix, node):
    if isinstance(node, yaml.ScalarNode):
        return loader.construct_scalar(node)
    if isinstance(node, yaml.SequenceNode):
        return loader.construct_sequence(node)
    return loader.construct_mapping(node)

Loader.add_multi_constructor('!', unknown)

path = Path("Integrations/ESPHome/TEMP-1_BLE.yaml")
with path.open() as f:
    yaml.load(f, Loader=Loader)

print(f"{path}: YAML parsed successfully")
PY

Repository: ApolloAutomation/TEMP-1

Length of output: 129


🏁 Script executed:

sed -n '70,85p' Integrations/ESPHome/TEMP-1_BLE.yaml | cat -A

Repository: ApolloAutomation/TEMP-1

Length of output: 608


🏁 Script executed:

python3 << 'EOF'
from pathlib import Path

path = Path("Integrations/ESPHome/TEMP-1_BLE.yaml")
with path.open() as f:
    lines = f.readlines()

# Check lines around 73-78 (0-indexed: 72-77)
for i in range(69, 85):
    if i < len(lines):
        line = lines[i]
        indent = len(line) - len(line.lstrip(' '))
        content = line.strip()
        print(f"Line {i+1:3d} [indent={indent:2d}]: {content[:60]}")
EOF

Repository: ApolloAutomation/TEMP-1

Length of output: 700


Indentation is valid YAML but inconsistent with the file's own style.

The YAML file parses successfully; the current indentation is syntactically correct. However, the then: block uses a different indentation style than the on_shutdown: block below it (lines 80–84), which indents list items by 2 spaces under the parent key for readability. For consistency, the then: block items should be indented to match that pattern.

Suggested style alignment
                      then:
-                      - light.turn_off:
-                          id: rgb_light
-                          transition_length: 0ms
-                      - delay: 200ms
-                      - deep_sleep.enter:
-                          id: deep_sleep_1
+                        - light.turn_off:
+                            id: rgb_light
+                            transition_length: 0ms
+                        - delay: 200ms
+                        - deep_sleep.enter:
+                            id: deep_sleep_1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- light.turn_off:
id: rgb_light
transition_length: 0ms
- delay: 200ms
- deep_sleep.enter:
id: deep_sleep_1
- light.turn_off:
id: rgb_light
transition_length: 0ms
- delay: 200ms
- deep_sleep.enter:
id: deep_sleep_1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Integrations/ESPHome/TEMP-1_BLE.yaml` around lines 73 - 78, The YAML's then:
action list uses a different indentation style than the on_shutdown: block;
update the then: block so each list item is indented two spaces under the parent
key to match the file style—adjust the lines containing the actions
light.turn_off (id: rgb_light), delay: 200ms, and deep_sleep.enter (id:
deep_sleep_1) so their leading hyphens and nested keys follow the same 2-space
indentation pattern as the on_shutdown: block.

@bharvey88
Copy link
Contributor Author

closing as cant fix due to esphome bug. esphome/issues#6800

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