Requiring 3.13 meant the device needed an interpreter the distribution does not
have, which is what dragged uv in, and uv then had to be matched to the Pi's
32-bit userland by hand and to build Pillow from source because no armv7 wheel
exists for a 3.13 ABI. Dropping to 3.11 removes all of that: apt provides the
interpreter and piwheels has prebuilt armhf wheels for the native dependencies.
The 3.13-only syntax was shallow - PEP 695 throughout, which converts back
mechanically:
type X = Y -> X: TypeAlias = Y
type Handler[E: Event] -> E = TypeVar("E", bound=Event) plus a plain alias,
which is generic anyway because it carries a TypeVar
def f[T: Bound](...) -> a module-level TypeVar
Also drop the one @override (3.12, and static-only), and stop the lirc test
harness calling Server.close_clients(), which is 3.13: the scripted handler now
releases its connection when asked, which is what that call was there to force.
Verified on 3.11.14 - 485 passed, mypy strict clean - and still 496 passed on
the 3.14 dev venv, which additionally has the analysis extra.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A show folder under Kinderpodcasts/ opts in by containing a feed.txt marker
naming its RSS feed. A new PodcastFeedService polls every such feed every 6
hours (and once at startup), downloads any episode not already on disk using
the existing YYYYMMDD - Title.ext convention, and triggers the same
rescan-and-broadcast sequence "Bibliothek neu einlesen" already uses - now
shared via App.rescan_library() instead of duplicated. A show with no
feed.txt is untouched, so there is no new config section for this.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The background worker now runs a real librosa analyzer (tempo, beat grid,
per-second energy/valence curves) instead of only the null baseline, kept
behind build_analyzer() so a plain checkout without the analysis extra still
runs fine. The web player reads that per-track analysis and drives a new
animated "Ambience" background (bubbles, colour, current) that reacts to the
beat and the mood curve as the track plays, plus a debug overlay for tuning
it. Also adds a one-off script to backfill podcast cover art from iTunes.
Implements the room-control page from the design mockup: a scenes row above cards
for shutters, color lamps, and brightness-only lamps, all driven by a new
`general.ha` config section (server URL, token, ordered device/scene lists).
The backend proxies every Home Assistant call server-side (GET/POST /api/ha/...)
rather than the browser calling Home Assistant directly, so the long-lived token
never leaves the LAN device and Home Assistant's own CORS settings don't need to
know about musicmouse at all. Card kind (shutter/color/brightness-only) is
inferred at runtime from what Home Assistant reports about each entity, not
configured explicitly.
Also stops tracking python-backend/config.yml, which had drifted into the repo
despite its own header saying it shouldn't be - it now carries real credentials
locally and needs to stay untracked.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>