Control your Sonos speaker and play podcasts using an Elgato StreamDeck+ with dials and touchscreen display.
- 🎚️ Volume Control - Dial 0 with visual percentage and progress bar
- ⏯️ Playback Scrubbing - Dial 1 to seek through tracks, push to play/pause
- 💡 Brightness Control - Dial 3 to adjust StreamDeck brightness
- 🎵 White Noise Loop - Button to play/pause white noise with repeat
- 📻 Podcast Management - Auto-download and play podcast episodes
- 📺 Rich Display - Touchscreen shows volume, playback position, and track info
Buttons:
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
│Loop │ Pod │ Pod │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
Dials:
┌──────────┬──────────┬──────────┬──────────┐
│ 0 │ 1 │ 2 │ 3 │
│ Volume │ Playback │ │Brightness│
└──────────┴──────────┴──────────┴──────────┘
Touchscreen:
┌─────────────┬─────────────┬──────────────────────────────┐
│ 75% │ 1:23 / 4:56 │ How Interest Works │
│ ████░░░ │ ███░░░░░ │ Million Bazillion │
│ Volume │ ▶ │ │
└─────────────┴─────────────┴──────────────────────────────┘
- Elgato StreamDeck+ (with dials and touchscreen)
- Sonos speaker on the same network
- Python 3.9+
# Clone the repository
git clone <your-repo-url>
cd koa-sonos
# Install dependencies
pip3 install -r requirements.txt
# Add your media files
cp /path/to/whitenoise.mp3 music/white_noise.mp3
cp /path/to/icons/*.png icons/
# Configure
nano config.yaml # Set your Sonos speaker name
# Download podcast episodes
python3 fetch_podcasts.py
# Run
python3 sonos_streamdeck.pySee SETUP.md for detailed instructions.
| Control | Function | Description |
|---|---|---|
| Button 0 | White noise loop | Toggle white noise on/off |
| Button 1 | Podcast 1 | Play next episode of first podcast |
| Button 2 | Podcast 2 | Play next episode of second podcast |
| Dial 0 Turn | Volume | Adjust Sonos speaker volume (0-100%) |
| Dial 0 Push | Loop toggle | Same as Button 0 |
| Dial 1 Turn | Scrub playback | Seek forward/backward (5 sec per turn) |
| Dial 1 Push | Play/Pause | Toggle playback |
| Dial 3 Turn | Brightness | Adjust StreamDeck brightness |
See docs/controls.md for complete control reference.
Edit config.yaml to customize:
sonos:
speaker_name: "Your Speaker Name"
podcasts:
feeds:
your-podcast:
name: "Your Podcast"
rss: "https://example.com/feed.xml"
icon: "icons/your-podcast.png"
button: 1See docs/configuration.md for all options.
- SETUP.md - Installation and setup guide
- docs/configuration.md - Configuration options
- docs/controls.md - Complete control reference
- docs/touchscreen.md - Display layout details
- docs/testing.md - Running tests
- docs/development/ - Development documentation
# Run all tests
python3 -m pytest -v
# Run specific test file
python3 -m pytest tests/test_sonos_streamdeck.py -v68 tests with full hardware mocking - no StreamDeck or Sonos required!
- sonos_streamdeck.py - Main application, StreamDeck control
- fetch_podcasts.py - Download podcast episodes from RSS feeds
- config.py - Configuration loader (reads config.yaml)
- config.yaml - User configuration (speaker, podcasts, etc.)
- tests/ - Comprehensive test suite with mocked hardware
- Python 3.9+
- Elgato StreamDeck+ (with dials and touchscreen)
- Sonos speaker
- See requirements.txt for Python packages
✅ Fully functional and tested (68 tests passing)
✅ Hardware fully mocked for testing
✅ Configuration externalized to YAML
✅ Comprehensive documentation
✅ Ready for deployment on Raspberry Pi
uv run pytest./run_mypy.sh
# or
uv run mypy podplayer/This project uses Black for consistent code formatting:
./run_black.sh
# or
uv run python -m black podplayer/ tests/ *.pyBlack is configured in pyproject.toml with a line length of 100 characters.
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2025 Raffi Krikorian
Built for Koa's room to make bedtime easier! 🌙
Technologies:
- python-soco - Sonos control library
- python-elgato-streamdeck - Stream Deck interface
- feedparser - RSS feed parsing
- Pillow - Image processing for touchscreen display