diff --git a/grafana_dashboard.json b/grafana_dashboard.json new file mode 100644 index 0000000..b15fbac --- /dev/null +++ b/grafana_dashboard.json @@ -0,0 +1,2893 @@ +{ + "__inputs": [ + { + "name": "DS_INFLUXDB", + "label": "InfluxDB", + "description": "", + "type": "datasource", + "pluginId": "influxdb", + "pluginName": "InfluxDB" + } + ], + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 100, + "title": "Aktuell", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "area", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"power_ac\") AS \"PV\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "PV aktuell", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"meter1_power\") AS \"Grid\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Netz aktuell (+ Bezug / - Einspeisung)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"battery1_power\") AS \"Battery\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batterie aktuell (+ Entladen / - Laden)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 1 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"house_load\") AS \"Hausverbrauch\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Hausverbrauch aktuell", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 20 + }, + { + "color": "yellow", + "value": 40 + }, + { + "color": "green", + "value": 60 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 1 + }, + "id": 5, + "options": { + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"battery1_soe\") AS \"SoE\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batterie SoE", + "type": "gauge" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Am Netz", + "color": "green", + "index": 0 + }, + "1": { + "text": "INSELBETRIEB", + "color": "red", + "index": 1 + } + } + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 6, + "options": { + "colorMode": "background", + "graphMode": "none", + "textMode": "value", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"offgrid_state\") AS \"Inselbetrieb\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Netzstatus", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 5 + }, + "id": 7, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT spread(\"energy_total\") / 1000 AS \"Ertrag\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "time": { + "from": "now-24h", + "to": "now" + }, + "title": "Ertrag (24h)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 5 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT integral(\"grid_import\", 1h) / 1000 AS \"Bezug\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "time": { + "from": "now-24h", + "to": "now" + }, + "title": "Netzbezug (24h)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 5 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT integral(\"grid_export\", 1h) / 1000 AS \"Einspeisung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "time": { + "from": "now-24h", + "to": "now" + }, + "title": "Einspeisung (24h)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 30 + }, + { + "color": "green", + "value": 60 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 5 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "hide": true, + "query": "SELECT integral(\"house_load\", 1h) FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "hide": true, + "query": "SELECT integral(\"grid_import\", 1h) FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "($A - $B) / $A * 100", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "time": { + "from": "now-24h", + "to": "now" + }, + "title": "Autarkie (24h)", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "none", + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "Aus", + "color": "dark-blue", + "index": 0 + }, + "2": { + "text": "Schlafmodus", + "color": "dark-blue", + "index": 1 + }, + "3": { + "text": "Netzüberwachung", + "color": "blue", + "index": 2 + }, + "4": { + "text": "Produziert", + "color": "green", + "index": 3 + }, + "5": { + "text": "Produziert (gedrosselt)", + "color": "yellow", + "index": 4 + }, + "6": { + "text": "Fährt herunter", + "color": "orange", + "index": 5 + }, + "7": { + "text": "Fehler", + "color": "red", + "index": 6 + }, + "8": { + "text": "Standby", + "color": "dark-blue", + "index": 7 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 5 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "value", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "rawQuery": true, + "resultFormat": "time_series", + "refId": "A", + "query": "SELECT last(\"status\") FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter" + } + ], + "title": "Wechselrichter-Status", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "OK", + "color": "green", + "index": 0 + } + } + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 5 + }, + "id": 12, + "options": { + "colorMode": "background", + "graphMode": "none", + "textMode": "value", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"error_code\") AS \"Error\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Wechselrichter-Fehler", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 101, + "title": "Leistungsflüsse", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 10, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 13, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"power_ac\") AS \"PV\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_power\") AS \"Netz (+Bezug/-Einspeisung)\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_power\") AS \"Batterie (+Entladen/-Laden)\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"house_load\") AS \"Hausverbrauch\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "D", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Leistungsflüsse", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 102, + "title": "Hausversorgung - woher kommt der Verbrauch", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 40, + "gradientMode": "opacity", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "normal", + "group": "A" + } + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Hausverbrauch" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "mode": "none" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 2 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 14, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"solar_to_house\") AS \"Aus Sonne\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery_discharge\") AS \"Aus Batterie\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"grid_import\") AS \"Aus Netz\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"house_load\") AS \"Hausverbrauch\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "D", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Bezugsquellen (gestapelt)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 40, + "gradientMode": "opacity", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "normal", + "group": "A" + }, + "transform": "negative-Y" + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 15, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"grid_export\") AS \"Einspeisung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery_charge\") AS \"Batterieladung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Überschuss (gestapelt, nach unten)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 103, + "title": "Energie", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 28 + }, + "id": 16, + "options": { + "pieType": "donut", + "displayLabels": [ + "name", + "percent", + "value" + ], + "legend": { + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "tooltip": { + "mode": "single", + "sort": "none" + }, + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT integral(\"solar_to_house\", 1h) / 1000 AS \"Aus Sonne\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT integral(\"battery_discharge\", 1h) / 1000 AS \"Aus Batterie\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT integral(\"grid_import\", 1h) / 1000 AS \"Aus Netz\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Energiemix (Zeitraum)", + "type": "piechart" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth", + "custom": { + "drawStyle": "bars", + "lineWidth": 1, + "fillOpacity": 80, + "gradientMode": "none", + "stacking": { + "mode": "normal" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 16, + "x": 8, + "y": 28 + }, + "id": 17, + "options": { + "xField": "time", + "showValue": "never", + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + }, + "groupWidth": 0.7, + "barWidth": 0.9 + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT non_negative_derivative(max(\"energy_total\"), 1h) / 1000 AS \"Ertrag\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time(1h) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Ertrag pro Stunde", + "type": "barchart" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watth", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 20, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 18, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_available_energy\") AS \"Verfügbar\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_max_energy\") AS \"Kapazität\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Gespeicherte Energie", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 104, + "title": "Netzqualität", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "volt", + "min": 200, + "max": 260, + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 44 + }, + "id": 19, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"p1n_voltage\") AS \"WR L1-N\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"p2n_voltage\") AS \"WR L2-N\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"p3n_voltage\") AS \"WR L3-N\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_l1\") AS \"Zähler L1\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "D", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_l2\") AS \"Zähler L2\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "E", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_l3\") AS \"Zähler L3\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "F", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Spannungen L-N", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "volt", + "min": 330, + "max": 460, + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 44 + }, + "id": 20, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_ll_l1\") AS \"L1-L2\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_ll_l2\") AS \"L2-L3\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_voltage_ll_l3\") AS \"L3-L1\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Spannungen L-L (verkettet)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "hertz", + "min": 49, + "max": 51, + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 44 + }, + "id": 21, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"frequency\") AS \"WR\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_frequency\") AS \"Zähler\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Frequenz", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 51 + }, + "id": 105, + "title": "Phasen", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 30, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "normal" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 52 + }, + "id": 22, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_power_l1\") AS \"L1\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_power_l2\") AS \"L2\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_power_l3\") AS \"L3\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Netzleistung pro Phase (gestapelt)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "amp", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 52 + }, + "id": 23, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_current_l1\") AS \"L1\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_current_l2\") AS \"L2\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_current_l3\") AS \"L3\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "C", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"meter1_current\") AS \"Summe\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "D", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Netzstrom pro Phase", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 106, + "title": "PV / DC-Seite", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "volt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 60 + }, + "id": 24, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"voltage_dc\") AS \"DC-Spannung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "DC-Spannung", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "amp", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 60 + }, + "id": 25, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"current_dc\") AS \"DC-Strom\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "DC-Strom", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "watt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Wirkungsgrad" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "min", + "value": 0 + }, + { + "id": "max", + "value": 100 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 60 + }, + "id": 26, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"power_ac\") AS \"AC-Leistung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"power_dc\") AS \"DC-Leistung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "($A / $B) * 100", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "title": "AC- vs DC-Leistung und Wirkungsgrad", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 67 + }, + "id": 107, + "title": "Batterie", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "custom": { + "drawStyle": "line", + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "fillOpacity": 10, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 68 + }, + "id": 27, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_soe\") AS \"SoE\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_soh\") AS \"SoH\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "rawQuery": true, + "resultFormat": "time_series", + "refId": "C", + "query": "SELECT mean(\"battery1_soe\") * mean(\"battery1_soh\") / 100 AS \"SoC\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)" + } + ], + "title": "Batterie SoE / SoH / SoC", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "volt", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 68 + }, + "id": 28, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_voltage\") AS \"Batteriespannung\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batteriespannung", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "amp", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 68 + }, + "id": 29, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_current\") AS \"Batteriestrom\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batteriestrom", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "none", + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Deaktiviert", + "color": "dark-blue", + "index": 0 + }, + "1": { + "text": "Max. Eigenverbrauch", + "color": "green", + "index": 1 + }, + "2": { + "text": "Zeitsteuerung", + "color": "blue", + "index": 2 + }, + "3": { + "text": "Nur Notstrom", + "color": "orange", + "index": 3 + }, + "4": { + "text": "Fernsteuerung", + "color": "purple", + "index": 4 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 75 + }, + "id": 30, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "value", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "rawQuery": true, + "resultFormat": "time_series", + "refId": "A", + "query": "SELECT last(\"storage_control_mode\") FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter" + } + ], + "title": "Speicher-Modus", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 75 + }, + "id": 31, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"storage_backup_reserved\") AS \"Reserved\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Notstrom-Reserve", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "none", + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Aus", + "color": "dark-blue", + "index": 0 + }, + "1": { + "text": "Standby", + "color": "dark-blue", + "index": 1 + }, + "2": { + "text": "Initialisierung", + "color": "blue", + "index": 2 + }, + "3": { + "text": "Laden", + "color": "green", + "index": 3 + }, + "4": { + "text": "Entladen", + "color": "yellow", + "index": 4 + }, + "5": { + "text": "Fehler", + "color": "red", + "index": 5 + }, + "6": { + "text": "Ruhend", + "color": "dark-blue", + "index": 6 + }, + "7": { + "text": "Ruhend", + "color": "dark-blue", + "index": 7 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 75 + }, + "id": 32, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "value", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "rawQuery": true, + "resultFormat": "time_series", + "refId": "A", + "query": "SELECT last(\"battery1_status\") FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter" + } + ], + "title": "Batteriestatus", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "kwatth" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 75 + }, + "id": 33, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"battery1_available_energy\") / 1000 AS \"Verfügbar\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batterie verfügbar", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100 + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 75 + }, + "id": 34, + "options": { + "colorMode": "value", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"battery1_soh\") AS \"SoH\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batterie SoH", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 20 + }, + { + "color": "green", + "value": 40 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 75 + }, + "id": 35, + "options": { + "colorMode": "none", + "graphMode": "none", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "rawQuery": true, + "resultFormat": "time_series", + "refId": "A", + "query": "SELECT last(\"battery1_soe\") * last(\"battery1_soh\") / 100 AS \"SoC\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter" + } + ], + "title": "Batterie SoC", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 79 + }, + "id": 108, + "title": "Betriebsverlauf", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "Aus", + "color": "dark-blue", + "index": 0 + }, + "2": { + "text": "Schlafmodus", + "color": "dark-blue", + "index": 1 + }, + "3": { + "text": "Netzüberwachung", + "color": "blue", + "index": 2 + }, + "4": { + "text": "Produziert", + "color": "green", + "index": 3 + }, + "5": { + "text": "Produziert (gedrosselt)", + "color": "yellow", + "index": 4 + }, + "6": { + "text": "Fährt herunter", + "color": "orange", + "index": 5 + }, + "7": { + "text": "Fehler", + "color": "red", + "index": 6 + }, + "8": { + "text": "Standby", + "color": "dark-blue", + "index": 7 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 80 + }, + "id": 36, + "options": { + "alignValue": "left", + "mergeValues": true, + "rowHeight": 0.9, + "showValue": "auto", + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"status\") AS \"Inverter status\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(previous)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Wechselrichter-Status", + "type": "state-timeline" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Am Netz", + "color": "green", + "index": 0 + }, + "1": { + "text": "INSELBETRIEB", + "color": "red", + "index": 1 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 80 + }, + "id": 37, + "options": { + "alignValue": "left", + "mergeValues": true, + "rowHeight": 0.9, + "showValue": "auto", + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"offgrid_state\") AS \"Inselbetrieb\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(previous)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Inselbetrieb-Verlauf", + "type": "state-timeline" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Aus", + "color": "dark-blue", + "index": 0 + }, + "1": { + "text": "Standby", + "color": "dark-blue", + "index": 1 + }, + "2": { + "text": "Initialisierung", + "color": "blue", + "index": 2 + }, + "3": { + "text": "Laden", + "color": "green", + "index": 3 + }, + "4": { + "text": "Entladen", + "color": "yellow", + "index": 4 + }, + "5": { + "text": "Fehler", + "color": "red", + "index": 5 + }, + "6": { + "text": "Ruhend", + "color": "dark-blue", + "index": 6 + }, + "7": { + "text": "Ruhend", + "color": "dark-blue", + "index": 7 + } + } + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 80 + }, + "id": 38, + "options": { + "alignValue": "left", + "mergeValues": true, + "rowHeight": 0.9, + "showValue": "auto", + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT last(\"battery1_status\") AS \"Battery status\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(previous)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Batteriestatus", + "type": "state-timeline" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "fieldConfig": { + "defaults": { + "unit": "celsius", + "custom": { + "drawStyle": "line", + "lineInterpolation": "linear", + "lineWidth": 1, + "fillOpacity": 0, + "gradientMode": "none", + "spanNulls": false, + "showPoints": "never", + "stacking": { + "mode": "none" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 87 + }, + "id": 39, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"temperature\") AS \"WR\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "A", + "rawQuery": true, + "resultFormat": "time_series" + }, + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "query": "SELECT mean(\"battery1_avg_temperature\") AS \"Batterie (mittl.)\" FROM \"$measurement\" WHERE serialnumber =~ /^$serial$/ AND $timeFilter GROUP BY time($__interval) fill(null)", + "refId": "B", + "rawQuery": true, + "resultFormat": "time_series" + } + ], + "title": "Temperaturen", + "type": "timeseries" + } + ], + "refresh": "1m", + "schemaVersion": 39, + "style": "dark", + "tags": [ + "solaredge", + "pv" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "solaredge", + "value": "solaredge" + }, + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "definition": "SHOW MEASUREMENTS", + "hide": 0, + "includeAll": false, + "label": "Messung", + "multi": false, + "name": "measurement", + "options": [], + "query": "SHOW MEASUREMENTS", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": ".+", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB}" + }, + "definition": "SHOW TAG VALUES WITH KEY = \"serialnumber\"", + "hide": 0, + "includeAll": true, + "label": "Seriennummer", + "multi": false, + "name": "serial", + "options": [], + "query": "SHOW TAG VALUES WITH KEY = \"serialnumber\"", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "SolarEdge", + "uid": "solaredge-influx", + "version": 1, + "weekStart": "" +} diff --git a/solaredge_modbus_mqtt.py b/solaredge_modbus_mqtt.py index 87ebde2..a1a8fac 100755 --- a/solaredge_modbus_mqtt.py +++ b/solaredge_modbus_mqtt.py @@ -5,6 +5,7 @@ import base64 import os import sys import time +import urllib.error import urllib.parse import urllib.request @@ -43,6 +44,18 @@ def publish(line, influx): send_to_influx(backlog + [line], influx) if backlog: os.remove(SPOOL_FILE) + except urllib.error.HTTPError as err: + body = err.read().decode('utf-8', 'replace')[:200] + if err.code == 400: + # Permanently rejected (malformed line or field type conflict). + # Re-spooling would poison every future write, so drop the batch. + print('InfluxDB rejected the write, dropping {0} spooled line(s): {1}'.format(len(backlog) + 1, body)) + if os.path.exists(SPOOL_FILE): + os.remove(SPOOL_FILE) + else: + print('InfluxDB write failed (HTTP {0}), spooling line: {1}'.format(err.code, body or err)) + with open(SPOOL_FILE, 'a') as f: + f.write(line + '\n') except Exception as err: print('InfluxDB write failed, spooling line: {0}'.format(err)) with open(SPOOL_FILE, 'a') as f: diff --git a/solaredge_modbus_mqtt/__init__.py b/solaredge_modbus_mqtt/__init__.py index 19750e4..fbe4449 100644 --- a/solaredge_modbus_mqtt/__init__.py +++ b/solaredge_modbus_mqtt/__init__.py @@ -261,7 +261,9 @@ class MyInverter: for i in range(self.retries): result = self.client.read_holding_registers(address=address, count=length, unit=self.unit) - if isinstance(result, ReadHoldingRegistersResponse): + # length check: the flaky gateway sometimes returns short responses, + # which still pass isinstance and would decode garbage + if isinstance(result, ReadHoldingRegistersResponse) and len(result.registers) == length: return BinaryPayloadDecoder.fromRegisters( result.registers, byteorder=Endian.Big, wordorder=wordorder) @@ -340,7 +342,7 @@ class SolarData: 'status': {}, 'status_text': {'field': 'status', 'map': inverter_status_map}, 'vendor_status': {}, - 'offgrid': {'field': 'event_1_vendor', 'bit': 1}, + 'offgrid_state': {'field': 'event_1_vendor', 'bit': 1}, 'error_code': {'field': 'event_4_vendor'}, 'current': {'scaleField': 'current_scale', 'unit': 'A'}, @@ -466,6 +468,10 @@ class SolarData: scale = data.get(config['scaleField']) if scale is False or scale is None: continue + # SunSpec scale factors live in [-10, 10]; anything else is a + # garbage decode that would overflow math.pow + if not isinstance(scale, int) or not -10 <= scale <= 10: + continue value = value * math.pow(10, scale) if 'bit' in config: @@ -475,6 +481,9 @@ class SolarData: if 'map' in config: value = config['map'][value] if 0 <= value < len(config['map']) else 'Unknown ({0})'.format(value) + if isinstance(value, float) and not math.isfinite(value): + continue + if isinstance(value, float): value = round(value, 4) diff --git a/solaredge_modbus_mqtt/test_SolarData.py b/solaredge_modbus_mqtt/test_SolarData.py index 3201fb5..69a8ae0 100644 --- a/solaredge_modbus_mqtt/test_SolarData.py +++ b/solaredge_modbus_mqtt/test_SolarData.py @@ -138,8 +138,32 @@ class TestSolarData(unittest.TestCase): self.assertIs(False, inverter._decode_value(decoder, 1, registerDataType.INT16, int)) def testOffgrid(self): - self.assertEqual(0, SolarData(probe_data()).data['offgrid']) - self.assertEqual(1, SolarData(probe_data(event_1_vendor=5)).data['offgrid']) + self.assertEqual(0, SolarData(probe_data()).data['offgrid_state']) + self.assertEqual(1, SolarData(probe_data(event_1_vendor=5)).data['offgrid_state']) + + def testGarbageScaleIsSkipped(self): + # a garbled block once produced a scale of ~4915 -> OverflowError + solarData = SolarData(probe_data(current_scale=4915)) + self.assertNotIn('current', solarData.data) + self.assertNotIn('p1_current', solarData.data) + self.assertAlmostEqual(939.4, solarData.data['meter1_power']) + + def testNonFiniteIsSkipped(self): + solarData = SolarData(probe_data(b1_soe=float('inf'), b1_soh=float('nan'))) + self.assertNotIn('battery1_soe', solarData.data) + self.assertNotIn('battery1_soh', solarData.data) + + def testShortModbusResponseRejected(self): + from pymodbus.register_read_message import ReadHoldingRegistersResponse + from . import MyInverter + + inverter = MyInverter(host='localhost', port=1502) + inverter.retries = 1 + inverter.client = type('FakeClient', (), { + 'read_holding_registers': lambda self, **kw: ReadHoldingRegistersResponse([1, 2, 3]) + })() + # asked for 5 registers, got 3 -> must be rejected, not half-decoded + self.assertIsNone(inverter._read_holding_registers(40020, 5)) def testMeter(self): solarData = SolarData(probe_data()) @@ -229,7 +253,7 @@ class TestSolarData(unittest.TestCase): self.assertTrue(line.startswith('solaredge,model=SE10K-RWB48BFN4,serialnumber=7E1FF4D1 ')) self.assertIn(',status=4i', line) - self.assertIn(',offgrid=0i', line) + self.assertIn(',offgrid_state=0i', line) self.assertIn(',power_ac=597.0', line) self.assertIn(',meter1_power=939.4', line) self.assertIn(',battery1_soe=100.0', line)