diff --git a/usermods/usermod_v2_weather/usermod_v2_weather.h b/usermods/usermod_v2_weather/usermod_v2_weather.h index 6927dcc7..fed5f76a 100644 --- a/usermods/usermod_v2_weather/usermod_v2_weather.h +++ b/usermods/usermod_v2_weather/usermod_v2_weather.h @@ -4,12 +4,6 @@ #define FX_MODE_2DWEATHER 185 // can we do this here? Can we also increase modeCount here? -#define pushLoopIndex 0 -#define tempsIndex 1 -#define timesIndex 2 -#define minTempIndex 3 -#define maxTempIndex 4 - //utility function, move somewhere else??? void epochToString(time_t time, char *timeString) { tmElements_t tm; @@ -17,21 +11,18 @@ 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) { - //or use um_data or make vars global static ...??? Looking at the amount of extra code, global static cleaner? - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_WEATHER)) { - SEGMENT.fill(SEGCOLOR(0)); - return FRAMETIME; - } - uint32_t *pushLoop = (uint32_t*)um_data->u_data[pushLoopIndex]; //pointer as it is set here - float *temps = (float*)um_data->u_data[tempsIndex]; - time_t *times = (time_t*)um_data->u_data[timesIndex]; - float minTemp = *(float*)um_data->u_data[minTempIndex]; - float maxTemp = *(float*)um_data->u_data[maxTempIndex]; - *pushLoop = millis(); //will be reset to 0 in usermod loop + pushLoop = millis(); //will be reset to 0 in usermod loop SEGMENT.fadeToBlackBy(10); @@ -95,37 +86,18 @@ static const char _data_FX_MODE_2DWEATHER[] PROGMEM = "Weather@;!;!;pal=54,2d"; class WeatherUsermod : public Usermod { private: unsigned long lastTime = 0; //will be used to download new forecast every hour - uint32_t pushLoop = 0; //effect pushes loop to execute. might be interesting for audioreactive too static const char _name[]; //usermod name //config variables - String apiKey = "get one from OpenWeatherMap.org"; - uint8_t units = 1; //metric (celsius) is default. (Standard=Kelvin, Imperial is Fahrenheit) - float minTemp = 0; - float maxTemp = 40; - - float temps[100]; //array of temperatures - time_t times[100]; //array of corresponding times + String apiKey = ""; + const char *cityName; + const char *countryName; public: void setup() { - um_data = new um_data_t; - um_data->u_size = 5; - um_data->u_type = new um_types_t[um_data->u_size]; - um_data->u_data = new void*[um_data->u_size]; - um_data->u_data[pushLoopIndex] = &pushLoop; - um_data->u_type[pushLoopIndex] = UMT_UINT32; - um_data->u_data[tempsIndex] = temps; - um_data->u_type[tempsIndex] = UMT_FLOAT_ARR; - um_data->u_data[timesIndex] = times; - um_data->u_type[timesIndex] = UMT_UINT32_ARR; - um_data->u_data[minTempIndex] = &minTemp; - um_data->u_type[minTempIndex] = UMT_FLOAT; - um_data->u_data[maxTempIndex] = &maxTemp; - um_data->u_type[maxTempIndex] = UMT_FLOAT; - strip.addEffect(FX_MODE_2DWEATHER, &mode_2DWeather, _data_FX_MODE_2DWEATHER); + strip.addEffect(255, &mode_2DWeather, _data_FX_MODE_2DWEATHER); } void connected() { @@ -136,9 +108,16 @@ class WeatherUsermod : public Usermod { if (pushLoop > millis() - 1000 && (lastTime == 0 || millis() - lastTime > 3600 * 1000)) { lastTime = millis(); + WiFiClient client; + + char url[180]; + sprintf(url, "GET /data/2.5/forecast?lat=%f&lon=%f&appid=%s&units=%s HTTP/1.0", latitude, longitude, apiKey.c_str(), units==0?"standard":units==1?"metric":"imperial"); + #ifdef WLED_DEBUG + Serial.println(url); + #endif + //https://arduinojson.org/v6/example/http-client/ //is this the most compact way to do http get and put it in arduinojson object??? - WiFiClient client; client.setTimeout(10000); if (!client.connect("api.openweathermap.org", 80)) { @@ -146,11 +125,6 @@ class WeatherUsermod : public Usermod { return; } - Serial.println(F("Connected!")); - - char url[180]; - sprintf(url, "GET /data/2.5/forecast?lat=%f&lon=%f&appid=%s&units=%s HTTP/1.0", latitude, longitude, apiKey.c_str(), units==0?"standard":units==1?"metric":"imperial"); - Serial.println(url); // Send HTTP request client.println(url); client.println(F("Host: api.openweathermap.org")); @@ -170,7 +144,6 @@ class WeatherUsermod : public Usermod { client.stop(); return; } - Serial.println(status); // Skip HTTP headers char endOfHeaders[] = "\r\n\r\n"; @@ -200,70 +173,63 @@ class WeatherUsermod : public Usermod { 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) { - JsonObject main = listElement["main"]; - - char timeString[64]; - epochToString(listElement["dt"], timeString); - Serial.print(timeString); - - float temp = main["temp"]; - Serial.print(" temp "); - Serial.print(temp); - - temps[i%100] = temp; times[i%100] = listElement["dt"]; - JsonObject city = weatherDocObject["city"]; - Serial.print(" city "); - Serial.print((const char *)city["name"]); - Serial.print(" - "); - Serial.print((const char *)city["country"]); - Serial.print(" sunrise "); - char sunriseString[64]; - epochToString(city["sunrise"], sunriseString); - Serial.print(sunriseString); + JsonObject main = listElement["main"]; + temps[i%100] = main["temp"]; - Serial.print(" localtime "); - char localTimeString[64]; - epochToString(localTime, localTimeString); - Serial.print(localTimeString); + #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 - Serial.println(); i++; } } pushLoop = 0; } - bool getUMData(um_data_t **data) //do not forget this or um_data doesn't work!! Can it be moved to superclass? - { - if (!data) return false; // no pointer provided by caller or not enabled -> exit - *data = um_data; - return true; - } - - /* * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. * Below it is shown how this could be used for e.g. a light sensor */ - /* void addToJsonInfo(JsonObject& root) { - int reading = 20; - //this code adds "u":{"Light":[20," lux"]} to the info object JsonObject user = root["u"]; if (user.isNull()) user = root.createNestedObject("u"); - JsonArray lightArr = user.createNestedArray("Light"); //name - lightArr.add(reading); //value - lightArr.add(" lux"); //unit + JsonArray infoArr = user.createNestedArray(FPSTR(_name)); + infoArr.add(cityName); //value + infoArr.add(countryName); //unit } - */ /* @@ -290,10 +256,10 @@ class WeatherUsermod : public Usermod { void addToConfig(JsonObject& root) { JsonObject top = root.createNestedObject(FPSTR(_name)); - top["apiKey"] = apiKey; - top["units"] = units; - top["minTemp"] = minTemp; - top["maxTemp"] = maxTemp; + top[F("apiKey")] = apiKey; + top[F("units")] = units; + top[F("minTemp")] = minTemp; + top[F("maxTemp")] = maxTemp; } @@ -303,10 +269,10 @@ class WeatherUsermod : public Usermod { bool configComplete = !top.isNull(); - configComplete &= getJsonValue(top["apiKey"], apiKey); - configComplete &= getJsonValue(top["units"], units); - configComplete &= getJsonValue(top["minTemp"], minTemp); - configComplete &= getJsonValue(top["maxTemp"], maxTemp); + configComplete &= getJsonValue(top[F("apiKey")], apiKey); + configComplete &= getJsonValue(top[F("units")], units); + configComplete &= getJsonValue(top[F("minTemp")], minTemp); + configComplete &= getJsonValue(top[F("maxTemp")], maxTemp); // * Return true in case the config values returned from Usermod Settings were complete, or false if you'd like WLED to save your defaults to disk (so any missing values are editable in Usermod Settings) return configComplete; diff --git a/wled00/FX.h b/wled00/FX.h index acc9582b..d3c7733c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -378,7 +378,7 @@ // #define FX_MODE_2DAKEMI 186 // audio enhanced //#define FX_MODE_CUSTOMEFFECT 187 //WLEDSR Custom Effects - #define MODE_COUNT 186 + #define MODE_COUNT 185 #endif typedef enum mapping1D2D {