inkplate-6-arduino-library/examples/3. Projects/1-Daily_weather_station_exa.../Network.cpp

315 lines
8.8 KiB
C++
Raw Normal View History

2020-07-31 12:09:01 +02:00
// Network.cpp contains various functions and classes that enable Weather station
// They have been declared in seperate file to increase readability
2020-07-29 08:51:24 +02:00
#include "Network.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
2020-07-31 12:09:01 +02:00
// Static Json from ArduinoJson library
2020-07-29 08:51:24 +02:00
StaticJsonDocument<6000> doc;
2020-07-31 12:09:01 +02:00
// Declared week days
2020-08-18 12:28:46 +02:00
char weekDays[8][8] = {
2020-07-29 08:51:24 +02:00
"Mon",
"Tue",
"Wed",
"Thr",
"Fri",
"Sat",
"Sun",
};
void Network::begin(char *city)
{
2020-07-31 12:09:01 +02:00
// Initiating wifi, like in BasicHttpClient example
2020-07-29 08:51:24 +02:00
WiFi.mode(WIFI_STA);
2020-08-06 14:43:47 +02:00
WiFi.begin(ssid, pass);
2020-07-29 08:51:24 +02:00
2020-08-18 12:28:46 +02:00
int cnt = 0;
Serial.print(F("Waiting for WiFi to connect..."));
while ((WiFi.status() != WL_CONNECTED))
{
Serial.print(F("."));
delay(1000);
++cnt;
2020-08-06 14:43:47 +02:00
2020-08-18 12:28:46 +02:00
if (cnt == 20)
2020-08-06 14:43:47 +02:00
{
2020-08-18 12:28:46 +02:00
Serial.println("Can't connect to WIFI, restarting");
delay(100);
ESP.restart();
2020-08-06 14:43:47 +02:00
}
2020-07-29 08:51:24 +02:00
}
2020-08-18 12:28:46 +02:00
Serial.println(F(" connected"));
2020-07-29 08:51:24 +02:00
2020-07-31 12:09:01 +02:00
// Find internet time
2020-07-29 08:51:24 +02:00
setTime();
2020-07-31 12:09:01 +02:00
// Search for given cities woeid
2020-07-29 08:51:24 +02:00
findCity(city);
}
2020-07-31 12:09:01 +02:00
// Gets time from ntp server
2020-07-29 08:51:24 +02:00
void Network::getTime(char *timeStr)
{
2020-07-31 12:09:01 +02:00
// Get seconds since 1.1.1970.
2020-07-29 08:51:24 +02:00
time_t nowSecs = time(nullptr);
2020-07-31 12:09:01 +02:00
// Used to store time
2020-07-29 08:51:24 +02:00
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
2020-07-29 09:37:28 +02:00
//Copies time string into timeStr
2020-07-29 08:51:24 +02:00
strncpy(timeStr, asctime(&timeinfo) + 11, 5);
2020-07-31 12:09:01 +02:00
// Setting time string timezone
2020-07-29 08:51:24 +02:00
int hr = 10 * timeStr[0] + timeStr[1] + timeZone;
2020-07-31 12:09:01 +02:00
// Better defined modulo, in case timezone makes hours to go below 0
2020-07-29 08:51:24 +02:00
hr = (hr % 24 + 24) % 24;
2020-07-31 12:09:01 +02:00
// Adding time to '0' char makes it into whatever time char, for both digits
2020-07-29 08:51:24 +02:00
timeStr[0] = hr / 10 + '0';
timeStr[1] = hr % 10 + '0';
}
void formatTemp(char *str, float temp)
{
2020-07-31 12:09:01 +02:00
// Built in function for float to char* conversion
2020-07-29 08:51:24 +02:00
dtostrf(temp, 2, 0, str);
}
void formatWind(char *str, float wind)
{
2020-07-31 12:09:01 +02:00
// Built in function for float to char* conversion
2020-07-29 09:37:28 +02:00
dtostrf(wind, 2, 0, str);
2020-07-29 08:51:24 +02:00
}
2020-08-18 12:28:46 +02:00
void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr, char *abbr1, char *abbr2, char *abbr3, char *abbr4)
2020-07-29 08:51:24 +02:00
{
2020-08-18 12:28:46 +02:00
// If not connected to wifi reconnect wifi
if (WiFi.status() != WL_CONNECTED)
{
2020-08-06 14:43:47 +02:00
WiFi.reconnect();
delay(5000);
2020-08-18 12:28:46 +02:00
int cnt = 0;
2020-08-06 14:43:47 +02:00
Serial.println(F("Waiting for WiFi to reconnect..."));
while ((WiFi.status() != WL_CONNECTED))
{
// Prints a dot every second that wifi isn't connected
Serial.print(F("."));
delay(1000);
2020-08-18 12:28:46 +02:00
++cnt;
if (cnt == 7)
{
Serial.println("Can't connect to WIFI, restart initiated.");
delay(100);
ESP.restart();
}
2020-08-06 14:43:47 +02:00
}
}
2020-07-29 08:51:24 +02:00
2020-07-31 12:09:01 +02:00
// Wake up if sleeping and save inital state
2020-07-29 08:51:24 +02:00
bool sleep = WiFi.getSleep();
WiFi.setSleep(false);
2020-07-31 12:09:01 +02:00
// Http object used to make get request
2020-07-29 08:51:24 +02:00
HTTPClient http;
http.getStream().setNoDelay(true);
http.getStream().setTimeout(1);
2020-07-31 12:09:01 +02:00
// Add woeid to api call
2020-07-29 08:51:24 +02:00
char url[256];
sprintf(url, "https://www.metaweather.com/api/location/%d/", location);
2020-07-31 12:09:01 +02:00
// Initiate http
2020-07-29 08:51:24 +02:00
http.begin(url);
2020-07-31 12:09:01 +02:00
// Actually do request
2020-07-29 08:51:24 +02:00
int httpCode = http.GET();
if (httpCode == 200)
{
int32_t len = http.getSize();
if (len > 0)
{
2020-07-31 12:09:01 +02:00
// Try parsing JSON object
2020-07-29 08:51:24 +02:00
DeserializationError error = deserializeJson(doc, http.getStream());
2020-07-31 12:09:01 +02:00
// If an error happens print it to Serial monitor
2020-07-29 08:51:24 +02:00
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
}
else
{
2020-07-31 12:09:01 +02:00
// Set all data got from internet using formatTemp and formatWind defined above
// This part relies heavily on ArduinoJson library
2020-07-29 08:51:24 +02:00
formatTemp(currentTemp, doc["consolidated_weather"][0][F("the_temp")].as<float>());
formatWind(currentWind, doc["consolidated_weather"][0][F("wind_speed")].as<float>());
strcpy(city, doc["title"].as<char *>());
strcpy(currentWeather, doc["consolidated_weather"][0]["weather_state_name"].as<char *>());
strcpy(currentWeatherAbbr, doc["consolidated_weather"][0]["weather_state_abbr"].as<char *>());
2020-08-11 09:26:59 +02:00
strcpy(abbr1, doc["consolidated_weather"][0]["weather_state_abbr"].as<char *>());
strcpy(abbr2, doc["consolidated_weather"][1]["weather_state_abbr"].as<char *>());
strcpy(abbr3, doc["consolidated_weather"][2]["weather_state_abbr"].as<char *>());
strcpy(abbr4, doc["consolidated_weather"][3]["weather_state_abbr"].as<char *>());
2020-07-29 08:51:24 +02:00
formatTemp(temp1, doc["consolidated_weather"][0][F("the_temp")].as<float>());
formatTemp(temp2, doc["consolidated_weather"][1][F("the_temp")].as<float>());
formatTemp(temp3, doc["consolidated_weather"][2][F("the_temp")].as<float>());
formatTemp(temp4, doc["consolidated_weather"][3][F("the_temp")].as<float>());
}
}
}
2020-07-31 12:09:01 +02:00
// Clear document and end http
2020-07-29 08:51:24 +02:00
doc.clear();
http.end();
2020-07-31 12:09:01 +02:00
// Return to initial state
2020-07-29 08:51:24 +02:00
WiFi.setSleep(sleep);
}
void Network::setTime()
{
2020-07-31 12:09:01 +02:00
// Used for setting correct time
2020-07-29 08:51:24 +02:00
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
Serial.print(F("Waiting for NTP time sync: "));
time_t nowSecs = time(nullptr);
while (nowSecs < 8 * 3600 * 2)
{
2020-07-29 09:37:28 +02:00
// Print a dot every half a second while time is not set
2020-07-29 08:51:24 +02:00
delay(500);
Serial.print(F("."));
yield();
nowSecs = time(nullptr);
}
Serial.println();
2020-07-31 12:09:01 +02:00
// Used to store time info
2020-07-29 08:51:24 +02:00
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
Serial.print(F("Current time: "));
Serial.print(asctime(&timeinfo));
}
void Network::getDays(char *day, char *day1, char *day2, char *day3)
{
2020-07-29 09:37:28 +02:00
// Seconds since 1.1.1970.
2020-07-29 08:51:24 +02:00
time_t nowSecs = time(nullptr);
2020-07-31 12:09:01 +02:00
// Find weekday
2020-07-29 08:51:24 +02:00
2020-07-31 12:09:01 +02:00
// We get seconds since 1970, add 3600 (1 hour) times the time zone and add 3 to
// make monday the first day of the week, as 1.1.1970. was a thursday
// finally do mod 7 to insure our day is within [0, 6]
2020-07-29 08:51:24 +02:00
int dayWeek = ((long)((nowSecs + 3600L * timeZone) / 86400L) + 3) % 7;
2020-07-29 09:37:28 +02:00
// Copy day data to globals in main file
2020-07-29 08:51:24 +02:00
strncpy(day, weekDays[dayWeek], 3);
strncpy(day1, weekDays[(dayWeek + 1) % 7], 3);
strncpy(day2, weekDays[(dayWeek + 2) % 7], 3);
strncpy(day3, weekDays[(dayWeek + 3) % 7], 3);
}
void Network::findCity(char *city)
{
2020-08-06 14:43:47 +02:00
// If not connected to wifi reconnect wifi
2020-08-18 12:28:46 +02:00
if (WiFi.status() != WL_CONNECTED)
{
2020-08-06 14:43:47 +02:00
WiFi.reconnect();
delay(5000);
2020-08-18 12:28:46 +02:00
int cnt = 0;
2020-08-06 14:43:47 +02:00
Serial.println(F("Waiting for WiFi to reconnect..."));
while ((WiFi.status() != WL_CONNECTED))
{
// Prints a dot every second that wifi isn't connected
Serial.print(F("."));
delay(1000);
2020-08-18 12:28:46 +02:00
++cnt;
if (cnt == 7)
{
Serial.println("Can't connect to WIFI, restart initiated.");
delay(100);
ESP.restart();
}
2020-08-06 14:43:47 +02:00
}
}
2020-07-29 08:51:24 +02:00
2020-07-31 12:09:01 +02:00
// Wake wifi module and save initial state
2020-07-29 08:51:24 +02:00
bool sleep = WiFi.getSleep();
WiFi.setSleep(false);
2020-07-31 12:09:01 +02:00
// Http object
2020-07-29 08:51:24 +02:00
HTTPClient http;
http.getStream().setNoDelay(true);
http.getStream().setTimeout(1);
2020-07-31 12:09:01 +02:00
// Add query param to url
2020-07-29 08:51:24 +02:00
char url[256];
strcpy(url, "https://www.metaweather.com/api/location/search/?query=");
strcat(url, city);
2020-07-31 12:09:01 +02:00
// Initiate http
2020-07-29 08:51:24 +02:00
http.begin(url);
2020-07-31 12:09:01 +02:00
// Do get request
2020-07-29 08:51:24 +02:00
int httpCode = http.GET();
if (httpCode == 200) // 200: http success
{
int32_t len = http.getSize();
if (len > 0)
{
2020-07-31 12:09:01 +02:00
// Try to parse JSON object
2020-07-29 08:51:24 +02:00
DeserializationError error = deserializeJson(doc, http.getStream());
2020-07-31 12:09:01 +02:00
// Print error to Serial monitor if one exsists
2020-07-29 08:51:24 +02:00
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
}
else
{
2020-07-31 12:09:01 +02:00
// Empty list means no matches
2020-07-29 08:51:24 +02:00
if (doc.size() == 0)
{
Serial.println(F("City not found"));
}
else
{
2020-07-31 12:09:01 +02:00
// Woeid id used for fetching data later on
2020-07-29 08:51:24 +02:00
location = doc[0]["woeid"].as<int>();
Serial.println(F("Found city, woied:"));
Serial.println(location);
}
}
}
}
2020-07-31 12:09:01 +02:00
// Clear document and end http
2020-07-29 08:51:24 +02:00
doc.clear();
http.end();
2020-07-31 12:09:01 +02:00
// Return module to initial state
2020-07-29 08:51:24 +02:00
WiFi.setSleep(sleep);
2020-07-31 12:09:01 +02:00
};