Files
musicmouse/python-backend/config.yml.example
Martin Bauer a8ed350aec Add "Mein Zimmer" room-control page (Home Assistant, proxied through the backend)
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>
2026-08-27 23:45:29 +02:00

127 lines
5.6 KiB
Plaintext

# Example config for the MusicMouse backend.
#
# python -m musicmouse --config /media/musicmouse/config.yml
#
# Unknown keys are rejected rather than ignored, and every problem in the file is
# reported at once, so a typo fails at startup with the path to the offending line.
# Keep the real config (with credentials) off the repo - on the device only.
general:
# The music collection. One path; the shelves underneath it are fixed names, not
# settings, because each one has its own quirks the code already knows about:
#
# <root>/Figuren/<figure name>/ one folder per figurine
# <root>/Musik/<Artist> - <Album>/ albums, grouped by artist
# <root>/Hörbücher/<Artist> - <Album>/ audiobooks, grouped by character
# <root>/Kinderpodcasts/<Show>/ shows, newest episode first
#
# A cover.jpg next to the audio is used if present, otherwise the art is pulled out
# of the files' tags. Relative paths resolve against this file's directory.
library:
root: /home/martin/Music
# Scan results, extracted cover art and track analysis. Safe to delete: the index
# is rebuilt on the next start. Deleting it does throw away track analysis, which
# is expensive to recompute.
cache: .musicmouse-cache
# Serial port the ESP32 firmware is on. A dropped link is retried, not fatal.
# Required - use "simulate" to run without the mouse attached, which is a complete
# setup on its own because the web front-end can drive the player by itself. RFID,
# buttons and LEDs then do nothing, and startup says so every boot.
serial_port: "/dev/ttyUSB0"
baudrate: 115200
reconnect_interval: 5.0
# ALSA output device passed to VLC, e.g. "hw:0,0", or "default" for the system
# default output. Required - use "simulate" for a player that makes no sound, which
# is handy when working on the web UI on a machine whose audio you would rather not
# commandeer. Startup says so every boot.
#
# Both of these are 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.
alsa_device: "softvol_effects"
# Volume, 0..100. min/max clamp everything, including the rotary encoder.
min_volume: 0
max_volume: 60
initial_volume: 40
volume_increment: 5 # per rotary-encoder click
# Backlight of the prev/next buttons while a figure is playing, 0..1.
button_leds_brightness: 0.5
# Which files count as music. Anything else - a podcast downloader's archive.json,
# a half-finished .tmp - is ignored.
audio_extensions: [".mp3", ".ogg", ".oga", ".opus", ".flac", ".wav", ".m4a", ".aac"]
# The web front-end. Omit the whole section to run without it.
#
# There is no authentication: this is a device on a home network. The settings panel
# at ?parentMode=1 is hidden from the child, not protected from them - it writes back
# to this file. Put it behind a reverse proxy if that is not good enough.
web:
host: "0.0.0.0"
port: 8080
# Built frontend to serve at /. Omit to expose only the JSON API.
static_dir: ../web/dist
# Home Assistant integration. Omit the whole section to run without MQTT.
# The backend exposes three lights, a player sensor, a volume slider, transport
# buttons, device triggers for every button/touch area, and a tag scanner.
mqtt:
server: "homeassistant.local"
port: 1883
user: "musicmouse"
password: "REPLACE_WITH_MQTT_PASSWORD"
base_topic: "musicmouse"
discovery_prefix: "homeassistant"
device_id: "musicmouse"
device_name: "Music Mouse"
reconnect_interval: 10.0
# Room control page ("Mein Zimmer"). Omit the whole section to hide the page. This is
# the opposite direction from mqtt above: it's musicmouse controlling Home Assistant
# entities, not the other way round. The backend proxies every call to Home
# Assistant's REST API with this token attached; the browser never sees it, only
# entity ids and display names. Home Assistant's own CORS settings do not need to
# allow musicmouse's origin for this - the browser only ever talks to musicmouse.
ha:
url: "http://homeassistant.local:8123"
# A long-lived access token, created under the HA user's own profile page.
token: "REPLACE_WITH_HA_LONG_LIVED_TOKEN"
# Cards on the room page, in this order. "name" is optional; falls back to the
# entity id if omitted.
devices:
- entity_id: cover.kinderzimmer_rollo
name: "Rollo"
- entity_id: light.kinderzimmer_hue_beyond_links
name: "Hue Beyond links"
- entity_id: light.kinderzimmer_deckenlampe
name: "Deckenlampe"
# Scene pill row above the cards, in this order.
scenes:
- entity_id: scene.kinderzimmer_lesen
name: "Lesen"
- entity_id: scene.kinderzimmer_gute_nacht
name: "Gute Nacht"
# One entry per figurine. The key is the figure name and the subfolder name.
figures:
fuchs:
# RFID tag id, 5 bytes as hex. Must be unique across figures.
id: "04a1b2c3d4"
# Exactly four colours: primary, secondary, background, accent.
# Either "#rrggbb" (RGB) or "wNN" (white channel only, hex).
colors: ["#ff6600", "#ffcc00", "#331100", "wff"]
# "music" (default) or "book". Every other shelf is named after what is on it, so
# its type is obvious; a figure folder is named after the figurine, so this is the
# one thing that has to be said out loud. The web UI draws albums square and
# audiobooks taller than wide, so getting it wrong is visible at a glance.
kind: music
eule:
id: "04b2c3d4e5"
colors: ["#3355ff", "#66aaff", "#001133", "#ffffff"]
kind: book