Skip to content

About

🐱 Autonomous weather display for the iDotMatrix 32Γ—32 LED panel. Fetches live weather, renders animated pixel scenes over BLE β€” no phone, no cloud. A pixel cat lives on the screen and wanders around between updates. Runs on Raspberry Pi Zero πŸ“

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

74 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

iDotMatrix-Meoweather

Autonomous weather display for the iDotMatrix 32Γ—32 LED pixel panel β€” no phone, no cloud, no interaction required. Current weather is fetched from the internet, rendered into a looping pixel animation, and pushed to the panel over Bluetooth Low Energy. πŸ“‘

A pixel cat 🐱 lives on the display and wanders around between weather updates.

Demo β€” weather scenes


Features

🌀️ Weather display

  • 9 animated weather scenes β€” clear day, clear night, partly cloudy, cloudy, fog, rain, heavy rain, snow, thunderstorm
  • Smooth animations β€” each scene loops with 6–12 frames; only changed pixels are sent over BLE, so the panel never flashes
  • Live temperature β€” rendered in a custom pixel font
  • Night tinting β€” colours shift warmer after sunset
  • Automatic refresh β€” fetches weather from Open-Meteo on a configurable interval (default: every 10 minutes)

🐾 Pixel pet

A 5-pixel-wide cat overlaid on every frame. It has a full behaviour state machine:

Behaviour Description
walk Strolls back and forth, blinks occasionally
sit Sits and breathes
lie Flops down
jump Leaps and lands
perch Climbs to a weather icon and sits on top
dream Sleeps with floating dream bubbles
burp Special move β€” leaves a little residue
poo Special move β€” also leaves a little residue

Day and night have different behaviour weights (night is calmer: more dreaming, less jumping).

πŸŽ›οΈ Control API & web UI

A local HTTP server (port 3000) exposes a REST API and a web UI for live control:

Endpoint Description
GET /api/health Current state: weather, pet behaviour, brightness, schedules
GET /api/state Server-sent events stream of the health object
GET /api/frame Server-sent events stream of the current rendered frame (base64 PNG)
GET /api/logs Live log stream
POST /api/control/brightness Set day/night brightness (0–100)
POST /api/control/night-hours Configure dimming window
POST /api/control/power-schedule Auto on/off by hour of day
POST /api/control/behavior Force the pet into a specific behaviour
POST /api/control/weather Override the weather (useful for testing)
POST /api/control/pause Pause/resume rendering

πŸ› οΈ Developer tools

npm run dev:sim opens a browser-based dev app with three tabs:

Simulator β€” live pixel preview with weather and pet controls, no hardware needed.

Simulator β€” rain Simulator β€” night

Studio β€” pixel sprite editor for the pet. Edit individual frames, preview them live in the simulator, and save directly to src/sprites.ts.

Studio

Logs β€” streamed output from the running app.

πŸš€ Deployment

Target How
macOS (dev) npm run dev β€” sidecar + TypeScript with hot-reload
macOS (background) npm run service:install β€” launchd Login Item, auto-restarts on crash
Raspberry Pi Docker Compose β€” two containers (app + sidecar), push-based deploy via GitHub Actions self-hosted runner

How it works

Open-Meteo API
     β”‚ HTTPS
     β–Ό
β”Œβ”€β”€β”€ TypeScript (Node.js) ──────────────────────┐
β”‚  weather/   β†’ WeatherSnapshot                  β”‚
β”‚  render/    β†’ 32Γ—32 RGB buffer β†’ PNG           β”‚
β”‚  scheduler/ β†’ every N minutes                  β”‚
β”‚  transport/ β†’ POST PNG ──────────────┐         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚ HTTP localhost
                                       β–Ό
                        β”Œβ”€β”€β”€ Python sidecar (bleak) ───┐
                        β”‚  FastAPI: /display, /health   β”‚
                        β”‚  idotmatrix-api-client        β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚ BLE GATT
                                       β–Ό
                              iDotMatrix 32Γ—32 panel

