Added weather station example

This commit is contained in:
nitko12 2020-07-29 09:37:28 +02:00
parent 56220ca45f
commit 5853e792ee
81 changed files with 195 additions and 140 deletions

View File

@ -10,6 +10,7 @@
IMPORTANT:
Make sure to change your desired city, timezone and wifi credentials below
Also have ArduinoJSON installed in your Arduino libraries
Want to learn more about Inkplate? Visit www.inkplate.io
Looking to get support? Write on our forums: http://forum.e-radionica.com/en/
@ -18,13 +19,13 @@
// ---------- CHANGE HERE -------------:
// time zone for adding hours
// Time zone for adding hours
int timeZone = 2;
// city search query
// City search query
char city[128] = "ZAGREB";
// change to your wifi ssid and password
// Change to your wifi ssid and password
char *ssid = "e-radionica.com";
char *pass = "croduino";
@ -33,31 +34,31 @@ char *pass = "croduino";
// Include Inkplate library to the sketch
#include "Inkplate.h"
// header file for easier code readability
// Header file for easier code readability
#include "Network.h"
// including fonts used
// Including fonts used
#include "Fonts/Roboto_Light_48.h"
#include "Fonts/Roboto_Light_36.h"
#include "Fonts/Roboto_Light_120.h"
// including icons generated by the py file
// Including icons generated by the py file
#include "icons.h"
// delay between API calls
// Delay between API calls
#define DELAY_MS 15000
// Inkplate object
Inkplate display(INKPLATE_1BIT);
// all our network functions are in this object, see Network.h
// All our network functions are in this object, see Network.h
Network network;
// contants used for drawing icons
// Contants used for drawing icons
char abbrs[32][16] = {"sn", "sl", "h", "t", "hr", "lr", "s", "hc", "lc", "c"};
const uint8_t *logos[16] = {icon_sn, icon_sl, icon_h, icon_t, icon_hr, icon_lr, icon_s, icon_hc, icon_lc, icon_c};
// variables for storing temperature
// Variables for storing temperature
char temps[8][4] = {
"0F",
"0F",
@ -65,7 +66,7 @@ char temps[8][4] = {
"0F",
};
// variables for storing days of the week
// Variables for storing days of the week
char days[8][4] = {
"",
"",
@ -73,7 +74,13 @@ char days[8][4] = {
"",
};
// variables for storing current time and weather info
// Variable for counting partial refreshes
long refreshes = 0;
// Constant to determine when to full update
const int fullRefresh = 10;
// Variables for storing current time and weather info
char currentTemp[16] = "0F";
char currentWind[16] = "0m/s";
@ -82,18 +89,88 @@ char currentTime[16] = "9:41";
char currentWeather[32] = "-";
char currentWeatherAbbr[8] = "th";
// function for drawing weather info
// functions defined below
void drawWeather();
void drawCurrent();
void drawTemps();
void drawCity();
void drawTime();
void setup()
{
// Begin serial and display
Serial.begin(115200);
display.begin();
// Initial cleaning of buffer and physical screen
display.clearDisplay();
display.clean();
// Calling our begin from network.h file
network.begin(city);
// If city not found, do nothing
if (network.location == -1)
{
display.setCursor(50, 290);
display.setTextSize(3);
display.print(F("City not in Metaweather Database"));
display.display();
while (1)
;
}
// Welcome screen
display.setCursor(50, 290);
display.setTextSize(3);
display.print(F("Welcome to Inkplate 6 weather example!"));
display.display();
// Wait a bit before proceeding
delay(5000);
}
void loop()
{
// Clear display
display.clearDisplay();
// Get all relevant data, see Network.cpp for info
network.getTime(currentTime);
network.getDays(days[0], days[1], days[2], days[3]);
network.getData(city, temps[0], temps[1], temps[2], temps[3], currentTemp, currentWind, currentTime, currentWeather, currentWeatherAbbr);
// Draw data, see functions below for info
drawWeather();
drawCurrent();
drawTemps();
drawCity();
drawTime();
// Refresh full screen every fullRefresh times, defined above
if (refreshes % fullRefresh == 0)
display.display();
else
display.partialUpdate();
// Go to sleep before checking again
esp_sleep_enable_timer_wakeup(1000L * DELAY_MS);
(void)esp_light_sleep_start();
++refreshes;
}
// Function for drawing weather info
void drawWeather()
{
// searching for weather state abbreviation
// Searching for weather state abbreviation
for (int i = 0; i < 10; ++i)
{
// if found draw specified icon
// If found draw specified icon
if (strcmp(abbrs[i], currentWeatherAbbr) == 0)
display.drawBitmap(50, 50, logos[i], 152, 152, BLACK);
}
// draw weather state
// Draw weather state
display.setTextColor(BLACK, WHITE);
display.setFont(&Roboto_Light_36);
display.setTextSize(1);
@ -101,10 +178,10 @@ void drawWeather()
display.println(currentWeather);
}
// function for drawing current time
// Function for drawing current time
void drawTime()
{
// drawing current time
// Drawing current time
display.setTextColor(BLACK, WHITE);
display.setFont(&Roboto_Light_36);
display.setTextSize(1);
@ -113,10 +190,10 @@ void drawTime()
display.println(currentTime);
}
// function for drawing city name
// Function for drawing city name
void drawCity()
{
// drawing city name
// Drawing city name
display.setTextColor(BLACK, WHITE);
display.setFont(&Roboto_Light_36);
display.setTextSize(1);
@ -125,10 +202,10 @@ void drawCity()
display.println(city);
}
// function for drawing temperatures
// Function for drawing temperatures
void drawTemps()
{
// drawing 4 black rectangles in which temperatures will be written
// Drawing 4 black rectangles in which temperatures will be written
int rectWidth = 150;
int rectSpacing = (800 - rectWidth * 4) / 5;
@ -155,7 +232,7 @@ void drawTemps()
display.setCursor(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 70);
display.println(days[3]);
// drawing temperature values into black rectangles
// Drawing temperature values into black rectangles
display.setFont(&Roboto_Light_48);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
@ -173,85 +250,52 @@ void drawTemps()
display.println(temps[3]);
}
// current weather drawing function
// Current weather drawing function
void drawCurrent()
{
// drawing current information
// Drawing current information
// Temperature:
display.setFont(&Roboto_Light_120);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
// temperature:
display.setCursor(245, 150);
display.println(currentTemp);
display.print(currentTemp);
int x = display.getCursorX();
int y = display.getCursorY();
display.setFont(&Roboto_Light_48);
display.setTextSize(1);
display.setCursor(x, y);
display.println(F("C"));
// Wind:
display.setFont(&Roboto_Light_120);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
// wind
display.setCursor(480, 150);
display.println(currentWind);
display.print(currentWind);
x = display.getCursorX();
y = display.getCursorY();
display.setFont(&Roboto_Light_48);
display.setTextSize(1);
display.setCursor(x, y);
display.println(F("m/s"));
// Labels underneath
display.setFont(&Roboto_Light_36);
display.setTextSize(1);
// labels underneath
display.setCursor(215, 210);
display.println(F("TEMPERATURE"));
display.setCursor(500, 210);
display.println(F("WIND SPEED"));
}
void setup()
{
// begin serial and display
Serial.begin(115200);
display.begin();
// initial cleaning of buffer and physical screen
display.clearDisplay();
display.clean();
// calling our begin from network.h file
network.begin(city);
// if city not found, do nothing
if (network.location == -1)
{
display.setCursor(50, 290);
display.setTextSize(3);
display.print(F("City not in Metaweather Database"));
display.display();
while (1)
;
}
// Welcome screen
display.setCursor(50, 290);
display.setTextSize(3);
display.print(F("Welcome to Inkplate 6 weather example!"));
display.display();
// wait a bit before proceeding
delay(5000);
}
void loop()
{
// clear display
display.clearDisplay();
// get all relevant data, see Network.cpp for info
network.getTime(currentTime);
network.getDays(days[0], days[1], days[2], days[3]);
network.getData(city, temps[0], temps[1], temps[2], temps[3], currentTemp, currentWind, currentTime, currentWeather, currentWeatherAbbr);
// draw data
drawWeather();
drawCurrent();
drawTemps();
drawCity();
drawTime();
// display and wait before doing it again
display.display();
delay(DELAY_MS);
}

View File

@ -1,4 +1,5 @@
// defines in header for readability
// Network.cpp contains various functions and classes that enable Weather station
// They have been declared in seperate file to increase readability
#include "Network.h"
#include <WiFi.h>
@ -14,7 +15,7 @@ WiFiMulti WiFiMulti;
// Static Json from ArduinoJson library
StaticJsonDocument<6000> doc;
// declared week days
// Declared week days
char weekDays[8][8] = {
"Mon",
"Tue",
@ -27,91 +28,89 @@ char weekDays[8][8] = {
void Network::begin(char *city)
{
// initiating wifi, like in BasicHttpClient example
// Initiating wifi, like in BasicHttpClient example
WiFi.mode(WIFI_STA);
WiFiMulti.addAP(ssid, pass);
Serial.print(F("Waiting for WiFi to connect..."));
while ((WiFiMulti.run() != WL_CONNECTED))
{
// Printing a dot to Serial monitor every second while waiting to connect
Serial.print(F("."));
delay(1000);
}
Serial.println(F(" connected"));
// find internet time
// Find internet time
setTime();
// search for given cities woeid
// Search for given cities woeid
findCity(city);
// reduce power by making WiFi module sleep
WiFi.setSleep(1);
}
// gets time from ntp server
// Gets time from ntp server
void Network::getTime(char *timeStr)
{
// get seconds since 1.1.1970.
// Get seconds since 1.1.1970.
time_t nowSecs = time(nullptr);
// used to store time
// Used to store time
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
//copies time string into timeStr
//Copies time string into timeStr
strncpy(timeStr, asctime(&timeinfo) + 11, 5);
// setting time string timezone
// Setting time string timezone
int hr = 10 * timeStr[0] + timeStr[1] + timeZone;
// better defined modulo, in case timezone makes hours to go below 0
// Better defined modulo, in case timezone makes hours to go below 0
hr = (hr % 24 + 24) % 24;
// adding time to '0' char makes it into whatever time char, for both digits
// Adding time to '0' char makes it into whatever time char, for both digits
timeStr[0] = hr / 10 + '0';
timeStr[1] = hr % 10 + '0';
}
void formatTemp(char *str, float temp)
{
// built in function for float to char* conversion
// Built in function for float to char* conversion
dtostrf(temp, 2, 0, str);
// concat "C" to end
strcat(str, "C");
}
void formatWind(char *str, float wind)
{
// built in function for float to char* conversion
dtostrf(14.0, 2, 0, str);
// concat m/s to end
strcat(str, "m/s");
// Built in function for float to char* conversion
dtostrf(wind, 2, 0, str);
}
void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr)
{
// return if wifi isn't connected
// Return if wifi isn't connected
if (WiFi.status() != WL_CONNECTED)
return;
// wake up if sleeping and save inital state
// Wake up if sleeping and save inital state
bool sleep = WiFi.getSleep();
WiFi.setSleep(false);
// http object used to make get request
// Http object used to make get request
HTTPClient http;
http.getStream().setNoDelay(true);
http.getStream().setTimeout(1);
// add woeid to api call
// Add woeid to api call
char url[256];
sprintf(url, "https://www.metaweather.com/api/location/%d/", location);
// initiate http
// Initiate http
http.begin(url);
// actually do request
// Actually do request
int httpCode = http.GET();
if (httpCode == 200)
{
@ -119,9 +118,10 @@ void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *t
if (len > 0)
{
// try parsing JSON object
// Try parsing JSON object
DeserializationError error = deserializeJson(doc, http.getStream());
// If an error happens print it to Serial monitor
if (error)
{
Serial.print(F("deserializeJson() failed: "));
@ -129,8 +129,8 @@ void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *t
}
else
{
// set all data got from internet using formatTemp and formatWind defined above
// this part relies heavily on ArduinoJson library
// Set all data got from internet using formatTemp and formatWind defined above
// This part relies heavily on ArduinoJson library
formatTemp(currentTemp, doc["consolidated_weather"][0][F("the_temp")].as<float>());
formatWind(currentWind, doc["consolidated_weather"][0][F("wind_speed")].as<float>());
@ -146,23 +146,24 @@ void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *t
}
}
// clear document and end http
// Clear document and end http
doc.clear();
http.end();
// return to initial state
// Return to initial state
WiFi.setSleep(sleep);
}
void Network::setTime()
{
// used for setting correct time
// Used for setting correct time
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)
{
// Print a dot every half a second while time is not set
delay(500);
Serial.print(F("."));
yield();
@ -171,7 +172,7 @@ void Network::setTime()
Serial.println();
// used to store time info
// Used to store time info
struct tm timeinfo;
gmtime_r(&nowSecs, &timeinfo);
@ -181,17 +182,17 @@ void Network::setTime()
void Network::getDays(char *day, char *day1, char *day2, char *day3)
{
// seconds since 1.1.1970.
// Seconds since 1.1.1970.
time_t nowSecs = time(nullptr);
// find weekday
// Find weekday
// we get seconds since 1970, add 3600 (1 hour) times the time zone and add 3 to
// 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]
int dayWeek = ((long)((nowSecs + 3600L * timeZone) / 86400L) + 3) % 7;
// copy day data to globals in main file
// Copy day data to globals in main file
strncpy(day, weekDays[dayWeek], 3);
strncpy(day1, weekDays[(dayWeek + 1) % 7], 3);
strncpy(day2, weekDays[(dayWeek + 2) % 7], 3);
@ -200,29 +201,29 @@ void Network::getDays(char *day, char *day1, char *day2, char *day3)
void Network::findCity(char *city)
{
// if not connected to wifi, return
// If not connected to wifi, return
if (WiFi.status() != WL_CONNECTED)
return;
// wake wifi module and save initial state
// Wake wifi module and save initial state
bool sleep = WiFi.getSleep();
WiFi.setSleep(false);
// http object
// Http object
HTTPClient http;
http.getStream().setNoDelay(true);
http.getStream().setTimeout(1);
// add query param to url
// Add query param to url
char url[256];
strcpy(url, "https://www.metaweather.com/api/location/search/?query=");
strcat(url, city);
// initiate http
// Initiate http
http.begin(url);
// do get request
// Do get request
int httpCode = http.GET();
if (httpCode == 200) // 200: http success
{
@ -230,9 +231,10 @@ void Network::findCity(char *city)
if (len > 0)
{
// try to parse JSON object
// Try to parse JSON object
DeserializationError error = deserializeJson(doc, http.getStream());
// Print error to Serial monitor if one exsists
if (error)
{
Serial.print(F("deserializeJson() failed: "));
@ -240,14 +242,14 @@ void Network::findCity(char *city)
}
else
{
// empty list means no matches
// Empty list means no matches
if (doc.size() == 0)
{
Serial.println(F("City not found"));
}
else
{
// woeid id used for fetching data later on
// Woeid id used for fetching data later on
location = doc[0]["woeid"].as<int>();
Serial.println(F("Found city, woied:"));
@ -257,10 +259,10 @@ void Network::findCity(char *city)
}
}
// clear document and end http
// Clear document and end http
doc.clear();
http.end();
// return module to initial state
// Return module to initial state
WiFi.setSleep(sleep);
};

View File

@ -6,7 +6,7 @@
#include <WiFiClientSecure.h>
// to get timeZone from main file
// To get timeZone from main file
extern int timeZone;
// wifi ssid and password
@ -16,22 +16,22 @@ extern char *pass;
#ifndef NETWORK_H
#define NETWORK_H
// all functions defined in Network.cpp
// All functions defined in Network.cpp
class Network
{
public:
// functions we can access in main file
// Functions we can access in main file
void begin(char *city);
void getTime(char *timeStr);
void getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr);
void getDays(char *day, char *day1, char *day2, char *day3);
// used to store loaction woeid (world id), set in findCity()
// Used to store loaction woeid (world id), set in findCity()
int location = -1;
private:
// functions called from within our class
// Functions called from within our class
void setTime();
void findCity(char *city);
};

View File

@ -1,3 +1,12 @@
# -----------
# Simple python script to
# create icon header files for Inkplate 6
# Arduino sketches
#
# Takes all files from /icons and saves them to /binary_icons
#
# -----------
from PIL import Image
import os, sys

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB