Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions platformio/include/_locale.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ extern const char *TXT_UNITS_PRECIP_MILLIMETERS;
extern const char *TXT_UNITS_PRECIP_CENTIMETERS;
extern const char *TXT_UNITS_PRECIP_INCHES;

// NEXT HOUR RAIN FORECAST
extern const char *TXT_RAIN_CONTINUOUS;
extern const char *TXT_RAIN_UNTIL;
extern const char *TXT_RAIN_FROM;
extern const char *TXT_RAIN_FROM_TO;

// MISCELLANEOUS MESSAGES
// Title Case
extern const char *TXT_LOW_BATTERY;
Expand Down
7 changes: 3 additions & 4 deletions platformio/include/api_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <HTTPClient.h>
#include <WiFi.h>

#define OWM_NUM_MINUTELY 1 // 61
#define OWM_NUM_MINUTELY 60 // 60
#define OWM_NUM_HOURLY 48 // 48
#define OWM_NUM_DAILY 8 // 8
#define OWM_NUM_ALERTS 8 // OpenWeatherMaps does not specify a limit, but if you need more alerts you are probably doomed.
Expand Down Expand Up @@ -93,7 +93,7 @@ typedef struct owm_current
typedef struct owm_minutely
{
int64_t dt; // Time of the forecasted data, unix, UTC
float precipitation; // Precipitation volume, mm
float precipitation; // Precipitation volume, mm/h
} owm_minutely_t;

