TeslaMate Grafana Dashboards: Complete Guide to Bundled Visualizations and PostgreSQL Queries
TeslaMate ships with a complete set of JSON-based Grafana dashboards stored in grafana/dashboards/ that query PostgreSQL directly using raw SQL statements via a datasource with UID TeslaMate.
TeslaMate is an open-source self-hosted data logger for Tesla vehicles that stores telemetry in PostgreSQL. The project includes production-ready Grafana dashboards that visualize this data through direct SQL queries. Understanding how these TeslaMate Grafana dashboards are structured and how they interact with the database enables users to customize visualizations and troubleshoot data issues effectively.
Dashboard Storage and Datasource Configuration
All bundled dashboards reside as JSON definition files in the grafana/dashboards/ directory of the repository. Each dashboard file defines panels, queries, and layout configurations that Grafana imports directly.
Every dashboard uses a PostgreSQL datasource configured with the specific UID TeslaMate. This is defined in the datasource block of each panel:
{
"datasource": {
"type": "grafana-postgresql-datasource",
"uid": "TeslaMate"
}
}
The datasource connects to the TeslaMate PostgreSQL database where tables like cars, positions, charges, charging_processes, drives, and drive_details store the collected vehicle telemetry.
How Dashboards Query the Database
TeslaMate dashboards use raw SQL queries (rawSql) defined within the targets array of each panel. This approach provides full flexibility to join multiple tables and perform complex aggregations.
Templating Variables
Dashboards utilize the $car_id templating variable to support multi-car fleets. The "repeat": "car_id" property ensures panels render individually for each vehicle:
SELECT battery_level, date
FROM positions
WHERE car_id = $car_id
AND ideal_battery_range_km IS NOT NULL
ORDER BY date DESC
LIMIT 1
Time Range Filtering
Queries leverage Grafana's $__timeFilter(column) macro to respect the dashboard's selected time range. This expands to column BETWEEN 'from' AND 'to' based on the time picker:
SELECT start_date, end_date, distance_km, consumption_kWh
FROM drives
WHERE car_id = $car_id
AND $__timeFilter(start_date)
ORDER BY start_date DESC
Key Bundled Dashboards and Query Patterns
Overview Dashboard
The overview.json dashboard provides a high-level summary of vehicle status including battery level, range, and charging state. It queries the positions and charges tables to display current metrics:
(SELECT battery_level, date
FROM positions
WHERE car_id = $car_id AND ideal_battery_range_km IS NOT NULL
ORDER BY date DESC
LIMIT 1)
UNION
SELECT battery_level, date
FROM charges c
JOIN charging_processes p ON p.id = c.charging_process_id
WHERE $__timeFilter(date) AND p.car_id = $car_id
ORDER BY date DESC
LIMIT 1
Drives and Charges Analysis
The drives.json and charges.json dashboards analyze trip efficiency and charging sessions. They join drives with drive_details and charges with charging_processes to calculate energy consumption and costs:
-- Drives query example
SELECT d.id, d.start_date, d.end_date,
d.distance_km, d.duration, d.consumption_kWh
FROM drives d
WHERE d.car_id = $car_id AND $__timeFilter(d.start_date)
ORDER BY d.start_date DESC
-- Charges query example
SELECT c.id, c.start_date, c.end_date,
c.charge_energy_added, c.charge_price
FROM charges c
JOIN charging_processes p ON p.id = c.charging_process_id
WHERE p.car_id = $car_id AND $__timeFilter(c.start_date)
ORDER BY c.start_date DESC
Battery Health and Efficiency Metrics
The battery-health.json dashboard tracks degradation using the cars table, while efficiency.json calculates consumption rates from drive_details:
-- Battery health query
SELECT id, max_range_km, battery_health, battery_degradation
FROM cars
WHERE id = $car_id
-- Efficiency calculation
SELECT drive_id, consumption_kWh, distance_km,
consumption_kWh / NULLIF(distance_km,0) AS kwh_per_km,
consumption_kWh / EXTRACT(EPOCH FROM duration) * 3600 AS kwh_per_h
FROM drive_details
WHERE car_id = $car_id AND $__timeFilter(start_date)
Locations and Trip Visualization
The locations.json dashboard maps vehicle positions using latitude and longitude from the positions table:
SELECT latitude, longitude, address, date
FROM positions
WHERE car_id = $car_id AND $__timeFilter(date)
ORDER BY date DESC
The trip.json dashboard provides detailed timeline visualizations of individual drives, querying elevation, speed, and power data from the drives table.
Database Diagnostics
The database-info.json dashboard offers administrative visibility into table sizes and row counts for troubleshooting:
SELECT relname AS table,
n_live_tup AS rows,
pg_total_relation_size(relid) AS size_bytes
FROM pg_stat_user_tables
ORDER BY size_bytes DESC
Query Implementation Details
Raw Query Mode
Panels set "rawQuery": true and define SQL in the rawSql field. This bypasses Grafana's query builder and allows complex PostgreSQL syntax including window functions and CTEs:
{
"targets": [
{
"rawSql": "SELECT * FROM drives WHERE car_id = $car_id AND $__timeFilter(start_date)",
"refId": "A",
"format": "table",
"rawQuery": true
}
]
}
Data Transformations
After SQL execution, many panels apply Grafana transformations (such as configFromData, merge, or organize) to format results for specific visualizations. These transformations handle threshold mapping for gauge panels and column renaming without modifying the underlying SQL.
Customizing and Extending Dashboards
To create a custom panel showing average charging power per session, define a new target in your dashboard JSON:
{
"datasource": {
"type": "grafana-postgresql-datasource",
"uid": "TeslaMate"
},
"type": "table",
"targets": [
{
"rawSql": "SELECT c.id, (c.charge_energy_added / EXTRACT(EPOCH FROM (c.end_date - c.start_date)) * 3600) AS avg_power_kw FROM charges c JOIN charging_processes p ON p.id = c.charging_process_id WHERE p.car_id = $car_id AND $__timeFilter(c.start_date)",
"refId": "A",
"format": "table"
}
],
"title": "Avg. Charging Power (kW)"
}
Import custom dashboards through the Grafana UI via Dashboard → Manage → Import, then select the TeslaMate datasource when prompted.
Summary
- TeslaMate Grafana dashboards are stored as JSON files in
grafana/dashboards/and use theTeslaMatePostgreSQL datasource UID. - Queries use raw SQL (
rawSql) targeting tables includingcars,positions,drives,charges, andcharging_processes. - The
$car_idvariable enables multi-car fleet support through panel repetition. - The
$__timeFilter()macro ensures queries respect Grafana's time range selection. - Key dashboards include Overview, Drives, Charges, Battery Health, Efficiency, Locations, Trip, and Database Info.
- Advanced users can extend dashboards by writing custom SQL queries that join multiple tables and leverage PostgreSQL's analytical functions.
Frequently Asked Questions
How do I import the bundled TeslaMate dashboards into Grafana?
Navigate to Dashboard → Manage → Import in the Grafana UI. Paste the JSON content from any file in grafana/dashboards/ (such as overview.json or drives.json) or upload the file directly. When prompted, select the PostgreSQL datasource configured with UID TeslaMate to establish the database connection.
Can I use these dashboards with multiple Tesla vehicles?
Yes. The dashboards utilize the $car_id templating variable with the "repeat": "car_id" property. This configuration automatically duplicates panels for each vehicle in your fleet, filtering data by the specific car_id in the SQL WHERE clause.
What PostgreSQL tables does TeslaMate query for vehicle data?
The dashboards query several core tables: cars for vehicle metadata and battery health, positions for GPS and battery status, drives and drive_details for trip information, and charges joined with charging_processes for charging session analysis. The database-info.json dashboard queries pg_stat_user_tables for administrative metrics.
How do I customize a query to show specific metrics not in the default dashboards?
Edit the dashboard JSON to add a new panel with a rawSql target. Write standard PostgreSQL querying the relevant tables (such as calculating custom efficiency metrics from drive_details), include $car_id for filtering and $__timeFilter() for time range constraints, then import the modified JSON into Grafana.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →