Air Quaility Meter into Home Assistant

Does anyone know whether it’s possible to get the data out of this device:

Into Home Assistant? I’m guessing this is a white label device sold as other manufacturers which is likely why the brand doesn’t seem to show up as an integration.

I don’t even know how it communicates to its app.

There is no way to tell but I decided after working from home many years (since covid) in my basement office that I had better start monitoring radon levels!

So after some research (I am very suspicious of the low price on the sensor you found, good sensors themselves (just the sensor itself on the circuit board itself) get expensive. I found this combination to be the most thorough with the highest quality sensors possible (without raising the prices too high).

  1. Airthings Wave 2 Radon Detector - unfortunately this does not connect to HA directly unless you do it through a BLE proxy. I have a bunch of Shelly relays throughout the house that can act a BLE gateways for a variety of things but for some reason that is a lightweight version of BLE that cannot handle the active BLE connection expected for this sensor. So in searching around I found the:
  2. Apollo AIR-1 Air Quality Sensor with the CO2 add-on which is based upon ESP32 and it can also act as a full-blown active BLE proxy of the type needed by the Wave2, as well as complementing it by offering other air quality measurements that are not measured by the Wave2.

Note, I already have Carbon Monoxide (CO) detectors nearby and throughout the home (included in smoke detectors I have in HA - note the “binary_sensor.bsmt_steps_smoke_co_alarm_co_detected” in the source code below) and so I did not purchase that addon for the AIR-1 (you might want to consider that addon, but many smoke detectors also include carbon monoxide detection, if you have smoke detectors you should check).

Setup:
A. When you get them both, DO NOT add the Apollo AIR-1 integration to HA first through their HA integration (that comes later), or else the next step will not work!
B. Install the ESPHOME integration which will (assuming you did not do step #1) which then gives you the “ESPHome Builder” sidebar, click on that and then you can add the AIR-1 (I learned the hard way it will never find the AIR-1 if you already did step #1), so add it first here! Once added then you will see instructions (on the air-1 website) for turning on the BLE Proxy on the unit).
C. As soon as you finish B (turning on the proxy) then your HA instance will instantly recognize the Wave 2 and ask you to add it! Also you can then obvously add the Air-1 integration.

Here is a dashboard I created using the values from both:

If you look at the first screen shot, you will see a rollup card that says “explanation”. I put that there for myself so I would not forget the meanings of half of these (clicking on it shows the below that open up):

And here is the source code for that dashboard:

views:
  - title: Basement Air Quality
    path: overview
    icon: mdi:molecule-co2
    cards:
      - type: markdown
        content: |
          {% set green = '#00c853' %}
          {% set orange = '#ff9800' %}
          {% set red = '#ff1744' %}

          {% set co = states('binary_sensor.bsmt_steps_smoke_co_alarm_co_detected') | lower %}
          {% set co_color = green if co == 'off' else red if co == 'on' else '' %}

          {% set radon1 = states('sensor.basement_airthings_wave2_radon_sensor_radon_1_day_average') | float(0) %}
          {% set radon1_color = green if radon1 < 2 else orange if radon1 < 4 else red %}

          {% set radonlt = states('sensor.basement_airthings_wave2_radon_sensor_radon_longterm_average') | float(0) %}
          {% set radonlt_color = green if radonlt < 2 else orange if radonlt < 4 else red %}

          {% set radon_level = states('sensor.basement_airthings_wave2_radon_sensor_radon_1_day_level') | lower %}
          {% set radon_level_color = green if radon_level in ['excellent','normal','good','off','ideal'] else orange if radon_level in ['moderate','watch'] else red if radon_level in ['high','very high','abnormal','very abnormal','extremely abnormal','extermely anormal','poor','unhealthy','extremely unhealthy'] else '' %}

          {% set co2 = states('sensor.basement_apollo_air_1_air_sensor_co2') | float(0) %}
          {% set co2_color = green if co2 < 800 else orange if co2 <= 1200 else red %}

          {% set aqi_bsmt = states('sensor.basement_apollo_air_1_air_sensor_nowcast_aqi') | float(0) %}
          {% set aqi_bsmt_color = green if aqi_bsmt <= 50 else orange if aqi_bsmt <= 100 else red %}

          {% set aqi_nyc = states('sensor.airnow_aqi') | float(0) %}
          {% set aqi_nyc_color = green if aqi_nyc <= 50 else orange if aqi_nyc <= 100 else red %}

          {% set voc_index = states('sensor.basement_apollo_air_1_air_sensor_sen55_voc') | float(0) %}
          {% set voc_index_color = green if voc_index < 150 else orange if voc_index < 250 else red %}

          {% set voc_quality = states('sensor.basement_apollo_air_1_air_sensor_voc_quality') | lower %}
          {% set voc_quality_color = green if voc_quality in ['improved','normal','excellent','good','off','ideal'] else orange if voc_quality in ['abnormal','moderate','watch'] else red if voc_quality in ['very abnormal','extremely abnormal','high','very high','extermely anormal','poor','unhealthy','extremely unhealthy'] else '' %}

          {% set humidity = states('sensor.basement_airthings_wave2_radon_sensor_humidity') | float(0) %}
          {% set humidity_color = orange if humidity < 30 else green if humidity < 50 else orange if humidity <= 60 else red %}

          {% set pm25 = states('sensor.basement_apollo_air_1_air_sensor_pm_2_5mm_weight_concentration') | float(0) %}
          {% set pm25_color = green if pm25 <= 9 else orange if pm25 <= 35.4 else red %}

          {% set pm10 = states('sensor.basement_apollo_air_1_air_sensor_pm_10mm_weight_concentration') | float(0) %}
          {% set pm10_color = green if pm10 < 50 else orange if pm10 <= 100 else red %}

          ### Sensor Levels
          
          <table>
            <tr>
              <td>
                <table>
                  <tr><th>Reading</th><th>Currently</th></tr>
                  <tr><td><font color="{{ co_color }}">CO Alarm</font></td><td><font color="{{ co_color }}">{{ states('binary_sensor.bsmt_steps_smoke_co_alarm_co_detected') }}</font></td></tr>
                  <tr><td><font color="{{ radon_level_color }}">Radon Level</font></td><td><font color="{{ radon_level_color }}">{{ states('sensor.basement_airthings_wave2_radon_sensor_radon_1_day_level') }}</font></td></tr>
                  <tr><td><font color="{{ radon1_color }}">Radon 1-Day</font></td><td><font color="{{ radon1_color }}">{{ radon1 | round(2) }} pCi/L</font></td></tr>
                  <tr><td><font color="{{ radonlt_color }}">Radon Long Term</font></td><td><font color="{{ radonlt_color }}">{{ radonlt | round(2) }} pCi/L</font></td></tr>
                  <tr><td><font color="{{ co2_color }}">CO₂</font></td><td><font color="{{ co2_color }}">{{ co2 | round(0) }} ppm</font></td></tr>
                  <tr><td>PM1</td><td>{{ states('sensor.basement_apollo_air_1_air_sensor_pm_1mm_weight_concentration') | float(0) | round(1) }} µg/m³</td></tr>
                  <tr><td><font color="{{ pm25_color }}">PM2.5</font></td><td><font color="{{ pm25_color }}">{{ pm25 | round(1) }} µg/m³</font></td></tr>
                  <tr><td><font color="{{ pm10_color }}">PM10</font></td><td><font color="{{ pm10_color }}">{{ pm10 | round(1) }} µg/m³</font></td></tr>
                </table>
              </td>
              <td>
                <table>
                  <tr><th>Reading</th><th>Currently</th></tr>
                  <tr><td><font color="{{ voc_index_color }}">VOC Index</font></td><td><font color="{{ voc_index_color }}">{{ voc_index | round(0) }}</font></td></tr>
                  <tr><td><font color="{{ voc_quality_color }}">VOC Quality</font></td><td><font color="{{ voc_quality_color }}">{{ states('sensor.basement_apollo_air_1_air_sensor_voc_quality') }}</font></td></tr>
                  <tr><td>Temperature</td><td>{{ states('sensor.basement_airthings_wave2_radon_sensor_temperature') | float(0) | round(1) }} °F</td></tr>
                  <tr><td><font color="{{ humidity_color }}">Humidity</font></td><td><font color="{{ humidity_color }}">{{ humidity | round(1) }}%</font></td></tr>
                  <tr><td>Barometric Pressure</td><td>{{ states('sensor.basement_apollo_air_1_air_sensor_dps310_pressure') | float(0) | round(2) }} psi</td></tr>
                  <tr><td><font color="{{ aqi_bsmt_color }}">AQI Bsmt</font></td><td><font color="{{ aqi_bsmt_color }}">{{ aqi_bsmt | round(0) }}</font></td></tr>
                  <tr><td><font color="{{ aqi_nyc_color }}">AQI NYC</font></td><td><font color="{{ aqi_nyc_color }}">{{ aqi_nyc | round(0) }}</font></td></tr>
                  <tr><td>Light Level</td><td>{{ states('sensor.basement_airthings_wave2_radon_sensor_illuminance') | float(0) | round(0) }}%</td></tr>
                </table>
              </td>
            </tr>
          </table>
          
          ### Particulate Matter Quantity by Size
          
          <table style="margin-top:6px;">
            <tr>
              <td>
                <table>
                  <tr><th>µm Band</th><th>Currently</th></tr>
                  <tr><td>PM 0.3 to 1.0</td><td>{{ states('sensor.apollo_air_1_2b9738_pm_0_3_to_1_mm') | float(0) | round(1) }} µg/m³</td></tr>
                  <tr><td>PM 1.1 to 2.5</td><td>{{ states('sensor.apollo_air_1_2b9738_pm_1_to_2_5_mm') | float(0) | round(1) }} µg/m³</td></tr>
                </table>
              </td>
              <td>
                <table>
                  <tr><th>µm Band</th><th>Currently</th></tr>
                  <tr><td>PM 2.5 to 4.0</td><td>{{ states('sensor.apollo_air_1_2b9738_pm_2_5_to_4_mm') | float(0) | round(1) }} µg/m³</td></tr>
                  <tr><td>PM 4.1 to 10</td><td>{{ states('sensor.apollo_air_1_2b9738_pm_4_to_10_mm') | float(0) | round(1) }} µg/m³</td></tr>
                </table>
              </td>
            </tr>
          </table>
        card_mod:
          style: |
            ha-card { font-size: 12px; line-height: 1.2; }
            ha-markdown h3 { font-size: 14px; margin: 8px 0 6px 0; }
            ha-markdown table { width: 100% !important; border-collapse: collapse; table-layout: fixed; }
            ha-markdown > table > tbody > tr > td { width: 50% !important; vertical-align: top; padding: 0 8px 0 0; border: none !important; }
            ha-markdown th:first-child, ha-markdown td:first-child { width: 70%; white-space: normal; }
            ha-markdown th:last-child, ha-markdown td:last-child { width: 30%; text-align: right; white-space: nowrap; }
            ha-markdown td, ha-markdown th { padding: 2px 4px; }

      - type: markdown
        content: |
          <details>
          <summary><b>Explanation</b></summary>

          - **CO Alarm:** Carbon monoxide alarm from the smoke/CO detector.
              - <font color="#00c853"><b>Off:</b> normal.</font>
              - <font color="#ff1744"><b>On:</b> dangerous carbon monoxide may be present.</font>
          - **Radon:** Radioactive gas from the ground. Long-term average matters most.
              - <font color="#00c853"><b>Good:</b> less than 2 pCi/L.</font>
              - <font color="#ff9800"><b>Watch:</b> 2 pCi/L or higher, but less than 4 pCi/L.</font>
              - <font color="#ff1744"><b>Action:</b> 4 pCi/L or higher.</font>
          - **CO₂:** Carbon dioxide. A ventilation and stale-air indicator.
              - <font color="#00c853"><b>Good:</b> less than 800 ppm.</font>
              - <font color="#ff9800"><b>Watch:</b> 800 ppm through 1200 ppm.</font>
              - <font color="#ff1744"><b>High:</b> more than 1200 ppm.</font>
          - **AQI:** Air Quality Index: Bsmt is local Apollo. NYC is regional AirNow.
              - <font color="#00c853"><b>Good:</b> 0 through 50.</font>
              - <font color="#ff9800"><b>Moderate:</b> 51 through 100.</font>
              - <font color="#ff1744"><b>Unhealthy:</b> 101 or higher.</font>
          - **VOC:** Volatile Organic Compounds. These can come from cleaners, paints, solvents, glues, fragrances, plastics, furniture, stored household items, cooking, smoke, and other materials that release gases into the air.
              - **VOC Index:** Apollo says the AIR-1 VOC Quality follows the SEN55 VOC Index:
                  - <font color="#00c853"><b>Improved:</b> 0 through 79.</font>
                  - <font color="#00c853"><b>Normal:</b> 80 through 149.</font>
                  - <font color="#ff9800"><b>Abnormal:</b> 150 through 249.</font>
                  - <font color="#ff1744"><b>Very abnormal:</b> 250 through 399.</font>
                  - <font color="#ff1744"><b>Extremely abnormal:</b> 400 or higher.</font>
              - **VOC Quality:** Text version of the VOC Index.
                  - <font color="#00c853"><b>Green:</b> Improved or Normal.</font>
                  - <font color="#ff9800"><b>Orange:</b> Abnormal.</font>
                  - <font color="#ff1744"><b>Red:</b> Very abnormal or Extremely abnormal.</font>
              - **Percentage style:** You can think of the VOC Index as a 0 to 500 severity scale, where 250 is about 50% of the way to 500. It is not a true percent of VOC concentration, but it is useful as a severity indicator.
          - **Humidity:** Moisture level in the air.
              - <font color="#ff9800"><b>Dry / Watch:</b> less than 30%.</font>
              - <font color="#00c853"><b>Ideal:</b> 30% or higher, but less than 50%.</font>
              - <font color="#ff9800"><b>Watch:</b> 50% through 60%.</font>
              - <font color="#ff1744"><b>Mold risk:</b> more than 60%.</font>
          - **Pressure:** Barometric pressure.
              - <font color="#00c853"><b>Rising pressure:</b> usually points toward clearing or stable weather.</font>
              - <font color="#ff9800"><b>Falling pressure:</b> usually points toward unsettled weather or storms.</font>
          - **Light Level:** Relative ambient light around the Airthings sensor.
              - ~0% = dark.
              - ~20% = dim or low room lighting.
              - ~50% or higher = brighter lighting.
          - **PM:** Particulate Matter (tiny particles suspended in the air). 
              - µg/m³ = Micrograms per Cubic Meter
              - **PM1:** Ultra-fine particles ≤ 1.0 µm
                  - Smoke, candle soot, diesel exhaust, wildfire smoke, cooking fumes
                  - Lower values are generally better.
              - **PM2.5:** Fine particles ≤ 2.5 microns (includes PM1):
                  - Smoke, combustion particles, aerosols, fine dust, some mold spores
                  - <font color="#00c853"><b>Good:</b> 0 through 9 µg/m³.</font>
                  - <font color="#ff9800"><b>Moderate:</b> more than 9 through 35.4 µg/m³.</font>
                  - <font color="#ff1744"><b>Unhealthy:</b> more than 35.4 µg/m³.</font>
              - **PM10:** Larger particles ≤ 10 microns (includes PM1, PM5)
                  - Dust, pollen, pet dander, construction dust, textile fibers
                  - <font color="#00c853"><b>Excellent / Good:</b> less than 50 µg/m³.</font>
                  - <font color="#ff9800"><b>Watch:</b> 50 through 100 µg/m³.</font>
                  - <font color="#ff1744"><b>Poor:</b> more than 100 µg/m³.</font>

          </details>
        card_mod:
          style: |
            ha-card { font-size: 12px; line-height: 1.2; }
            ha-markdown li { margin-bottom: 1px; }

      - type: history-graph
        title: Volatile Organic Compounds - 24 Hours
        hours_to_show: 24
        entities:
          - sensor.basement_apollo_air_1_air_sensor_sen55_voc
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: CO₂ - Last 24 Hours
        hours_to_show: 24
        entities:
          - sensor.basement_apollo_air_1_air_sensor_co2
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: Radon - Last 7 Days
        hours_to_show: 168
        entities:
          - sensor.basement_airthings_wave2_radon_sensor_radon_1_day_average
          - sensor.basement_airthings_wave2_radon_sensor_radon_longterm_average
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: PM Particles 24 Hr Wt Concentration
        hours_to_show: 24
        entities:
          - sensor.basement_apollo_air_1_air_sensor_pm_2_5mm_weight_concentration
          - sensor.basement_apollo_air_1_air_sensor_pm_10mm_weight_concentration
          - sensor.apollo_air_1_2b9738_pm_0_3_to_1_mm
          - sensor.apollo_air_1_2b9738_pm_1_to_2_5_mm
          - sensor.apollo_air_1_2b9738_pm_2_5_to_4_mm
          - sensor.apollo_air_1_2b9738_pm_4_to_10_mm
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: Air Quality Index - 24 Hours
        hours_to_show: 24
        entities:
          - sensor.basement_apollo_air_1_air_sensor_nowcast_aqi
          - sensor.airnow_aqi
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: Temp & Humidity last 24 Hrs
        hours_to_show: 24
        entities:
          - sensor.basement_airthings_wave2_radon_sensor_temperature
          - sensor.basement_airthings_wave2_radon_sensor_humidity
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

      - type: history-graph
        title: Barometer (Rising->Clearing, Falling->Storms)
        hours_to_show: 168
        entities:
          - sensor.basement_apollo_air_1_air_sensor_dps310_pressure
        card_mod:
          style: |
            .card-header {
              font-size: 18px !important;
              font-weight: 400 !important;
            }

Hope that helps! I know yes it gets a little pricey, but it is less expensive than cancer and your health is worth it LOL

Thank you for your detailed reply