--- /dev/null
+#include "aqi_calc.h"
+
+typedef struct aqi_lookup_s {
+ uint16_t aqi_low;
+ uint16_t aqi_high;
+ uint16_t pm10_low;
+ uint16_t pm10_high;
+ uint16_t pm25_low;
+ uint16_t pm25_high;
+} aqi_lookup_t;
+
+enum lookup_type {LOOKUP_PM10, LOOKUP_PM25};
+
+static const aqi_lookup_t AQI_LOOKUP_TABLE[] = {
+ {
+ .aqi_low = 0,
+ .aqi_high = 50,
+ .pm10_low = 0,
+ .pm10_high = 54,
+ .pm25_low = 0,
+ .pm25_high = 120,
+ },
+ {
+ .aqi_low = 51,
+ .aqi_high = 100,
+ .pm10_low = 55,
+ .pm10_high = 154,
+ .pm25_low = 121,
+ .pm25_high = 354,
+ },
+ {
+ .aqi_low = 101,
+ .aqi_high = 150,
+ .pm10_low = 155,
+ .pm10_high = 254,
+ .pm25_low = 355,
+ .pm25_high = 554,
+ },
+ {
+ .aqi_low = 151,
+ .aqi_high = 200,
+ .pm10_low = 255,
+ .pm10_high = 354,
+ .pm25_low = 555,
+ .pm25_high = 1504,
+ },
+ {
+ .aqi_low = 201,
+ .aqi_high = 300,
+ .pm10_low = 355,
+ .pm10_high = 424,
+ .pm25_low = 1505,
+ .pm25_high = 2504,
+ },
+ {
+ .aqi_low = 301,
+ .aqi_high = 500,
+ .pm10_low = 425,
+ .pm10_high = 604,
+ .pm25_low = 2505,
+ .pm25_high = 5004,
+ },
+};
+
+
+float linear_calc(uint16_t value, aqi_lookup_t lookup_row, int lookup_type){
+ uint16_t lookup_low, lookup_high, aqi_low, aqi_high;
+ if (lookup_type == LOOKUP_PM10){
+ lookup_low = lookup_row.pm10_low;
+ lookup_high = lookup_row.pm10_high;
+ } else if (lookup_type == LOOKUP_PM25){
+ lookup_low = lookup_row.pm25_low;
+ lookup_high = lookup_row.pm25_high;
+ } else {
+ lookup_low = 0;
+ lookup_high = 0;
+ }
+ // convenience
+ aqi_low = lookup_row.aqi_low;
+ aqi_high = lookup_row.aqi_high;
+
+ float retval = ((aqi_high - aqi_low)/((float)(lookup_high - lookup_low))*(value - lookup_low) + aqi_low);
+ printf("calculated aqi of %f, returning\n", retval);
+ return retval;
+}
+
+float aqi_calc_pm10(uint16_t pm10){
+ // precision is integer, so div 100
+ // ex. 2543 / 100 = 25 (real value: 25)
+ pm10 /= 100;
+ int i = 0;
+ while (i < 6){
+ if (pm10 < AQI_LOOKUP_TABLE[i].pm10_high ){
+ printf("found lookup index for pm10, %d\n", i);
+ break;
+ }
+ i++;
+ }
+ if (pm10 > AQI_LOOKUP_TABLE[i].pm10_high){
+ printf("pm10 too high for aqi lookup, this should never happen %d > %d\n", pm10, AQI_LOOKUP_TABLE[i].pm10_high );
+ return 0.0;
+ }
+ return linear_calc(pm10, AQI_LOOKUP_TABLE[i], LOOKUP_PM10);
+}
+
+float aqi_calc_pm25(uint16_t pm25){
+ // precision is one decimal, so div 10:
+ // ex. 2543 / 10 = 254 (real value: 25.4)
+ pm25 /= 10;
+ printf("modified pm25: %d\n", pm25);
+ int i = 0;
+ while (i < 6){
+ if (pm25 < AQI_LOOKUP_TABLE[i].pm25_high ){
+ printf("found lookup index for pm25, %d\n", i);
+ break;
+ }
+ i++;
+ }
+ if (pm25 > AQI_LOOKUP_TABLE[i].pm25_high){
+ printf("pm25 too high for aqi lookup, this should never happen %d > %d\n", pm25, AQI_LOOKUP_TABLE[i].pm25_high );
+ return 0.0;
+ }
+ return linear_calc(pm25, AQI_LOOKUP_TABLE[i], LOOKUP_PM25);
+}