Fix merging pollen + AQI

This commit is contained in:
Admar Schoonen 2024-09-01 13:24:40 +02:00
parent 60d91a5def
commit 5cba98368f
4 changed files with 88 additions and 57 deletions

View file

@ -27,6 +27,9 @@ class Display {
float findMaxValueInTwelveHourInterval(uint32_t p_time_stamp, ArduinoJson::V710PB22::JsonArray p_array);
std::vector<float> mergeJsonArraysFromTimestamp(uint32_t p_time_stamp, ArduinoJson::V710PB22::JsonArray p_array_a,
ArduinoJson::V710PB22::JsonArray p_array_b);
std::vector<float> mergeJsonArraysFromTimestampHelper(uint32_t p_time_stamp,
ArduinoJson::V710PB22::JsonArray p_array_a,
ArduinoJson::V710PB22::JsonArray p_array_b);
std::tuple<uint8_t, uint8_t, uint8_t> mapValueToColorRGB(float p_value);
std::tuple<uint8_t, uint8_t, uint8_t, uint8_t> mapValueToColorRGBW(float p_value);
void setPixelToColorMappedValue(uint8_t index, float p_value);

View file

@ -51,7 +51,7 @@ bool BackendCommunication::getConfig() {
bool BackendCommunication::getWeatherData() {
String url = "https://sinoptik.luon.net/forecast?address=" + urlencode(m_config["address"]) +
"&metrics=precipitation&metrics=UVI&metrics=AQI&metrics=pollen&metrics=PAQI";
"&metrics=precipitation&metrics=UVI&metrics=AQI&metrics=pollen";
String payload = "";
bool isSuccess = false;

View file

@ -13,15 +13,12 @@ Display::Display(Adafruit_NeoPixel& p_leds) : m_leds(p_leds) {
void Display::setPollenPlusAQIForecastLeds(uint32_t p_current_time, ArduinoJson::V710PB22::JsonArray p_pollen,
ArduinoJson::V710PB22::JsonArray p_aqi) {
uint32_t first_aqi_time = p_pollen[0]["aqi"].as<uint32_t>();
uint32_t first_pollen_time = p_pollen[0]["time"].as<uint32_t>();
std::vector<float> merged_array = mergeJsonArraysFromTimestamp(p_current_time, p_aqi, p_pollen);
std::vector<float> merged_array = {};
if (merged_array.size() > m_air_quality_forecast_map.size()) {
uint32_t number_of_elements_to_erase = merged_array.size() - m_air_quality_forecast_map.size();
if (first_aqi_time <= first_pollen_time) {
merged_array = mergeJsonArraysFromTimestamp(p_current_time, p_aqi, p_pollen);
} else {
merged_array = mergeJsonArraysFromTimestamp(p_current_time, p_pollen, p_aqi);
merged_array.erase(merged_array.end() - number_of_elements_to_erase, merged_array.end());
}
uint32_t index = 0;
@ -56,6 +53,10 @@ void Display::setPrecipitationForecastLeds(uint32_t p_current_time, ArduinoJson:
}
previous_value = value;
if (index >= m_precipitation_forecast_map.size()) {
break;
}
}
}
@ -106,28 +107,63 @@ float Display::findMaxValueInTwelveHourInterval(uint32_t p_time_stamp, ArduinoJs
std::vector<float> Display::mergeJsonArraysFromTimestamp(uint32_t p_time_stamp,
ArduinoJson::V710PB22::JsonArray p_array_a,
ArduinoJson::V710PB22::JsonArray p_array_b) {
// Assumption: timestamp in p_array_a <= p_array_b
uint32_t start_time_a = p_array_a[0]["time"].as<uint32_t>();
uint32_t start_time_b = p_array_b[0]["time"].as<uint32_t>();
std::vector<float> merged_array = {};
if (start_time_a <= start_time_b) {
merged_array = mergeJsonArraysFromTimestampHelper(p_time_stamp, p_array_a, p_array_b);
} else {
merged_array = mergeJsonArraysFromTimestampHelper(p_time_stamp, p_array_b, p_array_a);
}
return merged_array;
}
std::vector<float> Display::mergeJsonArraysFromTimestampHelper(uint32_t p_time_stamp,
ArduinoJson::V710PB22::JsonArray p_array_a,
ArduinoJson::V710PB22::JsonArray p_array_b) {
// Assumption: time stamp in first element of p_array_a <= p_array_b
std::vector<float> merged_vector = {};
size_t start_point_a = 0;
size_t start_point_b = 0;
for (auto elem_a : p_array_a) {
uint32_t time_a = elem_a["time"].as<uint32_t>();
for (size_t index_a = start_point_a; index_a < p_array_a.size(); index_a++) {
uint32_t time_a = p_array_a[index_a]["time"].as<uint32_t>();
if (time_a >= p_time_stamp) {
float merged_value = elem_a["value"].as<float>();
for (size_t index_b = start_point_b; index_b < p_array_b.size(); index_b++) {
uint32_t time_b = p_array_b[index_b]["time"].as<uint32_t>();
if (time_b >= time_a) {
float value_b = p_array_b[index_b]["value"].as<float>();
merged_value = std::max(merged_value, value_b);
merged_vector.push_back(merged_value);
start_point_b = index_b + 1U;
break;
}
if (time_a > p_time_stamp) {
if (index_a > 0) {
start_point_a = index_a - 1;
} else {
start_point_a = 0;
}
break;
}
}
for (size_t index_a = start_point_a; index_a < p_array_a.size(); index_a++) {
uint32_t time_a = p_array_a[index_a]["time"].as<uint32_t>();
float value_a = p_array_a[index_a]["value"].as<float>();
bool is_merged = false;
for (size_t index_b = start_point_b; index_b < p_array_b.size(); index_b++) {
uint32_t time_b = p_array_b[index_b]["time"].as<uint32_t>();
if (time_b == time_a) {
float value_b = p_array_b[index_b]["value"].as<float>();
float merged_value = std::max(value_a, value_b);
merged_vector.push_back(merged_value);
is_merged = true;
start_point_b = index_b + 1U;
break;
}
}
if (not is_merged) {
merged_vector.push_back(value_a);
}
}

View file

@ -46,6 +46,7 @@ void setup() {
}
wifi_handler.connect();
digitalWrite(LED_BUILTIN, LOW);
const char url[] =
"https://apikey:cqprlgiafadnidsgeqozcpldkaeqimqw@despatch.luon.net/"
@ -58,50 +59,41 @@ void setup() {
}
void loop(void) {
uint32_t time_start = millis();
backend_communication.getConfig();
if (not backend_communication.m_is_config_valid) {
Serial.println(String(millis()) + " Invalid config");
Serial.println(String("Uptime: " + String(millis())) + " Invalid config");
} else {
Serial.println(String(millis()) +
" Address: " + String(static_cast<const char*>(backend_communication.m_config["address"])));
backend_communication.getWeatherData();
String text = String(millis()) + " Precipitation:";
for (JsonObject elem : backend_communication.m_weather_data["precipitation"].as<JsonArray>()) {
text += " " + String(elem["value"].as<float>());
}
Serial.println(text);
uint32_t utc_time = backend_communication.m_weather_data["time"].as<JsonInteger>();
Serial.println("Uptime: " + String(millis()) + ", UTC time: " + String(utc_time));
text = String(millis()) + " AQI:";
for (JsonObject elem : backend_communication.m_weather_data["AQI"].as<JsonArray>()) {
text += " " + String(elem["value"].as<float>());
}
Serial.println(text);
display.setPollenPlusAQIForecastLeds(utc_time, backend_communication.m_weather_data["pollen"].as<JsonArray>(),
backend_communication.m_weather_data["AQI"].as<JsonArray>());
text = String(millis()) + " Pollen:";
for (JsonObject elem : backend_communication.m_weather_data["pollen"].as<JsonArray>()) {
text += " " + String(elem["value"].as<float>());
}
Serial.println(text);
text = String(millis()) + " UVI:";
for (JsonObject elem : backend_communication.m_weather_data["UVI"].as<JsonArray>()) {
text += " " + String(elem["value"].as<float>());
}
Serial.println(text);
display.setPrecipitationForecastLeds(utc_time,
backend_communication.m_weather_data["precipitation"].as<JsonArray>());
uint32_t time = backend_communication.m_weather_data["time"].as<JsonInteger>();
text = String(millis()) + " time: " + std::to_string(time).c_str();
Serial.println(text);
display.setUVIForecastLed(utc_time, backend_communication.m_weather_data["UVI"].as<JsonArray>());
// display.setPollenPlusAQIForecastLeds(time, backend_communication.m_weather_data["pollen"].as<JsonArray>(),
// backend_communication.m_weather_data["AQI"].as<JsonArray>());
// display.setPrecipitationForecastLeds(time,
// backend_communication.m_weather_data["precipitation"].as<JsonArray>());
display.setUVIForecastLed(time, backend_communication.m_weather_data["UVI"].as<JsonArray>());
display.show();
}
dESPatch.checkForUpdate(true);
delay(2000);
uint32_t time_end = millis();
uint32_t time_delta = time_end - time_start;
uint32_t delay_time = 0U;
constexpr uint32_t ONE_SECOND_IN_MILLISECONDS = 1000U;
constexpr uint32_t INTERVAL = 60U * ONE_SECOND_IN_MILLISECONDS;
if (time_delta < INTERVAL) {
delay_time = INTERVAL - time_delta;
}
delay(delay_time);
}