SwitchBot Temperature Dashboard
Dockerised SwitchBot temperature monitor with:
- Flask web dashboard for desktop and mobile.
- Python collector polling the SwitchBot API v1.1.
- MySQL storage.
- Auto-populated device names from the SwitchBot API.
- Configurable collection interval, defaulting to 15 minutes.
- Day-so-far temperature graph with high/low cards.
- Date-range reports with CSV export.
- PDF report generation and manual email sending through SMTP2GO.
Quick Start
Create your local environment file:
cp .env.example .env
Edit .env and set:
SWITCHBOT_TOKEN=your-token
SWITCHBOT_SECRET=your-secret
FLASK_SECRET_KEY=a-random-local-secret
Start everything:
docker compose up --build
Open:
http://localhost:8000
The collector service will create database tables, discover devices, and begin
recording temperature/humidity readings. To change the polling interval, update
COLLECT_INTERVAL_SECONDS in .env; 900 is 15 minutes.
Compose builds the internal database URL from MYSQL_USER, MYSQL_PASSWORD,
and MYSQL_DATABASE. Set DATABASE_URL only if you want to point the app at a
different database.
Maintenance
Remove bad readings where temperature, humidity, and battery are all zero:
scripts/remove_zero_readings.sh
Preview the count without deleting:
scripts/remove_zero_readings.sh --dry-run
Reports
Open /reports in the web app to generate a date-range summary. Use the
download button for a CSV export.
The same page can create and email a PDF report for the selected date range and
device filter. Configure SMTP2GO in .env before using it:
REPORT_SENDER_EMAIL=reports@example.com
REPORT_SENDER_NAME="SwitchBot Temps"
SMTP2GO_API_KEY=your-smtp2go-api-key
Generated PDFs and chart images are written under REPORT_OUTPUT_DIR, which
defaults to /tmp/switchbot-reports inside the web container.
Open /report-settings to manage scheduled report recipients and daily,
weekly, or monthly schedules. The report-scheduler service sends the previous
complete day, week, or month and records each period in the database before
sending so restarts do not duplicate emails.
Services
db: MySQL 8.4 with persistentmysql_datavolume.web: Flask app served by Gunicorn on port 8000.report-scheduler: recurring PDF report sender.collector: SwitchBot polling loop.
POC Script
The original proof-of-concept script is still available:
This demo signs a SwitchBot API v1.1 request and prints the JSON response.
Usage
Set your credentials as environment variables:
export SWITCHBOT_TOKEN="your-token"
export SWITCHBOT_SECRET="your-secret"
List devices:
python3 switchbot_poc.py
List devices with an empty-inventory diagnostic:
python3 switchbot_poc.py --diagnose
List scenes:
python3 switchbot_poc.py --endpoint /scenes
Get a device status:
python3 switchbot_poc.py --endpoint /devices/YOUR_DEVICE_ID/status
You can also pass credentials directly:
python3 switchbot_poc.py --token "your-token" --secret "your-secret"
The v1.1 signature is:
Base64(HMAC-SHA256(secret, token + timestamp_ms + nonce))
Empty Device List
If /devices returns:
{
"statusCode": 100,
"message": "success",
"body": {
"deviceList": [],
"infraredRemoteList": []
}
}
the signed API request is working, but the account behind that token has no Cloud API-visible devices.
Things to check:
- The token and secret were generated from the same SwitchBot app account that owns the devices.
- You are not logged into a different SwitchBot account, Apple/Google login, or home/family than the one containing the devices.
- The devices appear in the SwitchBot mobile app while logged into that account.
- Bluetooth-only devices such as Bots, Locks, Curtains, and Meters generally need to be reachable through a SwitchBot Hub for cloud/API access.
- If using app version 9 or newer, SwitchBot says the old manual "Cloud Service" toggle was removed for some devices; keep the device near a Hub and verify it is remotely controllable from the app.