Nightscout Pixel
Node-RED

Nightscout Pixel

Nightscout Pixel is a simple monitor for current Nighscout CGM data – direction, sensor glucose value, delta.
A flow by fabkai

Download flow Download assets

Flow Details

A JSON with the current Nightscout data is queried at a defined interval via the Nightscout V1 REST API (the implementation requires an access token created in the Subjects - People, Devices, etc. section of the Nightscout Admin Tools). The data from the JSON file is then processed in a function to display direction, sensor glucose value and delta. It can also be displayed if no more current data is available for a defined period of time. The icons and values are displayed via a custom app using MQTT (MQTT Broker is required).

[ { "id": "7057b52ef757d606", "type": "tab", "label": "Awtrix-Nightscout-Pixel", "disabled": false, "info": "", "env": [] }, { "id": "e7101a5caeb46470", "type": "inject", "z": "7057b52ef757d606", "name": "Start", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "5", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 180, "wires": [ [ "1ac6b90937457bf7" ] ] }, { "id": "25b695a46aa59b69", "type": "change", "z": "7057b52ef757d606", "name": "Command: Data query", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "curl -H \"Content-Type: application/json\" -H \"Authorization: Bearer TOKEN\" -X GET https://NIGHTSCOUT_URL:PORT/api/v1/entries.json?count=1", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 760, "y": 180, "wires": [ [ "1e1f42891a8b5b97" ] ] }, { "id": "fd30a342bc5bed2f", "type": "exec", "z": "7057b52ef757d606", "command": "", "addpay": "payload", "append": "", "useSpawn": "false", "timer": "", "winHide": false, "oldrc": false, "name": "cURL", "x": 1090, "y": 180, "wires": [ [ "317d17a92e168a53", "8f8bc645d83637d5" ], [], [] ] }, { "id": "7a090c427aadeb60", "type": "function", "z": "7057b52ef757d606", "name": "Function: Create Pixel", "func": "var glucose = msg.payload[0].sgv; // Data from Nightscout JSON\nvar delta = Math.round(msg.payload[0].delta);\nvar direction = msg.payload[0].direction;\nvar measuringtime = msg.payload[0].date;\nvar now = new Date();\nvar timestamp = now.getTime();\nvar nodataoffset = 660000; // Offset in milliseconds to the last measurement\nvar icon = \"\";\nvar color = \"\";\n\nif (delta >= 0) {\n delta = '+' + delta; // Insert plus sign for positive delta\n}\n\nif ((measuringtime + nodataoffset) < timestamp) {\n icon = 39552; // Set NoData icon if no data is available after the selected offset time\n} else { // Set icon depending on direction\n if (direction == \"SingleUp\") {\n icon = 39545;\n } else if (direction == \"SingleDown\") {\n icon = 39546;\n } else if (direction == \"Flat\") {\n icon = 39547;\n } else if (direction == \"FortyFiveDown\") {\n icon = 39548;\n } else if (direction == \"FortyFiveUp\") {\n icon = 39549;\n } else if (direction == \"DoubleUp\") {\n icon = 39550;\n } else if (direction == \"DoubleDown\") {\n icon = 39551;\n } \n}\n\n// Create payload to display on Awtrix depending on glucose level\nif (glucose > 250) {\n\n if ((measuringtime + nodataoffset) < timestamp) {\n color = [255, 255, 255];\n } else {\n color = [247, 133, 31];\n }\n\n msg.payload = {\n \"text\": glucose + ' ' + delta,\n \"icon\": icon,\n \"color\": color,\n \"pushIcon\": 0,\n \"save\": true,\n \"textCase\": 2\n };\n return [{ payload: msg.payload }, null];\n} else if (glucose < 70) {\n\n if ((measuringtime + nodataoffset) < timestamp) {\n color = [255, 255, 255];\n } else {\n color = [255, 0, 0];\n }\n\n msg.payload = {\n \"text\": glucose + ' ' + delta,\n \"icon\": icon,\n \"color\": color,\n \"pushIcon\": 0,\n \"save\": true,\n \"textCase\": 2\n };\n return [{ payload: msg.payload }, null];\n} else if (glucose => 70 && glucose <= 250) {\n\n if ((measuringtime + nodataoffset) < timestamp) {\n color = [255, 255, 255];\n } else {\n color = [0, 255, 0];\n }\n \n msg.payload = {\n \"text\": glucose + ' ' + delta,\n \"icon\": icon,\n \"color\": color,\n \"pushIcon\": 0,\n \"save\": true,\n \"textCase\": 2\n };\n return [{ payload: msg.payload }, null];\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1420, "y": 180, "wires": [ [ "d3ef3ba51867a7aa" ] ] }, { "id": "317d17a92e168a53", "type": "debug", "z": "7057b52ef757d606", "name": "Debug: Nightscout JSON", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1290, "y": 220, "wires": [] }, { "id": "1ac6b90937457bf7", "type": "change", "z": "7057b52ef757d606", "name": "Command: Token request", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "curl -X GET https://NIGHTSCOUT_URL:PORT/api/v2/authorization/request/ACCESS_TOKEN -H \"Content-Type: application/json\"", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 270, "y": 180, "wires": [ [ "018aaebd60f06dff" ] ] }, { "id": "018aaebd60f06dff", "type": "exec", "z": "7057b52ef757d606", "command": "", "addpay": "payload", "append": "", "useSpawn": "false", "timer": "", "winHide": false, "oldrc": false, "name": "cURL", "x": 450, "y": 180, "wires": [ [ "a3561344ac2dae6d" ], [], [] ] }, { "id": "a3561344ac2dae6d", "type": "json", "z": "7057b52ef757d606", "name": "parsing", "property": "payload", "action": "", "pretty": false, "x": 580, "y": 180, "wires": [ [ "25b695a46aa59b69", "360750b08aaad716" ] ] }, { "id": "360750b08aaad716", "type": "change", "z": "7057b52ef757d606", "name": "save token", "rules": [ { "t": "set", "p": "Nightscout.Token", "pt": "flow", "to": "payload.token", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 730, "y": 220, "wires": [ [] ] }, { "id": "1e1f42891a8b5b97", "type": "change", "z": "7057b52ef757d606", "name": "insert token", "rules": [ { "t": "change", "p": "payload", "pt": "msg", "from": "TOKEN", "fromt": "str", "to": "Nightscout.Token", "tot": "flow" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 950, "y": 180, "wires": [ [ "fd30a342bc5bed2f" ] ] }, { "id": "d3ef3ba51867a7aa", "type": "mqtt out", "z": "7057b52ef757d606", "name": "Nightscout Custom App", "topic": "PREFIX/custom/Nightscout", "qos": "1", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "326ea0d44da2b88f", "x": 1650, "y": 180, "wires": [] }, { "id": "8f8bc645d83637d5", "type": "json", "z": "7057b52ef757d606", "name": "parsing", "property": "payload", "action": "", "pretty": false, "x": 1240, "y": 180, "wires": [ [ "7a090c427aadeb60" ] ] }, { "id": "326ea0d44da2b88f", "type": "mqtt-broker", "name": "", "broker": "", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" } ]
/flows/wyMWodvk5nxX/39545.jpg
/flows/wyMWodvk5nxX/39546.jpg
/flows/wyMWodvk5nxX/39547.jpg
/flows/wyMWodvk5nxX/39548.jpg
/flows/wyMWodvk5nxX/39549.jpg
/flows/wyMWodvk5nxX/39550.jpg
/flows/wyMWodvk5nxX/39551.jpg
/flows/wyMWodvk5nxX/39552.jpg
-- Flow first published on April 20, 2024.