# TeslaMate Grafana Dashboards: Complete Guide to Bundled Visualizations and PostgreSQL Queries

> Explore TeslaMate's bundled Grafana dashboards and understand their PostgreSQL queries. Learn how to leverage these visualizations for your EV data.

- Repository: [TeslaMate/teslamate](https://github.com/teslamate-org/teslamate)
- Tags: deep-dive
- Published: 2026-06-23

---

**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:

```json
{
  "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:

```sql
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:

```sql
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`](https://github.com/teslamate-org/teslamate/blob/main/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:

```sql
(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`](https://github.com/teslamate-org/teslamate/blob/main/drives.json) and [`charges.json`](https://github.com/teslamate-org/teslamate/blob/main/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:

```sql
-- 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

```

```sql
-- 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`](https://github.com/teslamate-org/teslamate/blob/main/battery-health.json) dashboard tracks degradation using the `cars` table, while [`efficiency.json`](https://github.com/teslamate-org/teslamate/blob/main/efficiency.json) calculates consumption rates from `drive_details`:

```sql
-- Battery health query
SELECT id, max_range_km, battery_health, battery_degradation
FROM cars
WHERE id = $car_id

```

```sql
-- 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`](https://github.com/teslamate-org/teslamate/blob/main/locations.json) dashboard maps vehicle positions using latitude and longitude from the `positions` table:

```sql
SELECT latitude, longitude, address, date
FROM positions
WHERE car_id = $car_id AND $__timeFilter(date)
ORDER BY date DESC

```

The [`trip.json`](https://github.com/teslamate-org/teslamate/blob/main/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`](https://github.com/teslamate-org/teslamate/blob/main/database-info.json) dashboard offers administrative visibility into table sizes and row counts for troubleshooting:

```sql
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:

```json
{
  "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:

```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 the `TeslaMate` PostgreSQL datasource UID.
- Queries use **raw SQL** (`rawSql`) targeting tables including `cars`, `positions`, `drives`, `charges`, and `charging_processes`.
- The `$car_id` variable 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`](https://github.com/teslamate-org/teslamate/blob/main/overview.json) or [`drives.json`](https://github.com/teslamate-org/teslamate/blob/main/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`](https://github.com/teslamate-org/teslamate/blob/main/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.