Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \
| [NRL Scoreboard](./plugins/nrl-scoreboard/) | National Rugby League live, recent & upcoming games | |
| [F1 Scoreboard](./plugins/f1-scoreboard/) | Formula 1 race results, schedules, and standings | |
| [UFC Scoreboard](./plugins/ufc-scoreboard/) | UFC/MMA live fights, fighter headshots, records, odds & results — *by [LegoGuy1000](https://github.com/legoguy1000)* | |
| [Odds Ticker](./plugins/odds-ticker/) | Betting odds & lines across NFL, NBA, MLB, NHL, NCAA | <a href="./plugins/odds-ticker/"><img src="./docs/assets/odds-ticker/hero.png" width="240" alt="odds-ticker on an LED panel"></a> |
| [Masters Tournament](./plugins/masters-tournament/) | Live Masters golf leaderboard, hole tracking, player cards | <a href="./plugins/masters-tournament/"><img src="./docs/assets/masters-tournament/hero.png" width="240" alt="masters-tournament on an LED panel"></a> |
| [NFL Draft](./plugins/nfl-draft/) | Projected & live NFL draft picks from ESPN | <a href="./plugins/nfl-draft/"><img src="./docs/assets/nfl-draft/hero.png" width="240" alt="nfl-draft on an LED panel"></a> |
| [March Madness](./plugins/march-madness/) | NCAA tournament bracket tracker with round branding and live scores | <a href="./plugins/march-madness/"><img src="./docs/assets/march-madness/hero.png" width="240" alt="march-madness on an LED panel"></a> |
| [Odds Ticker](./plugins/odds-ticker/) | Betting odds & lines across NFL, NBA, MLB, NHL, NCAA | |
| [Sports Leaderboard](./plugins/ledmatrix-leaderboard/) | League standings, rankings, conference records | |
| [Olympics Countdown](./plugins/olympics/) | Countdown to next Olympics with live medal counts | <a href="./plugins/olympics/"><img src="./docs/assets/olympics/hero.png" width="240" alt="olympics on an LED panel"></a> |

Expand Down
Binary file added docs/assets/odds-ticker/channel-logos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/odds-ticker/hero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/odds-ticker/panel-sizes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
180 changes: 180 additions & 0 deletions docs/assets/odds-ticker/shots.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
{
"plugin": "odds-ticker",
"_comment": "Games are seeded onto the plugin instance rather than fetched from ESPN, and last_update is seeded too or display() would re-fetch and clear them. The ticker scrolls, so shots step frames. Team records are looked up live per team during update(), which these renders skip, so they show as (N/A). Matchups and lines are invented.",
"defaults": {
"width": 128,
"height": 32,
"scale": 6,
"freeze_time": "2026-09-12T18:00:00+00:00",
"skip_update": true,
"frames": 60,
"config": {
"enabled": true
},
"attrs": {
"games_data": [
{
"league": "nfl",
"away_team": "KC",
"away_id": "12",
"home_team": "BUF",
"home_id": "2",
"start_time": "2026-09-13T20:25:00Z",
"broadcast": "CBS",
"logo_dir": "assets/sports/nfl_logos",
"odds": {
"away_team_odds": {
"money_line": "+118"
},
"home_team_odds": {
"money_line": "-140"
},
"spread": -2.5,
"over_under": 48.5
}
},
{
"league": "nfl",
"away_team": "DAL",
"away_id": "6",
"home_team": "PHI",
"home_id": "21",
"start_time": "2026-09-14T00:20:00Z",
"broadcast": "NBC",
"logo_dir": "assets/sports/nfl_logos",
"odds": {
"away_team_odds": {
"money_line": "+165"
},
"home_team_odds": {
"money_line": "-195"
},
"spread": -4.0,
"over_under": 45.5
}
},
{
"league": "nba",
"away_team": "BOS",
"away_id": "2",
"home_team": "LAL",
"home_id": "13",
"start_time": "2026-09-14T02:30:00Z",
"broadcast": "ESPN",
"logo_dir": "assets/sports/nba_logos",
"odds": {
"away_team_odds": {
"money_line": "-105"
},
"home_team_odds": {
"money_line": "-115"
},
"spread": 1.5,
"over_under": 224.5
}
}
],
"last_update": 1789236000.0,
"is_enabled": true
}
},
"shots": [
{
"name": "hero",
"frames": 160,
"width": 256
},
{
"name": "card",
"frames": 160,
"width": 256,
"standalone": false
},
{
"name": "logos-on",
"frames": 160,
"width": 256,
"standalone": false,
"config": {
"display_options": {
"show_channel_logos": true
}
}
},
{
"name": "logos-off",
"frames": 160,
"width": 256,
"standalone": false,
"config": {
"display_options": {
"show_channel_logos": false
}
}
},
{
"name": "size-64x32",
"width": 64,
"frames": 160,
"standalone": false
},
{
"name": "size-128x32",
"width": 128,
"frames": 160,
"standalone": false
},
{
"name": "size-128x64",
"width": 128,
"height": 64,
"frames": 160,
"standalone": false
},
{
"name": "size-256x32",
"width": 256,
"frames": 160,
"standalone": false
}
],
"composites": [
{
"name": "channel-logos",
"columns": 1,
"cells": [
{
"shot": "logos-on",
"label": "show_channel_logos: true",
"sublabel": "the broadcaster's mark, where one is available"
},
{
"shot": "logos-off",
"label": "show_channel_logos: false"
}
]
},
{
"name": "panel-sizes",
"columns": 2,
"cells": [
{
"shot": "size-64x32",
"label": "64 x 32"
},
{
"shot": "size-128x32",
"label": "128 x 32"
},
{
"shot": "size-128x64",
"label": "128 x 64"
},
{
"shot": "size-256x32",
"label": "256 x 32"
}
]
}
]
}
4 changes: 2 additions & 2 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,10 @@
"plugin_path": "plugins/odds-ticker",
"stars": 0,
"downloads": 0,
"last_updated": "2026-08-05",
"last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
"latest_version": "1.3.3"
"latest_version": "1.4.0"
},
{
"id": "of-the-day",
Expand Down
169 changes: 99 additions & 70 deletions plugins/odds-ticker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

# Odds Ticker Plugin

![A game card on a 256x32 panel: both team logos, the abbreviations and records,
the spread and over/under, and the kick-off day and time](../../docs/assets/odds-ticker/hero.png)

*Every image in this README is real plugin output, rendered at the true panel
size from seeded games so it reproduces exactly. Team records come from a live
per-team ESPN lookup that these offline renders skip, which is why they read
`(N/A)`.*

A plugin for LEDMatrix that displays scrolling odds and betting lines for upcoming games across multiple sports leagues including NFL, NBA, MLB, NCAA Football, and NCAA Basketball.

## Features
Expand All @@ -27,83 +35,104 @@ A plugin for LEDMatrix that displays scrolling odds and betting lines for upcomi

## Configuration

### Global Settings

- `display_duration`: How long to show the ticker (10-300 seconds, default: 30)
- `scroll_speed`: Scrolling speed multiplier (0.5-10, default: 2)
- `scroll_delay`: Delay between scroll steps (0.01-0.5 seconds, default: 0.05)
- `show_favorite_teams_only`: Only show odds for favorite teams (default: false)
- `games_per_favorite_team`: Number of games per favorite team (1-5, default: 1)
- `max_games_per_league`: Maximum games per league (1-20, default: 5)
- `show_odds_only`: Show only odds, no game details (default: false)
- `future_fetch_days`: Days ahead to fetch games (1-14, default: 7)

### Per-League Settings

#### NFL Configuration

```json
{
"leagues": {
"nfl": {
"enabled": true,
"favorite_teams": ["TB", "DAL", "GB"]
}
}
}
```

#### NBA Configuration

```json
{
"leagues": {
"nba": {
"enabled": true,
"favorite_teams": ["LAL", "BOS", "GS"]
}
}
}
```

#### MLB Configuration

```json
{
"leagues": {
"mlb": {
"enabled": true,
"favorite_teams": ["NYY", "BOS", "LAD"]
}
}
}
```

#### NCAA Football Configuration
Every setting except `enabled` lives inside one of five blocks —
`display_options`, `data_settings`, `filtering`, `leagues` or `customization`.
The schema sets `additionalProperties: false`, so a key written at the top
level is **rejected**, not ignored. The full schema is
[`config_schema.json`](config_schema.json).

```json
{
"leagues": {
"ncaa_fb": {
"enabled": true,
"favorite_teams": ["UGA", "AUB", "BAMA"]
}
"odds-ticker": {
"enabled": true,
"display_options": { "scroll_speed": 1.0 },
"filtering": { "max_games_per_league": 5 },
"leagues": { "nfl": { "enabled": true, "favorite_teams": ["KC", "BUF"] } }
}
}
```

#### NCAA Basketball Configuration

```json
{
"leagues": {
"ncaam_basketball": {
"enabled": true,
"favorite_teams": ["DUKE", "UNC", "KANSAS"]
}
}
}
```
### Display

| Key | Default | Notes |
|---|---|---|
| `display_options.display_duration` | `30` | Duration in seconds to display the odds ticker (used when dynamic_duration is disabled) (10–300). |
| `display_options.dynamic_duration` | `true` | Enable dynamic duration based on content width. Automatically adjusts display time based on how much content there is. |
| `display_options.min_duration` | `30` | Minimum display duration in seconds when dynamic duration is enabled (10–300). |
| `display_options.max_duration` | `300` | Maximum display duration in seconds when dynamic duration is enabled (30–600). |
| `display_options.duration_buffer` | `0.1` | Extra buffer time added to calculated duration (as percentage, 0.1 = 10%) (0.01–1.0). |
| `display_options.scroll_speed` | `1.0` | Scrolling speed in pixels per frame (0.5–5.0). |
| `display_options.scroll_delay` | `0.02` | Delay between scroll steps in seconds (lower = faster scrolling) (0.001–0.1). |
| `display_options.scroll_pixels_per_second` | `50.0` | Scroll speed in pixels per second (used for dynamic duration calculation). Set to match your actual scroll rate: scroll_speed / scroll_delay (5.0–100.0). |
| `display_options.target_fps` | `120` | Target frames per second for smooth scrolling. Higher values = smoother animation (120 recommended) (30–200). |
| `display_options.loop` | `true` | Continuously loop the ticker. If false, stops at the end. |
| `display_options.show_channel_logos` | `true` | Show broadcast channel logos. |
| `display_options.broadcast_logo_height_ratio` | `0.8` | Height ratio for broadcast channel logos (0.8 = 80% of display height) (0.1–1.0). |
| `display_options.broadcast_logo_max_width_ratio` | `0.8` | Maximum width ratio for broadcast channel logos relative to display width (0.1–2.0). |

### Data fetching

| Key | Default | Notes |
|---|---|---|
| `data_settings.update_interval` | `3600` | How often to fetch new odds data in seconds when there are no live games (300–86400). |
| `data_settings.live_game_update_interval` | `60` | How often to fetch new odds data in seconds when there are live games being displayed (30–300). |
| `data_settings.future_fetch_days` | `7` | Days ahead to fetch upcoming games (1–90). |
| `data_settings.request_timeout` | `30` | Request timeout in seconds for API calls (5–120). |
| `data_settings.fetch_odds` | `true` | Enable fetching of betting odds. |

### Which games appear

| Key | Default | Notes |
|---|---|---|
| `filtering.show_favorite_teams_only` | `false` | Only show odds for favorite teams across all leagues. |
| `filtering.games_per_favorite_team` | `1` | Number of games to show per favorite team (1–5). |
| `filtering.max_games_per_league` | `5` | Maximum number of games to show per league (1–20). |
| `filtering.show_odds_only` | `false` | Include only games that have odds data; games without odds will be excluded from the ticker. |
| `filtering.sort_order` | `"soonest"` | Sort order for displaying games — one of `soonest`, `league`, `team`. |

### Fonts

| Key | Default | Notes |
|---|---|---|
| `customization.team_text.font` | `"PressStart2P-Regular.ttf"` | Select the font to use — one of `PressStart2P-Regular.ttf`, `4x6-font.ttf`, `5by7.regular.ttf`, `5x7.bdf`, `4x6.bdf`. |
| `customization.team_text.font_size` | `8` | Font size in pixels (4–16). |
| `customization.odds_text.font` | `"PressStart2P-Regular.ttf"` | Select the font to use — one of `PressStart2P-Regular.ttf`, `4x6-font.ttf`, `5by7.regular.ttf`, `5x7.bdf`, `4x6.bdf`. |
| `customization.odds_text.font_size` | `8` | Font size in pixels (4–16). |
| `customization.datetime_text.font` | `"PressStart2P-Regular.ttf"` | Select the font to use — one of `PressStart2P-Regular.ttf`, `4x6-font.ttf`, `5by7.regular.ttf`, `5x7.bdf`, `4x6.bdf`. |
| `customization.datetime_text.font_size` | `8` | Font size in pixels (4–16). |

### Leagues

Each league takes `enabled` and `favorite_teams`, and `ncaam_basketball` adds
`show_seeds_in_tournament`. `favorite_teams` defaults to `null`, which means
"no favourites for this league" rather than an empty list.

| Key | Default |
|---|---|
| `leagues.nfl.enabled` | `true` |
| `leagues.nfl.favorite_teams` | `null` |
| `leagues.nba.enabled` | `true` |
| `leagues.nba.favorite_teams` | `null` |
| `leagues.mlb.enabled` | `true` |
| `leagues.mlb.favorite_teams` | `null` |
| `leagues.nhl.enabled` | `true` |
| `leagues.nhl.favorite_teams` | `null` |
| `leagues.milb.enabled` | `false` |
| `leagues.milb.favorite_teams` | `null` |
| `leagues.ncaa_fb.enabled` | `false` |
| `leagues.ncaa_fb.favorite_teams` | `null` |
| `leagues.ncaam_basketball.enabled` | `false` |
| `leagues.ncaam_basketball.favorite_teams` | `null` |
| `leagues.ncaam_basketball.show_seeds_in_tournament` | `true` |
| `leagues.ncaa_baseball.enabled` | `false` |
| `leagues.ncaa_baseball.favorite_teams` | `null` |


### What the toggles look like

![show_channel_logos on and off](../../docs/assets/odds-ticker/channel-logos.png)

![The same card on four panel sizes](../../docs/assets/odds-ticker/panel-sizes.png)

## Display Format

Expand Down
Loading
Loading