Wer sein Tesla mit Teslamate loggt, möchte die Daten nicht nur sammeln, sondern auch übersichtlich darstellen.
Besonders spannend ist der monatliche Stromverbrauch zum Beispiel, um die Kosten besser im Blick zu behalten oder mit dem Haushaltsstrom abzugleichen.
In diesem Beitrag zeige ich dir, wie du den Monatsverbrauch aus Teslamate abfragst und in Home Assistant visualisierst.

SQL-Integration konfigurieren
In den Einstellungen -> Integrationen -> nach SQL suchen und hinzufügen.
Dort die Verbindungsdaten zu deiner Teslamate-PostgreSQL-Datenbank eintragen.
Monatliche Tesla Model 3 Auswertung
Name Der Name ist frei wählbar.
postgresql://<Benutzer>:<Passwort>@<IP-Telsmamate-DB>:5432/teslamate
Datenbank-URL An diese Stellen müssen <Benutzer>, <Passwort> und <IP-Teslamate-DB> durch die entsprechenden Zugangsdaten und die IP-Adresse deiner Teslamate-Datenbank ersetzt werden.
month_total_km
Spalte
WITH selected_car AS (
SELECT id AS car_id
FROM cars
WHERE UPPER(vin) = UPPER('<Deine VIN>')
LIMIT 1
),
time_range AS (
SELECT
date_trunc('month', CURRENT_DATE + INTERVAL '2 hours') AS month_start,
date_trunc('month', CURRENT_DATE + INTERVAL '2 hours') + INTERVAL '1 month' AS month_end
),
charging_sessions AS (
SELECT
cp.id,
COALESCE(NULLIF(cp.charge_energy_used, 0), cp.charge_energy_added) AS charge_energy,
cp.cost,
CASE
WHEN NULLIF(mode() WITHIN GROUP (ORDER BY c.charger_phases), 0) IS NULL THEN 'DC'
ELSE 'AC'
END AS charge_type,
COALESCE(
geofences.name,
CONCAT_WS(', ',
COALESCE(addresses.name, NULLIF(CONCAT_WS(' ', addresses.road, addresses.house_number), '')),
addresses.city
)
) AS address
FROM charging_processes cp
LEFT JOIN charges c ON cp.id = c.charging_process_id
LEFT JOIN addresses ON addresses.id = cp.address_id
LEFT JOIN public.geofences ON geofences.id = cp.geofence_id
CROSS JOIN time_range t
CROSS JOIN selected_car sc
WHERE
cp.car_id = sc.car_id AND
cp.start_date >= t.month_start AND
cp.start_date < t.month_end
GROUP BY
cp.id, cp.charge_energy_used, cp.charge_energy_added, cp.cost,
geofences.name, addresses.name, addresses.road, addresses.house_number, addresses.city
),
aggregated AS (
SELECT
address,
charge_type,
ROUND(SUM(charge_energy)::numeric, 2) AS total_kwh,
ROUND(SUM(cost)::numeric, 2) AS total_cost
FROM charging_sessions
GROUP BY address, charge_type
),
monthly_km AS (
SELECT
ROUND((MAX(odometer) - MIN(odometer))::numeric, 0) AS month_total_km
FROM public.positions p
CROSS JOIN time_range t
CROSS JOIN selected_car sc
WHERE
p.car_id = sc.car_id AND
DATE_TRUNC('month', p.date + INTERVAL '2 hours') = t.month_start
),
monthly_cost AS (
SELECT
ROUND(SUM(cp.cost)::numeric, 2) AS month_total_cost
FROM public.charging_processes cp
CROSS JOIN time_range t
CROSS JOIN selected_car sc
WHERE
cp.car_id = sc.car_id AND
cp.end_date >= t.month_start AND
cp.end_date < t.month_end
),
drive_data AS (
SELECT
distance,
duration_min,
end_date,
start_date,
car.efficiency AS car_efficiency,
NULLIF(GREATEST(start_ideal_range_km - end_ideal_range_km, 0), 0) AS range_diff,
duration_min > 1 AND distance > 1 AND (
start_position.usable_battery_level IS NULL OR end_position.usable_battery_level IS NULL OR
(end_position.battery_level - end_position.usable_battery_level) = 0
) AS is_sufficiently_precise
FROM drives
LEFT JOIN positions start_position ON start_position_id = start_position.id
LEFT JOIN positions end_position ON end_position_id = end_position.id
LEFT JOIN cars car ON car.id = drives.car_id
CROSS JOIN time_range t
CROSS JOIN selected_car sc
WHERE
start_date >= t.month_start AND
start_date < t.month_end AND
drives.car_id = sc.car_id AND
distance >= 1 AND
distance / COALESCE(NULLIF(duration_min, 0) * 60, extract(epoch from end_date - start_date)) * 3600 >= 5
),
avg_consumption AS (
SELECT
ROUND(AVG(
CASE
WHEN is_sufficiently_precise AND distance > 0 THEN
range_diff * car_efficiency / distance * 1000
ELSE NULL
END
)::numeric) AS month_avg_consumption_Wh_per_km
FROM drive_data
),
avg_prices AS (
SELECT
ROUND(SUM(total_cost) / NULLIF(SUM(total_kwh), 0), 2) AS month_avg_price_per_kwh,
json_agg(json_build_object(
'address', address,
'charge_type', charge_type,
'avg_price_per_kwh',
CASE WHEN total_kwh > 0 THEN ROUND(total_cost / total_kwh, 2) ELSE 0 END
) ORDER BY address, charge_type) AS avg_price_per_kwh_by_location
FROM aggregated
)
SELECT
(
SELECT json_agg(json_build_object(
'address', address,
'charge_type', charge_type,
'total_kwh', total_kwh,
'total_cost', total_cost,
'avg_price_per_kwh',
CASE WHEN total_kwh > 0 THEN ROUND(total_cost / total_kwh, 2) ELSE 0 END
) ORDER BY total_kwh DESC, address, charge_type)
FROM aggregated
) AS charging_sessions_json,
COALESCE(mk.month_total_km, 0) AS month_total_km,
COALESCE(mc.month_total_cost, 0) AS month_total_cost,
COALESCE(ac.month_avg_consumption_Wh_per_km, 0) AS month_avg_consumption_Wh_per_km,
COALESCE((SELECT ROUND(SUM(total_kwh)::numeric, 2) FROM aggregated), 0) AS month_total_kwh,
COALESCE(ROUND(
(mc.month_total_cost / NULLIF((SELECT ROUND(SUM(total_kwh)::numeric, 2) FROM aggregated), 0))
* (ac.month_avg_consumption_Wh_per_km / 1000)
, 3), 0.0) AS month_cost_per_km_estimated,
COALESCE(ROUND(mc.month_total_cost / NULLIF(mk.month_total_km, 0), 3), 0.0) AS month_cost_per_km_actual,
COALESCE(ap.month_avg_price_per_kwh, 0.0) AS month_avg_price_per_kwh
FROM avg_prices ap
CROSS JOIN monthly_km mk
CROSS JOIN monthly_cost mc
CROSS JOIN avg_consumption ac;
Abfrage An dieser Stelle muss lediglich <Deine VIN> durch die VIN deines Teslas ersetzt werden.
km
Maßeinheit
Messwert
Zustandsklasse
So sieht der fertige SQL-Sensor in Home Assistant nach der Einrichtung aus:

