From b486c4a992a071e9bdcab172ef476eb9327bcf86 Mon Sep 17 00:00:00 2001 From: pencilheart <495474804@qq.com> Date: Wed, 4 Mar 2026 23:13:07 +0800 Subject: [PATCH 1/3] add "day-trips.json" in dashboards --- grafana/dashboards/day-trips.json | 733 ++++++++++++++++++++++++++++++ 1 file changed, 733 insertions(+) create mode 100644 grafana/dashboards/day-trips.json diff --git a/grafana/dashboards/day-trips.json b/grafana/dashboards/day-trips.json new file mode 100644 index 0000000000..02a5bae2d4 --- /dev/null +++ b/grafana/dashboards/day-trips.json @@ -0,0 +1,733 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "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": "" + } + ], + "panels": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "description": "This dashboard provides a daily summary table of your trips, making it easy to compare driving distance, duration, energy use, and efficiency day by day.\n\nEach row represents a day-level record, and you can sort or filter to quickly find the longest, shortest, or least efficient days.\n\nYou can also jump to the Trips dashboard for detailed trip-level analysis via the link in the first column.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "footer": { + "reducers": [] + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "start_date" + }, + "properties": [ + { + "id": "displayName", + "value": "Start Date" + }, + { + "id": "unit", + "value": "dateTimeAsLocal" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "View Trip details", + "url": "d/zm7wN6Zgz/drive-details?from=${__data.fields.start_date.numeric}&to=${__data.fields.end_date.numeric}" + } + ] + }, + { + "id": "custom.minWidth", + "value": 180 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "distance_km" + }, + "properties": [ + { + "id": "displayName", + "value": "Distance" + }, + { + "id": "unit", + "value": "km" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.minWidth", + "value": 150 + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-BlPu" + } + }, + { + "id": "max", + "value": 400 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "end_date" + }, + "properties": [ + { + "id": "custom.minWidth", + "value": 180 + }, + { + "id": "displayName", + "value": "End Date" + }, + { + "id": "unit", + "value": "dateTimeAsLocal" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "duration_sec" + }, + "properties": [ + { + "id": "displayName", + "value": "Duration" + }, + { + "id": "unit", + "value": "clocks" + }, + { + "id": "custom.width", + "value": 80 + }, + { + "id": "decimals", + "value": 1 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "speed_km" + }, + "properties": [ + { + "id": "displayName", + "value": "Ø Speed" + }, + { + "id": "custom.width", + "value": 100 + }, + { + "id": "unit", + "value": "velocitykmh" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "text", + "value": 0 + }, + { + "color": "green", + "value": 40 + } + ] + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*_ts/" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.hideFrom.viz", + "value": true + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/%/" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.width", + "value": 75 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "avg_temp_c" + }, + "properties": [ + { + "id": "displayName", + "value": "Temp" + }, + { + "id": "unit", + "value": "celsius" + }, + { + "id": "custom.width", + "value": 75 + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consumption_wh_per_km_gross" + }, + "properties": [ + { + "id": "unit", + "value": "Wh/km" + }, + { + "id": "custom.width", + "value": 120 + }, + { + "id": "displayName", + "value": "Ø Gross Consumption" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consumption_wh_per_km_net" + }, + "properties": [ + { + "id": "unit", + "value": "Wh/km" + }, + { + "id": "custom.width", + "value": 120 + }, + { + "id": "displayName", + "value": "Ø Net Consumption" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consumption_total_kwh" + }, + "properties": [ + { + "id": "displayName", + "value": "Energy consumed (gross)" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.minWidth", + "value": 150 + }, + { + "id": "unit", + "value": "kWh" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "gauge" + } + }, + { + "id": "max", + "value": 70 + }, + { + "id": "color", + "value": { + "mode": "continuous-GrYlRd" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "gross_efficiency" + }, + "properties": [ + { + "id": "displayName", + "value": "Gross Efficiency" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "max", + "value": 1 + }, + { + "id": "min", + "value": 0 + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "net_efficiency" + }, + "properties": [ + { + "id": "displayName", + "value": "Net Efficiency" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "gauge" + } + }, + { + "id": "max", + "value": 1 + }, + { + "id": "min", + "value": 0 + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consume_percent" + }, + "properties": [ + { + "id": "displayName", + "value": "-%" + }, + { + "id": "custom.width", + "value": 55 + }, + { + "id": "decimals", + "value": 0 + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "text", + "value": 0 + }, + { + "color": "green", + "value": 59 + } + ] + } + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "unit", + "value": "percent" + } + ] + } + ] + }, + "gridPos": { + "h": 30, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "cellHeight": "sm", + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "12.4.0", + "targets": [ + { + "alias": "", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "editorMode": "code", + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "WITH car_efficiency AS (\r\n SELECT id, efficiency FROM cars WHERE id = 1\r\n),\r\n\r\nAux AS (\r\n SELECT car_id,\r\n COALESCE(efficiency, \r\n (SELECT efficiency FROM cars WHERE id = 1) * 100) AS efficiency\r\n FROM (\r\n SELECT \r\n ROUND((charge_energy_added / NULLIF(end_rated_range_km - start_rated_range_km, 0))::numeric, 3) * 100 as efficiency,\r\n COUNT(*) as count, 1 AS car_id\r\n FROM charging_processes\r\n WHERE car_id = 1\r\n AND duration_min > 10\r\n AND end_battery_level <= 95\r\n AND start_rated_range_km IS NOT NULL\r\n AND end_rated_range_km IS NOT NULL\r\n AND charge_energy_added > 0\r\n GROUP BY 1\r\n ORDER BY 2 DESC\r\n LIMIT 1\r\n ) AS DerivatedEfficiency\r\n),\r\n\r\nCurrentCapacity AS (\r\n SELECT AVG(Capacity) AS CurrentCapacity \r\n FROM (\r\n SELECT \r\n c.ideal_battery_range_km * aux.efficiency / c.usable_battery_level AS Capacity \r\n FROM charging_processes cp\r\n INNER JOIN charges c ON c.charging_process_id = cp.id \r\n INNER JOIN aux ON cp.car_id = aux.car_id\r\n WHERE cp.car_id = 1\r\n AND cp.end_date IS NOT NULL\r\n AND cp.charge_energy_added >= aux.efficiency\r\n AND c.usable_battery_level > 0\r\n ORDER BY cp.end_date DESC, c.date DESC \r\n LIMIT 100\r\n ) AS lastCharges\r\n),\r\n\r\ntrip AS (\r\n SELECT \r\n DATE(d.start_date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone') AS trip_date,\r\n MIN(d.start_date) AS start_date,\r\n MAX(d.end_date) AS end_date,\r\n SUM(d.distance) AS distance_km,\r\n SUM(d.duration_min) AS duration_min,\r\n AVG(d.outside_temp_avg) AS avg_temp_C,\r\n SUM(d.start_ideal_range_km - d.end_ideal_range_km) AS range_drop_km_net,\r\n SUM(d.start_ideal_range_km - d.end_ideal_range_km) * (SELECT efficiency FROM car_efficiency) AS consumption_total_kWh_net\r\n FROM drives d\r\n WHERE d.car_id = 1\r\n AND $__timeFilter(d.start_date)\r\n AND d.end_date IS NOT NULL\r\n AND d.duration_min > 0\r\n GROUP BY DATE(d.start_date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone')\r\n),\r\n\r\ndrives_start_event AS (\r\n SELECT 'drive_start' AS event, \r\n start_date AS date, \r\n start_ideal_range_km AS range, \r\n start_km AS odometer, \r\n car_id\r\n FROM drives\r\n WHERE car_id = 1 AND $__timeFilter(start_date)\r\n),\r\n\r\ndrives_end_event AS (\r\n SELECT 'drive_end' AS event, \r\n end_date AS date, \r\n end_ideal_range_km AS range, \r\n end_km AS odometer, \r\n car_id\r\n FROM drives\r\n WHERE car_id = 1 AND $__timeFilter(end_date)\r\n),\r\n\r\ncharging_processes_start_event AS (\r\n SELECT 'charging_process_start' AS event, \r\n cp.start_date AS date, \r\n p.ideal_battery_range_km AS range, \r\n p.odometer, \r\n cp.car_id\r\n FROM charging_processes cp\r\n INNER JOIN positions p ON cp.position_id = p.id\r\n WHERE cp.car_id = 1 AND $__timeFilter(cp.start_date)\r\n),\r\n\r\ncharging_processes_end_event AS (\r\n SELECT 'charging_process_end' AS event, \r\n cp.end_date AS date, \r\n p.ideal_battery_range_km AS range, \r\n p.odometer, \r\n cp.car_id\r\n FROM charging_processes cp\r\n INNER JOIN positions p ON cp.position_id = p.id\r\n WHERE cp.car_id = 1 AND $__timeFilter(cp.end_date)\r\n),\r\n\r\npositions_events AS (\r\n SELECT \r\n CASE WHEN drive_id IS NOT NULL AND LEAD(drive_id) OVER w IS NOT NULL THEN 'drive_start' ELSE 'other' END AS event,\r\n date,\r\n ideal_battery_range_km AS range,\r\n odometer,\r\n car_id\r\n FROM positions\r\n WHERE ideal_battery_range_km IS NOT NULL AND car_id = 1 AND $__timeFilter(date)\r\n WINDOW w AS (ORDER BY date)\r\n),\r\n\r\ncombined AS (\r\n SELECT * FROM drives_start_event\r\n UNION ALL\r\n SELECT * FROM drives_end_event\r\n UNION ALL\r\n SELECT * FROM charging_processes_start_event\r\n UNION ALL\r\n SELECT * FROM charging_processes_end_event\r\n UNION ALL\r\n SELECT * FROM positions_events\r\n),\r\n\r\nfinal_events_marked AS (\r\n SELECT\r\n *,\r\n ROW_NUMBER() OVER (PARTITION BY car_id ORDER BY date) AS rn\r\n FROM combined\r\n),\r\n\r\nfinal_events_filtered AS (\r\n SELECT\r\n car_id,\r\n date,\r\n odometer,\r\n range,\r\n LEAD(odometer) OVER w AS next_odometer,\r\n LEAD(range) OVER w AS next_range,\r\n DATE(date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone') AS trip_date,\r\n CASE \r\n WHEN event != 'drive_start' THEN GREATEST(range - LEAD(range) OVER w, 0)\r\n ELSE range - LEAD(range) OVER w\r\n END AS range_loss\r\n FROM final_events_marked\r\n WHERE event NOT IN ('charging_process_start', 'charging_process_end')\r\n WINDOW w AS (PARTITION BY car_id ORDER BY date)\r\n),\r\n\r\ndaily_energy_by_event AS (\r\n SELECT\r\n trip_date,\r\n SUM(range_loss) AS total_range_loss\r\n FROM final_events_filtered\r\n WHERE range_loss IS NOT NULL\r\n GROUP BY trip_date\r\n),\r\n\r\ndaily_energy_kwh AS (\r\n SELECT\r\n e.trip_date,\r\n e.total_range_loss * (SELECT efficiency FROM car_efficiency) AS consumption_total_kWh_gross\r\n FROM daily_energy_by_event e\r\n)\r\n\r\nSELECT\r\n t.start_date,\r\n t.end_date,\r\n t.distance_km,\r\n t.duration_min * 60 AS duration_sec,\r\n (t.distance_km / NULLIF(t.duration_min, 0) * 60) AS speed_km,\r\n t.avg_temp_C,\r\n d.consumption_total_kWh_gross AS consumption_total_kWh,\r\n (d.consumption_total_kWh_gross / cc.CurrentCapacity)*100 AS consume_percent,\r\n (t.consumption_total_kWh_net * 1000 / NULLIF(t.distance_km, 0)) AS consumption_Wh_per_km_net,\r\n t.distance_km / nullif(t.consumption_total_kWh_net/(SELECT efficiency FROM car_efficiency), 0) as net_efficiency,\r\n (d.consumption_total_kWh_gross * 1000 / NULLIF(t.distance_km, 0)) AS consumption_Wh_per_km_gross,\r\n t.distance_km / nullif(d.consumption_total_kWh_gross/(SELECT efficiency FROM car_efficiency), 0) as gross_efficiency\r\nFROM trip t\r\nLEFT JOIN daily_energy_kwh d ON t.trip_date = d.trip_date\r\nCROSS JOIN CurrentCapacity cc\r\nWHERE distance_$length_unit >= $min_dist AND (distance_$length_unit / duration_min * 60) >= $min_avg_speed\r\nORDER BY t.trip_date DESC;\r\n", + "refId": "A", + "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" + } + ] + } + ], + "title": "Day Trips", + "type": "table" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "tags": [ + "TeslamateCustomDashboards" + ], + "templating": { + "list": [ + { + "current": {}, + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "definition": "SELECT\n id as __value,\n CASE WHEN COUNT(id) OVER (PARTITION BY name) > 1 AND name IS NOT NULL THEN CONCAT(name, ' - ', RIGHT(vin, 6)) ELSE COALESCE(name, CONCAT('VIN ', vin)) end as __text \nFROM cars\nORDER BY display_priority ASC, name ASC, vin ASC", + "includeAll": false, + "label": "Car", + "name": "car_id", + "options": [], + "query": "SELECT\n id as __value,\n CASE WHEN COUNT(id) OVER (PARTITION BY name) > 1 AND name IS NOT NULL THEN CONCAT(name, ' - ', RIGHT(vin, 6)) ELSE COALESCE(name, CONCAT('VIN ', vin)) end as __text \nFROM cars\nORDER BY display_priority ASC, name ASC, vin ASC", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "definition": "SELECT unit_of_length FROM settings limit 1", + "hide": 2, + "includeAll": false, + "label": "length unit", + "name": "length_unit", + "options": [], + "query": "SELECT unit_of_length FROM settings limit 1", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "definition": "SELECT base_url FROM settings LIMIT 1", + "hide": 2, + "includeAll": false, + "name": "base_url", + "options": [], + "query": "SELECT base_url FROM settings LIMIT 1", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "definition": "SELECT preferred_range FROM settings LIMIT 1", + "hide": 2, + "includeAll": false, + "name": "preferred_range", + "options": [], + "query": "SELECT preferred_range FROM settings LIMIT 1", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "TeslaMate" + }, + "definition": "SELECT unit_of_temperature FROM settings LIMIT 1", + "hide": 2, + "includeAll": false, + "name": "temp_unit", + "options": [], + "query": "SELECT unit_of_temperature FROM settings LIMIT 1", + "refresh": 1, + "regex": "", + "regexApplyTo": "value", + "type": "query" + }, + { + "current": { + "text": "0", + "value": "0" + }, + "label": "Distance >=", + "name": "min_dist", + "options": [ + { + "selected": true, + "text": "0", + "value": "0" + } + ], + "query": "0", + "type": "textbox" + }, + { + "current": { + "text": "0", + "value": "0" + }, + "label": "Avg Speed >=", + "name": "min_avg_speed", + "options": [ + { + "selected": true, + "text": "0", + "value": "0" + } + ], + "query": "0", + "type": "textbox" + } + ] + }, + "time": { + "from": "now/y", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Day Trips", + "uid": "jchmY8upc6ZRj", + "version": 1, + "weekStart": "" +} From e659b3f9889ced5fc4479075d5f97f0c3dcbfbeb Mon Sep 17 00:00:00 2001 From: pencilheart <495474804@qq.com> Date: Tue, 10 Mar 2026 21:57:49 +0800 Subject: [PATCH 2/3] update "statistics.json" --- grafana/dashboards/day-trips.json | 733 ----------------------------- grafana/dashboards/statistics.json | 27 +- 2 files changed, 26 insertions(+), 734 deletions(-) delete mode 100644 grafana/dashboards/day-trips.json diff --git a/grafana/dashboards/day-trips.json b/grafana/dashboards/day-trips.json deleted file mode 100644 index 02a5bae2d4..0000000000 --- a/grafana/dashboards/day-trips.json +++ /dev/null @@ -1,733 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1, - "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": "" - } - ], - "panels": [ - { - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "description": "This dashboard provides a daily summary table of your trips, making it easy to compare driving distance, duration, energy use, and efficiency day by day.\n\nEach row represents a day-level record, and you can sort or filter to quickly find the longest, shortest, or least efficient days.\n\nYou can also jump to the Trips dashboard for detailed trip-level analysis via the link in the first column.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "filterable": false, - "footer": { - "reducers": [] - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": 0 - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "start_date" - }, - "properties": [ - { - "id": "displayName", - "value": "Start Date" - }, - { - "id": "unit", - "value": "dateTimeAsLocal" - }, - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "View Trip details", - "url": "d/zm7wN6Zgz/drive-details?from=${__data.fields.start_date.numeric}&to=${__data.fields.end_date.numeric}" - } - ] - }, - { - "id": "custom.minWidth", - "value": 180 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "distance_km" - }, - "properties": [ - { - "id": "displayName", - "value": "Distance" - }, - { - "id": "unit", - "value": "km" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.minWidth", - "value": 150 - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "gauge" - } - }, - { - "id": "color", - "value": { - "mode": "continuous-BlPu" - } - }, - { - "id": "max", - "value": 400 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "end_date" - }, - "properties": [ - { - "id": "custom.minWidth", - "value": 180 - }, - { - "id": "displayName", - "value": "End Date" - }, - { - "id": "unit", - "value": "dateTimeAsLocal" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "duration_sec" - }, - "properties": [ - { - "id": "displayName", - "value": "Duration" - }, - { - "id": "unit", - "value": "clocks" - }, - { - "id": "custom.width", - "value": 80 - }, - { - "id": "decimals", - "value": 1 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "speed_km" - }, - "properties": [ - { - "id": "displayName", - "value": "Ø Speed" - }, - { - "id": "custom.width", - "value": 100 - }, - { - "id": "unit", - "value": "velocitykmh" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "text", - "value": 0 - }, - { - "color": "green", - "value": 40 - } - ] - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*_ts/" - }, - "properties": [ - { - "id": "unit", - "value": "short" - }, - { - "id": "decimals", - "value": 2 - }, - { - "id": "custom.hideFrom.viz", - "value": true - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/%/" - }, - "properties": [ - { - "id": "unit", - "value": "percent" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.width", - "value": 75 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "avg_temp_c" - }, - "properties": [ - { - "id": "displayName", - "value": "Temp" - }, - { - "id": "unit", - "value": "celsius" - }, - { - "id": "custom.width", - "value": 75 - }, - { - "id": "decimals", - "value": 0 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "consumption_wh_per_km_gross" - }, - "properties": [ - { - "id": "unit", - "value": "Wh/km" - }, - { - "id": "custom.width", - "value": 120 - }, - { - "id": "displayName", - "value": "Ø Gross Consumption" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "consumption_wh_per_km_net" - }, - "properties": [ - { - "id": "unit", - "value": "Wh/km" - }, - { - "id": "custom.width", - "value": 120 - }, - { - "id": "displayName", - "value": "Ø Net Consumption" - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "consumption_total_kwh" - }, - "properties": [ - { - "id": "displayName", - "value": "Energy consumed (gross)" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.minWidth", - "value": 150 - }, - { - "id": "unit", - "value": "kWh" - }, - { - "id": "custom.cellOptions", - "value": { - "type": "gauge" - } - }, - { - "id": "max", - "value": 70 - }, - { - "id": "color", - "value": { - "mode": "continuous-GrYlRd" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "gross_efficiency" - }, - "properties": [ - { - "id": "displayName", - "value": "Gross Efficiency" - }, - { - "id": "unit", - "value": "percentunit" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "basic", - "type": "gauge" - } - }, - { - "id": "max", - "value": 1 - }, - { - "id": "min", - "value": 0 - }, - { - "id": "color", - "value": { - "mode": "continuous-RdYlGr" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "net_efficiency" - }, - "properties": [ - { - "id": "displayName", - "value": "Net Efficiency" - }, - { - "id": "unit", - "value": "percentunit" - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "basic", - "type": "gauge" - } - }, - { - "id": "max", - "value": 1 - }, - { - "id": "min", - "value": 0 - }, - { - "id": "color", - "value": { - "mode": "continuous-RdYlGr" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "consume_percent" - }, - "properties": [ - { - "id": "displayName", - "value": "-%" - }, - { - "id": "custom.width", - "value": 55 - }, - { - "id": "decimals", - "value": 0 - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "text", - "value": 0 - }, - { - "color": "green", - "value": 59 - } - ] - } - }, - { - "id": "custom.cellOptions", - "value": { - "type": "color-text" - } - }, - { - "id": "unit", - "value": "percent" - } - ] - } - ] - }, - "gridPos": { - "h": 30, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "cellHeight": "sm", - "showHeader": true, - "sortBy": [] - }, - "pluginVersion": "12.4.0", - "targets": [ - { - "alias": "", - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "editorMode": "code", - "format": "table", - "group": [], - "metricColumn": "none", - "rawQuery": true, - "rawSql": "WITH car_efficiency AS (\r\n SELECT id, efficiency FROM cars WHERE id = 1\r\n),\r\n\r\nAux AS (\r\n SELECT car_id,\r\n COALESCE(efficiency, \r\n (SELECT efficiency FROM cars WHERE id = 1) * 100) AS efficiency\r\n FROM (\r\n SELECT \r\n ROUND((charge_energy_added / NULLIF(end_rated_range_km - start_rated_range_km, 0))::numeric, 3) * 100 as efficiency,\r\n COUNT(*) as count, 1 AS car_id\r\n FROM charging_processes\r\n WHERE car_id = 1\r\n AND duration_min > 10\r\n AND end_battery_level <= 95\r\n AND start_rated_range_km IS NOT NULL\r\n AND end_rated_range_km IS NOT NULL\r\n AND charge_energy_added > 0\r\n GROUP BY 1\r\n ORDER BY 2 DESC\r\n LIMIT 1\r\n ) AS DerivatedEfficiency\r\n),\r\n\r\nCurrentCapacity AS (\r\n SELECT AVG(Capacity) AS CurrentCapacity \r\n FROM (\r\n SELECT \r\n c.ideal_battery_range_km * aux.efficiency / c.usable_battery_level AS Capacity \r\n FROM charging_processes cp\r\n INNER JOIN charges c ON c.charging_process_id = cp.id \r\n INNER JOIN aux ON cp.car_id = aux.car_id\r\n WHERE cp.car_id = 1\r\n AND cp.end_date IS NOT NULL\r\n AND cp.charge_energy_added >= aux.efficiency\r\n AND c.usable_battery_level > 0\r\n ORDER BY cp.end_date DESC, c.date DESC \r\n LIMIT 100\r\n ) AS lastCharges\r\n),\r\n\r\ntrip AS (\r\n SELECT \r\n DATE(d.start_date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone') AS trip_date,\r\n MIN(d.start_date) AS start_date,\r\n MAX(d.end_date) AS end_date,\r\n SUM(d.distance) AS distance_km,\r\n SUM(d.duration_min) AS duration_min,\r\n AVG(d.outside_temp_avg) AS avg_temp_C,\r\n SUM(d.start_ideal_range_km - d.end_ideal_range_km) AS range_drop_km_net,\r\n SUM(d.start_ideal_range_km - d.end_ideal_range_km) * (SELECT efficiency FROM car_efficiency) AS consumption_total_kWh_net\r\n FROM drives d\r\n WHERE d.car_id = 1\r\n AND $__timeFilter(d.start_date)\r\n AND d.end_date IS NOT NULL\r\n AND d.duration_min > 0\r\n GROUP BY DATE(d.start_date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone')\r\n),\r\n\r\ndrives_start_event AS (\r\n SELECT 'drive_start' AS event, \r\n start_date AS date, \r\n start_ideal_range_km AS range, \r\n start_km AS odometer, \r\n car_id\r\n FROM drives\r\n WHERE car_id = 1 AND $__timeFilter(start_date)\r\n),\r\n\r\ndrives_end_event AS (\r\n SELECT 'drive_end' AS event, \r\n end_date AS date, \r\n end_ideal_range_km AS range, \r\n end_km AS odometer, \r\n car_id\r\n FROM drives\r\n WHERE car_id = 1 AND $__timeFilter(end_date)\r\n),\r\n\r\ncharging_processes_start_event AS (\r\n SELECT 'charging_process_start' AS event, \r\n cp.start_date AS date, \r\n p.ideal_battery_range_km AS range, \r\n p.odometer, \r\n cp.car_id\r\n FROM charging_processes cp\r\n INNER JOIN positions p ON cp.position_id = p.id\r\n WHERE cp.car_id = 1 AND $__timeFilter(cp.start_date)\r\n),\r\n\r\ncharging_processes_end_event AS (\r\n SELECT 'charging_process_end' AS event, \r\n cp.end_date AS date, \r\n p.ideal_battery_range_km AS range, \r\n p.odometer, \r\n cp.car_id\r\n FROM charging_processes cp\r\n INNER JOIN positions p ON cp.position_id = p.id\r\n WHERE cp.car_id = 1 AND $__timeFilter(cp.end_date)\r\n),\r\n\r\npositions_events AS (\r\n SELECT \r\n CASE WHEN drive_id IS NOT NULL AND LEAD(drive_id) OVER w IS NOT NULL THEN 'drive_start' ELSE 'other' END AS event,\r\n date,\r\n ideal_battery_range_km AS range,\r\n odometer,\r\n car_id\r\n FROM positions\r\n WHERE ideal_battery_range_km IS NOT NULL AND car_id = 1 AND $__timeFilter(date)\r\n WINDOW w AS (ORDER BY date)\r\n),\r\n\r\ncombined AS (\r\n SELECT * FROM drives_start_event\r\n UNION ALL\r\n SELECT * FROM drives_end_event\r\n UNION ALL\r\n SELECT * FROM charging_processes_start_event\r\n UNION ALL\r\n SELECT * FROM charging_processes_end_event\r\n UNION ALL\r\n SELECT * FROM positions_events\r\n),\r\n\r\nfinal_events_marked AS (\r\n SELECT\r\n *,\r\n ROW_NUMBER() OVER (PARTITION BY car_id ORDER BY date) AS rn\r\n FROM combined\r\n),\r\n\r\nfinal_events_filtered AS (\r\n SELECT\r\n car_id,\r\n date,\r\n odometer,\r\n range,\r\n LEAD(odometer) OVER w AS next_odometer,\r\n LEAD(range) OVER w AS next_range,\r\n DATE(date AT TIME ZONE 'UTC' AT TIME ZONE '$__timezone') AS trip_date,\r\n CASE \r\n WHEN event != 'drive_start' THEN GREATEST(range - LEAD(range) OVER w, 0)\r\n ELSE range - LEAD(range) OVER w\r\n END AS range_loss\r\n FROM final_events_marked\r\n WHERE event NOT IN ('charging_process_start', 'charging_process_end')\r\n WINDOW w AS (PARTITION BY car_id ORDER BY date)\r\n),\r\n\r\ndaily_energy_by_event AS (\r\n SELECT\r\n trip_date,\r\n SUM(range_loss) AS total_range_loss\r\n FROM final_events_filtered\r\n WHERE range_loss IS NOT NULL\r\n GROUP BY trip_date\r\n),\r\n\r\ndaily_energy_kwh AS (\r\n SELECT\r\n e.trip_date,\r\n e.total_range_loss * (SELECT efficiency FROM car_efficiency) AS consumption_total_kWh_gross\r\n FROM daily_energy_by_event e\r\n)\r\n\r\nSELECT\r\n t.start_date,\r\n t.end_date,\r\n t.distance_km,\r\n t.duration_min * 60 AS duration_sec,\r\n (t.distance_km / NULLIF(t.duration_min, 0) * 60) AS speed_km,\r\n t.avg_temp_C,\r\n d.consumption_total_kWh_gross AS consumption_total_kWh,\r\n (d.consumption_total_kWh_gross / cc.CurrentCapacity)*100 AS consume_percent,\r\n (t.consumption_total_kWh_net * 1000 / NULLIF(t.distance_km, 0)) AS consumption_Wh_per_km_net,\r\n t.distance_km / nullif(t.consumption_total_kWh_net/(SELECT efficiency FROM car_efficiency), 0) as net_efficiency,\r\n (d.consumption_total_kWh_gross * 1000 / NULLIF(t.distance_km, 0)) AS consumption_Wh_per_km_gross,\r\n t.distance_km / nullif(d.consumption_total_kWh_gross/(SELECT efficiency FROM car_efficiency), 0) as gross_efficiency\r\nFROM trip t\r\nLEFT JOIN daily_energy_kwh d ON t.trip_date = d.trip_date\r\nCROSS JOIN CurrentCapacity cc\r\nWHERE distance_$length_unit >= $min_dist AND (distance_$length_unit / duration_min * 60) >= $min_avg_speed\r\nORDER BY t.trip_date DESC;\r\n", - "refId": "A", - "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" - } - ] - } - ], - "title": "Day Trips", - "type": "table" - } - ], - "preload": false, - "refresh": "", - "schemaVersion": 42, - "tags": [ - "TeslamateCustomDashboards" - ], - "templating": { - "list": [ - { - "current": {}, - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "definition": "SELECT\n id as __value,\n CASE WHEN COUNT(id) OVER (PARTITION BY name) > 1 AND name IS NOT NULL THEN CONCAT(name, ' - ', RIGHT(vin, 6)) ELSE COALESCE(name, CONCAT('VIN ', vin)) end as __text \nFROM cars\nORDER BY display_priority ASC, name ASC, vin ASC", - "includeAll": false, - "label": "Car", - "name": "car_id", - "options": [], - "query": "SELECT\n id as __value,\n CASE WHEN COUNT(id) OVER (PARTITION BY name) > 1 AND name IS NOT NULL THEN CONCAT(name, ' - ', RIGHT(vin, 6)) ELSE COALESCE(name, CONCAT('VIN ', vin)) end as __text \nFROM cars\nORDER BY display_priority ASC, name ASC, vin ASC", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": {}, - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "definition": "SELECT unit_of_length FROM settings limit 1", - "hide": 2, - "includeAll": false, - "label": "length unit", - "name": "length_unit", - "options": [], - "query": "SELECT unit_of_length FROM settings limit 1", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": {}, - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "definition": "SELECT base_url FROM settings LIMIT 1", - "hide": 2, - "includeAll": false, - "name": "base_url", - "options": [], - "query": "SELECT base_url FROM settings LIMIT 1", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": {}, - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "definition": "SELECT preferred_range FROM settings LIMIT 1", - "hide": 2, - "includeAll": false, - "name": "preferred_range", - "options": [], - "query": "SELECT preferred_range FROM settings LIMIT 1", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": {}, - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "TeslaMate" - }, - "definition": "SELECT unit_of_temperature FROM settings LIMIT 1", - "hide": 2, - "includeAll": false, - "name": "temp_unit", - "options": [], - "query": "SELECT unit_of_temperature FROM settings LIMIT 1", - "refresh": 1, - "regex": "", - "regexApplyTo": "value", - "type": "query" - }, - { - "current": { - "text": "0", - "value": "0" - }, - "label": "Distance >=", - "name": "min_dist", - "options": [ - { - "selected": true, - "text": "0", - "value": "0" - } - ], - "query": "0", - "type": "textbox" - }, - { - "current": { - "text": "0", - "value": "0" - }, - "label": "Avg Speed >=", - "name": "min_avg_speed", - "options": [ - { - "selected": true, - "text": "0", - "value": "0" - } - ], - "query": "0", - "type": "textbox" - } - ] - }, - "time": { - "from": "now/y", - "to": "now" - }, - "timepicker": {}, - "timezone": "browser", - "title": "Day Trips", - "uid": "jchmY8upc6ZRj", - "version": 1, - "weekStart": "" -} diff --git a/grafana/dashboards/statistics.json b/grafana/dashboards/statistics.json index fee10f79bf..f027925e7e 100644 --- a/grafana/dashboards/statistics.json +++ b/grafana/dashboards/statistics.json @@ -300,7 +300,32 @@ }, { "id": "custom.minWidth", - "value": 100 + "value": 150 + }, + { + "id": "custom.cellOptions", + "value": { + "type": "gauge", + "valueDisplayMode": "text" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-BlPu" + } + }, + { + "id": "max", + "value": 400 + }, + { + "id": "min", + "value": 0 + }, + { + "id": "decimals", + "value": 0 } ] }, From 78b565bce772eaa781c56310957bb87d2fd257a3 Mon Sep 17 00:00:00 2001 From: pencilheart <495474804@qq.com> Date: Tue, 10 Mar 2026 22:06:53 +0800 Subject: [PATCH 3/3] update "statistics.json" --- grafana/dashboards/statistics.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/grafana/dashboards/statistics.json b/grafana/dashboards/statistics.json index f027925e7e..9f7da67afc 100644 --- a/grafana/dashboards/statistics.json +++ b/grafana/dashboards/statistics.json @@ -391,7 +391,27 @@ }, { "id": "custom.minWidth", - "value": 100 + "value": 150 + }, + { + "id": "custom.cellOptions", + "value": { + "type": "gauge" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-BlPu" + } + }, + { + "id": "max", + "value": 400 + }, + { + "id": "min", + "value": 0 } ] },