Skip to content

Commit

Permalink
Merge pull request #21 from matthias-bs/20241012-feat-https
Browse files Browse the repository at this point in the history
Added OWM access with HTTPS
  • Loading branch information
matthias-bs authored Oct 12, 2024
2 parents bc3bf38 + acaa680 commit e375124
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 2 deletions.
154 changes: 154 additions & 0 deletions examples/Waveshare_7_5_T7_Sensors/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#ifndef COMMON_H_
#define COMMON_H_

#include <Arduino.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>

#include "forecast_record.h"
#include "common_functions.h"
#include "config.h"

#if defined(USE_HTTPS)
static const char owm_certificate[] PROGMEM = OWM_CERTIFICATE;
#endif

//#########################################################################################
void Convert_Readings_to_Imperial() {
WxConditions[0].Pressure = hPa_to_inHg(WxConditions[0].Pressure);
WxForecast[1].Rainfall = mm_to_inches(WxForecast[1].Rainfall);
WxForecast[1].Snowfall = mm_to_inches(WxForecast[1].Snowfall);
}

//#########################################################################################
// Problems with stucturing JSON decodes, see here: https://arduinojson.org/assistant/
bool DecodeWeather(WiFiClient& json, String Type) {
log_d("Creating JSON object");
// allocate the JsonDocument
JsonDocument doc;

// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, json);
// Test if parsing succeeds.
if (error) {
log_d("deserializeJson() failed: %s", error.c_str());
return false;
}
// convert it to a JsonObject
JsonObject root = doc.as<JsonObject>();
log_d("Decoding %s data", Type.c_str());
if (Type == "weather") {
WxConditions[0].lon = root["coord"]["lon"].as<float>(); log_d(" Lon: %f", WxConditions[0].lon);
WxConditions[0].lat = root["coord"]["lat"].as<float>(); log_d(" Lat: %f", WxConditions[0].lat);
WxConditions[0].Main0 = root["weather"][0]["main"].as<const char*>(); log_d("Main: %s", WxConditions[0].Main0);
WxConditions[0].Forecast0 = root["weather"][0]["description"].as<const char*>(); log_d("For0: %s", WxConditions[0].Forecast0);
WxConditions[0].Forecast1 = root["weather"][1]["description"].as<const char*>(); log_d("For1: %s", WxConditions[0].Forecast1);
WxConditions[0].Forecast2 = root["weather"][2]["description"].as<const char*>(); log_d("For2: %s", WxConditions[0].Forecast2);
WxConditions[0].Icon = root["weather"][0]["icon"].as<const char*>(); log_d("Icon: %s", WxConditions[0].Icon);
WxConditions[0].Temperature = root["main"]["temp"].as<float>(); log_d("Temp: %f", WxConditions[0].Temperature);
WxConditions[0].Pressure = root["main"]["pressure"].as<float>(); log_d("Pres: %f", WxConditions[0].Pressure);
WxConditions[0].Humidity = root["main"]["humidity"].as<float>(); log_d("Humi: %f", WxConditions[0].Humidity);
WxConditions[0].Low = root["main"]["temp_min"].as<float>(); log_d("TLow: %f", WxConditions[0].Low);
WxConditions[0].High = root["main"]["temp_max"].as<float>(); log_d("THig: %f", WxConditions[0].High);
WxConditions[0].Windspeed = root["wind"]["speed"].as<float>(); log_d("WSpd: %f", WxConditions[0].Windspeed);
WxConditions[0].Winddir = root["wind"]["deg"].as<float>(); log_d("WDir: %f", WxConditions[0].Winddir);
WxConditions[0].Cloudcover = root["clouds"]["all"].as<int>(); log_d("CCov: %d", WxConditions[0].Cloudcover); // in % of cloud cover
WxConditions[0].Visibility = root["visibility"].as<int>(); log_d("Visi: %d", WxConditions[0].Visibility); // in metres
WxConditions[0].Rainfall = root["rain"]["1h"].as<float>(); log_d("Rain: %f", WxConditions[0].Rainfall);
WxConditions[0].Snowfall = root["snow"]["1h"].as<float>(); log_d("Snow: %f", WxConditions[0].Snowfall);
WxConditions[0].Country = root["sys"]["country"].as<const char*>(); log_d("Ctry: %s", WxConditions[0].Country);
WxConditions[0].Sunrise = root["sys"]["sunrise"].as<int>(); log_d("SRis: %d", WxConditions[0].Sunrise);
WxConditions[0].Sunset = root["sys"]["sunset"].as<int>(); log_d("SSet: %d", WxConditions[0].Sunset);
WxConditions[0].Timezone = root["timezone"].as<int>(); log_d("TZon: %d", WxConditions[0].Timezone);
}
if (Type == "forecast") {
//log_d(json);
log_d("Receiving forecast - "); //------------------------------------------------
JsonArray list = root["list"];
for (byte r = 0; r < max_readings; r++) {
log_d("Period-%d--------------", r);
WxForecast[r].Dt = list[r]["dt"].as<int>(); log_d("DTim: %d", WxForecast[r].Dt);
WxForecast[r].Temperature = list[r]["main"]["temp"].as<float>(); log_d("Temp: %f", WxForecast[r].Temperature);
WxForecast[r].Low = list[r]["main"]["temp_min"].as<float>(); log_d("TLow: %f", WxForecast[r].Low);
WxForecast[r].High = list[r]["main"]["temp_max"].as<float>(); log_d("THig: %f", WxForecast[r].High);
WxForecast[r].Pressure = list[r]["main"]["pressure"].as<float>(); log_d("Pres: %f", WxForecast[r].Pressure);
WxForecast[r].Humidity = list[r]["main"]["humidity"].as<float>(); log_d("Humi: %f", WxForecast[r].Humidity);
WxForecast[r].Forecast0 = list[r]["weather"][0]["main"].as<const char*>(); log_d("For0: %s", WxForecast[r].Forecast0);
WxForecast[r].Forecast1 = list[r]["weather"][1]["main"].as<const char*>(); log_d("For1: %s", WxForecast[r].Forecast1);
WxForecast[r].Forecast2 = list[r]["weather"][2]["main"].as<const char*>(); log_d("For2: %s", WxForecast[r].Forecast2);
WxForecast[r].Icon = list[r]["weather"][0]["icon"].as<const char*>(); log_d("Icon: %s", WxForecast[r].Icon);
WxForecast[r].Description = list[r]["weather"][0]["description"].as<const char*>(); log_d("Desc: %s", WxForecast[r].Description);
WxForecast[r].Cloudcover = list[r]["clouds"]["all"].as<int>(); log_d("CCov: %d", WxForecast[r].Cloudcover); // in % of cloud cover
WxForecast[r].Windspeed = list[r]["wind"]["speed"].as<float>(); log_d("WSpd: %f", WxForecast[r].Windspeed);
WxForecast[r].Winddir = list[r]["wind"]["deg"].as<float>(); log_d("WDir: %f", WxForecast[r].Winddir);
WxForecast[r].Rainfall = list[r]["rain"]["3h"].as<float>(); log_d("Rain: %f", WxForecast[r].Rainfall);
WxForecast[r].Snowfall = list[r]["snow"]["3h"].as<float>(); log_d("Snow: %f", WxForecast[r].Snowfall);
WxForecast[r].Pop = list[r]["pop"].as<float>(); log_d("Pop: %f", WxForecast[r].Pop);
WxForecast[r].Period = list[r]["dt_txt"].as<const char*>(); log_d("Peri: %s", WxForecast[r].Period);
}
//------------------------------------------
float pressure_trend = WxForecast[2].Pressure - WxForecast[0].Pressure; // Measure pressure slope between ~now and later
pressure_trend = ((int)(pressure_trend * 10)) / 10.0; // Remove any small variations less than 0.1
WxConditions[0].Trend = "0";
if (pressure_trend > 0) WxConditions[0].Trend = "+";
if (pressure_trend < 0) WxConditions[0].Trend = "-";
if (pressure_trend == 0) WxConditions[0].Trend = "0";

if (Units == "I") Convert_Readings_to_Imperial();
}
return true;
}
//#########################################################################################
String ConvertUnixTime(int unix_time) {
// Returns either '21:12 ' or ' 09:12pm' depending on Units mode
time_t tm = unix_time;
struct tm *now_tm = gmtime(&tm);
char output[40];
if (Units == "M") {
strftime(output, sizeof(output), "%H:%M %d/%m/%y", now_tm);
}
else {
strftime(output, sizeof(output), "%I:%M%P %m/%d/%y", now_tm);
}
return output;
}
//#########################################################################################
bool obtain_wx_data(const String& RequestType) {
#if defined(USE_HTTPS)
NetworkClientSecure client;
client.setCACert(owm_certificate);
#else
WiFiClient client;
#endif

const String units = (Units == "M" ? "metric" : "imperial");
client.stop(); // close connection before sending a new request
HTTPClient http;
String uri = "/data/2.5/" + RequestType + "?q=" + City + "," + Country + "&APPID=" + apikey + "&mode=json&units=" + units + "&lang=" + Language;
if(RequestType != "weather")
{
uri += "&cnt=" + String(max_readings);
}
#if defined(USE_HTTPS)
http.begin(client, String("https://") + server + uri);
#else
http.begin(client, server, 80, uri);
#endif
int httpCode = http.GET();
if(httpCode == HTTP_CODE_OK) {
if (!DecodeWeather(http.getStream(), RequestType)) return false;
client.stop();
http.end();
return true;
}
else
{
log_i("HTTP connection failed, error: %s\n", http.errorToString(httpCode).c_str());
client.stop();
http.end();
return false;
}
http.end();
return true;
}
#endif /* ifndef COMMON_H_ */
2 changes: 2 additions & 0 deletions examples/Waveshare_7_5_T7_Sensors/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
// Arduino 1.8.19 ESP32 WiFiClientSecure.h: "SHA1 fingerprint is broken now!"
//#define CHECK_FINGERPRINT

