Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save LuczaGyuri/8be9f494fd2283bdf8a845c61fba5db6 to your computer and use it in GitHub Desktop.
Save LuczaGyuri/8be9f494fd2283bdf8a845c61fba5db6 to your computer and use it in GitHub Desktop.
openweathermap.org mod: pressure change hPa (mbar), add sunrise and sunset
#ifndef dsp_full_loc
#define dsp_full_loc
#include <pgmspace.h>
/*************************************************************************************
HOWTO:
Copy this file to yoRadio/locale/displayL10n_custom.h
and modify it
*************************************************************************************/
const char mon[] PROGMEM = "hé";
const char tue[] PROGMEM = "ke";
const char wed[] PROGMEM = "sz";
const char thu[] PROGMEM = "cs";
const char fri[] PROGMEM = "pé";
const char sat[] PROGMEM = "SZ";
const char sun[] PROGMEM = "VA";
const char monf[] PROGMEM = "hétfő";
const char tuef[] PROGMEM = "kedd";
const char wedf[] PROGMEM = "szerda";
const char thuf[] PROGMEM = "csütörtök";
const char frif[] PROGMEM = "péntek";
const char satf[] PROGMEM = "szombat";
const char sunf[] PROGMEM = "vasárnap";
const char jan[] PROGMEM = "január";
const char feb[] PROGMEM = "február";
const char mar[] PROGMEM = "március";
const char apr[] PROGMEM = "április";
const char may[] PROGMEM = "május";
const char jun[] PROGMEM = "június";
const char jul[] PROGMEM = "július";
const char aug[] PROGMEM = "augusztus";
const char sep[] PROGMEM = "szeptember";
const char oct[] PROGMEM = "október";
const char nov[] PROGMEM = "november";
const char dec[] PROGMEM = "december";
const char wn_N[] PROGMEM = "É";
const char wn_NNE[] PROGMEM = "É-ÉK";
const char wn_NE[] PROGMEM = "ÉK";
const char wn_ENE[] PROGMEM = "K-ÉK";
const char wn_E[] PROGMEM = "K";
const char wn_ESE[] PROGMEM = "K-DK";
const char wn_SE[] PROGMEM = "DK";
const char wn_SSE[] PROGMEM = "DK-D";
const char wn_S[] PROGMEM = "D";
const char wn_SSW[] PROGMEM = "D-DNy";
const char wn_SW[] PROGMEM = "DNy";
const char wn_WSW[] PROGMEM = "Ny-DNy";
const char wn_W[] PROGMEM = "Ny";
const char wn_WNW[] PROGMEM = "Ny-ÉNy";
const char wn_NW[] PROGMEM = "ÉNy";
const char wn_NNW[] PROGMEM = "ÉNy-Ny";
const char* const dow[] PROGMEM = { sun, mon, tue, wed, thu, fri, sat };
const char* const dowf[] PROGMEM = { sunf, monf, tuef, wedf, thuf, frif, satf };
const char* const mnths[] PROGMEM = { jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
const char* const wind[] PROGMEM = { wn_N, wn_NNE, wn_NE, wn_ENE, wn_E, wn_ESE, wn_SE, wn_SSE, wn_S, wn_SSW, wn_SW, wn_WSW, wn_W, wn_WNW, wn_NW, wn_NNW, wn_N };
const char const_PlReady[] PROGMEM = "[kész]";
const char const_PlStopped[] PROGMEM = "[stop]";
const char const_PlConnect[] PROGMEM = "[csatlakozás]";
const char const_DlgVolume[] PROGMEM = "Hangerő";
const char const_DlgLost[] PROGMEM = "* LESZAKADT *";
const char const_DlgUpdate[] PROGMEM = "* FRISSÍTES *";
const char const_DlgNextion[] PROGMEM = "* NEXTION *";
const char const_getWeather[] PROGMEM = "";
const char const_waitForSD[] PROGMEM = "INDEX SD";
const char apNameTxt[] PROGMEM = "WiFi AP";
const char apPassTxt[] PROGMEM = "Jelszó";
const char bootstrFmt[] PROGMEM = "Csatlakozás: %s";
const char apSettFmt[] PROGMEM = "A rádió elérhetősége: HTTP://%s/";
#if EXT_WEATHER
const char weatherFmt[] PROGMEM = "%s, %.1f\011C \007 hőérzet: %.1f\011C \007 légnyomás: %d hPa \007 páratartalom: %s%% \007 szél: %.1f m/s [%s] \007 nap: %s-%s";
#else
const char weatherFmt[] PROGMEM = "%s, %.1f\011C \007 légnyomás: %d hPa \007 páratartalom: %s%%";
#endif
const char weatherUnits[] PROGMEM = "metric"; /* standard, metric, imperial */
const char weatherLang[] PROGMEM = "hu"; /* https://openweathermap.org/current#multi */
#endif
#include "network.h"
#include "display.h"
#include "options.h"
#include "config.h"
#include "telnet.h"
#include "netserver.h"
#include "player.h"
#include "mqtt.h"
#ifndef WIFI_ATTEMPTS
#define WIFI_ATTEMPTS 16
#endif
Network network;
TaskHandle_t syncTaskHandle;
//TaskHandle_t reconnectTaskHandle;
bool getWeather(char *wstr);
void doSync(void * pvParameters);
void ticks() {
if(!display.ready()) return; //waiting for SD is ready
static const uint16_t weatherSyncInterval=1800;
//static const uint16_t weatherSyncIntervalFail=10;
#if RTCSUPPORTED
static const uint32_t timeSyncInterval=86400;
static uint32_t timeSyncTicks = 0;
#else
static const uint16_t timeSyncInterval=3600;
static uint16_t timeSyncTicks = 0;
#endif
static uint16_t weatherSyncTicks = 0;
static bool divrssi;
timeSyncTicks++;
weatherSyncTicks++;
divrssi = !divrssi;
if(network.status == CONNECTED){
if(network.forceTimeSync || network.forceWeather){
xTaskCreatePinnedToCore(doSync, "doSync", 1024 * 4, NULL, 0, &syncTaskHandle, 0);
}
if(timeSyncTicks >= timeSyncInterval){
timeSyncTicks=0;
network.forceTimeSync = true;
}
if(weatherSyncTicks >= weatherSyncInterval){
weatherSyncTicks=0;
network.forceWeather = true;
}
}
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
mktime(&network.timeinfo);
display.putRequest(CLOCK);
#else
if(network.timeinfo.tm_year>100 || network.status == SDREADY) {
network.timeinfo.tm_sec++;
mktime(&network.timeinfo);
display.putRequest(CLOCK);
}
#endif
if(player.isRunning() && config.getMode()==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
if(divrssi) {
if(network.status == CONNECTED){
netserver.setRSSI(WiFi.RSSI());
netserver.requestOnChange(NRSSI, 0);
display.putRequest(DSPRSSI, netserver.getRSSI());
}
#ifdef USE_SD
if(display.mode()!=SDCHANGE) player.sendCommand({PR_CHECKSD, 0});
#endif
}
}
void Network::WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info){
network.beginReconnect = false;
player.lockOutput = false;
delay(100);
display.putRequest(NEWMODE, PLAYER);
if(config.getMode()==PM_SDCARD) {
network.status=CONNECTED;
display.putRequest(NEWIP, 0);
}else{
display.putRequest(NEWMODE, PLAYER);
if (network.lostPlaying) player.sendCommand({PR_PLAY, config.store.lastStation});
}
#ifdef MQTT_ROOT_TOPIC
connectToMqtt();
#endif
}
void Network::WiFiLostConnection(WiFiEvent_t event, WiFiEventInfo_t info){
if(!network.beginReconnect){
Serial.printf("Lost connection, reconnecting to %s...\n", config.ssids[config.store.lastSSID-1].ssid);
if(config.getMode()==PM_SDCARD) {
network.status=SDREADY;
display.putRequest(NEWIP, 0);
}else{
network.lostPlaying = player.isRunning();
if (network.lostPlaying) { player.lockOutput = true; player.sendCommand({PR_STOP, 0}); }
display.putRequest(NEWMODE, LOST);
}
}
network.beginReconnect = true;
WiFi.reconnect();
}
bool Network::wifiBegin(bool silent){
uint8_t ls = (config.store.lastSSID == 0 || config.store.lastSSID > config.ssidsCount) ? 0 : config.store.lastSSID - 1;
uint8_t startedls = ls;
uint8_t errcnt = 0;
WiFi.mode(WIFI_STA);
while (true) {
if(!silent){
Serial.printf("##[BOOT]#\tAttempt to connect to %s\n", config.ssids[ls].ssid);
Serial.print("##[BOOT]#\t");
display.putRequest(BOOTSTRING, ls);
}
WiFi.begin(config.ssids[ls].ssid, config.ssids[ls].password);
while (WiFi.status() != WL_CONNECTED) {
if(!silent) Serial.print(".");
delay(500);
if(LED_BUILTIN!=255 && !silent) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
errcnt++;
if (errcnt > WIFI_ATTEMPTS) {
errcnt = 0;
ls++;
if (ls > config.ssidsCount - 1) ls = 0;
if(!silent) Serial.println();
break;
}
}
if (WiFi.status() != WL_CONNECTED && ls == startedls) {
return false; break;
}
if (WiFi.status() == WL_CONNECTED) {
config.setLastSSID(ls + 1);
return true; break;
}
}
return false;
}
void searchWiFi(void * pvParameters){
if(!network.wifiBegin(true)){
delay(10000);
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
}else{
network.status = CONNECTED;
netserver.begin(true);
telnet.begin(true);
network.setWifiParams();
display.putRequest(NEWIP, 0);
}
vTaskDelete( NULL );
}
#define DBGAP false
void Network::begin() {
BOOTLOG("network.begin");
config.initNetwork();
ctimer.detach();
forceTimeSync = forceWeather = true;
if (config.ssidsCount == 0 || DBGAP) {
raiseSoftAP();
return;
}
if(config.getMode()!=PM_SDCARD){
if(!wifiBegin()){
raiseSoftAP();
Serial.println("##[BOOT]#\tdone");
return;
}
Serial.println(".");
status = CONNECTED;
setWifiParams();
}else{
status = SDREADY;
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
}
Serial.println("##[BOOT]#\tdone");
if(LED_BUILTIN!=255) digitalWrite(LED_BUILTIN, LOW);
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
mktime(&network.timeinfo);
display.putRequest(CLOCK);
#endif
ctimer.attach(1, ticks);
if (network_on_connect) network_on_connect();
}
void Network::setWifiParams(){
WiFi.setSleep(false);
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
weatherBuf=NULL;
trueWeather = false;
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
weatherBuf = (char *) malloc(sizeof(char) * WEATHER_STRING_L);
memset(weatherBuf, 0, WEATHER_STRING_L);
#endif
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
}
}
void Network::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {
if (withTelnetOutput) {
char timeStringBuff[50];
strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%S", &timeinfo);
if (config.store.tzHour < 0) {
telnet.printf(clientId, "##SYS.DATE#: %s%03d:%02d\n> ", timeStringBuff, config.store.tzHour, config.store.tzMin);
} else {
telnet.printf(clientId, "##SYS.DATE#: %s+%02d:%02d\n> ", timeStringBuff, config.store.tzHour, config.store.tzMin);
}
}
}
void rebootTime() {
ESP.restart();
}
void Network::raiseSoftAP() {
WiFi.mode(WIFI_AP);
WiFi.softAP(apSsid, apPassword);
Serial.println("##[BOOT]#");
BOOTLOG("************************************************");
BOOTLOG("Running in AP mode");
BOOTLOG("Connect to AP %s with password %s", apSsid, apPassword);
BOOTLOG("and go to http:/192.168.4.1/ to configure");
BOOTLOG("************************************************");
status = SOFT_AP;
if(config.store.softapdelay>0)
rtimer.once(config.store.softapdelay*60, rebootTime);
}
void Network::requestWeatherSync(){
display.putRequest(NEWWEATHER);
}
void doSync( void * pvParameters ) {
static uint8_t tsFailCnt = 0;
//static uint8_t wsFailCnt = 0;
if(network.forceTimeSync){
network.forceTimeSync = false;
if(getLocalTime(&network.timeinfo)){
tsFailCnt = 0;
network.forceTimeSync = false;
mktime(&network.timeinfo);
display.putRequest(CLOCK);
network.requestTimeSync(true);
#if RTCSUPPORTED
if (config.isRTCFound()) rtc.setTime(&network.timeinfo);
#endif
}else{
if(tsFailCnt<4){
network.forceTimeSync = true;
tsFailCnt++;
}else{
network.forceTimeSync = false;
tsFailCnt=0;
}
}
}
if(network.weatherBuf && (strlen(config.store.weatherkey)!=0 && config.store.showweather) && network.forceWeather){
network.forceWeather = false;
network.trueWeather=getWeather(network.weatherBuf);
}
vTaskDelete( NULL );
}
bool getWeather(char *wstr) {
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
WiFiClient client;
const char* host = "api.openweathermap.org";
if (!client.connect(host, 80)) {
Serial.println("##WEATHER###: connection failed");
return false;
}
char httpget[250] = {0};
sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=%s&lang=%s&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, weatherUnits, weatherLang, config.store.weatherkey, host);
client.print(httpget);
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 3000UL) {
Serial.println("##WEATHER###: client available timeout !");
client.stop();
return false;
}
}
timeout = millis();
String line = "";
if (client.connected()) {
while (client.available())
{
line = client.readStringUntil('\n');
if (strstr(line.c_str(), "\"temp\"") != NULL) {
client.stop();
break;
}
if ((millis() - timeout) > 500)
{
client.stop();
Serial.println("##WEATHER###: client read timeout !");
return false;
}
}
}
if (strstr(line.c_str(), "\"temp\"") == NULL) {
Serial.println("##WEATHER###: weather not found !");
return false;
}
char *tmpe;
char *tmps;
char *tmpc;
const char* cursor = line.c_str();
char desc[120], temp[20], hum[20], press[20], icon[5], sunriseow[20], sunsetow[20];
tmps = strstr(cursor, "\"description\":\"");
if (tmps == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
tmps += 15;
tmpe = strstr(tmps, "\",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
strlcpy(desc, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
// "ясно","icon":"01d"}],
tmps = strstr(cursor, "\"icon\":\"");
if (tmps == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
tmps += 8;
tmpe = strstr(tmps, "\"}");
if (tmpe == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
strlcpy(icon, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
tmps = strstr(cursor, "\"temp\":");
if (tmps == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
tmps += 7;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
strlcpy(temp, tmps, tmpe - tmps + 1);
cursor = tmpe + 1;
float tempf = atof(temp);
tmps = strstr(cursor, "\"feels_like\":");
if (tmps == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
tmps += 13;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
strlcpy(temp, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
float tempfl = atof(temp); (void)tempfl;
tmps = strstr(cursor, "\"pressure\":");
if (tmps == NULL) { Serial.println("##WEATHER###: pressure not found !"); return false;}
tmps += 11;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: pressure not found !"); return false;}
strlcpy(press, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
int pressi = (float)atoi(press); // delete "/ 1.333"
tmps = strstr(cursor, "humidity\":");
if (tmps == NULL) { Serial.println("##WEATHER###: humidity not found !"); return false;}
tmps += 10;
tmpe = strstr(tmps, ",\"");
tmpc = strstr(tmps, "}");
if (tmpe == NULL) { Serial.println("##WEATHER###: humidity not found !"); return false;}
strlcpy(hum, tmps, tmpe - tmps + (tmpc>tmpe?1:0));
/*
tmps = strstr(cursor, "\"grnd_level\":");
bool grnd_level_pr = (tmps != NULL);
if(grnd_level_pr){
tmps += 13;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: grnd_level not found !"); return false;}
strlcpy(press, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
pressi = (float)atoi(press) / 1.333;
}
*/
tmps = strstr(cursor, "\"speed\":");
if (tmps == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
tmps += 8;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
strlcpy(temp, tmps, tmpe - tmps + 1);
cursor = tmpe + 1;
float wind_speed = atof(temp); (void)wind_speed;
tmps = strstr(cursor, "\"deg\":");
if (tmps == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
tmps += 6;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
strlcpy(temp, tmps, tmpe - tmps + 1);
cursor = tmpe + 1;
int wind_deg = atof(temp)/22.5;
if(wind_deg<0) wind_deg = 16+wind_deg;
tmps = strstr(cursor, "\"sunrise\":");
if (tmps == NULL) { Serial.println("##WEATHER###: sunrise not found !"); return false;}
tmps += 10;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("##WEATHER###: sunrise not found !"); return false;}
strlcpy(sunriseow, tmps, tmpe - tmps + 1);
cursor = tmpe + 1;
unsigned long sunriseowU = atol(sunriseow); // Unix időbélyeg kiolvasása a sunriseow változóból
unsigned long sunriseow_hours = ((sunriseowU % 86400L) / 3600) + config.store.tzHour; // időzóna óra korrekció
unsigned long sunriseow_minutes = ((sunriseowU % 3600) / 60) + config.store.tzMin; // időzóna perc korrekció
snprintf(sunriseow, 6, "%02lu:%02lu", sunriseow_hours, sunriseow_minutes);
tmps = strstr(cursor, "\"sunset\":");
if (tmps == NULL) { Serial.println("##WEATHER###: sunset not found !"); return false;}
tmps += 9;
tmpe = strstr(tmps, "\}\,");
if (tmpe == NULL) { Serial.println("##WEATHER###: sunset not found !"); return false;}
strlcpy(sunsetow, tmps, tmpe - tmps + 1);
cursor = tmpe + 1;
unsigned long sunsetowU = atol(sunsetow); // Unix időbélyeg kiolvasása a sunriseow változóból
unsigned long sunsetow_hours = ((sunsetowU % 86400L) / 3600) + config.store.tzHour; // időzóna óra korrekció
unsigned long sunsetow_minutes = ((sunsetowU % 3600) / 60) + config.store.tzMin; // időzóna perc korrekció
snprintf(sunsetow, 6, "%02lu:%02lu", sunsetow_hours, sunsetow_minutes);
#ifdef USE_NEXTION
nextion.putcmdf("press_txt.txt=\"%dmm\"", pressi);
nextion.putcmdf("hum_txt.txt=\"%d%%\"", atoi(hum));
char cmd[30];
snprintf(cmd, sizeof(cmd)-1,"temp_txt.txt=\"%.1f\"", tempf);
nextion.putcmd(cmd);
int iconofset;
if(strstr(icon,"01")!=NULL) iconofset = 0;
else if(strstr(icon,"02")!=NULL) iconofset = 1;
else if(strstr(icon,"03")!=NULL) iconofset = 2;
else if(strstr(icon,"04")!=NULL) iconofset = 3;
else if(strstr(icon,"09")!=NULL) iconofset = 4;
else if(strstr(icon,"10")!=NULL) iconofset = 5;
else if(strstr(icon,"11")!=NULL) iconofset = 6;
else if(strstr(icon,"13")!=NULL) iconofset = 7;
else if(strstr(icon,"50")!=NULL) iconofset = 8;
else iconofset = 9;
nextion.putcmd("cond_img.pic", 50+iconofset);
nextion.weatherVisible(1);
#endif
Serial.printf("##WEATHER###: description: %s, temp:%.1f C, pressure:%d hPa, humidity:%s, sunrise: %s, sunset: %s\n", desc, tempf, pressi, hum, sunriseow, sunsetow);
#ifdef WEATHER_FMT_SHORT
sprintf(wstr, weatherFmt, tempf, pressi, hum, sunriseow, sunriseow);
#else
#if EXT_WEATHER
sprintf(wstr, weatherFmt, desc, tempf, tempfl, pressi, hum, wind_speed, wind[wind_deg], sunriseow, sunsetow);
#else
sprintf(wstr, weatherFmt, desc, tempf, pressi, hum);
#endif
#endif
network.requestWeatherSync();
return true;
#endif // if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
return false;
}
@LuczaGyuri
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment