- Python 97.3%
- Shell 2.3%
- Dockerfile 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| media | ||
| .env.enc | ||
| .gitignore | ||
| .sops.yaml | ||
| app.py | ||
| calibrate-audio.py | ||
| compose.yaml | ||
| dashboard.json | ||
| Dockerfile | ||
| make_show.py | ||
| README.md | ||
| requirements.txt | ||
| safe-rebuild.sh | ||
thunderstorm
A whole-house lightning storm, in the spirit of the Hue "Thunderstorm" app but spanning Hue and Govee rather than one vendor.
Switched by input_boolean.thunderstorm. Participants are whatever carries
the Thunderstorm label in Home Assistant, so lights join or leave from the
UI -- nothing here needs editing.
How it works
Two tiers, driven completely differently, because their hardware differs:
| Tier | What | How it is driven |
|---|---|---|
| Conducted | Hue zones and rooms | Animated here via HA: slow blue rain shimmer, plus flash envelopes |
| Govee LAN | Govee devices with LAN Control enabled | Animated here too, straight over UDP (~33 ms) -- fully in sync |
| Native | Govee lights reachable only through the cloud bridge | Their built-in Thunderstorm scene, set once; the animation runs on the bulb |
Why Hue groups and not Hue bulbs
The bridge takes roughly ten light commands a second. There are 43 individual Hue bulbs here, so flashing them one by one would both exceed that budget and arrive as a visible wave. A Hue Room/Zone entity is a single HA entity that the bridge fans out internally, so one call flashes a whole room at once, truly simultaneously. That is the only reason synchronised lightning is affordable.
Govee: three speeds, and only one of them can keep time
Govee lights reach us by two completely different paths, and the gap is not subtle:
| Path | Measured round-trip | Can it flash in sync? |
|---|---|---|
| LAN API (UDP, local) | 20-67 ms, 33 ms median | Yes |
| MQTT bridge (cloud-backed) | 5-10 seconds | No |
Proof of the slow path, on a live bulb:
call light.turn_on effect=Thunderstorm -> +2s off +3s off +5s on, effect=Thunderstorm
So a Govee light is sorted into one of two tiers depending on which path is open to it:
- Answers the LAN scan -> driven directly over UDP, exactly like a Hue zone. It gets the real rain shimmer and lands its flashes with everything else.
- Does not -> given its native on-device
Thunderstormscene and otherwise left alone, because a flash sent through the bridge would arrive seconds after the thunder and merely interrupt the bulb's own animation.
Commands are fire-and-forget UDP with no acks. A dropped flash frame is a non-event; waiting on an ack would cost more than it could ever save.
Getting more Govee lights into the fast tier
LAN control is off by default and is per device. In the Govee Home app open the device -> settings -> LAN Control -> on. Only some models offer it at all (the H619D strip here does; the H6008 and H600B bulbs did not answer).
Nothing else to change: the storm rescans on every run, so a light moves from the native tier to the LAN tier by itself the next time you flip the switch. Check with:
docker compose logs | grep govee-lan
# govee-lan: 1 device(s) reachable locally: 192.168.0.238
Strike shapes
Lightning is not one flash. STRIKE_SHAPES in app.py holds five envelopes,
from a distant single swell to a close stuttering multi-flicker, each a list of
(brightness_pct, hold_seconds). A 0 means "back to the current rain level",
never off -- switching a zone off and on is slower than dimming it and reads as
a blink rather than lightning. Gaps between strikes are exponential with a
one-in-four chance of a fast follow-up, because real storms cluster.
The UI
A dedicated Home Assistant dashboard lives at /dashboard-thunderstorm
("Thunderstorm" in the sidebar). dashboard.json in this repo is the exported
config, so it can be restored with a lovelace/config/save websocket call
against that url_path. The switch is
input_boolean.thunderstorm; the rest are live tuning helpers, re-read at the
top of every strike cycle so the storm can be adjusted while it runs:
| Helper | Effect |
|---|---|
input_select.thunderstorm_intensity |
Distant / Building / Overhead — picks which strike envelopes are drawn from |
input_number.thunderstorm_strike_mean |
mean seconds between strikes |
input_number.thunderstorm_rain_min / _max |
brightness band between strikes |
If a helper is missing the corresponding .env default is used instead.
Config
Defaults, via .env (sops-encrypted as .env.enc). The helpers above override
the first four at runtime:
| Var | Default | Meaning |
|---|---|---|
STRIKE_MEAN_S |
22 | mean seconds between strikes |
STRIKE_MIN_GAP_S |
3 | floor on the gap |
RAIN_MIN_PCT / RAIN_MAX_PCT |
10 / 34 | brightness band for the rain shimmer |
RAIN_STEP_MIN_S / RAIN_STEP_MAX_S |
2.5 / 6.0 | how slowly the shimmer wanders |
FLASH_NATIVE |
0 | try to flash cloud-only Govee bulbs too (see above) |
GOVEE_LAN |
1 | discover and drive Govee devices over the local UDP API |
THUNDER_LABEL |
thunderstorm |
HA label id that selects participants |
State is snapshotted to scene.thunderstorm_restore at the start and restored
when the switch goes off.
Currently labelled
\nconducted\n
| entity | integration | area | note |
|---|---|---|---|
light.den |
hue | Den | Room |
light.front_yard |
hue | Front yard | Room |
light.kitchen |
hue | Kitchen | Room |
| \nnative\n | |||
| entity | integration | area | note |
| --- | --- | --- | --- |
light.bed_bulb_1 |
mqtt | - | Thunderstorm |
light.bed_bulb_2 |
mqtt | - | Thunderstorm |
light.can_bulb |
mqtt | - | Thunderstorm |
light.game_cabinet_1 |
mqtt | - | Thunderstorm |
light.game_cabinet_2 |
mqtt | - | Thunderstorm |
light.hall_bulb |
mqtt | - | Thunderstorm |
light.rainbow_lights |
mqtt | - | Lightning |
light.utility_far |
mqtt | - | Thunderstorm |
light.utility_near |
mqtt | - | Thunderstorm |
Everything else you could add
Add the Thunderstorm label to any of these in the HA UI and it joins on the
next run. Hue Room and Zone entities are strongly preferred over
individual bulbs, for the rate-limit reason above -- note the three purpose-built
zones thunder_indoor / thunder_outdoor / thunder_both, which overlap the
room groups, so use one scheme or the other, not both.
| entity | integration | kind | area | storm effect |
|---|---|---|---|---|
light.tidbyt_display |
? | bulb | Bedroom | - |
light.apollo_msr_2_278a20_rgb_light |
esphome | bulb | Utility Room | - |
light.ratgdov25i_47a254_light |
esphome | bulb | garage | - |
light.ratgdov25i_886c74_light |
esphome | bulb | garage | - |
light.my_hatch_baby_clock |
ha_hatch | bulb | - | - |
light.my_hatch_baby_light |
ha_hatch | bulb | - | - |
light.the_rainbow_connection_clock |
ha_hatch | bulb | - | - |
light.the_rainbow_connection_light |
ha_hatch | bulb | - | - |
light.basement_2 |
hue | Room | Basement | - |
light.bedroom |
hue | Room | Bedroom | - |
light.color_light_1 |
hue | bulb | - | - |
light.dining |
hue | Room | Dining | - |
light.door_bulb |
hue | bulb | Entrance | - |
light.entrance |
hue | Room | Entrance | - |
light.girls_room_door |
hue | bulb | Nursery | - |
light.girls_room_window |
hue | bulb | Nursery | - |
light.guest_room |
hue | Room | Guest Room | - |
light.hue_color_downlight_1 |
hue | bulb | Kitchen | - |
light.hue_color_downlight_1_2 |
hue | bulb | Kitchen | - |
light.hue_color_downlight_1_3 |
hue | bulb | Kitchen | - |
light.hue_color_downlight_2 |
hue | bulb | Kitchen | - |
light.hue_filament_far_right |
hue | bulb | Kitchen | - |
light.hue_lily_outdoor_spotlight_1 |
hue | bulb | Front yard | - |
light.hue_lily_outdoor_spotlight_2 |
hue | bulb | Front yard | - |
light.kitchen1 |
hue | bulb | Kitchen | - |
light.kitchen_far_left |
hue | bulb | Kitchen | - |
light.living_room |
hue | Room | Living Room | - |
light.living_room_bulb |
hue | bulb | Den | - |
light.outdoor_candle_1 |
hue | bulb | Front yard | - |
light.outdoor_candle_2 |
hue | bulb | Front yard | - |
light.pantry |
hue | Room | Pantry | - |
light.pantry_light |
hue | bulb | Pantry | - |
light.signe_gradient_floor_1 |
hue | bulb | Living Room | - |
light.small_lilly_2 |
hue | bulb | Front yard | - |
light.small_lilly_one |
hue | bulb | Front yard | - |
light.thunder_both |
hue | Zone | - | - |
light.thunder_indoor |
hue | Zone | - | - |
light.thunder_outdoor |
hue | Zone | Front yard | - |
light.eve_dimmer_switch_20ecq4101 |
matter | bulb | - | - |
light.eve_dimmer_switch_20ecq4101_2 |
matter | bulb | Stairway | - |
light.eve_light_switch_20ece4101 |
matter | bulb | Guest Room | - |
light.powder_room_downstairs_bathroom_left |
matter | bulb | Powder room | - |
light.powder_room_downstairs_bathroom_right |
matter | bulb | Powder room | - |
light.rainbow_lights_segment_001 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_002 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_003 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_004 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_005 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_006 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_007 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_008 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_009 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_010 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_011 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_012 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_013 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_014 |
mqtt | bulb | - | - |
light.rainbow_lights_segment_015 |
mqtt | bulb | - | - |
light.plug1_night_light |
tplink | bulb | - | - |
light.u6_mesh_basement_led |
unifi | bulb | - | - |
light.u6_mesh_bedroom_led |
unifi | bulb | - | - |
light.u6_mesh_ds_led |
unifi | bulb | - | - |
light.u6_mesh_led |
unifi | bulb | - | - |
light.usw_ultra_210w_led |
unifi | bulb | - | - |
light.bathroom_light_right |
zha | bulb | Girls bathroom | - |
light.girls_bathroom_left_ligut |
zha | bulb | Girls bathroom | - |
light.guest_motion_sensor |
zha | bulb | Landing | - |
light.middle_hue_down_light_light |
zha | bulb | Laundry Room | - |
light.right_hue_down_light_light_2 |
zha | bulb | Laundry Room | - |
light.third_reality_inc_3rsnl02043z |
zha | bulb | Girls bathroom | - |
light.third_reality_inc_3rsnl02043z_2 |
zha | bulb | Powder room | - |