@@ -84,46 +97,88 @@ The system can be configured through a JSON configuration file that allows users
## Hardware Requirements
- Raspberry Pi 3b or 4 (NOT RPI5!)
-- Amazon Affiliate Link: Raspberry Pi 4 4GB (https://amzn.to/4dJixuX)
-Adafruit RGB Matrix Bonnet/HAT
-- https://www.adafruit.com/product/3211
- 2x LED Matrix panels (64x32) (Designed for 128x32 but has a lot of dynamic scaling elements that could work on a variety of displays, pixel pitch is user preference)
-- https://www.adafruit.com/product/2278
- DC Power Supply for Adafruit RGB HAT
-- https://www.adafruit.com/product/658
- Raspberry Pi 3b or 4 (NOT RPI5!) : Amazon Affiliate Link: Raspberry Pi 4 4GB (https://amzn.to/4dJixuX)
-2x LED Matrix panels (64x32) (Designed for 128x32 but has a lot of dynamic scaling elements that could work on a variety of displays, pixel pitch is user preference) : https://www.adafruit.com/product/2278
- 5V 4A DC Power Supply for Adafruit RGB HAT : https://www.adafruit.com/product/1466
## Optional but recommended mod for Adafruit RGB Matrix Bonnet
- By soldering a jumper between pins 4 and 18, you can run a specialized command for polling the matrix display. This provides better brightness, less flicker, and better color.
- If you do the mod, we will use the command: --led-gpio-mapping=adafruit-hat-pwm, otherwise just use --led-gpio-mapping=adafruit-hat
- If you do the mod, we will use the default config with led-gpio-mapping=adafruit-hat-pwm, otherwise just adjust your mapping in config.json to adafruit-hat
- More information available: https://github.com/hzeller/rpi-rgb-led-matrix/tree/master?tab=readme-ov-file
I 3D printed stands to keep the panels upright and snug. STL Files are included in the Repo but are also available at https://www.thingiverse.com/thing:5169867 Thanks to "Randomwire" for making these for the 4mm Pixel Pitch LED Matrix.
These are not required and you can probably rig up something basic with stuff you have around the house. I used these screws: https://amzn.to/4mFwNJp (Amazon Affiliate Link)
1. Create RPI Image on a Micro-SD card (I use 16gb because I have it, size is not too important but I would use 8gb or more) using [Raspberry Pi Imager](https://www.raspberrypi.com/software/)
2. Choose your Raspberry Pi (3B+ in my case)
3. For Operating System (OS), choose "Other", then choose Raspbian OS Lite (64-bit)
6. Inside the OS Customization Settings, choose a name for your device. I use "ledpi". Choose a password, enter your WiFi information, and set your timezone.
7. Under the Services Tab, make sure that SSH is enabled. I recommend using password authentication for ease of use - it is the password you just chose above.
The calendar display module shows upcoming events from your Google Calendar. To configure it:
1. In `config/config.json`, add the following section:
```json
{
"calendar":{
"enabled":true,
"update_interval":300,// Update interval in seconds (default: 300)
"max_events":3,// Maximum number of events to display
"calendars":["primary"]// List of calendar IDs to display
}
}
```
2. Set up Google Calendar API access:
1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable the Google Calendar API
4. Create OAuth 2.0 credentials:
- Application type: TV and Limited Input Device
- Download the credentials file as `credentials.json`
5. Place the `credentials.json` file in your project root directory
3. On first run, the application will:
- Provide a code to enter at https://www.google.com/device for Google authentication
- Request calendar read-only access
- Save the authentication token as `token.pickle`
The calendar display will show:
- Event date and time
- Event title (wrapped to fit the display)
- Up to 3 upcoming events (configurable)
## Music Display Configuration
The Music Display module shows information about the currently playing track from either Spotify or YouTube Music (via the [YouTube Music Desktop App](https://ytmdesktop.app/) companion server).
**Setup Requirements:**
1.**Spotify:**
* Requires a Spotify account (for API access).
* You need to register an application on the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/) to get API credentials.
* Go to the dashboard, log in, and click "Create App".
* Give it a name (e.g., "LEDMatrix Display") and description.
* For the "Redirect URI", enter `http://127.0.0.1:8888/callback` (or another unused port if 8888 is taken). You **must** add this exact URI in your app settings on the Spotify dashboard.
* Note down the `Client ID` and `Client Secret`.
2.**YouTube Music (YTM):**
* Requires the [YouTube Music Desktop App](https://ytmdesktop.app/) (YTMD) to be installed and running on a computer on the *same network* as the Raspberry Pi.
* In YTMD settings, enable the "Companion Server" under Integration options. Note the URL it provides (usually `http://localhost:9863` if running on the same machine, or `http://<YTMD-Computer-IP>:9863` if running on a different computer).
**`preferred_source` Options:**
*`"spotify"`: Only uses Spotify. Ignores YTM.
*`"ytm"`: Only uses the YTM Companion Server. Ignores Spotify.
### Spotify Authentication for Music Display
If you are using the Spotify integration to display currently playing music, you will need to authenticate with Spotify. This project uses an authentication flow that requires a one-time setup. Due to how the display controller script may run with specific user permissions (even when using `sudo`), the following steps are crucial:
1.**Initial Setup & Secrets:**
* Ensure you have your Spotify API Client ID, Client Secret, and Redirect URI.
* The Redirect URI should be set to `http://127.0.0.1:8888/callback` in your Spotify Developer Dashboard.
* Copy `config/config_secrets.template.json` to `config/config_secrets.json`.
* Edit `config/config_secrets.json` and fill in your Spotify credentials under the `"music"` section:
* Execute the authentication script using `sudo`. This is important because it needs to create an authentication cache file (`spotify_auth.json`) that will be owned by root.
```bash
sudo python3 src/authenticate_spotify.py
```
* The script will output a URL. Copy this URL and paste it into a web browser on any device.
* Log in to Spotify and authorize the application.
* Your browser will be redirected to a URL starting with `http://127.0.0.1:8888/callback?code=...`. It will likely show an error page like "This site can't be reached" – this is expected.
* Copy the **entire** redirected URL from your browser's address bar.
* Paste this full URL back into the terminal when prompted by the script.
* If successful, it will indicate that token info has been cached.
3. **Adjust Cache File Permissions:**
* The main display script (`display_controller.py`), even when run with `sudo`, might operate with an effective User ID (e.g., UID 1 for 'daemon') that doesn't have permission to read the `spotify_auth.json` file created by `root` (which has -rw------- permissions by default).
* To allow the display script to read this cache file, change its permissions:
```bash
sudo chmod 644 config/spotify_auth.json
```
This makes the file readable by all users, including the effective user of the display script.
4. **Run the Main Application:**
* You should now be able to run your main display controller script using `sudo`:
```bash
sudo python3 display_controller.py
```
* The Spotify client should now authenticate successfully using the cached token.
**Why these specific permissions steps?**
The `authenticate_spotify.py` script, when run with `sudo`, creates `config/spotify_auth.json` owned by `root`. If the main `display_controller.py` (also run with `sudo`) effectively runs as a different user (e.g., UID 1/daemon, as observed during troubleshooting), that user won't be able to read the `root`-owned file unless its permissions are relaxed (e.g., to `644`). The `chmod 644` command allows the owner (`root`) to read/write, and everyone else (including the `daemon` user) to read.
### Youtube Music Authentication for Music Display
The system can display currently playing music information from [YouTube Music Desktop (YTMD)](https://ytmdesktop.app/) via its Companion server API.
### YouTube Display Configuration & API Key
The YouTube display module shows channel statistics for a specified YouTube channel. To configure it:
1. In `config/config.json`, add the following section:
```json
{
"youtube": {
"enabled": true,
"update_interval": 300 // Update interval in seconds (default: 300)
}
}
```
2. In `config/config_secrets.json`, add your YouTube API credentials:
```json
{
"youtube": {
"api_key": "YOUR_YOUTUBE_API_KEY",
"channel_id": "YOUR_CHANNEL_ID"
}
}
```
To get these credentials:
1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable the YouTube Data API v3
4. Create credentials (API key)
5. For the channel ID, you can find it in your YouTube channel URL or use the YouTube Data API to look it up
**Setup:**
1. **Enable Companion Server in YTMD:**
* In the YouTube Music Desktop application, go to `Settings` -> `Integrations`.
* Enable the "Companion Server".
* Note the IP address and Port it's listening on (default is usually `http://localhost:9863`), you'll need to know the local ip address if playing music on a device other than your rpi (probably are).
2. **Configure `config/config.json`:**
* Update the `music` section in your `config/config.json`:
```json
"music": {
"enabled": true,
"preferred_source": "ytm",
"YTM_COMPANION_URL": "http://YOUR_YTMD_IP_ADDRESS:PORT", // e.g., "http://localhost:9863" or "http://192.168.1.100:9863"
"POLLING_INTERVAL_SECONDS": 1
}
```
3. **Initial Authentication & Token Storage:**
* The first time you run ` python3 src/authenticate_ytm.py` after enabling YTM, it will attempt to register itself with the YTMD Companion Server.
* You will see log messages in the terminal prompting you to **approve the "LEDMatrixController" application within the YouTube Music Desktop app.** You typically have 30 seconds to do this.
* Once approved, an authentication token is saved to your `config/ytm_auth.json`.
* This ensures the `ledpi` user owns the config directory and file, and has the necessary write permissions.
**Troubleshooting:**
* "No authorized companions" in YTMD: Ensure you've approved the `LEDMatrixController` in YTMD settings after the first run.
* Connection errors: Double-check the `YTM_COMPANION_URL` in `config.json` matches what YTMD's companion server is set to.
* Ensure your firewall (Windows Firewall) allows YTM Desktop app to access local networks.
## Run on Startup Automatically with Systemd Service Installation
The LEDMatrix can be installed as a systemd service to run automatically at boot and be managed easily. The service runs as root to ensure proper hardware timing access for the LED matrix.
@@ -236,208 +509,72 @@ sudo ./start_display.sh
sudo ./stop_display.sh
```
# Configuration
1.Edit `config/config.json` with your preferences via `sudo nano config/config.json`
### Running the display without Sudo (Not recommended but can be useful for troubleshooting or overcoming write errors)
The YouTube display module shows channel statistics for a specified YouTube channel. To configure it:
To run the display script without `sudo`, the user executing the script needs access to GPIO pins. Add the user to the `gpio` group:
1. In `config/config.json`, add the following section:
```json
{
"youtube":{
"enabled":true,
"update_interval":300// Update interval in seconds (default: 300)
}
```bash
sudo usermod -a -G gpio <your_username>
# Example for user 'ledpi':
# sudo usermod -a -G gpio ledpi
```
**Important:** You must **reboot** the Raspberry Pi after adding the user to the group for the change to take effect.
You also need to disable hardware pulsing in the code (see `src/display_manager.py`, set `options.disable_hardware_pulsing = True`). This may result in a flickerying display
- hardware_mapping: Use "adafruit-hat-pwm" for Adafruit bonnet WITH the jumper mod. Remove -pwm if you did not solder the jumper.
- pwm_bits, pwm_dither_bits, pwm_lsb_nanoseconds: Affect color fidelity.
- limit_refresh_rate_hz: Cap refresh rate for better stability.
- runtime:
- gpio_slowdown: Tweak this depending on your Pi model. Match it to the generation (e.g., Pi 3 → 3, Pi 4 -> 4).
- display_durations:
- Control how long each display module stays visible in seconds. For example, if you want more focus on stocks, increase that value.
### Modules
- Each module (weather, stocks, crypto, calendar, etc.) has enabled, update_interval, and often display_format settings.
- Sports modules also support test_mode, live_update_interval, and favorite_teams.
- Logos are loaded from the logo_dir path under assets/sports/...
```bash
Example: NHL Configuration"nhl_scoreboard": {
"enabled": true,
"test_mode": false,
"update_interval_seconds": 300,
"live_update_interval": 15,
"recent_game_hours": 48,
"favorite_teams": ["TB", "DAL"],
"logo_dir": "assets/sports/nhl_logos",
"display_modes": {
"nhl_live": true,
"nhl_recent": true,
"nhl_upcoming": true
}
}
```
2. In `config/config_secrets.json`, add your YouTube API credentials:
```json
{
"youtube":{
"api_key":"YOUR_YOUTUBE_API_KEY",
"channel_id":"YOUR_CHANNEL_ID"
}
}
```
To get these credentials:
1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable the YouTube Data API v3
4. Create credentials (API key)
5. For the channel ID, you can find it in your YouTube channel URL or use the YouTube Data API to look it up
### Calendar Display Configuration
The calendar display module shows upcoming events from your Google Calendar. To configure it:
1. In `config/config.json`, add the following section:
```json
{
"calendar":{
"enabled":true,
"update_interval":300,// Update interval in seconds (default: 300)
"max_events":3,// Maximum number of events to display
"calendars":["primary"]// List of calendar IDs to display
}
}
```
2. Set up Google Calendar API access:
1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable the Google Calendar API
4. Create OAuth 2.0 credentials:
- Application type: Desktop app
- Download the credentials file as `credentials.json`
5. Place the `credentials.json` file in your project root directory
3. On first run, the application will:
- Open a browser window for Google authentication
- Request calendar read-only access
- Save the authentication token as `token.pickle`
The calendar display will show:
- Event date and time
- Event title (wrapped to fit the display)
- Up to 3 upcoming events (configurable)
### Music Display Configuration
The Music Display module shows information about the currently playing track from either Spotify or YouTube Music (via the [YouTube Music Desktop App](https://ytmdesktop.app/) companion server).
**Setup Requirements:**
1.**Spotify:**
* Requires a Spotify account (for API access).
* You need to register an application on the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/) to get API credentials.
* Go to the dashboard, log in, and click "Create App".
* Give it a name (e.g., "LEDMatrix Display") and description.
* For the "Redirect URI", enter `http://127.0.0.1:8888/callback` (or another unused port if 8888 is taken). You **must** add this exact URI in your app settings on the Spotify dashboard.
* Note down the `Client ID` and `Client Secret`.
2.**YouTube Music (YTM):**
* Requires the [YouTube Music Desktop App](https://ytmdesktop.app/) (YTMD) to be installed and running on a computer on the *same network* as the Raspberry Pi.
* In YTMD settings, enable the "Companion Server" under Integration options. Note the URL it provides (usually `http://localhost:9863` if running on the same machine, or `http://<YTMD-Computer-IP>:9863` if running on a different computer).
**`preferred_source` Options:**
*`"spotify"`: Only uses Spotify. Ignores YTM.
*`"ytm"`: Only uses the YTM Companion Server. Ignores Spotify.
## Spotify Authentication for Music Display
If you are using the Spotify integration to display currently playing music, you will need to authenticate with Spotify. This project uses an authentication flow that requires a one-time setup. Due to how the display controller script may run with specific user permissions (even when using `sudo`), the following steps are crucial:
1.**Initial Setup & Secrets:**
* Ensure you have your Spotify API Client ID, Client Secret, and Redirect URI.
* The Redirect URI should be set to `http://127.0.0.1:8888/callback` in your Spotify Developer Dashboard.
* Copy `config/config_secrets.template.json` to `config/config_secrets.json`.
* Edit `config/config_secrets.json` and fill in your Spotify credentials under the `"music"` section:
* Execute the authentication script using `sudo`. This is important because it needs to create an authentication cache file (`spotify_auth.json`) that will be owned by root.
```bash
sudo python3 src/authenticate_spotify.py
```
* The script will output a URL. Copy this URL and paste it into a web browser on any device.
* Log in to Spotify and authorize the application.
* Your browser will be redirected to a URL starting with `http://127.0.0.1:8888/callback?code=...`. It will likely show an error page like "This site can't be reached" – this is expected.
* Copy the **entire** redirected URL from your browser's address bar.
* Paste this full URL back into the terminal when prompted by the script.
* If successful, it will indicate that token info has been cached.
3. **Adjust Cache File Permissions:**
* The main display script (`display_controller.py`), even when run with `sudo`, might operate with an effective User ID (e.g., UID 1 for 'daemon') that doesn't have permission to read the `spotify_auth.json` file created by `root` (which has -rw------- permissions by default).
* To allow the display script to read this cache file, change its permissions:
```bash
sudo chmod 644 config/spotify_auth.json
```
This makes the file readable by all users, including the effective user of the display script.
4. **Run the Main Application:**
* You should now be able to run your main display controller script using `sudo`:
```bash
sudo python3 display_controller.py
```
* The Spotify client should now authenticate successfully using the cached token.
**Why these specific permissions steps?**
The `authenticate_spotify.py` script, when run with `sudo`, creates `config/spotify_auth.json` owned by `root`. If the main `display_controller.py` (also run with `sudo`) effectively runs as a different user (e.g., UID 1/daemon, as observed during troubleshooting), that user won't be able to read the `root`-owned file unless its permissions are relaxed (e.g., to `644`). The `chmod 644` command allows the owner (`root`) to read/write, and everyone else (including the `daemon` user) to read.
### Music Display (YouTube Music)
The system can display currently playing music information from YouTube Music Desktop (YTMD) via its Companion server API.
**Setup:**
1. **Enable Companion Server in YTMD:**
* In the YouTube Music Desktop application, go to `Settings` -> `Integrations`.
* Enable the "Companion Server".
* Note the IP address and Port it's listening on (default is usually `http://localhost:9863`), you'll need to know the local ip address if playing music on a device other than your rpi (probably are).
2. **Configure `config/config.json`:**
* Update the `music` section in your `config/config.json`:
```json
"music": {
"enabled": true,
"preferred_source": "ytm",
"YTM_COMPANION_URL": "http://YOUR_YTMD_IP_ADDRESS:PORT", // e.g., "http://localhost:9863" or "http://192.168.1.100:9863"
"POLLING_INTERVAL_SECONDS": 1
}
```
3. **Initial Authentication & Token Storage:**
* The first time you run ` python3 src/authenticate_ytm.py` after enabling YTM, it will attempt to register itself with the YTMD Companion Server.
* You will see log messages in the terminal prompting you to **approve the "LEDMatrixController" application within the YouTube Music Desktop app.** You typically have 30 seconds to do this.
* Once approved, an authentication token is saved to your `config/ytm_auth.json`.
* This ensures the `ledpi` user owns the config directory and file, and has the necessary write permissions.
**Troubleshooting:**
* "No authorized companions" in YTMD: Ensure you've approved the `LEDMatrixController` in YTMD settings after the first run.
* Connection errors: Double-check the `YTM_COMPANION_URL` in `config.json` matches what YTMD's companion server is set to.
* Ensure your firewall (Windows Firewall) allows YTM Desktop app to access local networks.
## Project Structure
@@ -498,6 +635,22 @@ The project is organized into several key components:
Each display module in `src/` is responsible for a specific feature (weather, sports, music, etc.) and follows a consistent pattern of data fetching, processing, and display rendering.
The LEDMatrix system includes a comprehensive scoreboard display system with three display modes:
### Display Modes
- **Live Games**: Shows currently playing games with live scores and game status
- **Recent Games**: Displays completed games from the last 48 hours (configurable)
- **Upcoming Games**: Shows scheduled games for favorite teams
### Features
- Real-time score updates from ESPN API
- Team logo display
- Game status indicators (period, time remaining)
- Configurable favorite teams
- Automatic game switching
- Built-in caching to reduce API calls
- Test mode for development
## Caching System
The LEDMatrix system includes a robust caching mechanism to optimize API calls and reduce network traffic:
@@ -529,25 +682,18 @@ The LEDMatrix system includes a robust caching mechanism to optimize API calls a
- Temporary files are used for safe updates
- JSON serialization handles all data types including timestamps
## Fonts
You can add any font to the assets/fonts/ folder but they need to be .ttf or .btf(less support) and updated in display_manager.py
## Final Notes
- Most configuration is done via config/config.json
- Refresh intervals for sports/weather/stocks are customizable
- A caching system reduces API strain and helps ensure the display doesn’t hammer external services (and ruin it for everyone)
- Font files should be placed in assets/fonts/
- You can test each module individually for debugging
### Running without Sudo (Optional and not recommended)
To run the display script without `sudo`, the user executing the script needs access to GPIO pins. Add the user to the `gpio` group:
##What's Next?
- Adding MQTT/HomeAssistant integration
- Gambling odds?
- Building a user-friendly UI for easier configuration
```bash
sudo usermod -a -G gpio <your_username>
# Example for user 'ledpi':
# sudo usermod -a -G gpio ledpi
```
**Important:** You must **reboot** the Raspberry Pi after adding the user to the group for the change to take effect.
You also need to disable hardware pulsing in the code (see `src/display_manager.py`, set `options.disable_hardware_pulsing = True`). This may result in a flickerying display
ifgameandgame['is_upcoming']andgame.get('is_within_window',True):# Assume within window if key missing
processed_games.append(game)
# Filter for favorite teams
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.