From 1e53b2bcf52e00eaf1034b031cb4b6ceb557ea19 Mon Sep 17 00:00:00 2001 From: Ewowi Date: Thu, 11 Aug 2022 18:15:51 +0200 Subject: [PATCH] Weather usermod, more blaz recommendations - add WEATHER_DEBUG - move globals to class statics => create forwards, move effect to end of file, refer to it as :: - move http get to httpGet utility function - add errorMessage variable and show in Info - increase JSON doc from 20000 to 24000 bytes --- .../usermod_v2_weather/usermod_v2_weather.h | 339 +++++++++--------- 1 file changed, 176 insertions(+), 163 deletions(-) diff --git a/usermods/usermod_v2_weather/usermod_v2_weather.h b/usermods/usermod_v2_weather/usermod_v2_weather.h index fed5f76a..01d35a9a 100644 --- a/usermods/usermod_v2_weather/usermod_v2_weather.h +++ b/usermods/usermod_v2_weather/usermod_v2_weather.h @@ -2,7 +2,12 @@ #include "wled.h" -#define FX_MODE_2DWEATHER 185 // can we do this here? Can we also increase modeCount here? +// #define WEATHER_DEBUG + +//forward declarations as usermod class needs them +uint16_t mode_2DWeather(void); +//would like _data_FX_MODE_2DWEATHER after effect declaration but due to class static vars not possible... +static const char _data_FX_MODE_2DWEATHER[] PROGMEM = "Weather@;!;!;pal=54,2d"; //temperature palette //utility function, move somewhere else??? void epochToString(time_t time, char *timeString) { @@ -11,92 +16,61 @@ void epochToString(time_t time, char *timeString) { sprintf(timeString, "%04d-%02d-%02d %02d:%02d:%02d", tm.Year + 1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); } -//globals used in effect -static uint32_t pushLoop = 0; //effect pushes loop to execute. might be interesting for audioreactive too -static uint8_t units = 1; //metric (celsius) is default. (Standard=Kelvin, Imperial is Fahrenheit) -static float temps[100]; //array of temperatures -static time_t times[100]; //array of corresponding times -static float minTemp = 0; //config var -static float maxTemp = 40; //config var - -//effect function -uint16_t mode_2DWeather(void) { - - pushLoop = millis(); //will be reset to 0 in usermod loop - - SEGMENT.fadeToBlackBy(10); - - float currentTemp = 0; - // time_t currentTime = 0; - - for (int x=0; x= localTime) { - color = RED; - currentTemp = map(localTime, times[x%100], times[(x+1)%100], temps[x%100] * 1000, temps[(x+1)%100] * 1000) / 1000.0; - // currentTime = localTime; - } - else - color = ColorFromPalette(SEGPALETTE, map((uint8_t)temps[x%100], 0, 40, 0, 255), 255, LINEARBLEND); - - for (int y=0; y(); + JsonArray list = weatherDocObject[F("list")]; + JsonObject city = weatherDocObject["city"]; + strcat(errorMessage, city["name"]); //api succesfull + strcat(errorMessage, city["country"]); - // Check HTTP status - char status[32] = {0}; - client.readBytesUntil('\r', status, sizeof(status)); - if (strcmp(status, "HTTP/1.1 200 OK") != 0) { - Serial.print(F("Unexpected response: ")); - Serial.println(status); - client.stop(); - return; - } + uint8_t i = 0; + for (JsonObject listElement: list) { + times[i%100] = listElement["dt"]; - // Skip HTTP headers - char endOfHeaders[] = "\r\n\r\n"; - if (!client.find(endOfHeaders)) { - Serial.println(F("Invalid response")); - client.stop(); - return; - } + JsonObject main = listElement["main"]; + temps[i%100] = main["temp"]; - // Allocate the JSON document - // Use arduinojson.org/v6/assistant to compute the capacity. - // const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; - DynamicJsonDocument weatherDoc(20000); + #ifdef WEATHER_DEBUG + char timeString[64]; + epochToString(listElement["dt"], timeString); + Serial.print(timeString); - // Parse JSON object - DeserializationError error = deserializeJson(weatherDoc, client); - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - client.stop(); - return; + Serial.print(" temp "); + Serial.print(temps[i%100]); + + Serial.print(" city "); + Serial.print(errorMessage); + + Serial.print(" sunrise "); + char sunriseString[64]; + epochToString(city["sunrise"], sunriseString); + Serial.print(sunriseString); + + Serial.print(" localtime "); + char localTimeString[64]; + epochToString(localTime, localTimeString); + Serial.print(localTimeString); + + Serial.println(); + #endif + + i++; + } + } } // Disconnect client.stop(); - - JsonObject weatherDocObject = weatherDoc.as(); - JsonArray list = weatherDocObject[F("list")]; - JsonObject city = weatherDocObject["city"]; - cityName = city["name"]; - countryName = city["country"]; - - uint8_t i = 0; - for (JsonObject listElement: list) { - times[i%100] = listElement["dt"]; - - JsonObject main = listElement["main"]; - temps[i%100] = main["temp"]; - - #ifdef WLED_DEBUG - char timeString[64]; - epochToString(listElement["dt"], timeString); - Serial.print(timeString); - - Serial.print(" temp "); - Serial.print(main["temp"]); - - Serial.print(" city "); - Serial.print(cityName); - Serial.print(" - "); - Serial.print(countryName); - - Serial.print(" sunrise "); - char sunriseString[64]; - epochToString(city["sunrise"], sunriseString); - Serial.print(sunriseString); - - Serial.print(" localtime "); - char localTimeString[64]; - epochToString(localTime, localTimeString); - Serial.print(localTimeString); - - Serial.println(); - #endif - - i++; - } } pushLoop = 0; } @@ -227,8 +169,8 @@ class WeatherUsermod : public Usermod { if (user.isNull()) user = root.createNestedObject("u"); JsonArray infoArr = user.createNestedArray(FPSTR(_name)); - infoArr.add(cityName); //value - infoArr.add(countryName); //unit + infoArr.add(errorMessage); //value + // infoArr.add(""); //unit } @@ -286,7 +228,7 @@ class WeatherUsermod : public Usermod { oappend(SET_F("addOption(dd,'Fahrenheit',2);")); oappend(SET_F("addInfo('WeatherUserMod:units',1,'Set time and location in time settings');")); oappend(SET_F("addInfo('WeatherUserMod:apiKey',1,'Create acount on openweathermap.org and copy the key');")); - oappend(SET_F("addInfo('WeatherUserMod:minTemp',1,'Reboot if you change apiKey to reload forecast');")); + oappend(SET_F("addInfo('WeatherUserMod:minTemp',1,'Changing values: Reboot to (re)load forecast');")); } /* @@ -312,3 +254,74 @@ class WeatherUsermod : public Usermod { // strings to reduce flash memory usage (used more than twice) const char WeatherUsermod::_name[] PROGMEM = "WeatherUserMod"; + +//define class static variables used in weather effect +String WeatherUsermod::apiKey = ""; //config var +float WeatherUsermod::minTemp = 0; //config var +float WeatherUsermod::maxTemp = 40; //config var +uint8_t WeatherUsermod::units = 1; //config var: metric (celsius) is default. (Standard=Kelvin, Imperial is Fahrenheit) +uint32_t WeatherUsermod::pushLoop = 0; +float WeatherUsermod::temps[100]; //array of temperatures +time_t WeatherUsermod::times[100]; //array of corresponding times + +//effect function +uint16_t mode_2DWeather(void) { + + WeatherUsermod::pushLoop = millis(); //will be reset to 0 in usermod loop + + SEGMENT.fadeToBlackBy(10); + + float currentTemp = 0; + // time_t currentTime = 0; + + for (int x=0; x= localTime) { + color = RED; + currentTemp = map(localTime, WeatherUsermod::times[x%100], WeatherUsermod::times[(x+1)%100], WeatherUsermod::temps[x%100] * 1000, WeatherUsermod::temps[(x+1)%100] * 1000) / 1000.0; + // currentTime = localTime; + } + else + color = ColorFromPalette(SEGPALETTE, map((uint8_t)WeatherUsermod::temps[x%100], 0, 40, 0, 255), 255, LINEARBLEND); + + for (int y=0; y