The BLE protocol is undocumented and only exists as a reverse-engineered Python library. TypeScript handles everything else; the Python sidecar is the only part that touches Bluetooth. The two communicate over a local HTTP boundary: TypeScript sends a 32Γ—32 PNG, the sidecar pushes it to the panel.


Requirements

  • iDotMatrix 32Γ—32 LED panel (the AliExpress model, Bluetooth name IDM_32*32_*)
  • macOS or Linux host within BLE range of the panel
  • Node.js β‰₯ 20
  • Python 3.11+
  • macOS: Bluetooth permission granted to your terminal app (System Settings β†’ Privacy & Security β†’ Bluetooth)

Quick start

macOS

# 1. Clone and install
git clone https://github.com/brmk/iDotMatrix-Meoweather.git
cd iDotMatrix-Meoweather
npm install

# 2. Set up the Python sidecar
cd sidecar
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cd ..

# 3. Configure
cp .env.example .env
# Edit LATITUDE, LONGITUDE, and optionally INTERVAL_SECONDS

# 4. Run
npm run dev

The TypeScript app and Python sidecar start together. The panel updates within a minute on the first cycle (BLE scan takes ~15 s on first connect).

Browser simulator (no hardware needed)

npm install
npm run dev:sim
# Open http://localhost:8766

Raspberry Pi (Docker Compose)

One-time host prep:

# On the Pi
sudo apt-get install -y docker.io docker-compose-plugin
sudo usermod -aG docker "$USER"
sudo loginctl enable-linger "$USER"

Deploy:

cp .env.example .env
# Edit LATITUDE, LONGITUDE
# Edit APP_IMAGE and SIDECAR_IMAGE to your GHCR namespace

./scripts/deploy-rpi.sh
./scripts/install-rpi-user-service.sh

Configuration

All variables are read from .env (copy from .env.example). All have sensible defaults.

Variable Default Description
LATITUDE / LONGITUDE 49.5535 / 25.5948 Your location
INTERVAL_SECONDS 600 Weather refresh interval
SHOW_CLOCK true Temperature (left) and clock (right) share the bottom line; false = temperature only
BLE_ADAPTER_MAC β€” Linux only: pin the panel to this Bluetooth adapter
BLE_PANEL_ADDRESS β€” Linux only: drop a stale BlueZ link to the panel on startup
BLE_FRAGMENT_SIZE negotiated MTU βˆ’ 3 Cap the size of a single BLE write
SIDECAR_URL http://127.0.0.1:8765 Local sidecar address
DEVICE_NAME_PREFIX IDM BLE name prefix used for discovery
SCAN_TIMEOUT 15 BLE discovery timeout (seconds)
DAY_BRIGHTNESS 80 Panel brightness during the day (0–100)
NIGHT_BRIGHTNESS 25 Panel brightness at night (0–100)

Brightness and night-hours settings persist across restarts in runtime.json and can be updated at runtime via the control API.


Project layout

src/
  weather/     # Open-Meteo client β†’ WeatherSnapshot
  render/
    icons/     # 9 weather icon animators
    text/      # Pixel font renderer
    pet/       # Pet sprite system and behaviour state machine
    scene/     # Frame composer, night tinting, temperature overlay
  scheduler/   # Interval loop
  transport/   # HTTP client for the sidecar
  control.ts   # REST API + SSE server
sidecar/       # Python BLE bridge (FastAPI + bleak)
dev/           # Vite + React dev app (simulator, studio, logs)
docs/          # Architecture, runbook, ADRs

Tech stack

Layer Tech
App TypeScript / Node.js
BLE bridge Python, FastAPI, bleak, idotmatrix-api-client
Weather data Open-Meteo (free, no API key)
Dev UI Vite + React
Tests Vitest (unit + deterministic render regression)
Production deploy Docker Compose + GitHub Actions

License

MIT β€” see LICENSE.

About

🐱 Autonomous weather display for the iDotMatrix 32Γ—32 LED panel. Fetches live weather, renders animated pixel scenes over BLE β€” no phone, no cloud. A pixel cat lives on the screen and wanders around between updates. Runs on Raspberry Pi Zero πŸ“

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages