Skip to content

Visualize data from the diyBMS

donnib edited this page Mar 2, 2021 · 1 revision

The controller can send data to either MQTT, influxDB or both. Not all data are pushed to influxDB for example you cannot see relay status. The controller is also quite overloaded so it's best to just enable either or.

Here is a description how to use MQTT then used NodeRED to push data into InfluxDB 2.0 database then visualise the data using Grafana.

Prerequisites :

  1. MQTT server - Mosquitto
  2. InfluxDB 2.0 server
  3. NodeRED server
  4. Grafana server

I assume you have done following :

  1. Created an user in Mosquitto
  2. Configure diyBMS to use the Mosquitto server and you are receiving data -> use MQTTBox to test and subscribe to diyBMS/# and see if data is indeed coming from diyBMS, if not check your diyBMS and Mosquitto settings
  3. Setup NodeRED server and make a connection to Mosquitto server. You can test that you get data by drawing a connection between the MQTT node and a debug node.

Do following

  1. Head over to Flux UI interface and login (it runs on port 8086 so url would be http://your-influx-host-ip:8086)
  2. Create a organization and a bucket (check the Influx documentation how to do that from the UI)
  3. When you have created the organization look at the url : http://your-influx-host-ip:8086/orgs/c6278d4a10130f7b notice the c6278d4a10130f7b, that is your organization ID which is needed in NodeRED together with the bucket name you created in Flux.
  4. Add following flows in NodeRED (change the bucketname and organization on the Flux node to match yours)
[
    {
        "id": "d737058.bd3b5f8",
        "type": "comment",
        "z": "efe93325.55893",
        "name": "Push cell data from MQTT to InfluxDB",
        "info": "",
        "x": 300,
        "y": 270,
        "wires": []
    },
    {
        "id": "4146fd37.aa7214",
        "type": "comment",
        "z": "efe93325.55893",
        "name": "Push diyBMS status from MQTT to InfluxDB",
        "info": "",
        "x": 320,
        "y": 375,
        "wires": []
    },
    {
        "id": "bb75249b.baa748",
        "type": "comment",
        "z": "efe93325.55893",
        "name": "Push diyBMS relay status from MQTT to InfluxDB",
        "info": "",
        "x": 330,
        "y": 495,
        "wires": []
    },
    {
        "id": "d2e3da5e.46cb48",
        "type": "influxdb out",
        "z": "efe93325.55893",
        "influxdb": "a6fdab90.b072d8",
        "name": "",
        "measurement": "",
        "precision": "",
        "retentionPolicy": "",
        "database": "database",
        "precisionV18FluxV20": "ms",
        "retentionPolicyV18Flux": "",
        "org": "home",
        "bucket": "diybms",
        "x": 910,
        "y": 675,
        "wires": []
    },
    {
        "id": "5f31136b.6f802c",
        "type": "comment",
        "z": "efe93325.55893",
        "name": "Push diyBMS rules status from MQTT to InfluxDB",
        "info": "",
        "x": 330,
        "y": 765,
        "wires": []
    },
    {
        "id": "60dc208.35703e",
        "type": "change",
        "z": "efe93325.55893",
        "name": "relay2",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "relays",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"1\"\t   },\t   {\t       \"relay\":\"2\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 585,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "a5494dd2.bb4c1",
        "type": "change",
        "z": "efe93325.55893",
        "name": "relay3",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "relays",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"2\"\t   },\t   {\t       \"relay\":\"3\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 630,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "c0aa04b9.bd0858",
        "type": "change",
        "z": "efe93325.55893",
        "name": "relay4",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "relays",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"3\"\t   },\t   {\t       \"relay\":\"4\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 675,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "11d99b54.441385",
        "type": "mqtt in",
        "z": "efe93325.55893",
        "name": "",
        "topic": "diybms/output",
        "qos": "2",
        "datatype": "json",
        "broker": "d77c97be.ca8e08",
        "x": 230,
        "y": 600,
        "wires": [
            [
                "4b948575.b5c37c",
                "60dc208.35703e",
                "a5494dd2.bb4c1",
                "c0aa04b9.bd0858"
            ]
        ]
    },
    {
        "id": "4b948575.b5c37c",
        "type": "change",
        "z": "efe93325.55893",
        "name": "relay1",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "relays",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"relay\":\"1\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 540,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "d860bb6e.6de468",
        "type": "change",
        "z": "efe93325.55893",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "cells",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   payload,\t   {\t       \"cell\":$substringAfter($.topic, 'diybms\\/0\\/')\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 410,
        "y": 315,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "2d6c5e93.760ba2",
        "type": "change",
        "z": "efe93325.55893",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "status",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "{\t  \"uptime\": payload.uptime,\t  \"bankVoltage\": payload.bankVoltage[0],\t  \"comserr\": payload.monitor.commserr,\t  \"sent\": payload.monitor.sent,\t  \"received\" : payload.monitor.received,\t  \"badcrc\" : payload.monitor.badcrc,\t  \"ignored\" : payload.monitor.ignored,\t  \"oss\" : payload.monitor.oss,\t  \"roundtrip\" : payload.monitor.roundtrip\t}",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 425,
        "y": 420,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "ca71e196.4e9b7",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule1",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"1\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 825,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "172d8ecc.c116a1",
        "type": "mqtt in",
        "z": "efe93325.55893",
        "name": "",
        "topic": "diybms/0/#",
        "qos": "2",
        "datatype": "json",
        "broker": "d77c97be.ca8e08",
        "x": 220,
        "y": 315,
        "wires": [
            [
                "d860bb6e.6de468"
            ]
        ]
    },
    {
        "id": "830f3ce9.9c478",
        "type": "mqtt in",
        "z": "efe93325.55893",
        "name": "",
        "topic": "diybms/status",
        "qos": "2",
        "datatype": "json",
        "broker": "d77c97be.ca8e08",
        "x": 220,
        "y": 420,
        "wires": [
            [
                "2d6c5e93.760ba2"
            ]
        ]
    },
    {
        "id": "f55b4ea.29e3cb",
        "type": "mqtt in",
        "z": "efe93325.55893",
        "name": "",
        "topic": "diybms/rule",
        "qos": "2",
        "datatype": "json",
        "broker": "d77c97be.ca8e08",
        "x": 220,
        "y": 1020,
        "wires": [
            [
                "ca71e196.4e9b7",
                "213a9d0f.eed592",
                "7f6f74a1.b55a2c",
                "749c1cc2.344c24",
                "1eac9398.9a358c",
                "c6f226e4.30ae78",
                "f721fa6a.7c75a8",
                "2637ac1d.928b54",
                "299e0e34.9876b2",
                "2a7fca0e.25e1c6",
                "25f975c8.dce94a"
            ]
        ]
    },
    {
        "id": "213a9d0f.eed592",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule2",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"2\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 870,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "7f6f74a1.b55a2c",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule3",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"3\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 915,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "749c1cc2.344c24",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule4",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"4\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 960,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "1eac9398.9a358c",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule5",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"5\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1005,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "c6f226e4.30ae78",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule6",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"6\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1050,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "f721fa6a.7c75a8",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule7",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"7\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1095,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "2637ac1d.928b54",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule8",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"8\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1140,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "299e0e34.9876b2",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule9",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"9\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1185,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "2a7fca0e.25e1c6",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule10",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"10\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1230,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "25f975c8.dce94a",
        "type": "change",
        "z": "efe93325.55893",
        "name": "rule11",
        "rules": [
            {
                "t": "set",
                "p": "measurement",
                "pt": "msg",
                "to": "rules",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[\t   {\t       \"state\":payload.\"0\"\t   },\t   {\t       \"rule\":\"11\"\t   }\t]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 500,
        "y": 1275,
        "wires": [
            [
                "d2e3da5e.46cb48"
            ]
        ]
    },
    {
        "id": "a6fdab90.b072d8",
        "type": "influxdb",
        "hostname": "127.0.0.1",
        "port": "8086",
        "protocol": "http",
        "database": "database",
        "name": "Influx",
        "usetls": false,
        "tls": "",
        "influxdbVersion": "2.0",
        "url": "http://influxdb:8086",
        "rejectUnauthorized": true
    },
    {
        "id": "d77c97be.ca8e08",
        "type": "mqtt-broker",
        "name": "Mosquitto",
        "broker": "10.10.0.9",
        "port": "1883",
        "clientid": "",
        "usetls": false,
        "compatmode": false,
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "willTopic": "",
        "willQos": "0",
        "willPayload": ""
    }
]

The flows looks like this :

  1. Deploy your NodeRED change
  2. Head over to Flux UI interface again and go to Data Explorer and select the bucket you created. As soon as you select it you should see tags like this :

If you don't see them then go back and check diyBMS -> mosquitto -> NodeRed -> InfluxDB settings.

  1. Head over to your Grafana server and add a Influx connection, make sure you choose Flux language and use same organization id and bucket as before.
  2. Import the dashboard i made from here (use Import in Grafana and either paste the JSON below or paste the JSON in a file and save it with extension .json then import the file :
``` { "__inputs": [ { "name": "DS_INFLUXDB2", "label": "InfluxDB2", "description": "", "type": "datasource", "pluginId": "influxdb", "pluginName": "InfluxDB" }, { "name": "DS_INFLUXDB", "label": "InfluxDB", "description": "", "type": "datasource", "pluginId": "influxdb", "pluginName": "InfluxDB" } ], "__requires": [ { "type": "panel", "id": "bargauge", "name": "Bar gauge", "version": "" }, { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "7.3.7" }, { "type": "panel", "id": "graph", "name": "Graph", "version": "" }, { "type": "datasource", "id": "influxdb", "name": "InfluxDB", "version": "1.0.0" }, { "type": "panel", "id": "stat", "name": "Stat", "version": "" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": null, "links": [], "panels": [ { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "custom": { "align": null, "filterable": false }, "decimals": 2, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "volt" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 }, "id": 5, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "/^bankVoltage$/", "values": false }, "textMode": "auto" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "from(bucket: \"diybms\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"status\")\n |> filter(fn: (r) => r[\"_field\"] == \"bankVoltage\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> last()\n |> yield(name: \"Bank Voltage\")", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Bank voltage", "type": "stat" }, { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "custom": { "align": null, "filterable": false }, "decimals": 0, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "mvolt" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 6, "y": 0 }, "id": 6, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "/^_value$/", "values": false }, "textMode": "auto" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "FinalOutput = [\"_field\", \"_time\", \"_value\"]\n\nRawSeries = from(bucket: \"diybms\") \n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"cells\" and\n r._field == \"voltage\" \n )\n |> last()\n |> group(columns: [\"r.cell\"])\n\nNamedSeries = RawSeries\n |> map(fn: (r) => ({_value:r._value, _time:r._time, _field:\"Range\"}))\n |> spread()\n |> map(fn:(r) => ({ r with _value: r._value*1000.0})) \n |> keep(columns:FinalOutput)\n\nNamedSeries |> yield()", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Cell range", "type": "stat" }, { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "custom": { "align": null, "filterable": false }, "decimals": 2, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 12, "y": 0 }, "id": 13, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "/^Roundtrip$/", "values": false }, "textMode": "auto" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "from(bucket: \"diybms\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"status\")\n |> last()\n |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n |> rename(columns: {roundtrip: \"Roundtrip\"})\n |> keep(columns: [\"Roundtrip\"])", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Roundtrip", "type": "stat" }, { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "custom": { "align": null, "filterable": false }, "decimals": 2, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "dtdhms" }, "overrides": [] }, "gridPos": { "h": 4, "w": 3, "x": 16, "y": 0 }, "id": 12, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "/^Uptime$/", "values": false }, "textMode": "auto" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "from(bucket: \"diybms\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"status\")\n |> last()\n |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n |> rename(columns: {uptime: \"Uptime\"})\n |> keep(columns: [\"Uptime\"])", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Uptime", "type": "stat" }, { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "custom": { "align": null, "filterable": false }, "decimals": 0, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 3, "x": 19, "y": 0 }, "id": 11, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": [ "last" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "from(bucket: \"diybms\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"status\")\n |> last()\n |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n |> rename(columns: {bankVoltage: \"Bank voltage\", comserr: \"Comm Ser.\", sent: \"Sent\", received: \"Received\", badcrc: \"Bad CRC\", ignored: \"Ignored\", roundtrip: \"Roundtrip\", uptime: \"Uptime\"})\n |> keep(columns: [\"Received\",\"Sent\",\"Bad CRC\",\"Ignored\",\"Comm Ser.\"])", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "BMS Stats", "transformations": [], "type": "stat" }, { "datasource": "${DS_INFLUXDB}", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": null, "filterable": false }, "mappings": [ { "from": "", "id": 1, "text": "Active", "to": "", "type": 1, "value": "1" }, { "from": "", "id": 2, "text": "Standby", "to": "", "type": 1, "value": "0" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "green", "value": 0 }, { "color": "orange", "value": 1 } ] } }, "overrides": [] }, "gridPos": { "h": 3, "w": 19, "x": 0, "y": 4 }, "id": 9, "links": [], "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "vertical", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "value_and_name" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "FinalOutput = [\"_field\", \"_time\", \"id\", \"_value\"]\n\nRawSeries = from(bucket: \"diybms\") \n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"rules\" and\n r._field == \"state\"\n )\n |> map(fn:(r) => ({ r with id: int(v: r.rule)})) \n |> last()\n |> group(columns: [\"id\"])\n\nNamedSeries = RawSeries\n |> map(fn: (r) => ({_value:r._value, _time:r._time, _field:\"Rule\", id:r.id}))\n |> keep(columns:FinalOutput)\n\nNamedSeries |> yield()", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Rules", "type": "stat" }, { "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": {}, "decimals": 3, "mappings": [], "max": 3.7, "min": 2.5, "thresholds": { "mode": "absolute", "steps": [ { "color": "light-green", "value": null }, { "color": "dark-green", "value": 3.4 }, { "color": "#6ED0E0", "value": 3.45 }, { "color": "red", "value": 3.6 } ] }, "unit": "volt" }, "overrides": [] }, "gridPos": { "h": 8, "w": 19, "x": 0, "y": 7 }, "id": 2, "options": { "displayMode": "gradient", "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "", "values": false }, "showUnfilled": true }, "pluginVersion": "7.3.7", "targets": [ { "alias": "$tag_cell", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "cell" ], "type": "tag" }, { "params": [ "linear" ], "type": "fill" } ], "measurement": "cells", "orderByTime": "ASC", "policy": "default", "query": "FinalOutput = [\"_field\", \"_time\", \"id\", \"_value\"]\n\nRawSeries = from(bucket: \"diybms\") \n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"cells\" and\n r._field == \"voltage\" \n )\n |> map(fn:(r) => ({ r with id: int(v: r.cell) +1})) \n |> last()\n |> group(columns: [\"id\"])\n\nNamedSeries = RawSeries\n |> map(fn: (r) => ({_value:r._value, _time:r._time, _field:\"Cell\", id:r.id}))\n |> keep(columns:FinalOutput)\n\nNamedSeries |> yield()", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "voltage" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [ { "key": "cell", "operator": "=", "value": "Cell 2" }, { "condition": "OR", "key": "cell", "operator": "=", "value": "Cell 3" } ] } ], "timeFrom": null, "timeShift": null, "title": "Cell voltage", "transformations": [], "type": "bargauge" }, { "datasource": "${DS_INFLUXDB}", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": null, "filterable": false }, "mappings": [ { "from": "", "id": 1, "text": "On", "to": "", "type": 1, "value": "1" }, { "from": "", "id": 2, "text": "Off", "to": "", "type": 1, "value": "0" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "dark-red", "value": 0 }, { "color": "green", "value": 1 } ] } }, "overrides": [] }, "gridPos": { "h": 16, "w": 3, "x": 19, "y": 8 }, "id": 8, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "value_and_name" }, "pluginVersion": "7.3.7", "targets": [ { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "orderByTime": "ASC", "policy": "default", "query": "FinalOutput = [\"_field\", \"_time\", \"id\", \"_value\"]\n\nRawSeries = from(bucket: \"diybms\") \n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"relays\" and\n r._field == \"state\" \n )\n |> map(fn:(r) => ({ r with id: int(v: r.relay)})) \n |> last()\n |> group(columns: [\"id\"])\n\nNamedSeries = RawSeries\n |> map(fn: (r) => ({_value:r._value, _time:r._time, _field:\"Relay\", id:r.id}))\n |> keep(columns:FinalOutput)\n\nNamedSeries |> yield()", "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "Relays", "type": "stat" }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "${DS_INFLUXDB2}", "fieldConfig": { "defaults": { "color": { "mode": "continuous-YlRd" }, "custom": {}, "decimals": 3, "mappings": [], "max": 3.7, "min": 2.5, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "#EAB839", "value": 3.4 }, { "color": "red", "value": 3.5 } ] }, "unit": "volt" }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 9, "w": 19, "x": 0, "y": 15 }, "hiddenSeries": false, "id": 3, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "maxDataPoints": 10000000, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.7", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "alias": "$tag_cell", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "cell" ], "type": "tag" }, { "params": [ "linear" ], "type": "fill" } ], "measurement": "cells", "orderByTime": "ASC", "policy": "default", "query": "FinalOutput = [\"_field\", \"_time\", \"id\", \"_value\"]\n\nRawSeries = from(bucket: \"diybms\") \n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"cells\" and\n r._field == \"voltage\" \n )\n |> map(fn:(r) => ({ r with id: int(v: r.cell)+1 })) \n |> group(columns: [\"id\"])\n\nNamedSeries = RawSeries\n |> map(fn: (r) => ({_value:r._value, _time:r._time, _field:\"Cell\", id:r.id}))\n |> keep(columns:FinalOutput)\n\nNamedSeries |> yield()", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "voltage" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [ { "key": "cell", "operator": "=", "value": "Cell 2" }, { "condition": "OR", "key": "cell", "operator": "=", "value": "Cell 3" } ] } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Cell voltage", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "transformations": [], "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "volt", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "refresh": "5s", "schemaVersion": 26, "style": "dark", "tags": [], "templating": { "list": [] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "diyBMS", "uid": "f5lApGPGk", "version": 5 } ```

Here is how the Grafana dashboard looks if everything works as it should:

Note: You should be all setup now but you probably have to fix the queries if your bucket is not named diybms and if your Influx connection in Grafana is not named InfluxDB2. Also the above covers only one pack, if you have multiple packs you would have to change some things.