{ "__elements": {}, "__requires": [ { "type": "panel", "id": "bargauge", "name": "Bar gauge", "version": "" }, { "type": "panel", "id": "gauge", "name": "Gauge", "version": "" }, { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "10.4.0" }, { "type": "datasource", "id": "grafana-postgresql-datasource", "name": "PostgreSQL", "version": "1.0.0" }, { "type": "panel", "id": "piechart", "name": "Pie chart", "version": "" }, { "type": "panel", "id": "stat", "name": "Stat", "version": "" }, { "type": "panel", "id": "xychart", "name": "XY Chart", "version": "" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "definition": "TeslaMate|U2FsdGVkX1/cEWK+8cz7pjEKXtzJnDN7b21ZDXt1MGneFGPWTLqOPtxKmu02mJPLzi/f29I+NBHd3vi0FB8R4Xn0+GtobWDgk6VAVSBTdSNniOKO8i2WPlhRaOsl2+hG7gnZ7wrf1Th2nxR7f1uYCrbwOek0IzkfLzrkjh7gkr6inT6bbDuJqrmogZajLxmAMrQ6V+/vHxBRGiwjJhgiEeq3hM1q2h04JKkNiZ8RHbsF5Cd/xd8Q9u0JVrZzIrtnhM/SFlaApU7RtRMu8CSj1llTX7WEOj6VDZAMSf+XUAanWdk725kEPN9MNu89o2zEq5P3E3cju8IbbBdPzXLV3oVuzD6/tMnxFToIIV1E/BrpF7s2RtNa8+KJJ1PF8xgs6m+/KTD2hy+WsP0636AgObRAmYg7+qotGrgNvpNPdE0EgrB7WHYlV7R/1q66bcq6tCe51X1Un70k+zo+K6AK0o4B1H6IyMlEVuRH/Fz8QVl9aYu2ztd08RbuKJlYVKpkH+pxVETAO9MclYQ90tzE6TfwDZrQZzsAlMenr4s1ZB1OlFXjLjVjnddnUilzO76cqv4yI2THQEuyQ47nuVQ4gUbx02K59vMQhns3C01JOAYokOaSXe66Y7QYdMlk09Lf|aes-256-cbc", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": null, "links": [ { "icon": "dashboard", "tags": [], "title": "TeslaMate", "tooltip": "", "type": "link", "url": "[[base_url:raw]]" }, { "asDropdown": true, "icon": "external link", "tags": ["tesla"], "title": "Dashboards", "type": "dashboards" }, { "asDropdown": true, "icon": "external link", "includeVars": false, "keepTime": false, "tags": ["TeslamateCustomDashboards"], "targetBlank": false, "title": "Custom Dashboards", "tooltip": "", "type": "dashboards", "url": "" } ], "liveNow": false, "panels": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "**Usable (now)** is the estimated current battery capacity. It is average of the estimated capacity reported by the last 10 charging sessions to have a better estimation.\n\nIf you see just '1.0 kWh' here, it means that you need at least a long charge session.\n\n**Usable (new)** is the estimated Battery Capacity since you begun to use Teslamate. That's why, the more data you have logged from your brand new car the better. For those who have not used Teslamate since they got their new car, or for those who have bought it second hand, it's possible to set the max range to 100% and the battery capacity of the car battery when it was new in order to get a better and accurate estimation.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "super-light-blue", "value": null }, { "color": "dark-red", "value": 1 }, { "color": "super-light-blue", "value": 2 } ] }, "unit": "kwatth" }, "overrides": [] }, "gridPos": { "h": 6, "w": 6, "x": 0, "y": 0 }, "id": 13, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showPercentChange": false, "textMode": "value_and_name", "wideLayout": true }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "format": "table", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT \n CASE WHEN $custom_kwh_new > 0 THEN $custom_kwh_new ELSE ('$aux'::json -> 'MaxCapacity')::text::float END as \"Usable (new)\", \n ('$aux'::json -> 'CurrentCapacity')::text::float as \"Usable (now)\",\n ('$aux'::json -> 'CurrentCapacity')::text::float - CASE WHEN $custom_kwh_new > 0 THEN $custom_kwh_new ELSE ('$aux'::json -> 'MaxCapacity')::text::float END as \"Difference\"\n \n \n \n \n \n \n ", "refId": "A", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Battery Capacity", "type": "stat" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "super-light-blue", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/.*_km/" }, "properties": [ { "id": "unit", "value": "lengthkm" } ] }, { "matcher": { "id": "byRegexp", "options": "/.*_mi/" }, "properties": [ { "id": "unit", "value": "lengthmi" } ] }, { "matcher": { "id": "byRegexp", "options": "/maxrange_.*/" }, "properties": [ { "id": "displayName", "value": "Max range (new)" } ] }, { "matcher": { "id": "byRegexp", "options": "/currentrange_.*/" }, "properties": [ { "id": "displayName", "value": "Max range (now)" } ] }, { "matcher": { "id": "byRegexp", "options": "/range_lost.*/" }, "properties": [ { "id": "displayName", "value": "Range lost" } ] } ] }, "gridPos": { "h": 6, "w": 6, "x": 6, "y": 0 }, "id": 14, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showPercentChange": false, "textMode": "value_and_name", "wideLayout": true }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "format": "table", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT \n CASE WHEN $custom_max_range > 0 THEN $custom_max_range ELSE ('$aux'::json -> 'MaxRange')::text::float END as \"maxrange_$length_unit\",\n ('$aux'::json -> 'CurrentRange')::text::float as \"currentrange_$length_unit\",\n CASE WHEN $custom_max_range > 0 THEN $custom_max_range ELSE ('$aux'::json -> 'MaxRange')::text::float END - ('$aux'::json -> 'CurrentRange')::text::float as \"range_lost_$length_unit\"", "refId": "A", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Ranges", "type": "stat" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "\"Logged\" is the distance traveled that is saved on Teslamate database.\n\n\"Mileage\" is the distance the car has traveled since using Teslamate.\n\nSo, if there is a difference between both values, it is the distance that for some reason a drive hasn't been fully recorded, for example due to a bug or an unexpected restart and that Teslamate has not been able to record, either due to lack of connection, areas without signal, or that it has been out of service.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "super-light-blue", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 6, "w": 6, "x": 12, "y": 0 }, "id": 37, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "/.*/", "values": false }, "showPercentChange": false, "textMode": "value_and_name", "wideLayout": true }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "hide": false, "rawQuery": true, "rawSql": "select ROUND(convert_km(sum(distance)::numeric, '$length_unit'),0)|| ' $length_unit' as \"Logged\"\r\nfrom drives \r\nwhere car_id = $car_id;\r\n", "refId": "Looged", "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 } }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "hide": false, "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT ROUND(convert_km((max(odometer) - min(odometer))::numeric, '$length_unit'),0)|| ' $length_unit' as \"Mileage\"\nfrom positions where car_id = $car_id;", "refId": "Mileage", "select": [ [ { "params": ["efficiency"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "cars", "timeColumn": "inserted_at", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "hide": false, "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT ROUND(convert_km(max(odometer)::numeric, '$length_unit'),0) || ' $length_unit' as \"Odometer\"\nfrom positions where car_id = $car_id;", "refId": "Odometer", "select": [ [ { "params": ["efficiency"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "cars", "timeColumn": "inserted_at", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Trips", "type": "stat" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "decimals": 2, "mappings": [], "unit": "kwatth" }, "overrides": [ { "matcher": { "id": "byName", "options": "AC" }, "properties": [ { "id": "color", "value": { "fixedColor": "semi-dark-green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "DC" }, "properties": [ { "id": "color", "value": { "fixedColor": "light-orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 13, "w": 6, "x": 18, "y": 0 }, "id": 34, "maxDataPoints": 3, "options": { "displayLabels": ["name", "percent", "value"], "legend": { "displayMode": "list", "placement": "right", "showLegend": false, "values": ["value"] }, "pieType": "pie", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "8.5.6", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "time_series", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "WITH data AS (\n SELECT\n\t\tcp.id,\n\t\tcp.charge_energy_added,\n\t\tCASE WHEN NULLIF(mode() within group (order by charger_phases),0) is null THEN 'DC'\n\t\t\t\t ELSE 'AC'\n\t\tEND AS current,\n\t\tcp.charge_energy_used\n\tFROM charging_processes cp\n RIGHT JOIN charges ON cp.id = charges.charging_process_id\n WHERE\n\t cp.car_id = $car_id\n\t AND cp.charge_energy_added > 0.01\n GROUP BY 1,2\n)\nSELECT\n\tnow() AS time,\n\tSUM(GREATEST(charge_energy_added, charge_energy_used)) AS value,\n\tcurrent AS metric\nFROM data\nGROUP BY 3\nORDER BY metric DESC;", "refId": "A", "select": [ [ { "params": ["latitude"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "addresses", "timeColumn": "inserted_at", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Summary AC/DC Energy Used", "type": "piechart" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "This dashboard is meant to have a look of the Battery health based on the data logged in Teslamate. So, the more data you have logged from your brand new car the better.\n\n**Degradation** is just an estimated value to have a reference, measured on **usable battery level** of every charging session with enough kWh added (in order to avoid dirty data from the sample), calculated according to the rated efficiency of the car.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "#EAB839", "value": 10 }, { "color": "red", "value": 20 }, { "color": "dark-red", "value": 30 } ] }, "unit": "%" }, "overrides": [] }, "gridPos": { "h": 7, "w": 6, "x": 0, "y": 6 }, "id": 17, "options": { "minVizHeight": 75, "minVizWidth": 75, "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "/^greatest$/", "values": false }, "showThresholdLabels": false, "showThresholdMarkers": true, "sizing": "auto" }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "format": "table", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT GREATEST(0, 100.0 - (('$aux'::json -> 'CurrentCapacity')::text::float * 100.0 / CASE WHEN $custom_kwh_new > 0 THEN $custom_kwh_new ELSE ('$aux'::json -> 'MaxCapacity')::text::float END))\n\n", "refId": "A", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Estimated Degradation", "type": "gauge" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "max": 100, "min": 1, "thresholds": { "mode": "absolute", "steps": [ { "color": "light-red", "value": null }, { "color": "#EAB839", "value": 80 }, { "color": "light-green", "value": 90 } ] }, "unit": "%" }, "overrides": [] }, "gridPos": { "h": 3, "w": 6, "x": 6, "y": 6 }, "id": 12, "options": { "displayMode": "gradient", "maxVizHeight": 300, "minVizHeight": 10, "minVizWidth": 0, "namePlacement": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showUnfilled": true, "sizing": "auto", "valueMode": "color" }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "format": "table", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT \n LEAST(100, (100 - GREATEST(0, 100.0 - (('$aux'::json -> 'CurrentCapacity')::text::float * 100.0 / CASE WHEN $custom_kwh_new > 0 THEN $custom_kwh_new ELSE ('$aux'::json -> 'MaxCapacity')::text::float END)))) as \"Battery Health (%)\"\n \n", "refId": "A", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Battery Health", "type": "bargauge" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "\"Charging cycles\" are estimations based on the whole energy added to the battery.\n\n\"Charge Efficiency\" is estimated on the difference between energy used from the charger and energy added to the battery.", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "light-yellow", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Total energy added" }, "properties": [ { "id": "unit", "value": "kwatth" } ] }, { "matcher": { "id": "byName", "options": "Total energy used" }, "properties": [ { "id": "unit", "value": "kwatth" } ] }, { "matcher": { "id": "byName", "options": "Charge Efficiency" }, "properties": [ { "id": "unit", "value": "percent" } ] } ] }, "gridPos": { "h": 7, "w": 6, "x": 12, "y": 6 }, "id": 36, "maxDataPoints": 100, "options": { "colorMode": "value", "fieldOptions": { "calcs": ["mean"] }, "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["mean"], "fields": "", "values": false }, "showPercentChange": false, "textMode": "value_and_name", "wideLayout": true }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "hide": false, "rawQuery": true, "rawSql": "SELECT\r\n\tCOUNT(*) AS \"Total charges\"\r\nFROM\r\n\tcharging_processes\r\nWHERE\r\n\tcar_id = $car_id AND charge_energy_added > 0.01\r\n\t", "refId": "Total charges", "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 } }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "hide": false, "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT\n\tfloor(sum(charge_energy_added) / CASE WHEN $custom_kwh_new > 0 THEN $custom_kwh_new ELSE ('$aux'::json -> 'MaxCapacity')::text::float END) AS \"Charging cycles\"\nFROM charging_processes WHERE car_id = $car_id AND charge_energy_added > 0.01", "refId": "Charging cycles", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT\n\tsum(charge_energy_added) as \"Total energy added\"\nFROM\n\tcharging_processes\nWHERE\n\tcar_id = $car_id AND charge_energy_added > 0.01", "refId": "Total energy added", "select": [ [ { "params": ["efficiency"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "cars", "timeColumn": "inserted_at", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "hide": false, "rawQuery": true, "rawSql": "SELECT\r\n\tSUM(charge_energy_used) AS \"Total energy used\"\r\nFROM\r\n\tcharging_processes\r\nWHERE\r\n\tcar_id = $car_id AND charge_energy_added > 0.01\r\n", "refId": "Total energy used", "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 } }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "hide": false, "rawQuery": true, "rawSql": "SELECT\r\n\tSUM(charge_energy_added) * 100 / SUM(charge_energy_used) AS \"Charge Efficiency\"\r\nFROM\r\n\tcharging_processes\r\nWHERE\r\n\tcar_id = $car_id AND charge_energy_added > 0.01\r\n", "refId": "Charge Efficiency", "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 } } ], "title": "Battery Stats", "type": "stat" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "dark-red", "value": null }, { "color": "semi-dark-green", "value": 20 }, { "color": "semi-dark-orange", "value": 80 }, { "color": "light-blue", "value": 100 } ] }, "unit": "%" }, "overrides": [] }, "gridPos": { "h": 2, "w": 4, "x": 6, "y": 9 }, "id": 25, "options": { "displayMode": "lcd", "maxVizHeight": 300, "minVizHeight": 10, "minVizWidth": 0, "namePlacement": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showUnfilled": true, "sizing": "auto", "text": {}, "valueMode": "color" }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "format": "table", "group": [], "groupBy": [ { "params": ["$__interval"], "type": "time" }, { "params": ["null"], "type": "fill" } ], "measurement": "%", "metricColumn": "none", "orderByTime": "ASC", "policy": "default", "rawQuery": true, "rawSql": "SELECT * FROM ((SELECT usable_battery_level, date\r\nFROM positions\r\nWHERE car_id = $car_id AND usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)\r\nUNION\r\n(SELECT usable_battery_level, date\r\nFROM charges c\r\nJOIN charging_processes p ON p.id = c.charging_process_id\r\nWHERE p.car_id = $car_id AND usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)) AS last_usable_battery_level LIMIT 1", "refId": "SOC", "resultFormat": "time_series", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Current SOC", "type": "bargauge" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "This is the Derived Rated Efficiency that TeslaMate calculates based on battery charges. \nThis information can be seen in more detail on the \"Efficiency\" dashboard.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 0, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "super-light-blue", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/.*_km/" }, "properties": [ { "id": "unit", "value": "Wh/km" } ] }, { "matcher": { "id": "byRegexp", "options": "/.*_mi/" }, "properties": [ { "id": "unit", "value": "Wh/mi" } ] } ] }, "gridPos": { "h": 4, "w": 2, "x": 10, "y": 9 }, "id": 32, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "/.*/", "values": false }, "showPercentChange": false, "textMode": "value", "wideLayout": true }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "hide": false, "rawQuery": true, "rawSql": "SELECT ('$aux'::json -> 'RatedEfficiency')::text::float * \r\n CASE \r\n WHEN '$length_unit' = 'km' THEN 10\r\n WHEN '$length_unit' = 'mi' THEN 16.0934 \r\n END AS efficiency_$length_unit", "refId": "Looged", "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 } } ], "title": "Efficiency", "type": "stat" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "decimals": 1, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "dark-red", "value": null }, { "color": "dark-green", "value": 7.84 }, { "color": "semi-dark-orange", "value": 31.36 }, { "color": "light-blue", "value": 35.28 } ] }, "unit": "kwatth" }, "overrides": [] }, "gridPos": { "h": 2, "w": 4, "x": 6, "y": 11 }, "id": 27, "options": { "displayMode": "gradient", "maxVizHeight": 300, "minVizHeight": 10, "minVizWidth": 0, "namePlacement": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "/^kwh$/", "values": false }, "showUnfilled": true, "sizing": "auto", "text": {}, "valueMode": "color" }, "pluginVersion": "10.4.0", "targets": [ { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "groupBy": [ { "params": ["$__interval"], "type": "time" }, { "params": ["null"], "type": "fill" } ], "measurement": "%", "metricColumn": "none", "orderByTime": "ASC", "policy": "default", "rawQuery": true, "rawSql": "SELECT * FROM ((SELECT usable_battery_level * ('$aux'::json -> 'CurrentCapacity')::text::float / 100 as kWh, date, ('$aux'::json -> 'CurrentCapacity')::text::float as Total\nFROM positions\nWHERE car_id = $car_id AND usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)\nUNION\n(SELECT battery_level * ('$aux'::json -> 'CurrentCapacity')::text::float / 100 as kWh, date, ('$aux'::json -> 'CurrentCapacity')::text::float as Total\nFROM charges c\nJOIN charging_processes p ON p.id = c.charging_process_id\nWHERE p.car_id = $car_id AND usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)) AS last_usable_battery_level LIMIT 1", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Current Capacity", "type": "bargauge" }, { "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "fieldConfig": { "defaults": { "color": { "mode": "continuous-RdYlGr" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "pointSize": { "fixed": 6 }, "scaleDistribution": { "type": "linear" }, "show": "points" }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "Median" }, "properties": [ { "id": "custom.lineWidth", "value": 2 }, { "id": "custom.show", "value": "lines" } ] } ] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 13 }, "id": 28, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "series": [ { "name": "Odometer", "pointColor": { "field": "kWh" }, "pointSize": { "fixed": 5, "max": 100, "min": 1 }, "x": "odometer", "y": "kWh" }, { "name": "Median Odometer", "pointColor": { "fixed": "dark-red" }, "x": "M-Odometer", "y": "M-kWh" } ], "seriesMapping": "manual", "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "8.5.6", "targets": [ { "alias": "", "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "hide": false, "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT convert_km(AVG(p.odometer)::numeric,'$length_unit') AS odometer, \r\n\tAVG(c.rated_battery_range_km * ('$aux'::json -> 'RatedEfficiency')::text::float / c.usable_battery_level) AS \"kWh\",\r\n\tMAX(cp.id) AS id,\r\n\tto_char(cp.end_date, 'YYYY-MM-dd') AS Title\r\n\tFROM charging_processes cp\r\n\t\tJOIN (SELECT charging_process_id, MAX(date) as date\tFROM charges WHERE usable_battery_level > 0 GROUP BY charging_process_id) AS last_charges\tON cp.id = last_charges.charging_process_id\r\n\t\tINNER JOIN charges c\r\n\t\tON c.charging_process_id = cp.id AND c.date = last_charges.date\r\n\t\tINNER JOIN positions p ON p.id = cp.position_id\r\n\tWHERE cp.car_id = $car_id\r\n\t\tAND cp.end_date IS NOT NULL\r\n\t\tAND cp.charge_energy_added >= ('$aux'::json -> 'RatedEfficiency')::text::float\r\n\tGROUP BY 4", "refId": "Projected Range", "select": [ [ { "params": ["value"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "timeColumn": "time", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] }, { "alias": "", "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "editorMode": "code", "format": "table", "group": [], "hide": false, "metricColumn": "none", "rawQuery": true, "rawSql": "SELECT \n ROUND(MIN(convert_km(p.odometer::numeric,'$length_unit')),0) AS \"M-Odometer\",\n\tROUND(PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY c.rated_battery_range_km * ('$aux'::json -> 'RatedEfficiency')::text::float / c.usable_battery_level)::numeric,1) AS \"M-kWh\",\n\tto_char(cp.end_date, 'YYYYMM') || CASE WHEN to_char(cp.end_date, 'DD')::int <= 15 THEN '1' ELSE '2' END AS Title\n\tFROM charging_processes cp\n\t\tJOIN (SELECT charging_process_id, MAX(date) as date\tFROM charges WHERE usable_battery_level > 0 GROUP BY charging_process_id) AS last_charges\tON cp.id = last_charges.charging_process_id\n\t\tINNER JOIN charges c\n\t\tON c.charging_process_id = cp.id AND c.date = last_charges.date\n\t\tINNER JOIN positions p ON p.id = cp.position_id\n\tWHERE cp.car_id = $car_id\n\t\tAND cp.end_date IS NOT NULL\n\t\tAND cp.charge_energy_added >= ('$aux'::json -> 'RatedEfficiency')::text::float\n\tGROUP BY 3", "refId": "Median", "select": [ [ { "params": ["start_km"], "type": "column" } ] ], "sql": { "columns": [ { "parameters": [], "type": "function" } ], "groupBy": [ { "property": { "type": "string" }, "type": "groupBy" } ], "limit": 50 }, "table": "drives", "timeColumn": "start_date", "timeColumnType": "timestamp", "where": [ { "name": "$__timeFilter", "params": [], "type": "macro" } ] } ], "title": "Battery Capacity by Mileage", "type": "xychart" } ], "refresh": "", "schemaVersion": 39, "tags": ["TeslamateCustomDashboards"], "templating": { "list": [ { "current": {}, "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "definition": "SELECT name AS __text, id AS __value FROM cars ORDER BY display_priority ASC, name ASC", "hide": 0, "includeAll": false, "label": "Car", "multi": false, "name": "car_id", "options": [], "query": "SELECT name AS __text, id AS __value FROM cars ORDER BY display_priority ASC, name ASC", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false }, { "current": {}, "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "definition": "SELECT unit_of_length FROM settings LIMIT 1", "hide": 2, "includeAll": false, "label": "", "multi": false, "name": "length_unit", "options": [], "query": "SELECT unit_of_length FROM settings LIMIT 1", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false }, { "current": {}, "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "definition": "SELECT preferred_range FROM settings LIMIT 1", "hide": 2, "includeAll": false, "multi": false, "name": "preferred_range", "options": [], "query": "SELECT preferred_range FROM settings LIMIT 1", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "type": "query" }, { "current": {}, "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "definition": "SELECT base_url FROM settings LIMIT 1", "hide": 2, "includeAll": false, "label": "", "multi": false, "name": "base_url", "options": [], "query": "SELECT base_url FROM settings LIMIT 1", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false }, { "current": {}, "datasource": { "type": "grafana-postgresql-datasource", "uid": "TeslaMate" }, "definition": "-- CONCATENATED JOIN QUERIES TO IMPROVE PERFORMANCE\n-- The following query is the result of many tests and hours of work. This panel is for your own personal use. \n-- If you think you can improve it and contribute, please create a pull request and do not take it to your repository, \n-- much less upload it to another repository as if the original idea were yours, nor do you share it on social media\n-- without mentioning the author. Respect the ingenuity and work of others. Cheers!\n-- 2024-03-19\n-- By @jheredianet - Twitter: @juanheredia", "hide": 2, "includeAll": false, "multi": false, "name": "aux", "options": [], "query": "WITH Aux AS\n(\n\t\tSELECT \n car_id,\n\t\tCOALESCE(efficiency, \n\t\t(SELECT efficiency\n\t\t\tFROM cars WHERE id = $car_id) * 100) AS efficiency\n\tFROM (\n\t\tSELECT ROUND((charge_energy_added / NULLIF(end_rated_range_km - start_rated_range_km, 0))::numeric, 3) * 100 as efficiency,\n\t\t\tCOUNT(*) as count, $car_id AS car_id \n\t\tFROM charging_processes\n\t\tWHERE car_id = $car_id\n\t\t\tAND duration_min > 10\n\t\t\tAND end_battery_level <= 95\n\t\t\tAND start_rated_range_km IS NOT NULL\n\t\t\tAND end_rated_range_km IS NOT NULL\n\t\t\tAND charge_energy_added > 0\n\t\tGROUP BY 1\n\t\tORDER BY 2 DESC\n\t\tLIMIT 1\n\t) AS DerivatedEfficiency\n),\nCurrentCapacity\t AS\n(\n\tSELECT AVG(Capacity) AS Capacity\nFROM (\nSELECT \n\tc.[[preferred_range]]_battery_range_km * aux.efficiency / c.usable_battery_level AS Capacity\n\tFROM charging_processes cp\n\t\tINNER JOIN charges c\n\t\tON c.charging_process_id = cp.id \n INNER JOIN aux ON cp.car_id = aux.car_id\n\tWHERE cp.car_id = $car_id\n\t\tAND cp.end_date IS NOT NULL\n\t\tAND cp.charge_energy_added >= aux.efficiency\n\t\tAND c.usable_battery_level > 0\n\t ORDER BY cp.end_date DESC LIMIT 10) AS lastCharges\n), \nMaxCapacity AS\n(\n\tSELECT \n\t\tMAX(c.[[preferred_range]]_battery_range_km * aux.efficiency / c.usable_battery_level) AS Capacity\n\tFROM charging_processes cp\n\t\tINNER JOIN (\n\t\t\tSELECT charging_process_id, MAX(date) as date FROM charges WHERE usable_battery_level > 0 GROUP BY charging_process_id) AS gcharges\t\n\t\t\tON cp.id = gcharges.charging_process_id\n\t\tINNER JOIN charges c\n\t\tON c.charging_process_id = cp.id AND c.date = gcharges.date\n\t\tINNER JOIN aux ON cp.car_id = aux.car_id\n\tWHERE cp.car_id = $car_id\n\t\tAND cp.end_date IS NOT NULL\n\t\tAND cp.charge_energy_added >= aux.efficiency\n), \nCurrentRange AS\n(\n SELECT (range * 100.0 / usable_battery_level) AS range\n\tFROM (\n\t\t(SELECT date, [[preferred_range]]_battery_range_km AS range, usable_battery_level AS usable_battery_level\n\t\t\tFROM positions\tWHERE car_id = $car_id AND [[preferred_range]]_battery_range_km IS NOT NULL AND usable_battery_level > 0 ORDER BY date DESC LIMIT 1)\n\t\tUNION ALL\n\t\t(SELECT date, [[preferred_range]]_battery_range_km AS range, usable_battery_level as usable_battery_level\n\t\t\tFROM charges c JOIN charging_processes p ON p.id = c.charging_process_id\n\t\t\tWHERE p.car_id = $car_id AND usable_battery_level > 0 ORDER BY date DESC LIMIT 1)\n\t) AS data\n\tORDER BY date DESC\n\tLIMIT 1\n), \nMaxRange AS\n(\n SELECT\n\t\tfloor(extract(epoch from date)/86400)*86400 AS time,\n\t CASE WHEN sum(usable_battery_level) = 0 THEN sum([[preferred_range]]_battery_range_km) * 100\n\t\t ELSE sum([[preferred_range]]_battery_range_km) / sum(usable_battery_level) * 100\n\tEND AS range\n FROM (\n\t\tSELECT battery_level, usable_battery_level, date, [[preferred_range]]_battery_range_km from charges c \n\t\tJOIN charging_processes p ON p.id = c.charging_process_id \n\t\tWHERE p.car_id = $car_id AND usable_battery_level IS NOT NULL) AS data\n\tGROUP BY 1\n\tORDER BY 2 DESC\n\tLIMIT 1\n) \nSELECT CONCAT('{\"MaxRange\": ', convert_km(MaxRange.range,'$length_unit'),\n ', \"CurrentRange\": ',convert_km(CurrentRange.range,'$length_unit'),\n ', \"MaxCapacity\": ', MaxCapacity.Capacity,\n ', \"CurrentCapacity\": ', CASE WHEN CurrentCapacity.Capacity IS NULL THEN 1 ELSE CurrentCapacity.Capacity END,\n ', \"RatedEfficiency\": ', aux.efficiency, '}') \nFROM MaxRange, CurrentRange, Aux, MaxCapacity, CurrentCapacity", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "type": "query" }, { "current": { "selected": false, "text": "0", "value": "0" }, "description": "Set the capacity of your car battery when it was new, in case you started using Teslamate after a while of having it. If not, leave it at 0, it will be calculated with the data that is logged in Teslamate", "hide": 0, "label": "Custom Battery Capacity (kWh) when new", "name": "custom_kwh_new", "options": [ { "selected": true, "text": "0", "value": "0" } ], "query": "0", "skipUrlSync": false, "type": "textbox" }, { "current": { "selected": false, "text": "0", "value": "0" }, "description": "Set the max range to 100% of your car when it was new, in case you started using Teslamate after a while of having it. If not, leave it at 0, the degradation will be calculated with the data that is logged in Teslamate", "hide": 0, "label": "Custom Max Range when new", "name": "custom_max_range", "options": [ { "selected": true, "text": "0", "value": "0" } ], "query": "0", "skipUrlSync": false, "type": "textbox" } ] }, "timepicker": { "hidden": true }, "timezone": "browser", "title": "Battery Health V2", "uid": "jchmRiqUfXgRx", "version": 23, "weekStart": "" }