can be send to a "Text" sensor in the Energy board.
This Node-RED flow retrieves environmental data from https://app.electricitymaps.com/map
This project aims to make users aware of their ecological footprint.
This is the easiest by monitoring your electrical energy consumption and know, where your energy comes from.
If you are the owner of a set of solar panels, you use a lot of fossil-free energy, but not all.
Sometimes you need the grid and in this case, while being aware, where the energy comes from, you can plan to use as much as
carbon free energy.
This flow retrieves the energy data from an API available at https://www.electricitymaps.com/free-tier-api
Documentation can be found at: hxxps://static.electricitymaps.com/api/docs/index.html
Get your free API key at: hxxps://www.electricitymaps.com/free-tier-api
Although more than 200 regions are available, I use the lat/lon coordinates, as configured in Domoticz.
This will avoid, that users has to lookup their "Region".
The health and the zones can be requested without an API key.
Beside actual data, historical data is available in the free tier.
However I use only 2(3) sensors.
1. For information I added a Carbon Intensity sensor.
This is a Custom sensor with an x-axis gCO2eq/kWh
2. I also added an Electrical (usage and counter) device.
3. I added an unused "Text¨ device in order to send some text to the Energy Dashboard
The Carbon Intensity sensor gets the data from:hxxps://api.electricitymap.org/v3/carbon-intensity/latest
The amount of used fossil-free energy is calculated from the data from the P1 Smartmeter and the value fossilFreePercentage from
hxxps://api.electricitymap.org/v3/power-breakdown/latest
As the P1 Smartmeter only the "Consumed Power" (and "Produced Power") has available as useful data Node-RED calculates
the daily used Energy themselves. Therefore the contrib node "Watt2kWh" has to be installed.
Domoticz can also calculate the Energy, based on the Power, but that widget cannot be used as input to the Energy Dashboard.
I need a Text device for that.
Perhaps a suggestion to @gizmocuz to make that possible.
After testing over a longer period and some fine-tuning, I think it is time to share it with the community.
A picture of the flow see below.
Code: Select all
[
{
"id": "38eba13e2b291140",
"type": "tab",
"label": "Electricity Map",
"disabled": false,
"info": "",
"env": []
},
{
"id": "47ea0daa093a0e0e",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Request Areas",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 180,
"y": 400,
"wires": [
[
"3a9e851de597d511"
]
]
},
{
"id": "3a9e851de597d511",
"type": "http request",
"z": "38eba13e2b291140",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.electricitymap.org/v3/zones",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 390,
"y": 400,
"wires": [
[
"7ced18af8ff74714"
]
]
},
{
"id": "7ced18af8ff74714",
"type": "debug",
"z": "38eba13e2b291140",
"name": "debug 272",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 590,
"y": 400,
"wires": []
},
{
"id": "eb852f83ee231945",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Get Domoticz Settings",
"props": [],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 200,
"y": 120,
"wires": [
[
"57780ec1ad27d090"
]
]
},
{
"id": "57780ec1ad27d090",
"type": "http request",
"z": "38eba13e2b291140",
"name": "Check Domoticz Settings",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://192.168.10.50:8080/json.htm?type=command¶m=getsettings",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 470,
"y": 120,
"wires": [
[
"78ba556b0e4c6897"
]
]
},
{
"id": "78ba556b0e4c6897",
"type": "change",
"z": "38eba13e2b291140",
"name": "Import Home Lat/Lon",
"rules": [
{
"t": "set",
"p": "homeLat",
"pt": "global",
"to": "payload.Location.Latitude",
"tot": "msg"
},
{
"t": "set",
"p": "homeLon",
"pt": "global",
"to": "payload.Location.Longitude",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 740,
"y": 120,
"wires": [
[
"2570cecd25c0c4cc"
]
]
},
{
"id": "6750401a206385d6",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Start",
"props": [],
"repeat": "30",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 150,
"y": 600,
"wires": [
[
"9adb98a595f08fbc"
]
]
},
{
"id": "dc2492dfc9d7baa0",
"type": "comment",
"z": "38eba13e2b291140",
"name": "Zones",
"info": "",
"x": 390,
"y": 360,
"wires": []
},
{
"id": "797e8bf67221bd06",
"type": "comment",
"z": "38eba13e2b291140",
"name": "Carbon Intensity",
"info": "",
"x": 540,
"y": 560,
"wires": []
},
{
"id": "02809b553e120547",
"type": "comment",
"z": "38eba13e2b291140",
"name": "Check Global Lat/Lon",
"info": "",
"x": 980,
"y": 60,
"wires": []
},
{
"id": "29bbcc343972c09e",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Request Health",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 180,
"y": 300,
"wires": [
[
"d21c9d04e9adac83"
]
]
},
{
"id": "d21c9d04e9adac83",
"type": "http request",
"z": "38eba13e2b291140",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.electricitymap.org/health",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 390,
"y": 300,
"wires": [
[
"47330cb648c5ef3b"
]
]
},
{
"id": "47330cb648c5ef3b",
"type": "debug",
"z": "38eba13e2b291140",
"name": "debug 277",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 590,
"y": 300,
"wires": []
},
{
"id": "03fe1f30617003cb",
"type": "comment",
"z": "38eba13e2b291140",
"name": "API Health",
"info": "",
"x": 400,
"y": 260,
"wires": []
},
{
"id": "1b38ec45eb389464",
"type": "comment",
"z": "38eba13e2b291140",
"name": "Live power breakdown",
"info": "",
"x": 760,
"y": 660,
"wires": []
},
{
"id": "e2b96b2acef9687e",
"type": "comment",
"z": "38eba13e2b291140",
"name": "Retrieve Domoticz Lat/Lon coordinates and store these in Global variables",
"info": "",
"x": 580,
"y": 60,
"wires": []
},
{
"id": "2849bf72b217d1c6",
"type": "function",
"z": "38eba13e2b291140",
"name": "Carbon Intensity to Domoticz",
"func": "msg.payload = { \"command\": \"udevice\", \"idx\": 650, \"svalue\": msg.payload.carbonIntensity.toString() }\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 800,
"y": 600,
"wires": [
[
"0644f915d488aba7"
]
]
},
{
"id": "0644f915d488aba7",
"type": "mqtt out",
"z": "38eba13e2b291140",
"name": "To Domoticz",
"topic": "domoticz/in",
"qos": "0",
"retain": "false",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "7aff5cd755ba2941",
"x": 1050,
"y": 600,
"wires": []
},
{
"id": "71f182d3980c16bf",
"type": "mqtt in",
"z": "38eba13e2b291140",
"name": "Domoticz Out",
"topic": "domoticz/out",
"qos": "0",
"datatype": "auto-detect",
"broker": "7aff5cd755ba2941",
"nl": false,
"rap": false,
"inputs": 0,
"x": 130,
"y": 700,
"wires": [
[
"cb34da93c0df30ae"
]
]
},
{
"id": "cb34da93c0df30ae",
"type": "switch",
"z": "38eba13e2b291140",
"name": "Filter P1 meter",
"property": "payload.idx",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "17",
"vt": "num"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 340,
"y": 700,
"wires": [
[
"06532e8d36b6425d"
]
]
},
{
"id": "2570cecd25c0c4cc",
"type": "change",
"z": "38eba13e2b291140",
"name": "Check lat/Lon",
"rules": [
{
"t": "delete",
"p": "payload",
"pt": "msg"
},
{
"t": "set",
"p": "payload.Lat",
"pt": "msg",
"to": "homeLat",
"tot": "global"
},
{
"t": "set",
"p": "payload.Lon",
"pt": "msg",
"to": "homeLon",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 980,
"y": 120,
"wires": [
[
"f68d9f4a12c9489a"
]
]
},
{
"id": "f68d9f4a12c9489a",
"type": "debug",
"z": "38eba13e2b291140",
"name": "debug 284",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1190,
"y": 120,
"wires": []
},
{
"id": "06532e8d36b6425d",
"type": "change",
"z": "38eba13e2b291140",
"name": "Store variables",
"rules": [
{
"t": "set",
"p": "totalPowerGrid",
"pt": "flow",
"to": "payload.svalue5",
"tot": "msg"
},
{
"t": "set",
"p": "lat",
"pt": "msg",
"to": "homeLat",
"tot": "global"
},
{
"t": "set",
"p": "lon",
"pt": "msg",
"to": "homeLon",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 560,
"y": 700,
"wires": [
[
"0b5559dabc93d987"
]
]
},
{
"id": "0b5559dabc93d987",
"type": "http request",
"z": "38eba13e2b291140",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.electricitymap.org/v3/power-breakdown/latest?lat={{{lat}}}&lon={{{lon}}}",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [
{
"keyType": "other",
"keyValue": "auth-token",
"valueType": "other",
"valueValue": "YbDsNLqFKuJaZ"
}
],
"x": 770,
"y": 700,
"wires": [
[
"131a3795372a54bc"
]
]
},
{
"id": "131a3795372a54bc",
"type": "function",
"z": "38eba13e2b291140",
"name": "Set Fossil-free Power",
"func": "msg.topic = \"fossilFreePower\";\n\nflow.set(\"ffpower\", (Number(flow.get(\"totalPowerGrid\")) * (msg.payload.fossilFreePercentage / 100)));\n\nmsg.payload = flow.get(\"ffpower\");\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1000,
"y": 700,
"wires": [
[
"58d0e70c57c59a32"
]
]
},
{
"id": "58d0e70c57c59a32",
"type": "watt2kwh",
"z": "38eba13e2b291140",
"format": "kwh",
"maximum": "60",
"maximumunit": "mins",
"name": "Energy Calc.",
"x": 1230,
"y": 700,
"wires": [
[
"a188464d18e4940f"
]
]
},
{
"id": "e3eb2523fb6562af",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Reset Midnight",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "00 00 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "reset",
"payloadType": "str",
"x": 1210,
"y": 760,
"wires": [
[
"a188464d18e4940f"
]
]
},
{
"id": "a188464d18e4940f",
"type": "function",
"z": "38eba13e2b291140",
"name": "Fossil-free to Domoticz",
"func": "let msg1 = {};\nlet msg2 = {};\nmsg1.topic = \"fossilFreePowerEnergy\";\nmsg2.topic = \"fossilFreeEnergy\";\n\nif (msg.payload == \"reset\") {\n flow.set(\"ffEnergy\", 0);\n} else {\n let storedVal = flow.get(\"ffEnergy\") || 0;\n storedVal += msg.payload;\n// flow.set(\"ffEnergy\", (flow.get(\"ffEnergy\"),storedVal));\n flow.set(\"ffEnergy\", storedVal);\n\nmsg1.payload = { \"command\": \"udevice\", \"idx\": 656, \"svalue\": flow.get(\"ffpower\").toFixed(0) + \";\" + (flow.get(\"ffEnergy\") * 1000).toFixed(0)};\nmsg2.payload = { \"command\": \"udevice\", \"idx\": 652, \"svalue\": \"Fossil free Energy: \" + flow.get(\"ffEnergy\").toFixed(3) + \" kWh\" };\n\nreturn [[msg1,msg2]];\n}",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1470,
"y": 700,
"wires": [
[
"47bf4a712b389eb9",
"00eb0671e8713d71"
]
]
},
{
"id": "00eb0671e8713d71",
"type": "mqtt out",
"z": "38eba13e2b291140",
"name": "To Domoticz",
"topic": "domoticz/in",
"qos": "0",
"retain": "false",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "7aff5cd755ba2941",
"x": 1710,
"y": 700,
"wires": []
},
{
"id": "47bf4a712b389eb9",
"type": "debug",
"z": "38eba13e2b291140",
"name": "debug 290",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1710,
"y": 760,
"wires": []
},
{
"id": "46c0661344ebc0e4",
"type": "http request",
"z": "38eba13e2b291140",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.electricitymap.org/v3/carbon-intensity/latest?lat={{{lat}}}&lon={{{lon}}}",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [
{
"keyType": "other",
"keyValue": "auth-token",
"valueType": "other",
"valueValue": "YbDsNLqFKuJaZ"
}
],
"x": 550,
"y": 600,
"wires": [
[
"2849bf72b217d1c6"
]
]
},
{
"id": "9adb98a595f08fbc",
"type": "change",
"z": "38eba13e2b291140",
"name": "Store variables",
"rules": [
{
"t": "set",
"p": "lat",
"pt": "msg",
"to": "homeLat",
"tot": "global"
},
{
"t": "set",
"p": "lon",
"pt": "msg",
"to": "homeLon",
"tot": "global"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 600,
"wires": [
[
"46c0661344ebc0e4"
]
]
},
{
"id": "d493d15681a6f831",
"type": "function",
"z": "38eba13e2b291140",
"name": "Set URL/API key/Lat/Lon",
"func": "msg.headers = {};\nmsg.headers['auth-token'] = \"YbDsNLqFKuJaZ\";\n\nmsg.url = \"https://api.electricitymap.org/v3/power-breakdown/latest?lat=\" + global.get(\"homeLat\") + \"&lon=\" + global.get(\"homeLon\");\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1210,
"y": 1460,
"wires": [
[
"9a76d040e6a5832f"
]
]
},
{
"id": "9a76d040e6a5832f",
"type": "http request",
"z": "38eba13e2b291140",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 1450,
"y": 1460,
"wires": [
[
"e6192d31446baaa7"
]
]
},
{
"id": "e6192d31446baaa7",
"type": "change",
"z": "38eba13e2b291140",
"name": "Collect Fossil-free percentage",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.fossilFreePercentage",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "fossilFreePercentage",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1710,
"y": 1460,
"wires": [
[
"2b799b7f6a5a60f7"
]
]
},
{
"id": "98a96603de0d6af8",
"type": "change",
"z": "38eba13e2b291140",
"name": "Collect Total Power Grid",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.svalue5",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "totalPowerGrid",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1730,
"y": 1540,
"wires": [
[
"2b799b7f6a5a60f7"
]
]
},
{
"id": "2b799b7f6a5a60f7",
"type": "join",
"z": "38eba13e2b291140",
"name": "Join Power Grid Percentage",
"mode": "custom",
"build": "object",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\\n",
"joinerType": "str",
"useparts": false,
"accumulate": false,
"timeout": "",
"count": "2",
"reduceRight": false,
"reduceExp": "",
"reduceInit": "",
"reduceInitType": "",
"reduceFixup": "",
"x": 2030,
"y": 1500,
"wires": [
[
"e22f4a964bdf5e54",
"2b2b5866db754842"
]
]
},
{
"id": "2b2b5866db754842",
"type": "function",
"z": "38eba13e2b291140",
"name": "String2Number",
"func": "msg.topic = \"fossilFreePower\";\n\nmsg.payload = Number(msg.payload.totalPowerGrid) * (msg.payload.fossilFreePercentage / 100);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2300,
"y": 1540,
"wires": [
[
"cf02c272945bd1e2"
]
]
},
{
"id": "e22f4a964bdf5e54",
"type": "function",
"z": "38eba13e2b291140",
"name": "Calculate Fossil-free percentage to Domoticz",
"func": "let ffpower = Number(msg.payload.totalPowerGrid) * (msg.payload.fossilFreePercentage / 100);\n\nmsg.payload = { \"command\": \"udevice\", \"idx\": 651, \"svalue\": ffpower.toFixed(0) + \";0\" };\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2400,
"y": 1460,
"wires": [
[]
]
},
{
"id": "cf02c272945bd1e2",
"type": "watt2kwh",
"z": "38eba13e2b291140",
"format": "kwh",
"maximum": "60",
"maximumunit": "mins",
"name": "Energy Calc.",
"x": 2510,
"y": 1540,
"wires": [
[
"3ee1b453b632de64"
]
]
},
{
"id": "3953a16fefa09bdf",
"type": "inject",
"z": "38eba13e2b291140",
"name": "Reset Midnight",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "00 00 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "reset",
"payloadType": "str",
"x": 2490,
"y": 1580,
"wires": [
[
"3ee1b453b632de64"
]
]
},
{
"id": "3ee1b453b632de64",
"type": "function",
"z": "38eba13e2b291140",
"name": "Fossil-free Text to Domoticz",
"func": "msg.topic = \"fossilFreeEnergy\";\n\nlet inputVal = msg.payload;\nif (inputVal == \"reset\") {\n flow.set(\"energyVal\", 0);\n} else {\n let savedVal = flow.get(\"energyVal\") || 0;\n savedVal += inputVal;\n flow.set(\"energyVal\", savedVal);\n msg.payload = { \"command\": \"udevice\", \"idx\": 652, \"svalue\": \"Fossil free Energy: \" + savedVal.toFixed(3) + \" kWh\" };\nreturn msg;\n}",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2760,
"y": 1540,
"wires": [
[]
]
},
{
"id": "7aff5cd755ba2941",
"type": "mqtt-broker",
"name": "Jonas_MQTT_Server",
"broker": "192.168.10.24",
"port": "1883",
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
}
]
To use the flow do the following:
1. Go to the URL: https://www.electricitymaps.com/free-tier-api and get your free API key.
2. Create 3 Dummy devices:
1. Custom Sensor and for the Horizontal (x-axes) axis insert gCO2eq/Watt2kWh
2. Electric (Instant + Counter) Sensor. Set the configuration to Type: "Usage" and Energy read: "From device".
Actually it doesn't matter, whether Domoticz calculate the Energy or node-RED.
I preferred Node RED, just to be sure that the Electricity device and the Text device show exactly the same value
3. Text device. In Settings ==> Devices set this sensor to "Unused" after you configured the Energy dashboard.
(This sensor is only used as Text device in the Energy Dashboard).
3. Note down the IDX of your 3 newly created sensors
4. In the "http request" node insert your API key in the "Header" section. Note: Not necessary in the first 2 streams (API Health and Zones)
5. For the "Carbon Intensity" insert the correct IDX for Domoticz.
6. In the "Filter P1 meter" insert the correct IDX for your P1 device in Domoticz.
7. From the "Palette" install the "Custom" node, called "node-red-contrib-watt2kwh".
8. In the "Function" node, configure the correct IDX's in line 14 and 15.
You can select either the "Electricity" device or the "Text" device or both by modifying the "Function" node.
9. Configure your MQTT server.
Note: Replace in the links above hxxps into https.
I'm open for ideas, comment or suggestions.
Regards