PREFACE
The solution below makes use of Node-RED and a MQTT server configured in Home Assistant. Directions on how to install and setup them are not provided herein.
Node-RED Home Assistant palette is not required.
BACKGROUND
I own an air quality sensor enrolled in the Sensor.Community.
I make use of the corresponding Home Assistant integration to plot the values accordingly.
THE ISSUE
I have been experiencing plot quality issues for quite sometime:
THE ANALYSIS
The header of the HA log shows: Unexpected error fetching luftdaten_XXXXX data
which seems concerning a timeout issue. I found the issue has been registered in GitHub.
Note
Although the GitHub issue is closed, I still experience the problem.
THE SOLUTION
The solution I built is based on the workaround posted by ignisf in GitHub.
I decided to make use of Node-RED to solve the issue.
The Node-RED Flow
The Flow in JSON
[
{
"id": "c5bc630a86565761",
"type": "tab",
"label": "Home Assistant & Sensor.Community",
"disabled": false,
"info": "",
"env": []
},
{
"id": "caae032a51a9ec72",
"type": "http request",
"z": "c5bc630a86565761",
"name": "luftdaten API",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 550,
"y": 160,
"wires": [
[
"0ee3fca891178449"
]
]
},
{
"id": "c1c520a860d82996",
"type": "inject",
"z": "c5bc630a86565761",
"name": "sensorId",
"props": [
{
"p": "payload"
}
],
"repeat": "300",
"crontab": "",
"once": true,
"onceDelay": "30",
"topic": "",
"payload": "",
"payloadType": "str",
"x": 160,
"y": 160,
"wires": [
[
"195d30fdbe19ea29"
]
]
},
{
"id": "a56737d36492e822",
"type": "mqtt out",
"z": "c5bc630a86565761",
"name": "HA MQTT",
"topic": "",
"qos": "",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "28edf644b1616230",
"x": 1220,
"y": 160,
"wires": []
},
{
"id": "8604b48a797bf09e",
"type": "debug",
"z": "c5bc630a86565761",
"name": "to MQTT",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1220,
"y": 120,
"wires": []
},
{
"id": "0ee3fca891178449",
"type": "switch",
"z": "c5bc630a86565761",
"name": "Is empty or error?",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "empty"
},
{
"t": "nempty"
},
{
"t": "cont",
"v": "RequestError",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 3,
"x": 770,
"y": 160,
"wires": [
[
"3032f69cb8eed27a"
],
[
"a9a1975ce7be5c0e"
],
[
"f86a3e4651d21fb2"
]
]
},
{
"id": "3032f69cb8eed27a",
"type": "debug",
"z": "c5bc630a86565761",
"name": "empty",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 970,
"y": 120,
"wires": []
},
{
"id": "195d30fdbe19ea29",
"type": "change",
"z": "c5bc630a86565761",
"name": "",
"rules": [
{
"t": "set",
"p": "url",
"pt": "msg",
"to": "\"https://data.sensor.community/airrohr/v1/sensor/\" & msg.payload & \"/\"",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 350,
"y": 160,
"wires": [
[
"caae032a51a9ec72"
]
]
},
{
"id": "f94524013fa18737",
"type": "comment",
"z": "c5bc630a86565761",
"name": "Luftdaten - Home Assistant Integration",
"info": "**RELEASE NOTES**\n\n**Author**: Tamadite\n\n**Date**: November 14th, 2022\n\n**Reference**: https://github.com/home-assistant/core/issues/61687\n\n1. Type the **sensorId** in the injector, e.g. 12345\n2. P1 -> PM10 --- UoM: µg/m³\n3. P2 -> PM2.5 --- UoM: µg/m³\n4. The solution assumes that API response object[0] provides latest update. \n\n",
"x": 230,
"y": 80,
"wires": []
},
{
"id": "a9a1975ce7be5c0e",
"type": "function",
"z": "c5bc630a86565761",
"name": "get PM10 & PM2.5",
"func": "var i = 0;\nvar found = 0; // counter when P1 or P2 is found\nvar msg_out = []; // array for message objects\n\nwhile (i < msg.payload[0].sensordatavalues.length && found < 2) {\n var newmsg = null;\n if (msg.payload[0].sensordatavalues[i].value_type == \"P1\") {\n newmsg = {payload: msg.payload[0].sensordatavalues[i].value, topic: \"luftdaten/\" + msg.payload[0].sensor.id + \"/PM10\"};\n found ++;\n } else {\n if (msg.payload[0].sensordatavalues[i].value_type == \"P2\") {\n newmsg = {payload: msg.payload[0].sensordatavalues[i].value, topic: \"luftdaten/\" + msg.payload[0].sensor.id + \"/PM2_5\"};\n found ++;\n }\n }\n if (newmsg) {\n msg_out.push(newmsg);\n }\n i ++;\n}\nreturn [msg_out];",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1010,
"y": 160,
"wires": [
[
"8604b48a797bf09e",
"a56737d36492e822"
]
]
},
{
"id": "f86a3e4651d21fb2",
"type": "debug",
"z": "c5bc630a86565761",
"name": "error",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 970,
"y": 200,
"wires": []
},
{
"id": "28edf644b1616230",
"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": ""
}
]
Node-RED Flow Notes
- The Injector node needs to be configured with the sensorId.
- The sensorId can be retrieved from the sensor.community map when clicking on the desire station.
- The Injector automatically starts 30 seconds after deployment (see Injector node).
- The Injector repeat interval is set to every five minutes (see Injector node).
- The MQTT Out node has to be configured with the corresponding MQTT server used by HA.
- The Switch node is necessary because the API returns empty sometimes.
- The flow assumes the API response object [0] contains the latest update.
- The data gets published in MQTT as:
**luftdaten/[sensorId]/PM10
**luftdaten/[sensorId]/PM2_5
The HA Configuration
In the configuration.yaml
file under section mqtt:
add the following:
mqtt:
sensor:
- name: "luftdaten_pm10"
state_topic: "luftdaten/[sensorId]/PM10"
unit_of_measurement: "μg/m³"
- name: "luftdaten_pm2_5"
state_topic: "luftdaten/[sensorId]/PM2_5"
unit_of_measurement: "μg/m³"
Remark: Replace [sensorId]
by the sensorId introduced in the Node-RED Injector node.
THE RESULT
FINAL NOTE
The Sensor Community was formerly known as Luftdaten.