Skip to content

Commit a3a61b9

Browse files
authored
Merge pull request #48 from fowlerk/master
Additions to Weather Underground client to support weather alerts
2 parents d5e43ea + 6d3bd3d commit a3a61b9

File tree

2 files changed

+220
-24
lines changed

2 files changed

+220
-24
lines changed

WundergroundClient.cpp

Lines changed: 178 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ WundergroundClient::WundergroundClient(boolean _isMetric) {
3333
isMetric = _isMetric;
3434
}
3535

36+
// Added by fowlerk, 12/22/16, as an option to change metric setting other than at instantiation
37+
void WundergroundClient::initMetric(boolean _isMetric) {
38+
isMetric = _isMetric;
39+
}
40+
// end add fowlerk, 12/22/16
41+
3642
void WundergroundClient::updateConditions(String apiKey, String language, String country, String city) {
3743
isForecast = false;
3844
doUpdate("/api/" + apiKey + "/conditions/lang:" + language + "/q/" + country + "/" + city + ".json");
@@ -59,7 +65,19 @@ void WundergroundClient::updateAstronomy(String apiKey, String language, String
5965

6066
// fowlerk added
6167
void WundergroundClient::updateAlerts(String apiKey, String language, String country, String city) {
62-
isForecast = true;
68+
currentAlert = 0;
69+
activeAlertsCnt = 0;
70+
isForecast = false;
71+
isSimpleForecast = false;
72+
isCurrentObservation = false;
73+
isAlerts = true;
74+
if (country == "US") {
75+
isAlertUS = true;
76+
isAlertEU = false;
77+
} else {
78+
isAlertUS = false;
79+
isAlertEU = true;
80+
}
6381
doUpdate("/api/" + apiKey + "/alerts/lang:" + language + "/q/" + country + "/" + city + ".json");
6482
}
6583
// end fowlerk add
@@ -182,14 +200,18 @@ void WundergroundClient::value(String value) {
182200
isPM = true;
183201
}
184202
else isPM = false;
185-
sunriseTime = String(tempHour);
203+
char tempHourBuff[3] = ""; // fowlerk add for formatting, 12/22/16
204+
sprintf(tempHourBuff, "%2d", tempHour); // fowlerk add for formatting, 12/22/16
205+
sunriseTime = String(tempHourBuff); // fowlerk add for formatting, 12/22/16
186206
//sunriseTime = value;
187207
}
188208
if (currentKey == "minute") {
189-
sunriseTime += ":" + value;
190-
if (isPM) sunriseTime += "pm";
191-
else if (usePM) sunriseTime += "am";
192-
}
209+
char tempMinBuff[3] = ""; // fowlerk add for formatting, 12/22/16
210+
sprintf(tempMinBuff, "%02d", value.toInt()); // fowlerk add for formatting, 12/22/16
211+
sunriseTime += ":" + String(tempMinBuff); // fowlerk add for formatting, 12/22/16
212+
if (isPM) sunriseTime += "pm";
213+
else if (usePM) sunriseTime += "am";
214+
}
193215
}
194216

195217

@@ -201,14 +223,18 @@ void WundergroundClient::value(String value) {
201223
isPM = true;
202224
}
203225
else isPM = false;
204-
sunsetTime = String(tempHour);
226+
char tempHourBuff[3] = ""; // fowlerk add for formatting, 12/22/16
227+
sprintf(tempHourBuff, "%2d", tempHour); // fowlerk add for formatting, 12/22/16
228+
sunsetTime = String(tempHourBuff); // fowlerk add for formatting, 12/22/16
205229
// sunsetTime = value;
206230
}
207231
if (currentKey == "minute") {
208-
sunsetTime += ":" + value;
209-
if (isPM) sunsetTime += "pm";
210-
else if(usePM) sunsetTime += "am";
211-
}
232+
char tempMinBuff[3] = ""; // fowlerk add for formatting, 12/22/16
233+
sprintf(tempMinBuff, "%02d", value.toInt()); // fowlerk add for formatting, 12/22/16
234+
sunsetTime += ":" + String(tempMinBuff); // fowlerk add for formatting, 12/22/16
235+
if (isPM) sunsetTime += "pm";
236+
else if(usePM) sunsetTime += "am";
237+
}
212238
}
213239

