I have made detailed instructions as well for setting up MQTT that might be helpfull for others:
In your example, as well as on the Russian site, an error was made.
The tvoc unit is âmg/mÂłâ and not â”g/mÂłâ.
For myself, I did not divide by 218.77 and round, but use the value sent by Qingping Air Monitor. And he indicated that the unit of measurement is ppb. I donât even understand why, but somehow itâs closer to me.
I followed your instructions, but the airmonitor doesnât appear in HA.
Here are my Mosquitto broker HA-Addon logs:
[18:33:10] INFO: Successfully send discovery information to Home Assistant.
[18:33:10] INFO: Successfully send service information to the Supervisor.
2023-10-23 18:33:32: New connection from 192.168.0.65:56605 on port 1883.
2023-10-23 18:33:32: New client connected from 192.168.0.65:56605 as qingping-582D340140AD (p2, c1, k30, u'homeassistant').
2023-10-23 18:33:32: Client qingping-582D340140AD disconnected.
2023-10-23 18:33:35: New connection from 172.30.32.1:33043 on port 1883.
2023-10-23 18:33:35: New client connected from 172.30.32.1:33043 as 5B8xCiLMCdE3hNZyUorIe9 (p2, c1, k60, u'homeassistant').
2023-10-23 18:34:02: New connection from 192.168.0.65:56606 on port 1883.
2023-10-23 18:34:02: New client connected from 192.168.0.65:56606 as qingping-582D340140AD (p2, c1, k30, u'homeassistant').
2023-10-23 18:34:21: New connection from 172.30.32.1:46279 on port 1883.
2023-10-23 18:34:21: New client connected from 172.30.32.1:46279 as 1ulw4OlKfryhWGB6963n88 (p2, c1, k60, u'homeassistant').
2023-10-23 18:34:55: New connection from 172.30.32.2:40632 on port 1883.
2023-10-23 18:34:55: Client <unknown> closed its connection.
2023-10-23 18:35:09: Client 2GhIwVS8iKclb6ffsKYVBU has exceeded timeout, disconnecting.
2023-10-23 18:35:51: Client 5B8xCiLMCdE3hNZyUorIe9 has exceeded timeout, disconnecting.
2023-10-23 18:36:46: Client qingping-582D340140AD disconnected.
2023-10-23 18:36:47: New connection from 192.168.0.65:56630 on port 1883.
2023-10-23 18:36:47: New client connected from 192.168.0.65:56630 as qingping-582D340140AD (p2, c1, k30, u'homeassistant').
2023-10-23 18:36:55: New connection from 172.30.32.2:40896 on port 1883.
2023-10-23 18:36:55: Client <unknown> closed its connection.
Sorry, canât help with this. The instructions are limited to sending data to a MQTT broker, which seems to be happening in your case. Why it is not showing in HA, I donât know Iâm using HA Core and to have it work there you need to add template sensors. Not sure, if you need that as well. If you do, check some samples in my repository under the issue section. Someone asked recently.
never mind, got it to work, thanks !
Iâm just wondering, the CGS1 is not advertised to have PM10 detection, how come we can pull data from it?
Also here is my HA config: (replace MACID with the CGS1âs MAC ID, without dashes)
mqtt:
sensor:
- object_id: AIR_co2
name: "Air CO2"
state_topic: "qingping/MACID/up"
device_class: carbon_dioxide
unique_id: "qingping_dioxide"
value_template: >-
{{ value_json.sensorData.0.co2.value
if value_json.type=="12" }}
unit_of_measurement: "ppm"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: AIR_pm25
name: "Air pm25"
state_topic: "qingping/MACID/up"
device_class: pm25
unique_id: "qingping_pm25"
value_template: >-
{{ value_json.sensorData.0.pm25.value
if value_json.type=="12" and value_json.sensorData.0.pm25.status==0 }}
unit_of_measurement: "”g/m³"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: AIR_pm10
name: "Air pm10"
state_topic: "qingping/MACID/up"
device_class: pm10
unique_id: "qingping_pm10"
value_template: >-
{{ value_json.sensorData.0.pm10.value
if value_json.type=="12" }}
unit_of_measurement: "”g/m³"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: AIR_tvoc
name: "Air tvoc"
state_topic: "qingping/MACID/up"
device_class: volatile_organic_compounds
unique_id: "qingping_tvoc"
value_template: >-
{{ (value_json.sensorData.0.tvoc.value/218.77)|round(3)
if value_json.type=="12" and value_json.sensorData.0.tvoc.status==0 }}
unit_of_measurement: "ppb"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: AIR_hum
name: "Air humidity"
state_topic: "qingping/MACID/up"
device_class: humidity
unique_id: "qingping_hum"
value_template: >-
{{ value_json.sensorData.0.humidity.value|round(2)
if value_json.type=="12" and value_json.sensorData.0.humidity.status==0 }}
unit_of_measurement: "%"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: AIR_temp
name: "Air temp"
state_topic: "qingping/MACID/up"
device_class: temperature
unique_id: "qingping_temp"
value_template: >-
{{ value_json.sensorData.0.temperature.value|round(2)
if value_json.type=="12" and value_json.sensorData.0.temperature.status==0 }}
unit_of_measurement: "°C"
device:
identifiers: ["MACID"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
I also gather that it is limited to pulling data every 15 minutes? no way of making that shorter?
Actually, it is. You can use MQTT to send the configuration to your device: https://developer.qingping.co/main/private/public_mqtt#316-modify-data-report-interval
I set 15 seconds for mine, works without problems
Youâre correct about the wrong unit, however the dividing by 218.77 is giving me the correct value.
Hello, can you describe how to send configuration to my device?
Iâm too noob to understand your comment.
So, you configured yours to work with MQTT right? Take the MQTT client application, for example [https://mqtt-explorer.com/](https://MQTT Explorer). You be able to find your device reporting topic, it depends on how you configured it on the Private Access Config page. In my case, it is: qingping/<device_mac_address>/up
.
To send a command to devise use qingping/<device_mac_address>/down
topic
Send something like:
{
"id": 1,
"need_ack": 1,
"type": "17",
"setting": {
"report_interval": 15,
"collect_interval": 15,
"co2_sampling_interval": 15,
"pm_sampling_interval":15
}
}
That should do the trick
I can now see in MQTT explorer new data every 15 sec, but in HA MQTT it still only refreshes once every 15 minutesâŠ
Just unpacked my air sensor, found this thread, and got everything up and running. Same problem here that HA MQTT still refreshes once every 15 minutes. This is the configuration message what I sent via HA:
service: mqtt.publish
data:
topic: qingping/<device_mac_address>/down
payload: >-
{"id":1,"need_ack":1,"type":"17","setting":{"report_interval":15,"collect_interval":15,"co2_sampling_interval":15,"pm_sampling_interval":15}}
I worked it out. Problem is that type=="12"
messages are only sent every 15 minutes, and the configuration message above only configures the interval for type=="17
messages. These contain a history of values but also the latest value. So this YAML works pretty well for me:
mqtt:
sensor:
- object_id: air_monitor_co2
name: "CO2"
unique_id: "qingping_air_monitor_<device_mac_address>_co2"
device_class: carbon_dioxide
unit_of_measurement: "ppm"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ value_json.sensorData.0.co2.value
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_co2_status
name: "CO2 Status"
unique_id: "qingping_air_monitor_<device_mac_address>_co2_status"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ {0: "normal", 1: "erhöht", 2: "hoch", 3: "sehr hoch"}[[1000, 2000, 3000] | select("<=", value_json.sensorData.0.co2.status | float(0)) | list | length]
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_pm25
name: "PM2.5"
unique_id: "qingping_air_monitor_<device_mac_address>_pm25"
device_class: pm25
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ value_json.sensorData.0.pm25.value
if value_json.type=="17" else this.state }}
unit_of_measurement: "”g/m³"
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_pm25_status
name: "PM2.5 Status"
unique_id: "qingping_air_monitor_<device_mac_address>_pm25_status"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ {0: "gut", 1: "moderat", 2: "leicht ungesund", 3: "ungesund", 4: "sehr ungesund", 5: "gefÀhrlich"}[value_json.sensorData.0.pm25.status]
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_pm10
name: "PM1.0"
unique_id: "qingping_air_monitor_<device_mac_address>_pm10"
device_class: pm10
unit_of_measurement: "”g/m³"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ value_json.sensorData.0.pm10.value
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_pm10_status
name: "PM1.0 Status"
unique_id: "qingping_air_monitor_<device_mac_address>_pm10_status"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ {0: "gut", 1: "moderat", 2: "leicht ungesund", 3: "ungesund", 4: "sehr ungesund", 5: "gefÀhrlich"}[value_json.sensorData.0.pm10.status]
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_tvoc
name: "TVOC"
unique_id: "qingping_air_monitor_<device_mac_address>_tvoc"
device_class: volatile_organic_compounds
unit_of_measurement: "ppb"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ (value_json.sensorData.0.tvoc.value / 218.77) | round(3)
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_tvoc_status
name: "TVOC Status"
unique_id: "qingping_air_monitor_<device_mac_address>_tvoc_status"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ {0: "ausgezeichnet", 1: "gut", 2: "erhöht", 3: "hoch", 4: "sehr hoch"}[[0.3, 1, 3, 9] | select("<=", (value_json.sensorData.0.tvoc.value / 218.77)| round(3)) | list | length]
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_humidity
name: "Luftfeuchtigkeit"
unique_id: "qingping_air_monitor_<device_mac_address>_humidity"
device_class: humidity
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ value_json.sensorData.0.humidity.value|round(2)
if value_json.type=="17" else this.state }}
unit_of_measurement: "%"
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
- object_id: air_monitor_temperature
name: "Temperatur"
unique_id: "qingping_air_monitor_<device_mac_address>_temperature"
device_class: temperature
unit_of_measurement: "°C"
state_topic: "qingping/<device_mac_address>/up"
value_template: >-
{{ value_json.sensorData.0.temperature.value|round(2)
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/<device_mac_address>/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["<device_mac_address>"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
I also worked out availability, graceful behavior against messages of type!="17
(the else this.state
thing), and sensors for the different regimes of the sensor values (except the area in the T/rH diagram). Since the status can actually (and probably should, DRY principle!) be derived from the sensor value it can be implemented as plain template sensor (not platform: mqtt
).
This is the prefinal version with derived template sensors for the status values:
mqtt:
sensor:
- name: "CO2"
object_id: air_monitor_co2
device_class: carbon_dioxide
unit_of_measurement: "ppm"
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ value_json.sensorData.0.co2.value
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: f0864ae1d3e66cdb5a29c894dd6a192f8ba528ec
- name: "PM2.5"
object_id: air_monitor_pm25
device_class: pm25
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ value_json.sensorData.0.pm25.value
if value_json.type=="17" else this.state }}
unit_of_measurement: "”g/m³"
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: 0c4f328dd042cdfc17f01ec2f880e7dd5317750b
- name: "PM10"
object_id: air_monitor_pm10
device_class: pm10
unit_of_measurement: "”g/m³"
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ value_json.sensorData.0.pm10.value
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: 0e330464965310305e8df5187ba00e5a6b515471
- name: "TVOC"
object_id: air_monitor_tvoc
device_class: volatile_organic_compounds
unit_of_measurement: "mg/mÂł"
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ (value_json.sensorData.0.tvoc.value / 218.77) | round(3)
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: 145ba4f594273ed8cfcf44f8df1983e3a229b0d1
- name: "Luftfeuchtigkeit"
object_id: air_monitor_humidity
device_class: humidity
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ value_json.sensorData.0.humidity.value|round(2)
if value_json.type=="17" else this.state }}
unit_of_measurement: "%"
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: 5648fe503a9c4c7563643425de97f184a3282a66
- object_id: air_monitor_temperature
name: "Temperatur"
device_class: temperature
unit_of_measurement: "°C"
state_topic: "qingping/582D34700B3E/up"
value_template: >-
{{ value_json.sensorData.0.temperature.value|round(2)
if value_json.type=="17" else this.state }}
availability:
- topic: "qingping/582D34700B3E/up"
payload_available: "true"
payload_not_available: "false"
value_template: >-
{{ "true" if value_json else "false" }}
device:
identifiers: ["582D34700B3E"]
name: "Air monitor"
model: "CGS1"
manufacturer: "qingping"
unique_id: eeac725e7c2bc220e8ef3602b7a506a9855a36c6
template:
- sensor:
- name: "Air Monitor CO2 Status"
unique_id: air_monitor_co2_status
state: >
{{ {0: "normal", 1: "erhöht", 2: "hoch", 3: "sehr hoch"}[
[1000, 2000, 3000] | select("<=", states('sensor.air_monitor_co2') | float(0)) | list | length
] }}
availability: >
{{ not is_state('sensor.air_monitor_tvoc', 'unavailable') }}
icon: mdi:molecule
- name: "Air Monitor PM2.5 Status"
unique_id: air_monitor_pm25_status
state: >
{{ {0: "gut", 1: "moderat", 2: "etwas ungesund", 3: "ungesund", 4: "sehr ungesund", 5: "gefÀhrlich"}[
[12, 35, 55, 150, 250] | select("<=", states('sensor.air_monitor_pm25') | float(0) ) | list | length
] }}
availability: >
{{ not is_state('sensor.air_monitor_pm25', 'unavailable') }}
icon: mdi:molecule
- name: "Air Monitor TVOC Status"
unique_id: air_monitor_tvoc_status
state: >
{{ {0: "ausgezeichnet", 1: "gut", 2: "erhöht", 3: "hoch", 4: "sehr hoch"}[
[0.3, 1, 3, 9] | select("<=", states('sensor.air_monitor_tvoc') | float(0) ) | list | length
] }}
availability: >
{{ not is_state('sensor.air_monitor_tvoc', 'unavailable') }}
icon: mdi:molecule
I generated the unique IDs as follows (pbcopy
is a Mac command):
$ date +%s | shasum | pbcopy
If anyone knows what the US thresholds and descriptions for PM10 are Iâm happy to learn.
And this is a Lovelace card with colored status:
type: entities
entities:
- entity: sensor.air_monitor_co2_status
type: custom:multiple-entity-row
name: COâ
secondary_info: false
show_state: false
show_header: false
entities:
- entity: sensor.air_monitor_co2
name: false
- icon: mdi:circle
card_mod:
style:
hui-generic-entity-row $: ''
.: |
div.entity:nth-child(2) state-badge {
color: {{ {"normal": "green", "erhöht": "yellow", "hoch": "orange", "sehr hoch": "red"}[states('sensor.air_monitor_co2_status')] }}
}
- entity: sensor.air_monitor_pm25_status
type: custom:multiple-entity-row
name: Feinstaub (PM2.5)
secondary_info: false
show_state: false
show_header: false
entities:
- entity: sensor.air_monitor_pm25
name: false
- icon: mdi:circle
card_mod:
style:
hui-generic-entity-row $: ''
.: |
div.entity:nth-child(2) state-badge {
color: {{ {"gut": "green", "moderat": "yellow", "etwas ungesund": "orange", "ungesund": "red", "sehr ungesund": "purple", "gefÀhrlich": "brown"}[states('sensor.air_monitor_pm25_status')] }}
}
- entity: sensor.air_monitor_tvoc_status
type: custom:multiple-entity-row
name: flĂŒchtige organische Verbindungen
secondary_info: false
show_state: false
show_header: false
entities:
- entity: sensor.air_monitor_tvoc
name: false
- icon: mdi:circle
card_mod:
style:
hui-generic-entity-row $: ''
.: |
div.entity:nth-child(2) state-badge {
color: {{ {"ausgezeichnet": "green", "gut": "green", "erhöht": "yellow", "hoch": "red", "sehr hoch": "brown"}[states('sensor.air_monitor_tvoc_status')] }}
}
It makes use of the HACS frontend addons card-mod and Multiple Entity Row.
Another possible approach that doesnât require accounting for type 17 (history) vs type 12 (regular) messages within the sensor data is you can send:
MQTT Payload
{
"type" : "12",
"up_itvl" : "15",
"duration": "86400"
}
Destination
qingping/replace_with_your_id/down
From the Qingping docs (https://developer.qingping.co/main/private/public_mqtt#312-server-send-setting-for-temporary-report-and-duration-time)
The original duration value was 60 seconds, so far the 86400 seconds (24 hours) value appears to be working, which Iâll send once a day with an HA automation. up_itvl was set at 15 seconds, which worked but I later changed to 60 to avoid logging too much data.
jadz, Thanks. This is a great solution for me.
Remove the content type in the request. Not sure why but qingping will return an error when itâs set.
Thank you so much, i can add it
but i got problem, it refresh every 14-15minute, and when refresh the number is abnormal, when see at graph will show like this, how can i fix it
Does anyone use the Qingping Air Monitor Gen 2 (CGS2) with HA? Iâm new to HA and Iâm wondering if it would be safer to buy CGS1 or officially supported Lite CGDN1. Thanks