grafana
visualization
timescaledb
dashboard
Grafana Dashboard
Grafana is our visualization layer, displaying real-time car telemetry from TimescaleDB.
Installation (macOS)
brew install grafana
brew services start grafana
Access at: http://localhost:3000
Default login: admin / admin
Remote Access Configuration
To access Grafana from other machines (via local network IP):
Edit /opt/homebrew/etc/grafana/grafana.ini:
[server]
http_addr = 0.0.0.0
http_port = 3000
Restart: brew services restart grafana
Data Source Setup
- Go to Connections → Data Sources → Add data source
- Select PostgreSQL
- Configure:
| Field | Value |
|---|---|
| Host | localhost:5433 |
| Database | telemetry |
| User | postgres |
| Password | telemetry123 |
| TLS/SSL Mode | disable |
- Click Save & Test → Should show "Database OK"
Dashboard Panels
Gauge Panels (Current Values)
All gauges use this query pattern:
SELECT time, <column> as "<Label>"
FROM car_metrics
ORDER BY time DESC
LIMIT 1
| Panel | Query | Min | Max | Unit |
|---|---|---|---|---|
| RPM | SELECT time, rpm as "RPM" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 8000 | RPM |
| Speed | SELECT time, speed as "Speed" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 200 | km/h |
| Coolant Temp | SELECT time, coolant as "Coolant" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 130 | °C |
| Intake Temp | SELECT time, intake_temp as "Intake" FROM car_metrics ORDER BY time DESC LIMIT 1 |
-20 | 80 | °C |
| Throttle | SELECT time, throttle as "Throttle" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 100 | % |
| Engine Load | SELECT time, engine_load as "Load" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 100 | % |
| MAP | SELECT time, map_kpa as "MAP" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 250 | kPa |
| Fuel Level | SELECT time, fuel_level as "Fuel" FROM car_metrics ORDER BY time DESC LIMIT 1 |
0 | 100 | % |
| Timing Advance | SELECT time, timing_adv as "Timing" FROM car_metrics ORDER BY time DESC LIMIT 1 |
-10 | 50 | ° |
| Battery | SELECT time, battery_voltage as "Battery" FROM car_metrics ORDER BY time DESC LIMIT 1 |
10 | 16 | V |
Finding Units
- In panel editor, scroll to Standard options
- Click Unit dropdown
- Search for unit name:
celsius→ Temperaturepercent→ Misc → Percent (0-100)kPa→ Pressure → Kilopascalvelocitykmh→ Velocity → km/hvolt→ Electrical → Volt
Time Series Panel (History)
SELECT time, rpm, speed, coolant
FROM car_metrics
WHERE time > NOW() - INTERVAL '1 hour'
ORDER BY time
- Type: Time series
- Title:
Telemetry History
Dashboard Layout
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ RPM │ Speed │Throttle │ Load │ Battery │
│ Gauge │ Gauge │ Gauge │ Gauge │ Gauge │
├─────────┼─────────┼─────────┼─────────┼─────────┤
│ Coolant │ Intake │ MAP │ Fuel │ Timing │
│ Gauge │ Gauge │ Gauge │ Gauge │ Gauge │
├─────────┴─────────┴─────────┴─────────┴─────────┤
│ Time Series Graph │
│ (RPM, Speed, Coolant over time) │
└─────────────────────────────────────────────────┘
Refresh Rate
For real-time monitoring:
- Click the refresh icon (top right)
- Set to
5sor10sauto-refresh - Set time range to "Last 5 minutes" or "Last 15 minutes"
Threshold Colors (Gauges)
To add color thresholds:
- Edit panel → scroll to Thresholds
- Add threshold values:
Example for RPM:
- Base (green): 0
- Yellow: 5000
- Red: 6500
Example for Coolant:
- Base (blue): 0
- Green: 80
- Yellow: 100
- Red: 110
Useful Queries for Analytics
Max Speed During Trip
SELECT MAX(speed) as "Max Speed"
FROM car_metrics
WHERE time > NOW() - INTERVAL '2 hours'
Average Fuel Consumption Estimate
SELECT
AVG(engine_load) as avg_load,
AVG(rpm) as avg_rpm,
AVG(throttle) as avg_throttle
FROM car_metrics
WHERE time > NOW() - INTERVAL '1 hour'
Time at High RPM
SELECT
COUNT(*) as high_rpm_seconds
FROM car_metrics
WHERE time > NOW() - INTERVAL '1 hour'
AND rpm > 4000
Exporting Dashboard
To backup or share your dashboard:
- Dashboard settings (gear icon)
- JSON Model
- Copy JSON or click "Save to file"
Troubleshooting
"No data" shown
- Check time range (top right) - data might be outside range
- Verify query in Query Inspector
- Check TimescaleDB has data:
SELECT COUNT(*) FROM car_metrics;
Query syntax errors
- Don't use Grafana macros like
$__timeFilter()with PostgreSQL - Use plain SQL with
WHERE time > NOW() - INTERVAL '1 hour'
Slow dashboard
- Add index:
CREATE INDEX ON car_metrics (time DESC); - Limit data range in queries
- Use time_bucket() for aggregations