Files

Presto Music Library

MicroPython app for the Pimoroni Presto that connects to the Music Library API. It runs full-resolution on the 480x480 touch display and lets you search the collection or browse records released on a selected date.

What It Does

  • Home screen with Search Collection and Today's Records
  • Month calendar with day navigation and today's date highlighted
  • Day list with cover art, title, artists, format, and release year
  • Search input with on-screen keyboard and scrollable results
  • Record detail page with larger cover art, genres, metadata, purchase date, and optional Last.fm scrobble button
  • Display sleep after 1 minute of inactivity, with wake-on-touch
  • WiFi reconnect, NTP sync, and simple network error states

Requirements

  • Pimoroni Presto running stock firmware with MicroPython, PicoGraphics, touch, urequests, ntptime, and usually jpegdec
  • WiFi with internet access
  • Music Library API token

Setup

Create secrets.py from the template:

cp config.example.py secrets.py

Fill in:

WIFI_SSID = "your-wifi-ssid"
WIFI_PASSWORD = "your-wifi-password"
API_TOKEN = "your-api-token"

secrets.py is git-ignored and must not be committed.

Deploy

First-time deployment needs both the app and credentials on the device:

mpremote fs cp main.py :main.py
mpremote fs cp secrets.py :secrets.py
mpremote reset

After secrets.py has been copied once, use the project task:

mise run presto

That task copies main.py to :main.py and resets the Presto. It does not copy secrets.py.

The Presto runs main.py on boot, connects to WiFi, syncs time, then opens the home screen.

An equivalent Elm-style implementation is available in music_library.py. It uses messages, model updates, and effects for the application runtime while providing the same Music Library screens and API interactions. Deploy it as the device entrypoint with:

mise run music_library

This task copies music_library.py to :main.py on the device and resets it.

Usage

Home: tap Search Collection to search by text, or Today's Records to open the current month with today highlighted.

Month view: use the arrow buttons to change month, tap a day to load records released on that date, or tap H to return home.

Day view: drag vertically to scroll long lists. During drag scrolling, covers are drawn as placeholders and restored when the drag ends. Tap a row to open its detail page.

Search: type with the on-screen keyboard and tap OK. Results use the same row and detail views as the day list. Back from results returns to the search input with the query preserved.

Record detail: shows title, artists, medium cover, genres, record type, format, release year, and purchase date. Records with selected_release_id show a Scrobble button; successful scrobbles show Done until you leave the detail page.

Display sleep: after 1 minute without touch input, the backlight turns off. The first touch wakes the display and is consumed so it does not also press a button or start a scroll.

Testing

Run the headless smoke tests from this directory:

mise run test

The tests use pimoroni-emulator mock MicroPython modules, import both main.py and music_library.py without starting their event loops, and block accidental network calls. They render all screen states and save screenshots to tests/fixtures/ for manual inspection. Additional runtime tests cover the message/effect boundary in music_library.py.

For a syntax-only check without creating __pycache__:

python3 -c "import py_compile; py_compile.compile('main.py', cfile='/tmp/main.pyc', doraise=True)"
python3 -c "import py_compile; py_compile.compile('music_library.py', cfile='/tmp/music_library.pyc', doraise=True)"

Troubleshooting

Symptom Likely cause Fix
secrets.py not found Credentials are missing on the device Copy secrets.py to the Presto root
WIFI_SSID not set or API_TOKEN not set Required value is blank Check secrets.py
WiFi connection failed Wrong credentials or network unavailable Verify SSID, password, and network
Could not reach server API token invalid, server down, or network lost Check API_TOKEN and server status
Grey cover placeholders JPEG decoder unavailable or image URL failed Check firmware and internet access
Black display after idle Display sleep is active Touch once to wake

API Contract

All requests use:

Authorization: Bearer <API_TOKEN>

The app calls:

GET /api/v1/collection/on_this_day?date=YYYY-MM-DD
GET /api/v1/collection?q=QUERY&limit=20
POST /api/v1/collection/:record_id/scrobble

Both GET endpoints return { "records": [...] }. Fields used by the client:

  • id
  • selected_release_id
  • title
  • artists
  • format
  • release_date
  • genres
  • record_type
  • purchased_at
  • covers.small
  • covers.medium

The day and search lists use covers.small as an 80x80 row thumbnail. Detail pages use covers.medium in a 400x400 cover area. The app expects display-ready JPEGs and does not resize covers on the device.

License

This application is part of the Music Library project.