The backend now targets 3.11, which is what Raspberry Pi OS ships, so there is nothing left for uv to solve. It was only ever there to obtain a 3.13 the distro does not have, and it brought its own problems: the download had to be matched to the Pi's 32-bit userland by hand, and no armv7 wheel exists for a 3.13 ABI, so Pillow was compiled from source and needed image headers installed alongside. apt for the interpreter, python3 -m venv, pip for the rest - and piwheels then supplies prebuilt armhf wheels for the native dependencies. A venv cannot be migrated between interpreters (it holds absolute paths into the one that made it), and `creates:` would keep the old one forever, so check what built it and rebuild when it does not match the current python3. That is what carries a device off the uv-installed 3.13 without hand-holding. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
3.9 KiB
Markdown
70 lines
3.9 KiB
Markdown
# pi_musicmouse
|
|
|
|
Deploys the MusicMouse backend (`python-backend/`) and its built web frontend.
|
|
|
|
- Checks out `musicmouse_version` from `pi_musicmouse_repo` to `/opt/musicmouse`, then
|
|
**fails early** if that checkout has no `python-backend/pyproject.toml` - see
|
|
"Which version" below.
|
|
- Creates `/opt/musicmouse/.venv` from the distribution's own `python3` and pip-installs
|
|
the backend into it. The backend targets the Python that Raspberry Pi OS ships (3.11
|
|
on Bookworm) precisely so this step stays boring: apt and piwheels have prebuilt
|
|
armhf wheels for the native dependencies, so nothing has to be compiled on the Pi.
|
|
If the venv was built by a different interpreter than the current `python3`, it is
|
|
thrown away and rebuilt.
|
|
- Builds the frontend (`web/`) on the *control machine* (delegated to `localhost`, not
|
|
the Pi - no Node/npm is installed on the Pi) and syncs `web/dist` over.
|
|
- Installs `/media/musicmouse/config.yml` from `files/config-<inventory_hostname>.yml`
|
|
(one file per host - the schema differs between a host with a real mouse attached and
|
|
a display-only one; see those files' own comments), the typing game's curriculum
|
|
beside it, and the systemd unit copied straight from the checked-out repo's
|
|
`python-backend/musicmouse.service`, so it can never drift from what's actually in the
|
|
app repo.
|
|
- Sets up a Samba share of `/media/musicmouse` for copying music onto the device.
|
|
|
|
## Which version
|
|
|
|
`musicmouse_version` is set per host in `host_vars`, with no default, and points at a
|
|
`deploy/<host>` branch on the remote. Those branches are the deployment record: what is
|
|
installed on that box right now. Moving one is a force-push, and the next run follows it
|
|
(the `git:` task uses `force: true`):
|
|
|
|
git push -f origin rearchitect-backend:deploy/musicdolphin
|
|
just mediapis musicdolphin
|
|
|
|
This role only understands the post-rearchitecture layout - `python-backend/` as an
|
|
installable package plus a `web/` frontend. On older commits the host driver lives at
|
|
`espmusicmouse/host_driver/main.py`, there is no `pyproject.toml`, the unit file is
|
|
under `esp-firmware/`, there is no frontend at all, and the config is a different format
|
|
that this role's config files would fail to load. There is deliberately no legacy path:
|
|
the role stops at the checkout with an explanation instead.
|
|
|
|
`musicmouse` (Kinderzimmer) is on such an older commit and still working, so it has
|
|
`mediapi_install_kidsmusic: false` and this role skips it entirely; `deploy/musicmouse`
|
|
exists purely as the rollback marker for what is installed there. Migrating it means
|
|
moving `/media/musicmouse/<figure>/` into `Figuren/` and switching to the new config
|
|
schema - `files/config-musicmouse.yml` is already written for that.
|
|
|
|
## config.yml is install-once
|
|
|
|
The app writes to its own config at runtime: parent mode (`?parentMode=1`) patches the
|
|
volume keys, and the remote-control page rewrites the whole `remote:` block. A plain
|
|
`copy:` would throw those away on every ansible run, so the config task is
|
|
`force: "{{ pi_musicmouse_force_config }}"`, default `false`. Push a changed config when
|
|
you actually mean to:
|
|
|
|
just run mediapis.yml musicdolphin -e pi_musicmouse_force_config=true
|
|
|
|
The curriculum file is not written by the app, so it is installed unconditionally. A
|
|
config with a `tippen:` section will not start without it - `curriculum_file` is
|
|
validated as must-exist - so a host whose config has no `tippen:` section should set
|
|
`pi_musicmouse_curriculum_file: ""`.
|
|
|
|
## Manual steps after a first deploy
|
|
|
|
- Set the Samba password with `smbpasswd`.
|
|
- Get the music onto the device. The app repo's `scripts/sync-library.sh` is the way to
|
|
do it: as well as the library it carries over the cover and track-analysis cache,
|
|
which is the part that costs minutes of DSP per track to recompute, and it knows which
|
|
parts of that cache survive the move and which must not be copied. The Samba share
|
|
works too, and then the device does all that work itself.
|