Add optional per-device follow-the-sun / schedule automation - #1
Merged
Merged
Conversation
added 2 commits
July 6, 2026 23:51
Each blind can now drive itself from the sun and the clock, with an emphasis on
being battery-frugal: the decision is pure local math over the cached position,
so evaluating costs no Bluetooth — only an actual move connects, which keeps
automation compatible with the command-only power mode.
New packages:
- pkg/solar: pure, dependency-free NOAA solar position (altitude/azimuth),
profile angle, and sunrise/sunset/solar-noon with polar-day/night handling.
Validated by oracle-free invariant tests (subsolar-point altitude, solstice
declinations, equation-of-time extrema, azimuth quadrants, high latitudes).
- pkg/blissha controller.go: a pure Decide() engine returning a target and
reason via a fixed precedence ladder (override → presence-sim → after-dark
privacy → mode → occupancy gate → battery guards), exhaustively table-tested.
Modes (per blind): sun_glare (proportional profile-angle cut-off that keeps
direct sun off a protected zone, simple sensitivity knob or precise geometry),
sun_shade (discrete + hysteresis), schedule (clock sleep/wake with a gradual
host-driven wake ramp, decoupled from the sun with optional solar clamps for
high latitudes), and thermal. Battery guards: deadband, quantize-to-step,
min-move-interval and an hourly cap; a manual or RF-remote move pauses
automation for override_timeout so it never fights the user.
Manager integration adds a sibling control channel and an independent eval timer
in both run modes (including command-only, where it fires while disconnected and
only a resulting move wakes the link), op-origin tagging for override, and
at-rest external-move detection.
Signals (room/home occupancy, lux, outdoor temp) are supplied via a new embed
API on Bridge (SetRoomOccupancy/SetHomeAway/SetLux/SetOutdoorTemp), routed
O(1) via a byID map. The YAML layer gains a home location: block (explicit IANA
timezone, with the tz database embedded via time/tzdata — no system-default
fallback) and a per-blind automation: block. `blissha -dry-run` prints each
blind's hourly decisions without touching Bluetooth or MQTT.
An on-demand blind could get stuck "unavailable" in Home Assistant even though commands were working. The bliss client reconnects on its own inside Send (it retries a dropped write by tearing down and re-establishing the link), which the manager never observes. ensureConnected only published "online" when it did the Connect itself; when it later saw the link already up (restored by Send's internal reconnect) it returned early, so an "offline" published by an earlier failed connect was never corrected. With availability_mode "all", that left both the cover and the battery sensor unavailable. Fix: reconcile availability with the real connection state. ensureConnected now publishes "online" whenever the link is up (not only when it connected), a successful command publishes "online" immediately, and publishAvailability is change-tracked so reconciling on every poll/track tick stays quiet (and is mutex-guarded, since the bridge's shutdown path also publishes it).
viggfred
force-pushed
the
feat/follow-the-sun
branch
from
July 6, 2026 21:57
5f12c5c to
119b3cd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Each blind can now drive itself from the sun and the clock, with an emphasis on being battery-frugal: the decision is pure local math over the cached position, so evaluating costs no Bluetooth — only an actual move connects, which keeps automation compatible with the command-only power mode.
New packages:
Modes (per blind): sun_glare (proportional profile-angle cut-off that keeps direct sun off a protected zone, simple sensitivity knob or precise geometry), sun_shade (discrete + hysteresis), schedule (clock sleep/wake with a gradual host-driven wake ramp, decoupled from the sun with optional solar clamps for high latitudes), and thermal. Battery guards: deadband, quantize-to-step, min-move-interval and an hourly cap; a manual or RF-remote move pauses automation for override_timeout so it never fights the user.
Manager integration adds a sibling control channel and an independent eval timer in both run modes (including command-only, where it fires while disconnected and only a resulting move wakes the link), op-origin tagging for override, and at-rest external-move detection.
Signals (room/home occupancy, lux, outdoor temp) are supplied via a new embed API on Bridge (SetRoomOccupancy/SetHomeAway/SetLux/SetOutdoorTemp), routed O(1) via a byID map. The YAML layer gains a home location: block (explicit IANA timezone, with the tz database embedded via time/tzdata — no system-default fallback) and a per-blind automation: block.
blissha -dry-runprints each blind's hourly decisions without touching Bluetooth or MQTT.