214240
if (currentParent == "moonrise") { // Has a Parent key and 2 sub-keys
@@ -219,24 +245,31 @@ void WundergroundClient::value(String value) {
219245
isPM = true;
220246
}
221247
else isPM = false;
222-
moonriseTime = String(tempHour);
248+
char tempHourBuff[3] = ""; // fowlerk add for formatting, 12/22/16
249+
sprintf(tempHourBuff, "%2d", tempHour); // fowlerk add for formatting, 12/22/16
250+
moonriseTime = String(tempHourBuff); // fowlerk add for formatting, 12/22/16
223251
// moonriseTime = value;
224252
}
225253
if (currentKey == "minute") {
226-
moonriseTime += ":" + value;
227-
if (isPM) moonriseTime += "pm";
228-
else if (usePM) moonriseTime += "am";
229-
230-
}
254+
char tempMinBuff[3] = ""; // fowlerk add for formatting, 12/22/16
255+
sprintf(tempMinBuff, "%02d", value.toInt()); // fowlerk add for formatting, 12/22/16
256+
moonriseTime += ":" + String(tempMinBuff); // fowlerk add for formatting, 12/22/16
257+
if (isPM) moonriseTime += "pm";
258+
else if (usePM) moonriseTime += "am";
259+
}
231260
}
232261

233262
if (currentParent == "moonset") { // Not used - has a Parent key and 2 sub-keys
234263
if (currentKey == "hour") {
235-
moonsetTime = value;
236-
}
264+
char tempHourBuff[3] = ""; // fowlerk add for formatting, 12/22/16
265+
sprintf(tempHourBuff, "%2d", value.toInt()); // fowlerk add for formatting, 12/22/16
266+
moonsetTime = String(tempHourBuff); // fowlerk add for formatting, 12/22/16
267+
}
237268
if (currentKey == "minute") {
238-
moonsetTime += ":" + value;
239-
}
269+
char tempMinBuff[3] = ""; // fowlerk add for formatting, 12/22/16
270+
sprintf(tempMinBuff, "%02d", value.toInt()); // fowlerk add for formatting, 12/22/16
271+
moonsetTime += ":" + String(tempMinBuff); // fowlerk add for formatting, 12/22/16
272+
}
240273
}
241274