/*
Expand Down Expand Up @@ -172,8 +172,7 @@ typedef struct owm_resp_onecall
String timezone; // Timezone name for the requested location
int timezone_offset; // Shift in seconds from UTC
owm_current_t current;
// owm_minutely_t minutely[OWM_NUM_MINUTELY];

owm_minutely_t minutely[OWM_NUM_MINUTELY];
owm_hourly_t hourly[OWM_NUM_HOURLY];
owm_daily_t daily[OWM_NUM_DAILY];
std::vector<owm_alerts_t> alerts;
Expand Down
10 changes: 10 additions & 0 deletions platformio/include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,16 @@
// Disable alerts by changing the DISPLAY_ALERTS macro to 0.
#define DISPLAY_ALERTS 1

// When there are no alerts to display (either DISPLAY_ALERTS is set to 0 or
// there are no current alerts), the precipirations for the next hour can be
// displayed in the alerts area.
// Disable by changing the DISPLAY_NEXT_HOUR_PRECIP macro to 0.
#define DISPLAY_NEXT_HOUR_PRECIP 1
// Threshold to consider precipitation as "rain" for a period (mm/h)
#define PRECIP_THRESHOLD_PERIOD 0.1f
// Maximum gap in minutes to group precipitations as a single period
#define PRECIP_MAX_GAP_MINUTES 5

// STATUS BAR EXTRAS
// Extra information that can be displayed on the status bar. Set to 1 to
// enable.
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_de_DE.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Low Battery";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_en_GB.inc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Low Battery";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_en_US.inc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Low Battery";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_et_EE.inc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Aku t\xFChi";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_fi_FI.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Low Battery";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_fr_FR.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Pluie sans interruption";
const char *TXT_RAIN_UNTIL = "Pluie jusqu'\340 %s";
const char *TXT_RAIN_FROM = "Pluie \340 partir de %s";
const char *TXT_RAIN_FROM_TO = "Pluie de %s \340 %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Batterie Faible";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_it_IT.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Batteria quasi scarica";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_nl_BE.inc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Low Battery";
Expand Down
6 changes: 6 additions & 0 deletions platformio/include/locales/locale_pt_BR.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ const char *TXT_UNITS_PRECIP_MILLIMETERS = "mm";
const char *TXT_UNITS_PRECIP_CENTIMETERS = "cm";
const char *TXT_UNITS_PRECIP_INCHES = "in";

// NEXT HOUR RAIN FORECAST
const char *TXT_RAIN_CONTINUOUS = "Continuous rain";
const char *TXT_RAIN_UNTIL = "Rain until %s";
const char *TXT_RAIN_FROM = "Rain from %s";
const char *TXT_RAIN_FROM_TO = "Rain from %s to %s";

// MISCELLANEOUS MESSAGES
// Title Case
const char *TXT_LOW_BATTERY = "Bateria Baixa";
Expand Down
2 changes: 2 additions & 0 deletions platformio/include/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ void drawCurrentConditions(const owm_current_t &current,
void drawForecast(const owm_daily_t *daily, tm timeInfo);
void drawAlerts(std::vector<owm_alerts_t> &alerts,
const String &city, const String &date);
void drawNextHourPrecip(const owm_minutely_t *minutely,
const String &city, const String &date);
void drawLocationDate(const String &city, const String &date);
void drawOutlookGraph(const owm_hourly_t *hourly, const owm_daily_t *daily,
tm timeInfo);
Expand Down
29 changes: 15 additions & 14 deletions platformio/src/api_response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ DeserializationError deserializeOneCall(WiFiClient &json,

JsonDocument filter;
filter["current"] = true;
filter["minutely"] = false;
filter["minutely"] = DISPLAY_NEXT_HOUR_PRECIP;
filter["hourly"] = true;
filter["daily"] = true;
#if !DISPLAY_ALERTS
Expand Down Expand Up @@ -89,19 +89,20 @@ DeserializationError deserializeOneCall(WiFiClient &json,
r.current.weather.description = current_weather["description"].as<const char *>();
r.current.weather.icon = current_weather["icon"] .as<const char *>();

// minutely forecast is currently unused
// i = 0;
// for (JsonObject minutely : doc["minutely"].as<JsonArray>())
// {
// r.minutely[i].dt = minutely["dt"] .as<int64_t>();
// r.minutely[i].precipitation = minutely["precipitation"].as<float>();

// if (i == OWM_NUM_MINUTELY - 1)
// {
// break;
// }
// ++i;
// }
#if DISPLAY_NEXT_HOUR_PRECIP
i = 0;
for (JsonObject minutely : doc["minutely"].as<JsonArray>())
{
r.minutely[i].dt = minutely["dt"] .as<int64_t>();
r.minutely[i].precipitation = minutely["precipitation"].as<float>();

if (i == OWM_NUM_MINUTELY - 1)
{
break;
}
++i;
}
#endif

i = 0;
for (JsonObject hourly : doc["hourly"].as<JsonArray>())
Expand Down
11 changes: 7 additions & 4 deletions platformio/src/client_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ bool waitForSNTPSync(tm *timeInfo)
DeserializationError jsonErr = {};
String uri = "/data/" + OWM_ONECALL_VERSION
+ "/onecall?lat=" + LAT + "&lon=" + LON + "&lang=" + OWM_LANG
+ "&units=standard&exclude=minutely";
#if !DISPLAY_ALERTS
// exclude alerts
uri += ",alerts";
+ "&units=standard";
#if !DISPLAY_NEXT_HOUR_PRECIP && !DISPLAY_ALERTS
uri += "&exclude=minutely,alerts";
#elif !DISPLAY_NEXT_HOUR_PRECIP
uri += "&exclude=minutely";
#elif !DISPLAY_ALERTS
uri += "&exclude=alerts";
#endif

// This string is printed to terminal to help with debugging. The API key is
Expand Down
7 changes: 7 additions & 0 deletions platformio/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,13 @@ void setup()
drawLocationDate(CITY_STRING, dateStr);
#if DISPLAY_ALERTS
drawAlerts(owm_onecall.alerts, CITY_STRING, dateStr);
#endif
#if DISPLAY_NEXT_HOUR_PRECIP
// Display next hour precipitations at the alerts location if none
if (owm_onecall.alerts.size() == 0)
{
drawNextHourPrecip(owm_onecall.minutely, CITY_STRING, dateStr);
}
#endif
drawStatusBar(statusStr, refreshTimeStr, wifiRSSI, batteryVoltage);
} while (display.nextPage());
Expand Down
112 changes: 112 additions & 0 deletions platformio/src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,118 @@ void drawForecast(const owm_daily_t *daily, tm timeInfo)
return;
} // end drawAlerts


void drawNextHourPrecip(const owm_minutely_t *minutely,
const String &city, const String &date)
{
float period_precipitation_mm = 0;

// Find continuous rain periods with gap tolerance
int rain_start_idx = -1;
int rain_end_idx = -1;
int gap_counter = 0;

for (int i = 0; i < OWM_NUM_MINUTELY; i++)
{
if (minutely[i].precipitation > 0)
{
// Value is given in mm/h
period_precipitation_mm += (minutely[i].precipitation / 60);

// Start of rain period
if (rain_start_idx == -1) {
rain_start_idx = i;
}

// Reset gap counter while it rains
gap_counter = 0;
rain_end_idx = i;
}
else if (rain_start_idx != -1)
{
// We're in a potential gap
gap_counter++;

// If gap exceeds threshold, close the rain period
if (gap_counter > PRECIP_MAX_GAP_MINUTES)
{
rain_end_idx = i - gap_counter;
break;
}
}
}

if (rain_start_idx == -1 || period_precipitation_mm < PRECIP_THRESHOLD_PERIOD)
{
#if DEBUG_LEVEL >= 1
Serial.println("[debug] no rain forecasted within the next hour");
#endif
return;
}


char timeBufferStart[12] = {}; // big enough to accommodate "hh:mm:ss am"
if (rain_start_idx >= 0 && rain_start_idx < OWM_NUM_MINUTELY) {
time_t ts = minutely[rain_start_idx].dt;
tm *timeInfo = localtime(&ts);
_strftime(timeBufferStart, sizeof(timeBufferStart), TIME_FORMAT, timeInfo);
}

char timeBufferEnd[12] = {}; // big enough to accommodate "hh:mm:ss am"
if (rain_end_idx >= 0 && rain_end_idx < OWM_NUM_MINUTELY) {
time_t ts = minutely[rain_end_idx].dt;
tm *timeInfo = localtime(&ts);
_strftime(timeBufferEnd, sizeof(timeBufferEnd), TIME_FORMAT, timeInfo);
}

char rain_alert_msg[100]; // big enough to accommodate full message based on the language

if (rain_start_idx == 0)
{
if (rain_end_idx == OWM_NUM_MINUTELY - 1)
{
sprintf(rain_alert_msg, TXT_RAIN_CONTINUOUS);
}
else
{
sprintf(rain_alert_msg, TXT_RAIN_UNTIL, timeBufferEnd);
}
}
else
{
if (rain_end_idx == OWM_NUM_MINUTELY - 1)
{
sprintf(rain_alert_msg, TXT_RAIN_FROM, timeBufferStart);
}
else
{
sprintf(rain_alert_msg, TXT_RAIN_FROM_TO, timeBufferStart, timeBufferEnd);
}
}

// TODO: Share this render code with drawAlerts ?
// But is expects owm_alerts_t and uses an icom the the event message which is not localized.

display.setFont(&FONT_16pt8b);
int city_w = getStringWidth(city);
display.setFont(&FONT_12pt8b);
int date_w = getStringWidth(date);
int max_w = DISP_WIDTH - 2 - std::max(city_w, date_w) - (196 + 4) - 8;

max_w -= 48;
display.drawInvertedBitmap(196, 8, wi_rain_48x48, 48, 48, GxEPD_BLACK);

display.setFont(&FONT_12pt8b);
if (getStringWidth(rain_alert_msg) <= max_w)
{ // Fits on a single line with smaller font, draw along bottom
drawString(196 + 48 + 4, 24 + 8 - 12 + 17 + 1, rain_alert_msg, LEFT);
}
else
{ // Does not fit on a single line, draw higher to allow room for 2nd line
drawMultiLnString(196 + 48 + 4, 24 + 8 - 12 + 17 - 11, rain_alert_msg, LEFT, max_w, 2, 23);
}
}

/* This function is responsible for drawing the city string and date
* information in the top right corner.
*/
Expand Down