· 2 years ago · Jun 16, 2023, 11:40 AM
1/*
2Mini Local Weather Station
3Copyright (c) Mayer Mihály 2023
4*/
5#include "SSD1306Wire.h"
6#include <ESP8266WiFiMulti.h>
7#include <ESP8266HTTPClient.h>
8#include <WiFiClientSecureBearSSL.h>
9#include <ArduinoJson.h>
10#include "weather.h" // weather_sunny, weather_rain, weather_cloud
11
12SSD1306Wire display(0x3c, SCL, SDA);
13
14const char* googleHost = "https://www.googleapis.com/geolocation/v1/geolocate";
15const char* GOOGLE_APIKEY = "key=<Google API key>";
16const char* weatherPage = "http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&units=metric&APPID=<OpenWeatherMap API ID>";
17
18double latitude = 0.0;
19double longitude = 0.0;
20char buffer[8];
21char sbuffer[256];
22char* wbuffer;
23String line = "";
24String weatherMain = "";
25double temperature = 0.0;
26double humidity = 0.0;
27
28ESP8266WiFiMulti wifiMulti;
29IPAddress ip(192, 168, 0, 99);
30IPAddress gateway(192, 168, 0, 1);
31IPAddress subnet(255, 255, 255, 0);
32IPAddress dns(8, 8, 8, 8);
33char WiFiPassword[] = "<password>";
34char router_ssid_1[] = "<router1>";
35char router_ssid_2[] = "<router2>";
36char router_ssid_3[] = "<router3>";
37
38unsigned long previousMillis = 0UL;
39unsigned long interval = 60000UL;
40
41bool connectToWifi()
42{
43 wifiMulti.addAP(router_ssid_1, WiFiPassword);
44 wifiMulti.addAP(router_ssid_2, WiFiPassword);
45 wifiMulti.addAP(router_ssid_3, WiFiPassword);
46
47 int count = 0;
48 while (wifiMulti.run() != WL_CONNECTED && count++ < 20) {}
49 if (wifiMulti.run() == WL_CONNECTED) {
50 WiFi.config(ip, gateway, subnet, dns);
51 Serial.println("Connect to " + WiFi.SSID());
52 return true;
53 } else {
54 Serial.println("Unable to connect Wifi.");
55 return false;
56 }
57}
58
59void getWeather(String wBuffer)
60{
61 if (wifiMulti.run() == WL_CONNECTED) {
62 DynamicJsonDocument document(1024);
63 WiFiClient client;
64 HTTPClient http;
65 http.begin(client, wBuffer);
66 http.addHeader("Content-Type", "application/x-www-form-urlencoded");
67 int httpResponseCode = http.GET();
68 Serial.println(httpResponseCode);
69 if (httpResponseCode > 0) {
70 if (httpResponseCode == HTTP_CODE_OK || httpResponseCode == HTTP_CODE_MOVED_PERMANENTLY) {
71 String response = http.getString();
72 Serial.println(response);
73 deserializeJson(document, response);
74 JsonObject object = document.as<JsonObject>();
75 weatherMain = object["weather"][0]["main"].as<String>();
76 temperature = object["main"]["temp"].as<float>();
77 humidity = object["main"]["humidity"].as<float>();
78 }
79 }
80 http.end();
81 client.flush();
82 }
83}
84
85void getLocation()
86{
87 if (wifiMulti.run() == WL_CONNECTED) {
88 DynamicJsonDocument document(1024);
89 HTTPClient http;
90 std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
91 client->setInsecure();
92 http.begin(*client, googleHost);
93 http.addHeader("Content-Type", "application/x-www-form-urlencoded");
94 http.addHeader("Content-Length", String(sizeof(GOOGLE_APIKEY)));
95 http.setTimeout(10000);
96 int httpResponseCode = http.POST(GOOGLE_APIKEY);
97 Serial.println(httpResponseCode);
98 if (httpResponseCode > 0) {
99 if (httpResponseCode == HTTP_CODE_OK || httpResponseCode == HTTP_CODE_MOVED_PERMANENTLY) {
100 String response = http.getString();
101 Serial.println(response);
102 deserializeJson(document, response);
103 JsonObject object = document.as<JsonObject>();
104 latitude = object["location"]["lat"].as<float>();
105 longitude = object["location"]["lng"].as<float>();
106 Serial.println(String(latitude) + "," + String(longitude));
107 }
108 }
109 http.end();
110 }
111}
112
113void getWeather_and_display()
114{
115 sprintf(sbuffer,weatherPage,latitude,longitude);
116 getWeather(sbuffer);
117 sprintf(sbuffer,"%.1f °C",temperature);
118 display.drawString(70, 8, String(sbuffer));
119 sprintf(sbuffer,"%.1f %%",humidity);
120 display.drawString(70, 40, String(sbuffer));
121 weatherMain.toLowerCase();
122 if (weatherMain.indexOf("rain") >= 0) {
123 display.drawXbm(0, 0, 60, 60, weather_rain);
124 } else if (weatherMain.indexOf("clouds") >= 0) {
125 display.drawXbm(0, 0, 60, 60, weather_cloud);
126 } else {
127 display.drawXbm(0, 0, 60, 60, weather_sunny);
128 }
129 display.display();
130}
131
132void setup() {
133 Serial.begin(9600);
134
135 connectToWifi();
136 display.init();
137 display.clear();
138 display.setFont(ArialMT_Plain_16);
139 display.setTextAlignment(TEXT_ALIGN_LEFT);
140 display.drawVerticalLine(63,0,63);
141
142 getLocation();
143 getWeather_and_display();
144 previousMillis = millis();
145}
146
147void loop() {
148 if (wifiMulti.run() != WL_CONNECTED) connectToWifi();
149 unsigned long currentMillis = millis();
150 if(currentMillis - previousMillis > interval)
151 {
152 getWeather_and_display();
153 previousMillis = currentMillis;
154 }
155}
156