242275
if (currentKey == "wind_mph") {
@@ -299,6 +332,70 @@ void WundergroundClient::value(String value) {
299332
UV = value;
300333
}
301334

335+
// Active alerts...added 18-Dec-2016
336+
if (currentKey == "type" && isAlerts) {
337+
activeAlertsCnt++;
338+
currentAlert++;
339+
activeAlerts[currentAlert-1] = value;
340+
Serial.print("Alert type processed, value: "); Serial.println(activeAlerts[currentAlert-1]);
341+
}
342+
if (currentKey == "description" && isAlerts && isAlertUS) {
343+
activeAlertsText[currentAlert-1] = value;
344+
Serial.print("Alert description processed, value: "); Serial.println(activeAlertsText[currentAlert-1]);
345+
}
346+
if (currentKey == "wtype_meteoalarm_name" && isAlerts && isAlertEU) {
347+
activeAlertsText[currentAlert-1] = value;
348+
Serial.print("Alert description processed, value: "); Serial.println(activeAlertsText[currentAlert-1]);
349+
}
350+
if (currentKey == "message" && isAlerts) {
351+
activeAlertsMessage[currentAlert-1] = value;
352+
Serial.print("Alert msg length: "); Serial.println(activeAlertsMessage[currentAlert-1].length());
353+
if(activeAlertsMessage[currentAlert-1].length() >= 511) {
354+
activeAlertsMessageTrunc[currentAlert-1] = true;
355+
} else {
356+
activeAlertsMessageTrunc[currentAlert-1] = false;
357+
}
358+
Serial.print("Alert message processed, value: "); Serial.println(activeAlertsMessage[currentAlert-1]);
359+
}
360+
if (currentKey == "date" && isAlerts) {
361+
activeAlertsStart[currentAlert-1] = value;
362+
// Check last char for a "/"; the returned value sometimes includes this; if so, strip it (47 is a "/" char)
363+
if (activeAlertsStart[currentAlert-1].charAt(activeAlertsStart[currentAlert-1].length()-1) == 47) {
364+
Serial.println("...last char is a slash...");
365+
activeAlertsStart[currentAlert-1] = activeAlertsStart[currentAlert-1].substring(0,(activeAlertsStart[currentAlert-1].length()-1));
366+
}
367+
// For meteoalarms, the start field is returned with the UTC=0 by default (not used?)
368+
if (isAlertEU && activeAlertsStart[currentAlert-1] == "1970-01-01 00:00:00 GMT") {
369+
activeAlertsStart[currentAlert-1] = "<Not specified>";
370+
}
371+
Serial.print("Alert start processed, value: "); Serial.println(activeAlertsStart[currentAlert-1]);
372+
}
373+
if (currentKey == "expires" && isAlerts) {
374+
activeAlertsEnd[currentAlert-1] = value;
375+
Serial.print("Alert expiration processed, value: "); Serial.println(activeAlertsEnd[currentAlert-1]);
376+
}
377+
if (currentKey == "phenomena" && isAlerts) {
378+
activeAlertsPhenomena[currentAlert-1] = value;
379+
Serial.print("Alert phenomena processed, value: "); Serial.println(activeAlertsPhenomena[currentAlert-1]);
380+
}
381+
if (currentKey == "significance" && isAlerts && isAlertUS) {
382+
activeAlertsSignificance[currentAlert-1] = value;
383+
Serial.print("Alert significance processed, value: "); Serial.println(activeAlertsSignificance[currentAlert-1]);
384+
}
385+
// Map meteoalarm level to the field for significance for consistency (used for European alerts)
386+
if (currentKey == "level_meteoalarm" && isAlerts && isAlertEU) {
387+
activeAlertsSignificance[currentAlert-1] = value;
388+
Serial.print("Meteo alert significance processed, value: "); Serial.println(activeAlertsSignificance[currentAlert-1]);
389+
}
390+
// For meteoalarms only (European alerts); attribution must be displayed according to the T&C's of use
391+
if (currentKey == "attribution" && isAlerts) {
392+
activeAlertsAttribution[currentAlert-1] = value;
393+
// Remove some of the markup in the attribution
394+
activeAlertsAttribution[currentAlert-1].replace(" <a href='"," ");
395+
activeAlertsAttribution[currentAlert-1].replace("</a>","");
396+
activeAlertsAttribution[currentAlert-1].replace("/'>"," ");
397+
}
398+
302399
// end fowlerk add
303400

304401
if (currentKey == "dewpoint_f" && !isMetric) {
@@ -327,11 +424,21 @@ void WundergroundClient::value(String value) {
327424
}
328425

329426
// Added forecastText key following...fowlerk, 12/3/16
330-
if (currentKey == "fcttext" && isForecast && currentForecastPeriod < MAX_FORECAST_PERIODS) {
427+
if (currentKey == "fcttext" && isForecast && !isMetric && currentForecastPeriod < MAX_FORECAST_PERIODS) {
428+
forecastText[currentForecastPeriod] = value;
429+
}
430+
// Added option for metric forecast following...fowlerk, 12/22/16
431+
if (currentKey == "fcttext_metric" && isForecast && isMetric && currentForecastPeriod < MAX_FORECAST_PERIODS) {
331432
forecastText[currentForecastPeriod] = value;
332433
}
333434
// end fowlerk add, 12/3/16
334435

436+
// Added PoP (probability of precipitation) key following...fowlerk, 12/22/16
437+
if (currentKey == "pop" && isForecast && currentForecastPeriod < MAX_FORECAST_PERIODS) {
438+
PoP[currentForecastPeriod] = value;
439+
}
440+
// end fowlerk add, 12/22/16
441+
335442
// The detailed forecast period has only one forecast per day with low/high for both
336443
// night and day, starting at index 1.
337444
int dailyForecastPeriod = (currentForecastPeriod - 1) * 2;
@@ -513,6 +620,48 @@ String WundergroundClient::getUV() {
513620
String WundergroundClient::getObservationTime() {
514621
return observationTime;
515622
}
623+
624+
// Active alerts...added 18-Dec-2016
625+
String WundergroundClient::getActiveAlerts(int alertIndex) {
626+
return activeAlerts[alertIndex];
627+
}
628+
629+
String WundergroundClient::getActiveAlertsText(int alertIndex) {
630+
return activeAlertsText[alertIndex];
631+
}
632+
633+
String WundergroundClient::getActiveAlertsMessage(int alertIndex) {
634+
return activeAlertsMessage[alertIndex];
635+
}
636+
637+
bool WundergroundClient::getActiveAlertsMessageTrunc(int alertIndex) {
638+
return activeAlertsMessageTrunc[alertIndex];
639+
}
640+
641+
String WundergroundClient::getActiveAlertsStart(int alertIndex) {
642+
return activeAlertsStart[alertIndex];
643+
}
644+
645+
String WundergroundClient::getActiveAlertsEnd(int alertIndex) {
646+
return activeAlertsEnd[alertIndex];
647+
}
648+
649+
String WundergroundClient::getActiveAlertsPhenomena(int alertIndex) {
650+
return activeAlertsPhenomena[alertIndex];
651+
}
652+
653+
String WundergroundClient::getActiveAlertsSignificance(int alertIndex) {
654+
return activeAlertsSignificance[alertIndex];
655+
}
656+
657+
String WundergroundClient::getActiveAlertsAttribution(int alertIndex) {
658+
return activeAlertsAttribution[alertIndex];
659+
}
660+
661+
int WundergroundClient::getActiveAlertsCnt() {
662+
return activeAlertsCnt;
663+
}
664+
516665
// end fowlerk add
517666

518667

@@ -555,9 +704,14 @@ String WundergroundClient::getForecastMonth(int period) {
555704
}
556705

557706
String WundergroundClient::getForecastText(int period) {
558-
Serial.print("Forecast period: "); Serial.println(period);
707+
// Serial.print("Forecast period: "); Serial.println(period);
559708
return forecastText[period];
560709
}
710+
711+
// Added PoP...12/22/16
712+
String WundergroundClient::getPoP(int period) {
713+
return PoP[period];
714+
}
561715
// end fowlerk add
562716

563717

@@ -603,4 +757,4 @@ String WundergroundClient::getMeteoconIcon(String iconText) {
603757
if (iconText == "nt_tstorms") return "&";
604758

605759
return ")";
606-
}
760+
}

WundergroundClient.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ See more at http://blog.squix.ch
3131
#define MAX_FORECAST_PERIODS 20 // Changed from 7 to 12 to support 6 day / 2 screen forecast (Neptune)
3232
// Changed to 20 to support max 10-day forecast returned from 'forecast10day' API (fowlerk)
3333

34+
#define MAX_WEATHER_ALERTS 6 // The maximum number of concurrent weather alerts supported by the library
35+
3436
class WundergroundClient: public JsonListener {
3537
private:
3638
String currentKey;
@@ -71,6 +73,8 @@ class WundergroundClient: public JsonListener {
7173
boolean isSimpleForecast = false; // true; fowlerk
7274
boolean isCurrentObservation = false; // Added by fowlerk
7375
boolean isAlerts = false; // Added by fowlerk
76+
boolean isAlertUS = false; // Added by fowlerk
77+
boolean isAlertEU = false; // Added by fowlerk
7478
int currentForecastPeriod;
7579
String forecastIcon [MAX_FORECAST_PERIODS];
7680
String forecastTitle [MAX_FORECAST_PERIODS];
@@ -80,6 +84,19 @@ class WundergroundClient: public JsonListener {
8084
String forecastDay [MAX_FORECAST_PERIODS/2];
8185
String forecastMonth [MAX_FORECAST_PERIODS/2];
8286
String forecastText [MAX_FORECAST_PERIODS];
87+
String PoP [MAX_FORECAST_PERIODS];
88+
// Active alerts...added 18-Dec-2016
89+
String activeAlerts [MAX_WEATHER_ALERTS]; // For a max of 6 currently-active alerts
90+
String activeAlertsMessage [MAX_WEATHER_ALERTS]; // Alert full-text message
91+
bool activeAlertsMessageTrunc [MAX_WEATHER_ALERTS]; // Alert full-text message truncation flag
92+
String activeAlertsText [MAX_WEATHER_ALERTS]; // Alerts description text
93+
String activeAlertsStart [MAX_WEATHER_ALERTS]; // Start of alert date/time
94+
String activeAlertsEnd [MAX_WEATHER_ALERTS]; // Expiration of alert date/time
95+
String activeAlertsPhenomena [MAX_WEATHER_ALERTS]; // Alert phenomena code
96+
String activeAlertsSignificance [MAX_WEATHER_ALERTS]; // Alert significance code
97+
String activeAlertsAttribution [MAX_WEATHER_ALERTS]; // Alert significance code
98+
int activeAlertsCnt; // Number of active alerts
99+
int currentAlert; // For indexing the current active alert
83100
// end fowlerk add
84101

85102
public:
@@ -89,6 +106,8 @@ class WundergroundClient: public JsonListener {
89106
void updateForecast(String apiKey, String language, String country, String city);
90107
void updateAstronomy(String apiKey, String language, String country, String city);
91108
void updateAlerts(String apiKey, String language, String country, String city); // Added by fowlerk, 18-Dec-2016
109+
void initMetric(boolean isMetric); // Added by fowlerk, 12/22/16, as an option to change metric setting other than at instantiation
110+
92111
// JJG added
93112
String getHours();
94113
String getMinutes();
@@ -145,6 +164,29 @@ class WundergroundClient: public JsonListener {
145164
String getForecastMonth(int period);
146165

147166
String getForecastText(int period);
167+
168+
String getPoP(int period);
169+
170+
int getActiveAlertsCnt();
171+
172+
String getActiveAlerts(int alertIndex);
173+
174+
String getActiveAlertsText(int alertIndex);
175+
176+
String getActiveAlertsMessage(int alertIndex);
177+
178+
bool getActiveAlertsMessageTrunc(int alertIndex);
179+
180+
String getActiveAlertsStart(int alertIndex);
181+
182+
String getActiveAlertsEnd(int alertIndex);
183+
184+
String getActiveAlertsPhenomena(int alertIndex);
185+
186+
String getActiveAlertsSignificance(int alertIndex);
187+
188+
String getActiveAlertsAttribution(int alertIndex);
189+
148190
// end fowlerk add
149191

150192
virtual void whitespace(char c);

0 commit comments

Comments
 (0)