From 5cba98368f53f546ee0e80efa77c98933c447da3 Mon Sep 17 00:00:00 2001 From: admar Date: Sun, 1 Sep 2024 13:24:40 +0200 Subject: [PATCH] Fix merging pollen + AQI --- include/display.hpp | 3 ++ src/backend_communication.cpp | 2 +- src/display.cpp | 82 +++++++++++++++++++++++++---------- src/main.cpp | 58 +++++++++++-------------- 4 files changed, 88 insertions(+), 57 deletions(-) diff --git a/include/display.hpp b/include/display.hpp index 5610350..d0b5a03 100644 --- a/include/display.hpp +++ b/include/display.hpp @@ -27,6 +27,9 @@ class Display { float findMaxValueInTwelveHourInterval(uint32_t p_time_stamp, ArduinoJson::V710PB22::JsonArray p_array); std::vector mergeJsonArraysFromTimestamp(uint32_t p_time_stamp, ArduinoJson::V710PB22::JsonArray p_array_a, ArduinoJson::V710PB22::JsonArray p_array_b); + std::vector mergeJsonArraysFromTimestampHelper(uint32_t p_time_stamp, + ArduinoJson::V710PB22::JsonArray p_array_a, + ArduinoJson::V710PB22::JsonArray p_array_b); std::tuple mapValueToColorRGB(float p_value); std::tuple mapValueToColorRGBW(float p_value); void setPixelToColorMappedValue(uint8_t index, float p_value); diff --git a/src/backend_communication.cpp b/src/backend_communication.cpp index 9c4ba1c..0fd2061 100644 --- a/src/backend_communication.cpp +++ b/src/backend_communication.cpp @@ -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; diff --git a/src/display.cpp b/src/display.cpp index bb2bd02..43faa25 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -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 first_pollen_time = p_pollen[0]["time"].as(); + std::vector merged_array = mergeJsonArraysFromTimestamp(p_current_time, p_aqi, p_pollen); - std::vector 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 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 start_time_b = p_array_b[0]["time"].as(); + + std::vector 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 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 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(); + 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(); - if (time_a >= p_time_stamp) { - float merged_value = elem_a["value"].as(); - - 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(); - - if (time_b >= time_a) { - float value_b = p_array_b[index_b]["value"].as(); - 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(); + float value_a = p_array_a[index_a]["value"].as(); + + 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(); + + if (time_b == time_a) { + float value_b = p_array_b[index_b]["value"].as(); + 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); } } diff --git a/src/main.cpp b/src/main.cpp index d2db1e8..13a69a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(backend_communication.m_config["address"]))); - backend_communication.getWeatherData(); - String text = String(millis()) + " Precipitation:"; - for (JsonObject elem : backend_communication.m_weather_data["precipitation"].as()) { - text += " " + String(elem["value"].as()); - } - Serial.println(text); + uint32_t utc_time = backend_communication.m_weather_data["time"].as(); + Serial.println("Uptime: " + String(millis()) + ", UTC time: " + String(utc_time)); - text = String(millis()) + " AQI:"; - for (JsonObject elem : backend_communication.m_weather_data["AQI"].as()) { - text += " " + String(elem["value"].as()); - } - Serial.println(text); + display.setPollenPlusAQIForecastLeds(utc_time, backend_communication.m_weather_data["pollen"].as(), + backend_communication.m_weather_data["AQI"].as()); - text = String(millis()) + " Pollen:"; - for (JsonObject elem : backend_communication.m_weather_data["pollen"].as()) { - text += " " + String(elem["value"].as()); - } - Serial.println(text); - text = String(millis()) + " UVI:"; - for (JsonObject elem : backend_communication.m_weather_data["UVI"].as()) { - text += " " + String(elem["value"].as()); - } - Serial.println(text); + display.setPrecipitationForecastLeds(utc_time, + backend_communication.m_weather_data["precipitation"].as()); - uint32_t time = backend_communication.m_weather_data["time"].as(); - text = String(millis()) + " time: " + std::to_string(time).c_str(); - Serial.println(text); + display.setUVIForecastLed(utc_time, backend_communication.m_weather_data["UVI"].as()); - // display.setPollenPlusAQIForecastLeds(time, backend_communication.m_weather_data["pollen"].as(), - // backend_communication.m_weather_data["AQI"].as()); - // display.setPrecipitationForecastLeds(time, - // backend_communication.m_weather_data["precipitation"].as()); - display.setUVIForecastLed(time, backend_communication.m_weather_data["UVI"].as()); 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); }