From 0b48b6044e26f55bdf6955164c77db6f713da7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomislav=20Kopi=C4=87?= Date: Wed, 7 Feb 2024 20:06:07 +0100 Subject: [PATCH] Migrate --- Bitmaps/Clear.png | Bin 0 -> 393 bytes Bitmaps/Drizzle.png | Bin 0 -> 382 bytes Bitmaps/Fog.png | Bin 0 -> 481 bytes Bitmaps/Hail.png | Bin 0 -> 482 bytes Bitmaps/Rain.png | Bin 0 -> 436 bytes Bitmaps/Snow.png | Bin 0 -> 406 bytes Bitmaps/Thunderstorms.png | Bin 0 -> 370 bytes D1_mini_weather_station.ino | 207 ++++++++++++++++++++++++++++++++++++ bitmaps.h | 71 +++++++++++++ 9 files changed, 278 insertions(+) create mode 100644 Bitmaps/Clear.png create mode 100644 Bitmaps/Drizzle.png create mode 100644 Bitmaps/Fog.png create mode 100644 Bitmaps/Hail.png create mode 100644 Bitmaps/Rain.png create mode 100644 Bitmaps/Snow.png create mode 100644 Bitmaps/Thunderstorms.png create mode 100644 D1_mini_weather_station.ino create mode 100644 bitmaps.h diff --git a/Bitmaps/Clear.png b/Bitmaps/Clear.png new file mode 100644 index 0000000000000000000000000000000000000000..4c25681e6ad079008403674193ef35b7e076d618 GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?- z-5|_3H?j$&NV3E=q9iy!t)x7$D3zhSyj(9cFS|H7u^?41zbJk7I~yqm21Yhd7sn8b z-rmcGeuo`IST1bun8tQ7x>3z!XY*{6B^*M$>K@%wx|cj$b$Y|5zg${ujtX7AYnQBgO3dtN(f)js zXFm??(9GyOKGWFVNF~%O i7miE*>eXkiwYT+DUvjx+?ge15F?hQAxvX9ICjhC(snxQy2+$6(7N#MX`|zDpIU*J#;4Fy3TQz(g;(BRbA z5Y6rV9}P{>AJB9NK_U#HDHQ}88p`3o(TqNDFbIs>;k{2uoLWxL_VV2C^E}seMP}+} z4MIc&&R_z&nc3+z91#;3K?k2QGXoFt0ORH1vB%)Op-nJFSp;gTlfHeP4u!5;?>;)bSH z2b-DsHSiesi@jY=ju+C=jI;QGt#UPrCsEJb&CGXoQ{cKL(=P-~#y45a5pe+{|0UxT z?&0zg2Q4gNwdSt*ow4g+15djSe%2G)nq&*beXiX$9)31X= X8sL6ZYAMnJ00000NkvXXu0mjftp3Mz literal 0 HcmV?d00001 diff --git a/Bitmaps/Hail.png b/Bitmaps/Hail.png new file mode 100644 index 0000000000000000000000000000000000000000..dc48ca5c0fe6e8a59a235c32e60eee52261d5a30 GIT binary patch literal 482 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?- zNDyXRHFsqjkRe&(8c`CQpH@mmtT}V`<;yx0|R5cr;B5V zMQ`mTdylX{3APXSzyH)+qS(~cF)5+hxviz;!2-1#VJe;8Yt2}48=Wm~2(5S^z~LvP ztJ&1e;+L0X)-n0Ql5g&UQc4phENUxW7nAq>myZ7PJ?|^eeYUd+{pT)OThVj>$0Xz8 z#-KI4JGuq0B(Y0Zbbho5?q2?*Z)wYdrpTD1W^oTpz8+Lux6oeb>{0()A516SZklWn za#G{YajA6)Jkc}U(xVRQ*Bq;^@&0MhZ_M*By{&@3e1oP}^$f`!ec@e!hqPXuYKm0e zSSbJfgZjIBF%BQXKjdxdkza8nnbzwU7h1mK|THwqI;wc=gB#;^Ko(XwaV-{ zovn5B literal 0 HcmV?d00001 diff --git a/Bitmaps/Rain.png b/Bitmaps/Rain.png new file mode 100644 index 0000000000000000000000000000000000000000..0429782f475214a6dc0d418696801e1a33553f45 GIT binary patch literal 436 zcmV;l0ZaagP)xJk(<#5{s0}sz}#ubm{J< z8%Uze2BV!)%*vup*+eN4%iX1n#4T9FaLXCKzo)*Q=aC=p?fd?|KmXs9VhksEz%P6) zqj?dN_=7>zU;w`{lP0(lH^>+9Ex5-W&M{FgxB}mkmdl|Vjp)NQhU3qA9N-Y+DLVaz zjhI-*3Nk5z;UgZghT06S(2vWM37`Q>_zxFoenW7ahT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjTBH(a)3{W z>;M1%flQi$`fVTX0WDA{3GxeOU}Te!QBv11G%~jHj!sUi>*(&8Fmd|49s3WTJazl? z7sH01Yk_JjJzX3_B*Jt1J^308c$nF}Zk`e=soGnxG_kNleZRGNNP{&jW3K36NKbLh*2~7Yc C_;DKm literal 0 HcmV?d00001 diff --git a/Bitmaps/Thunderstorms.png b/Bitmaps/Thunderstorms.png new file mode 100644 index 0000000000000000000000000000000000000000..188741ea35a2692c17e7a1aed2fad1474949c408 GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?- zG7x6;t5)LxG9*h}BT9nv(@M${i&7cN%ggmL^RkPR6AM!H@{7`Ezq647Dthnf;uvDl zJNMFFJ(oZc)(81&!5Sw579Mt4sK_P4Wz}zB)Ot*~ql5jzIc*@%)utCF?f@$PGr_nKv|g5M;m6|6d8)86j0zW4Tl>OV<#Vi%6Y9c-$V zIo2j>lWb%(|CsQxWJd2F$CBH4rxYkwo^uK@oR%alJ;}cC-q|^>lIv%FVdQ I&MBb@0B=x=kpKVy literal 0 HcmV?d00001 diff --git a/D1_mini_weather_station.ino b/D1_mini_weather_station.ino new file mode 100644 index 0000000..6368dce --- /dev/null +++ b/D1_mini_weather_station.ino @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "bitmaps.h" +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 +#define OLED_RESET -1 +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); +WiFiClient client; + +// set Wi-Fi SSID and password +const char *ssid = "wifinetwork"; +const char *password = "12345678"; + +// Define NTP Client to get time +WiFiUDP ntpUDP; +NTPClient timeClient(ntpUDP, "pool.ntp.org"); + +// set location and API key +const String Location = "Osijek"; +const String API_Key = "someapikey"; +int icon = 0; + +void capitalizeFirstLetter(char* str) { + if (str != nullptr && *str != '\0') { + // Create a copy of the string + char temp[48]; + strcpy(temp, str); + + // Capitalize the first letter + temp[0] = toupper(temp[0]); + + // Copy the modified string back to the original pointer + strcpy(str, temp); + } +} + +void setup(void) +{ + display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) + delay(1000); + display.clearDisplay(); // clear the display buffer + display.display(); + display.setTextColor(WHITE, BLACK); + display.setTextSize(1); + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + WiFi.begin(ssid, password); + display.setCursor(0, 0); + display.print("Connecting"); + display.display(); + int cnt = 0; + while ( WiFi.status() != WL_CONNECTED ) + { + if (cnt == 3) { + cnt = 0; + display.clearDisplay(); + display.setCursor(0, 0); + display.print("Connecting"); + display.display(); + } else { + display.print("."); + display.display(); + cnt++; + } + delay(1000); + } + WiFi.setAutoReconnect(true); + WiFi.persistent(true); + display.print("\nconnected"); + display.display(); + timeClient.begin(); + delay(500); + timeClient.setTimeOffset(3600); +} + +void loop() +{ + if (WiFi.status() == WL_CONNECTED) { + + timeClient.update(); + // PowerSave + int currentHour = timeClient.getHours(); + if (currentHour >= 23 || currentHour < 6) { + display.clearDisplay(); + display.display(); + display.ssd1306_command(SSD1306_DISPLAYOFF); + delay(300000); + return; + } + else { + display.ssd1306_command(SSD1306_DISPLAYON); + } + //Get a time structure + time_t epochTime = timeClient.getEpochTime(); + struct tm *ptm = gmtime ((time_t *)&epochTime); + int currentDay = ptm->tm_mday; + int currentMonth = ptm->tm_mon + 1; + int currentYear = ptm->tm_year + 1900; + HTTPClient http; //Declare an object of class HTTPClient + + // specify request destination + http.begin(client, "http://api.openweathermap.org/data/2.5/weather?q=" + Location + "&APPID=" + API_Key); // !! + int httpCode = http.GET(); // send the request + if (httpCode > 0) { + String payload = http.getString(); //Get the request response payload + + DynamicJsonBuffer jsonBuffer(1024); + + // Parse JSON object + JsonObject& root = jsonBuffer.parseObject(payload); + if (!root.success()) { + return; + } + http.end(); //Close connection + const char* state = root["weather"][0]["description"]; // get status as string + capitalizeFirstLetter(const_cast(state)); // Capitalize the first letter + float temp = (float)(root["main"]["temp"]) - 273.15; // get temperature in °C + int humidity = root["main"]["humidity"]; // get humidity in % + float pressure = (float)(root["main"]["pressure"]) / 1000; // get pressure in bar + float wind_speed = root["wind"]["speed"]; // get wind speed in m/s + int statusSize = 2; + if (strlen(state) > 12) { + statusSize = 1; + } + // print data + display.clearDisplay(); // clear the display buffer + display.setTextSize(1); + display.setCursor(0, 0); + display.printf("%d-%d-%d\r\n", currentYear, currentMonth, currentDay); + display.setCursor(0, 9); + display.printf("%s",Location); + display.setTextSize(statusSize); + display.setCursor(0, 21); + display.printf("%s\r\n", state); + display.setCursor(0, 39); + display.setTextSize(1); + display.printf(" %5.2f C %d%%\r\n", temp, humidity); + display.drawRect(43, 39, 3, 3, WHITE); // put degree symbol ( ° ) + display.setCursor(0, 52); + display.printf(" %.3fbar %.1fm/s \r\n", pressure, wind_speed); + display.drawLine(0, 18, 127, 18, 1); + display.drawLine(65, 18, 65, 0, 1); + display.drawBitmap(0, 38, temperature_icon, 10, 10, WHITE); + display.drawBitmap(74, 38, humidity_icon, 10, 10, WHITE); + display.drawBitmap(0, 51, pressure_icon, 10, 10, WHITE); + display.drawBitmap(74, 51, wind_icon, 10, 10, WHITE); + display.display(); + } + + // specify request destination + http.begin(client, "http://api.openweathermap.org/data/2.5/forecast?q=" + Location + "&APPID=" + API_Key + "&cnt=3"); // !! + httpCode = http.GET(); // send the request + if (httpCode > 0) { + String payload = http.getString(); //Get the request response payload + DynamicJsonBuffer jsonBuffer(1024); + + // Parse JSON object + JsonObject& forecast = jsonBuffer.parseObject(payload); + if (!forecast.success()) { + return; + } + http.end(); //Close connection + + // State id info + // 200-232 Thunderstorm + // 300-321 Drizzle + // 500-531 Rain + // 600-622 Snow + // 701-781 Mist + // 800 Clear + // 801-804 Clouds + int pos = 69; + for (int day = 0; day <= 2; day++) { + int state = forecast["list"][day]["weather"][0]["id"]; // get state id + // Display bitmap based on state_id + if (state >= 200 && state <= 232) { + icon = 6; // Thunderstorm + } else if (state >= 300 && state <= 321) { + icon = 5; // Drizzle + } else if (state >= 500 && state <= 531) { + icon = 3; // Rain + } else if (state >= 600 && state <= 622) { + icon = 4; // Snow + } else if (state >= 701 && state <= 781) { + icon = 2; // Mist + } else if (state == 800) { + icon = 0; // Clear + } else if (state >= 801 && state <= 804) { + icon = 1; // Clouds + } else { + // Handle unknown state_id + icon = 0; // Default to Clear icon + } + display.drawBitmap(pos, 0, bitmap_icons[icon], 16, 16, WHITE); + pos = pos + 20; + display.display(); + } + } + } + delay(1800000); +} diff --git a/bitmaps.h b/bitmaps.h new file mode 100644 index 0000000..835215b --- /dev/null +++ b/bitmaps.h @@ -0,0 +1,71 @@ +// 'clear', 16x16px +const unsigned char bitmap_clear [] PROGMEM = { + 0x01, 0x80, 0x01, 0x80, 0x31, 0x8c, 0x38, 0x1c, 0x1f, 0xf8, 0x0f, 0xf0, 0x0c, 0x30, 0xec, 0x37, + 0xec, 0x37, 0x0c, 0x30, 0x0f, 0xf0, 0x1f, 0xf8, 0x38, 0x1c, 0x31, 0x8c, 0x01, 0x80, 0x01, 0x80 +}; + +// 'cloudy', 16x16px +const unsigned char bitmap_cloudy [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xf8, 0x0f, 0x9e, 0x1f, 0xcf, 0x78, 0xf3, + 0xf0, 0x7b, 0xc0, 0x1f, 0xc0, 0x1f, 0xff, 0xf8, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +// 'fog', 16x16px +const unsigned char bitmap_fog [] PROGMEM = { + 0x00, 0x00, 0x78, 0x1e, 0xff, 0xff, 0xef, 0xf7, 0x00, 0x00, 0xfe, 0x7f, 0xff, 0xff, 0x03, 0xc0, + 0x7c, 0x3e, 0xff, 0xff, 0xcf, 0xf3, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0x00, 0x00 +}; + +// 'rain', 16x16px +const unsigned char bitmap_rain [] PROGMEM = { + 0x0f, 0x80, 0x1f, 0xc0, 0x38, 0xf8, 0x70, 0x7c, 0xf0, 0x0c, 0xe0, 0x0f, 0xc0, 0x07, 0xc0, 0x03, + 0xc0, 0x03, 0xff, 0xff, 0x7f, 0xfe, 0x66, 0x33, 0xe6, 0x73, 0xff, 0xff, 0xff, 0xfe, 0x73, 0x38 +}; + +// 'snow', 16x16px +const unsigned char bitmap_snow [] PROGMEM = { + 0x01, 0x80, 0x07, 0xe0, 0x1f, 0xf8, 0x7b, 0xde, 0x79, 0x9e, 0x7d, 0xbe, 0x7f, 0xfe, 0x67, 0xe6, + 0x67, 0xe6, 0x7f, 0xfe, 0x7d, 0xbe, 0x79, 0x9e, 0x7b, 0xde, 0x1f, 0xf8, 0x07, 0xe0, 0x01, 0x80 +}; + +// 'thunderstorm', 16x16px +const unsigned char bitmap_thunderstorm [] PROGMEM = { + 0x07, 0xf0, 0x06, 0x60, 0x0e, 0x60, 0x0c, 0xc0, 0x0c, 0xf8, 0x18, 0xfc, 0x18, 0x18, 0x38, 0x38, + 0x3f, 0xf0, 0x1f, 0xe0, 0x03, 0xe0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x07, 0x00, 0x07, 0x00 +}; + +// 'drizzle', 16x16px +const unsigned char bitmap_drizzle [] PROGMEM = { + 0x00, 0x00, 0x06, 0x00, 0x36, 0xc0, 0x3f, 0x80, 0x1f, 0xf0, 0x7b, 0xb8, 0x1e, 0x18, 0x18, 0x0e, + 0x18, 0x06, 0x19, 0x32, 0x0f, 0xfe, 0x07, 0xfc, 0x01, 0xf0, 0x03, 0xf0, 0x00, 0xc0, 0x00, 0x00 +}; + +// Array of all bitmaps for convenience +const unsigned char* bitmap_icons[7] = { + bitmap_clear, + bitmap_cloudy, + bitmap_fog, + bitmap_rain, + bitmap_snow, + bitmap_drizzle, + bitmap_thunderstorm, +}; + +const unsigned char temperature_icon [] PROGMEM = { + 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3f, 0x00, + 0x3f, 0x00, 0x1e, 0x00 +}; + +const unsigned char humidity_icon [] PROGMEM = { + 0x0c, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3f, 0x00, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, + 0x3f, 0x00, 0x3f, 0x00 +}; + +const unsigned char wind_icon [] PROGMEM = { + 0x00, 0x00, 0x07, 0x00, 0x07, 0x80, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x07, 0x80, + 0x07, 0x00, 0x00, 0x00 +}; + +const unsigned char pressure_icon [] PROGMEM = { + 0x1e, 0x00, 0x3f, 0x00, 0x73, 0x80, 0xe7, 0xc0, 0xce, 0xc0, 0xdc, 0xc0, 0xe9, 0xc0, 0x73, 0x80, + 0x3f, 0x00, 0x1e, 0x00 +};