ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
caqi_calculator.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5#include <limits>
7
8namespace esphome::aqi {
9
11 public:
12 uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override {
13 float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID);
14 float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID);
15 float aqi = std::max({pm2_5_index, pm10_0_index, 0.0f});
16 return static_cast<uint16_t>(std::lround(aqi));
17 }
18
19 protected:
20 static constexpr int NUM_LEVELS = 5;
21
22 static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 75}, {76, 100}, {101, 400}};
23
24 static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {
25 // clang-format off
26 {0.0f, 15.1f},
27 {15.1f, 30.1f},
28 {30.1f, 55.1f},
29 {55.1f, 110.1f},
30 {110.1f, std::numeric_limits<float>::max()}
31 // clang-format on
32 };
33
34 static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {
35 // clang-format off
36 {0.0f, 25.1f},
37 {25.1f, 50.1f},
38 {50.1f, 90.1f},
39 {90.1f, 180.1f},
40 {180.1f, std::numeric_limits<float>::max()}
41 // clang-format on
42 };
43
44 static float calculate_index(float value, const float array[NUM_LEVELS][2]) {
45 int grid_index = get_grid_index(value, array);
46 if (grid_index == -1) {
47 return -1.0f;
48 }
49
50 float aqi_lo = INDEX_GRID[grid_index][0];
51 float aqi_hi = INDEX_GRID[grid_index][1];
52 float conc_lo = array[grid_index][0];
53 float conc_hi = array[grid_index][1];
54
55 return (value - conc_lo) * (aqi_hi - aqi_lo) / (conc_hi - conc_lo) + aqi_lo;
56 }
57
58 static int get_grid_index(float value, const float array[NUM_LEVELS][2]) {
59 for (int i = 0; i < NUM_LEVELS; i++) {
60 const bool in_range =
61 (value >= array[i][0]) && ((i == NUM_LEVELS - 1) ? (value <= array[i][1]) // last bucket inclusive
62 : (value < array[i][1])); // others exclusive on hi
63 if (in_range) {
64 return i;
65 }
66 }
67 return -1;
68 }
69};
70
71} // namespace esphome::aqi
static constexpr int INDEX_GRID[NUM_LEVELS][2]
static constexpr float PM10_0_GRID[NUM_LEVELS][2]
static constexpr float PM2_5_GRID[NUM_LEVELS][2]
static float calculate_index(float value, const float array[NUM_LEVELS][2])
static int get_grid_index(float value, const float array[NUM_LEVELS][2])
static constexpr int NUM_LEVELS
uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override