Visualisierung der Statistik für den aktuellen Monat
Da der Sensor eingerichtet ist, können wir die Daten direkt im Dashboard auswerten und übersichtlich darstellen. Die Darstellung zeigt alle relevanten Informationen zu den Ladevorgängen des aktuellen Monats:
- 🏠 Adresse: Jede Ladesäule, an der dein Tesla geladen hat, wird hier aufgelistet.
Mit farblicher Markierung siehst du auf einen Blick, wie teuer der Strom pro kWh war,
von grün (günstig) über gelb/orange bis rot (teuer). - ⚡ Typ: Typ der Ladung z. B. AC oder DC
- 🔋 Energie: Geladene kWh Gesamtenergie der Ladevorgänge
- 💶 Kosten: Gesamtkosten der Ladevorgänge
Unterhalb der einzelnen Ladevorgänge zeigt die Übersicht wichtige Durchschnittswerte und Summen für den aktuellen Monat:
- 📉 Ø Verbrauch: Durchschnittlicher Energieverbrauch pro Kilometer (Wh/km)
- 💶 Ø Kosten pro km: Durchschnittliche Kosten pro gefahrenem Kilometer
- 💶 Ø Kosten pro kWh: Durchschnittspreis pro Kilowattstunde
- 🚗 Gefahrene Kilometer: Gesamte Kilometer im Monat
- 🔋 Gesamtladung: Summe aller geladenen kWh
- 💰 Gesamtkosten: Gesamtkosten für alle Ladevorgänge
Karte im Dashboard hinzufügen
Nun, da der Sensor eingerichtet ist, kannst du die Monatsstatistik im Dashboard anzeigen:
- Gehe in dein Dashboard und klicke oben rechts auf „Bearbeiten“.
- Wähle „Karte hinzufügen“ → „Manuell“.
- Kopiere den folgenden Code in das Eingabefeld der manuellen Karte
(<Dein eben erstellten Sensor> muss ersetzt werden!)
type: markdown
content: |-
<h3>Statistik für den aktuellen Monat</h3>
<table width=100%>
<tr>
<th align=left>🏠 Adresse</th>
<th align=left>⚡ Typ</th>
<th align=right>🔋 Energy</th>
<th align=right>💶 Kosten</th>
</tr>
{%- set auswertungs_Sensor = '<Dein eben erstellten Sensor>' -%}
{%- macro blend_with_white(r, g, b, alpha=0.6) -%}
{# alpha = Anteil Originalfarbe, 1-alpha = Anteil Weiß #}
{%- set r_new = (r * alpha + 255 * (1 - alpha)) | round -%}
{%- set g_new = (g * alpha + 255 * (1 - alpha)) | round -%}
{%- set b_new = (b * alpha + 255 * (1 - alpha)) | round -%}
{{ '#%02x%02x%02x' % (r_new, g_new, b_new) }}
{%- endmacro -%}
{%- set sessions = state_attr(auswertungs_Sensor, 'charging_sessions_json') -%}
{%- if sessions and sessions | count > 0 -%}
{%- set max_price = (sessions | map(attribute='avg_price_per_kwh') | max) | float -%}
{%- for item in sessions -%}
{%- set price = item.avg_price_per_kwh | float(0) -%}
{%- if price == 0 -%}
{%- set color = '#90EE90' %} {# Blassgrün #}
{%- elif price <= 0.40 -%}
{# Verlauf Grün (#90EE90) bis Gelb (#FFFF00) #}
{%- set ratio = (price / 0.40) | float(1) -%}
{%- set r = (144 + (255 - 144) * ratio) | round -%}
{%- set g = (238 + (255 - 238) * ratio) | round -%}
{%- set b = (144 + (0 - 144) * ratio) | round -%}
{%- set color = blend_with_white(r, g, b, 0.6) -%}
{%- elif price < 0.50 -%}
{# Verlauf Gelb (#FFFF00) bis Orange (#FFA500) #}
{%- set ratio = ((price - 0.40) / 0.10) | float(1) -%}
{%- set r = 255 -%}
{%- set g = (255 + (165 - 255) * ratio) | round -%}
{%- set b = 0 -%}
{%- set color = blend_with_white(r, g, b, 0.6) -%}
{%- else -%}
{# Verlauf Orange (#FFA500) bis Rot (#FF0000) #}
{%- set max_price_capped = max_price if max_price > 0 else 0.50 -%}
{%- set capped_price = price if price <= max_price_capped else max_price_capped -%}
{%- set ratio = ((capped_price - 0.50) / (max_price_capped - 0.50)) | float(1) -%}
{%- set r = 255 -%}
{%- set g = (165 + (0 - 165) * ratio) | round -%}
{%- set b = 0 -%}
{%- set color = blend_with_white(r, g, b, 0.6) -%}
{%- endif -%}
<tr>
<td align=left>
{{ item.address }}<br>
<font color="{{ color }}">
<small>Ø {{ '%.2f' | format(price) }} €/kWh</small>
</font>
</td>
<td align=center>{{ item.charge_type }}</td>
{%- if item.total_kwh is not none -%}
<td align=right>{{ '%.0f' | format(item.total_kwh) }} kWh</td>
<td align=right>{{ '%.2f' | format(item.total_cost | default(0, true)) }} €</td>
{%- else -%}
<td align=right>🔌 Lädt…</td>
<td align=right>--.-- €</td>
{%- endif -%}
</tr>
{%- endfor -%}
{%- else -%}
<tr>
<td colspan=4 align=center><br><b>Keine Ladevorgänge verfügbar.</b></td>
</tr>
{%- endif -%}
<tr><td colspan=4><hr></td></tr>
<tr>
<td colspan=2 align=left><strong>📉 Ø Verbrauch:</strong></td>
<td colspan=2 align=right>{{ state_attr(auswertungs_Sensor, 'month_avg_consumption_wh_per_km') | int }} Wh/km</td>
</tr>
<tr>
<td colspan=2 align=left><strong>💶 Ø Kosten per km:</strong></td>
<td colspan=2 align=right>{{ state_attr(auswertungs_Sensor, 'month_cost_per_km_estimated') }} €/km</td>
</tr>
<tr>
<td colspan=2 align=left><strong>💶 Ø Kosten per kWh:</strong></td>
<td colspan=2 align=right>{{ state_attr(auswertungs_Sensor, 'month_avg_price_per_kwh') }} €/kWh</td>
</tr>
<tr>
<td colspan=2 align=left><strong>🚗 Gefahrene Kilometer:</strong></td>
<td colspan=2 align=right>{{ states(auswertungs_Sensor) }} km</td>
</tr>
<tr>
<td colspan=2 align=left><strong>🔋 Gesamtladung:</strong></td>
<td colspan=2 align=right>{{ '%.0f' | format(state_attr(auswertungs_Sensor, 'month_total_kwh')) }} kWh</td>
</tr>
<tr>
<td colspan=2 align=left><strong>💰 Gesamtkosten:</strong></td>
<td colspan=2 align=right>{{ state_attr(auswertungs_Sensor, 'month_total_cost') }} €</td>
</tr>
</table>
- Klicke auf Speichern die Monatsstatistik sollte nun direkt im Dashboard angezeigt werden.
Fertig! Jetzt hast du alle Ladevorgänge des aktuellen Monats übersichtlich mit Energie, Kosten und farblicher Kennzeichnung auf einen Blick verfügbar.