/ #esphome #esp32 

Cheap 15$ Air quality monitor: ESP32, Bluetooth & Home assistant

If you are a DIY lover, the first sensors you look at are : temperature sensor and airquality sensor. #Metoo.

I have started with the temperature sensor in this article and found that amazing. I decided to go try the airquality monitoring.

I wanted something cheap, and ideally with bluetooth to connect it easily to my ESP32 and Home assistant, I found that Airbox WP6003 can do the job.



Collecting information

BLE devices normally has characteristics that can be access using an ID. These characteristics contains the data. This is the easiest way.

However some manufacturers have decided to make it more complicated and to not store this information in a characteristic. The data is sent using a notification only. This is the case for WP6003.

To see what I am talking about, execute the following command on your linux shell:

$ gatttool -I -b XX:XX:XX:XX:XX:XX
[XX:XX:XX:XX:XX:XX] connect

# you should be connected now to the airbox
# wait some minutes... A notification should appear
Notification handle = 0x0012 value: 0a 16 02 0e 0d 2d 00 c3 58 02 03 39 00 83 01 00 02 dc

# If you don't want to wait, execute the commands below to receive the data instantly
[XX:XX:XX:XX:XX:XX][LE]> char-write-req 0x0013 0100
Characteristic value was written successfully
[XX:XX:XX:XX:XX:XX][LE]> char-write-cmd 0x0010 aa15031a000935
Notification handle = 0x0012 value: aa 15 03 1a 00 09 35
[XX:XX:XX:XX:XX:XX][LE]> char-write-cmd 0x0010 ab
Notification handle = 0x0012 value: 0a 16 02 0e 0d 2d 00 c3 58 02 03 39 00 83 01 00 02 dc

Decoding the information

Alright, we have all we want :) NOOOO ! It is not that easy because you should to figure out where are the 4 data we are looking for:

  • CO2
  • HCHO
  • TVOC

I know that for the notification above, I had the following values on my application:

co2 : 582         => we should look for 582 => HEX : 0x0246
temperature 19.5  => we should look for 195 => HEX : 0xc3
hcho: 0.116       => we should look for 116 => HEX : 0x83
tvoc: 0.825       => we should look for 825 => HEX : 0x0339

By comparing the notification data and the data above, we can understand that:

Notification handle = 0x0012 value: 0a 16 02 0e 0d 2d 00 c3 58 02 03 39 00 83 01 00 02 dc
                                                         19.5       825   116         732 - (150)
                                                         temp       tvoc   hcho

Receive data in ESPHOME

Esphome had recently an update to receive the notification. This update will provide us the byte array as received by the device.

All we should do is to parse the data and extract the values from the byte array and set the data as a sensor value.

  name: livingroom
  platform: ESP32
  board: esp32doit-devkit-v1

  ssid: !secret wifi_ssid
  password: !secret wifi_password

# Enable logging

# Enable Home Assistant API

  port: 80


  - platform: homeassistant
    id: homeassistant_time

# Example configuration entry
  - platform: restart
    name: "Living Room Restart"

# Enable Bluetooth scanning for this ESP32

# CHANGE mac_address to your airquality box wp6003
  - mac_address: XX:XX:XX:XX:XX:XX
    id: airquality

  - platform: template
    name: "Xiaomei temperature"
    id: xiaomei_temperature
    device_class: "temperature"
    state_class: "measurement"
    unit_of_measurement: "°C"
  - platform: template
    name: "CO2"
    id: xiaomei_co2
    device_class: "carbon_dioxide"
    state_class: "measurement"
    unit_of_measurement: "ppm"
  - platform: template
    name: "TVOC"
    id: xiaomei_tvoc
    state_class: "measurement"
    unit_of_measurement: "mg/m3"
  - platform: template
    name: "HCHO"
    id: xiaomei_hcho
    state_class: "measurement"
    unit_of_measurement: "mg/m3"

  - platform: ble_client
    ble_client_id: airquality
    name: "Airquality level"
    service_uuid: "fff0"
    characteristic_uuid: "fff4"
    icon: "mdi:air"
    update_interval: never
    notify: true
    lambda: |-
      uint8_t* pdata = (uint8_t*) x.data();
      float temperature =  float((pdata[6] << 8) + pdata[7]) / 10;
      float tvoc =  float((pdata[10] << 8) + pdata[11]) / 1000;
      float hcho =  float((pdata[12] << 8) + pdata[13]) / 1000;
      float co2 =  (pdata[16] << 8) + pdata[17] - 150;
      return (float)x.size();      

Flash the esp32 with the above configuration

Connect ESPHome to Home assistant

Now that your esp32 is ready and connected to the airquality wp6003 box, connect the esp32 to home assistant if it’s not connected yet.

Refer to this article if you want to connect it.

Home assistant Demo

Now that your home assistant is connected and collecting the air info from the ESP32 and WP6003 box, you can create a card in your dashboard as I do.

Airquality VSON WP6003 esp32 home assistant