Pin each MusicMouse host to a deploy branch, and freeze musicmouse
musicmouse_version pointed both hosts at rearchitect-backend, a branch that only ever existed on a laptop - so the previous commit's rework could never actually have run. Point each host at a deploy/<host> branch on the remote instead. Those branches are the deployment record: what is installed on that box right now, moved with a force-push when you mean to deploy. musicmouse (Kinderzimmer) is the reason this matters. It is in daily use and still runs the pre-rearchitecture backend out of /opt/musicmouse_venv and espmusicmouse/host_driver/main.py. That commit has no python-backend/ pyproject.toml, no python-backend/musicmouse.service and no web/ at all, so this role cannot install it - and a run would have force-checked-out incompatible code over a working device first and failed afterwards. Set mediapi_install_kidsmusic: false there and leave it alone; deploy/musicmouse records the commit that is installed, for rollback. Add a stat + fail right after the checkout so the same mistake stops with an explanation instead of failing three tasks deeper. Also in the role: - Install the typing game's curriculum next to config.yml. A config with a tippen: section refuses to start without it - curriculum_file is validated as must-exist - so musicdolphin's new config needs it present. - Stop clobbering config.yml. The app writes to it at runtime: parent mode patches the volume keys and the remote-control page rewrites the remote: block. A plain copy: undid that on every run. Install-once by default, with -e pi_musicmouse_force_config=true to push a change deliberately. - Fill out config-musicdolphin.yml against the current schema: library root and cache, an absolute static_dir (../web/dist would resolve to /media/web/dist from /media/musicmouse and silently serve nothing), tippen, and the volume range for a screen-driven instance. ha: is left commented out until the Wohnzimmer-oben entity ids are picked - the ones in the dev config are Arbeitszimmer. No mqtt: (it would publish a device of dead entities on a simulate-only host) and no lirc:/remote: (this host runs irserver, a serial daemon, not the lircd this speaks TCP to). The curriculum is a verbatim copy of app content, so exclude it from ansible-lint rather than reformat it away from its source. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,25 +1,89 @@
|
||||
---
|
||||
# musicdolphin: display-only instance. No physical mouse attached (for
|
||||
# now), so serial and audio are both "simulate" - the web front-end (shown locally in
|
||||
# the pi_kiosk role's Firefox kiosk window, and reachable on the LAN for a tablet) is a
|
||||
# complete way to drive the player on its own. `figures` still needs at least one entry
|
||||
# (the schema requires it) even though nothing will ever scan a tag here.
|
||||
# musicdolphin: display-only instance. No physical mouse attached, so serial and audio
|
||||
# are both "simulate" - the web front-end (shown locally in the pi_kiosk Firefox window,
|
||||
# and reachable on the LAN for a tablet) is a complete way to drive the player on its
|
||||
# own. `figures` still needs at least one entry (the schema requires it) even though
|
||||
# nothing will ever scan a tag here.
|
||||
#
|
||||
# This Pi does have a HifiBerry amp (mediapi_has_hifiberry_amp, alsa_card_name
|
||||
# sndrpihifiberry), so the `softvol_effects` slot from pi_alsasetup exists on it.
|
||||
# Swapping alsa_device to that is the one-line change that gives this instance real
|
||||
# sound - the amp is currently shared by squeezelite and shairport only.
|
||||
#
|
||||
# Unknown keys are rejected rather than ignored, so a typo fails at startup with the
|
||||
# path to the offending line. Every key is documented in the app repo's
|
||||
# python-backend/config.yml.example.
|
||||
general:
|
||||
library:
|
||||
# The four shelves underneath are fixed names, not settings: Figuren/, Musik/,
|
||||
# Hoerbuecher/ (with real umlauts) and Kinderpodcasts/.
|
||||
root: /media/musicmouse
|
||||
# Relative, so it resolves against *this file's* directory -
|
||||
# /media/musicmouse/.musicmouse-cache. Seeded by the app repo's
|
||||
# scripts/sync-library.sh; safe to delete, at the cost of recomputing analysis.
|
||||
cache: .musicmouse-cache
|
||||
# analysis_workers: 2
|
||||
# ^ pointless until this role installs the backend's `analysis` extra
|
||||
# (librosa + numpy, a heavy build on a Pi). Without it build_analyzer() falls
|
||||
# back to NullAnalyzer and the reactive background stays static.
|
||||
|
||||
# Both required rather than optional on purpose: running blind or silent has to be
|
||||
# asked for, so a config that lost a line fails loudly instead of booting into
|
||||
# something that looks like it is working. Startup says so every boot.
|
||||
serial_port: "simulate"
|
||||
alsa_device: "simulate"
|
||||
|
||||
web:
|
||||
host: "0.0.0.0"
|
||||
port: 8080
|
||||
# Absolute on purpose. The repo's example uses ../web/dist because its config sits
|
||||
# in python-backend/; from /media/musicmouse that would resolve to /media/web/dist
|
||||
# and silently serve nothing.
|
||||
static_dir: /opt/musicmouse/web/dist
|
||||
|
||||
# The typing game. Both paths are relative, so both land in /media/musicmouse/.
|
||||
# curriculum_file must exist at startup and is installed by this role;
|
||||
# progress_file is created and written by the app itself.
|
||||
tippen:
|
||||
curriculum_file: tippen-curriculum.yml
|
||||
progress_file: tippen-progress.json
|
||||
|
||||
# Home Assistant "Mein Zimmer" page. Left out until the Wohnzimmer-oben entity ids
|
||||
# are picked - the dev config's entities are Arbeitszimmer, the wrong room for this
|
||||
# Pi. An empty ha: block is invalid; the section needs at least one device or scene,
|
||||
# so uncomment it only once it is filled in:
|
||||
#
|
||||
# ha:
|
||||
# url: "https://ha.bauer.tech"
|
||||
# token: "<long-lived access token>"
|
||||
# devices:
|
||||
# - entity_id: cover.wohnzimmer_oben_rollo
|
||||
# name: "Rollo"
|
||||
# - entity_id: light.wohnzimmer_oben_...
|
||||
# name: "Licht"
|
||||
# scenes:
|
||||
# - entity_id: scene.wohnzimmer_oben_...
|
||||
# name: "Lesen"
|
||||
|
||||
# No mqtt: section. The Home Assistant integration exposes the *mouse's* lights,
|
||||
# buttons, touch areas and tag scanner, none of which exist on a simulate-only
|
||||
# instance - it would publish a device of dead entities.
|
||||
#
|
||||
# No lirc: section either, and consequently no top-level `remote:` mapping. This host
|
||||
# uses mediapi_ir_control: irserver, a custom serial daemon on /dev/ttyUSB0; the
|
||||
# backend's LircConfig speaks lircd's TCP protocol (pi_lirc, port 2222) and cannot
|
||||
# talk to it.
|
||||
|
||||
# Backlight of the prev/next buttons while a figure is playing, 0..1. Inert here
|
||||
# (no mouse), kept so the file reads the same as the other hosts'.
|
||||
button_leds_brightness: 0.5
|
||||
volume_increment: 5
|
||||
|
||||
# Volume, 0..100. The full range: this one is driven from a screen, not from a knob a
|
||||
# child can spin, so there is nothing to protect against.
|
||||
min_volume: 0
|
||||
max_volume: 100
|
||||
initial_volume: 40
|
||||
volume_increment: 5
|
||||
|
||||
figures:
|
||||
# Placeholder - serial_port is "simulate" so no reader ever reports a tag id, but the
|
||||
|
||||
Reference in New Issue
Block a user