//#define USE_HTTPS

// Domain Name Server - separate bytes by comma!
#define MY_DNS 192,168,0,1

Expand Down
36 changes: 36 additions & 0 deletions examples/Waveshare_7_5_T7_Sensors/owm_credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,41 @@ String Language = "EN"; // NOTE: Only the wea
String Hemisphere = "north"; // or "south"
String Units = "M"; // Use 'M' for Metric or I for Imperial

#define OWM_CERTIFICATE "\
-----BEGIN CERTIFICATE-----\n\
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB\
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw\
MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV\
BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy\
dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\
AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B\
3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY\
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/\
Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2\
VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT\
79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6\
c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT\
Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l\
c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee\
UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE\
Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd\
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G\
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF\
Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO\
VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3\
ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs\
8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR\
iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze\
Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ\
XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/\
qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB\
VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB\
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG\
jjxDah2nGN59PRbxYvnKkKj9\n\
-----END CERTIFICATE-----\
"

#endif
17 changes: 15 additions & 2 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

#include "forecast_record.h"
#include "common_functions.h"
#include "config.h"

#if defined(USE_HTTPS)
static const char owm_certificate[] PROGMEM = OWM_CERTIFICATE;
#endif

//#########################################################################################
void Convert_Readings_to_Imperial() {
Expand Down Expand Up @@ -109,8 +114,13 @@ String ConvertUnixTime(int unix_time) {
}
//#########################################################################################
bool obtain_wx_data(const String& RequestType) {
#if defined(USE_HTTPS)
NetworkClientSecure client;
client.setCACert(owm_certificate);
#else
WiFiClient client;

#endif

const String units = (Units == "M" ? "metric" : "imperial");
client.stop(); // close connection before sending a new request
HTTPClient http;
Expand All @@ -119,8 +129,11 @@ bool obtain_wx_data(const String& RequestType) {
{
uri += "&cnt=" + String(max_readings);
}
//http.begin(uri,test_root_ca); //HTTPS example connection
#if defined(USE_HTTPS)
http.begin(client, String("https://") + server + uri);
#else
http.begin(client, server, 80, uri);
#endif
int httpCode = http.GET();
if(httpCode == HTTP_CODE_OK) {
if (!DecodeWeather(http.getStream(), RequestType)) return false;
Expand Down

0 comments on commit e375124

Please sign in to comment.