Over the past few years I’ve been having lots of fun playing with Home Assistant and home automation in general. One of the things which is underdocumented but kind of interesting is how to get air quality monitors connected to Home Assistant.

I currently use two different types of air quality monitors, both made by Qingping. There are, of course, alternatives, but the Qingping devices are reasonably priced when they’re on sale and they tend to look pretty nice.

Air Quality Monitor (CGS-1)

The Qingping Air Quality Monitor is actually pretty full-featured. It has a touchscreen where you can configure connecting it to Wifi and the Qingping+ app (or Mi Home, since Qingping IOT is compatible with Xiaomi IOT). More importantly, the device actually has support for self-hosted MQTT!

Qingping CGS1 Air Quality Monitor

I got most of the information for setting this up from this thread.

Step 1. Set up a locally hosted MQTT server

I use docker compose for my Home Assistant setup, so I added an instance of the Mosquitto MQTT server and exposed it locally. My Home Assistant container runs in host networking mode, so it was easier this way. This also lets you debug the MQTT traffic using MQTT Explorer.

mosquitto:
  <<: *common-keys-core
  container_name: mosquitto
  image: eclipse-mosquitto
  volumes:
    - $DOCKERDIR/appdata/mosquitto:/mosquitto
    - $DOCKERDIR/appdata/mosquitto/data:/mosquitto/data
    - $DOCKERDIR/appdata/mosquitto/log:/mosquitto/log
  ports:
    - "1883:1883"
    - "8083:8083"
    - "9001:9001"
  environment:
    - TZ=$TZ

Step 2. Configure the Air Quality Monitor to send data to your MQTT server

In order to configure the Air Quality Monitor to send data to a local MQTT server, you need to register for a Qingping account (e.g. via the Qingping+ app) and then go to the developer API console.

You’ll also need to have set up the Air Quality Monitor in the Qingping+ app so it knows it is associated with your account, though you only have to do this once to get the MAC address linked.

In the developer console you will need to add a “Private Access Config”:

Private access configuration

You then have to assign that configuration to your actual device, which you can do in the Devices page

Assigning the configuration to the device

In order for the device to pick up the new configuration, you will need to reset the device! The actual device has a menu item in the settings which supposedly reloads the MQTT configuration and connects to the server, but it doesn’t actually send any data unless you reset it.

To test whether things are working, open up MQTT Explorer and you should see your device beginning to send data on its qingping/{MAC}/up topic.

MQTT data

Normally, the Air Quality Monitor is configured to send data only once every 15 minutes; I want a (more) live feed and so configured it to send every 15 seconds.

You can do this by sending a message to the qingping/{MAC}/down topic:

{
  "id": 1,
  "need_ack": 1,
  "type": "17",
  "setting": {
    "report_interval": 15,
    "collect_interval": 15,
    "co2_sampling_interval": 15,
    "pm_sampling_interval": 15
  }
}

Step 3. Configure Home Assistant to create sensors for the data that the Air Quality Monitor sends

In Home Assistant, we need to make sure that we have configured the MQTT integration (the server is running on localhost:1883), and then we need to tell it about the sensors – the Qingping Air Quality Monitor doesn’t produce the data in a format that Home Assistant understands natively.

Then, in configuration.yaml, you can add all of the sensors:

mqtt:
  sensor:
    - name: "CO2"
      object_id: air_monitor_co2
      device_class: carbon_dioxide
      unit_of_measurement: "ppm"
      state_topic: "qingping/{mac}/up"
      value_template: >-
        {{ value_json.sensorData.0.co2.value
          if value_json.type=="17" else this.state }}
      availability:
        - topic: "qingping/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        name: "Air monitor"
        model: "CGS1"
        manufacturer: "qingping"
      unique_id: f0864ae1d3e66cdb5a29c894dd6a192f8ba528ec
    - name: "PM2.5"
      object_id: air_monitor_pm25
      device_class: pm25
      state_topic: "qingping/{mac}/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/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        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/{mac}/up"
      value_template: >-
        {{ value_json.sensorData.0.pm10.value
          if value_json.type=="17" else this.state }}
      availability:
        - topic: "qingping/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        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/{mac}/up"
      value_template: >-
        {{ (value_json.sensorData.0.tvoc.value / 218.77) | round(3)
          if value_json.type=="17" else this.state }}
      availability:
        - topic: "qingping/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        name: "Air monitor"
        model: "CGS1"
        manufacturer: "qingping"
      unique_id: 145ba4f594273ed8cfcf44f8df1983e3a229b0d1
    - name: "Humidity"
      object_id: air_monitor_humidity
      device_class: humidity
      state_topic: "qingping/{mac}/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/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        name: "Air monitor"
        model: "CGS1"
        manufacturer: "qingping"
      unique_id: 5648fe503a9c4c7563643425de97f184a3282a66
    - object_id: air_monitor_temperature
      name: "Temperature"
      device_class: temperature
      unit_of_measurement: "°C"
      state_topic: "qingping/{mac}/up"
      value_template: >-
        {{ value_json.sensorData.0.temperature.value|round(2)
            if value_json.type=="17" else this.state }}
      availability:
        - topic: "qingping/{mac}/up"
          payload_available: "true"
          payload_not_available: "false"
          value_template: >-
            {{ "true" if value_json else "false" }}
      device:
        identifiers: ["{mac}"]
        name: "Air monitor"
        model: "CGS1"
        manufacturer: "qingping"
      unique_id: eeac725e7c2bc220e8ef3602b7a506a9855a36c6

The unique IDs and object IDs just need to be unique - if you have more than one sensor, update appropriately. You can then add the sensors in your dashboard!

Air Quality Monitor Lite

The Air Quality Monitor Lite is much easier to set up, because it’s actually HomeKit compatible!

Qingping Air Quality Monitor Lite

Step 1. Start setup using the Qingping+ App in HomeKit mode

This is easiest on an iPhone: install the Qingping+ app and follow the instructions to set up the Air Quality Monitor Lite in HomeKit mode (not Qingping+ mode).

Step 2. Ensure the HomeKit integration is enabled in Home Assistant

You’ll want to make sure that both the HomeKit Bridge and the HomeKit Device integrations are enabled on your Home Assistant installation.

Step 3. Remove the Air Quality Monitor Lite from your phone and add it to Home Assistant

The Air Quality Monitor Lite only knows how to talk to a single coordinator, and it’s currently set to talk to your phone! Remove it from HomeKit on the phone and Home Assistant will automatically detect a HomeKit device on the network.

Once you add it to Home Assistant, the sensors should be available for you to graph and record.

Step 4. Bridge the sensors back to your HomeKit setup

If you still want to be able to access the Air Quality Monitor Lite from your phone in the Home app, you can actually set up a HomeKit Bridge from Home Assistant back to your phone.