#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
#include "DHTesp.h"
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
const char* ssid = "Wokwi-GUEST"; // 更改為你的WiFi SSID
const char* password = ""; // 更改為你的WiFi密碼
int ledTaiNan[] = {16, 17, 18}; // 臺南的LED pins
int lastPm25 = -1; // 上次的PM2.5值
RTC_DS1307 rtc;
const int DHT_PIN = 15;
DHTesp dhtSensor;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 50
#define LOGO_WIDTH 50
static const unsigned char PROGMEM logo_bmp1[] =
{// 'face_1_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0x7f, 0xff,
0x81, 0xff, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xf8,
0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf0, 0xff, 0xff,
0xff, 0xff, 0xc3, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xf1, 0xc0, 0xc3, 0xfc, 0x3f, 0xff, 0x0f, 0xf0, 0xc0, 0xc7, 0xf0, 0x1f, 0xfe, 0x03, 0xf8, 0xc0,
0xc7, 0xe0, 0x0f, 0xfc, 0x01, 0xf8, 0xc0, 0x8f, 0xc3, 0x87, 0xf8, 0x70, 0xfc, 0x40, 0x8f, 0xc7,
0xc7, 0xf8, 0xf8, 0xfc, 0x40, 0x8f, 0x8f, 0xe3, 0xf1, 0xfc, 0x7c, 0x40, 0x1f, 0x8f, 0xe3, 0xf1,
0xfc, 0x7e, 0x00, 0x1f, 0xcf, 0xf7, 0xfb, 0xfc, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xef, 0xff, 0xff, 0xfd, 0xfe, 0x00, 0x1f, 0xc7, 0xff, 0xff, 0xf8,
0xfe, 0x00, 0x8f, 0xc3, 0xff, 0xff, 0xf0, 0xfc, 0x40, 0x8f, 0xe3, 0xff, 0xff, 0xf1, 0xfc, 0x40,
0x8f, 0xe1, 0xff, 0xff, 0xe1, 0xfc, 0x40, 0xc7, 0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xc0, 0xc7, 0xf8,
0x7f, 0xff, 0x87, 0xf8, 0xc0, 0xc3, 0xf8, 0x3f, 0xff, 0x07, 0xf0, 0xc0, 0xe3, 0xfc, 0x0f, 0xfc,
0x0f, 0xf1, 0xc0, 0xe1, 0xff, 0x01, 0xe0, 0x3f, 0xe1, 0xc0, 0xf0, 0xff, 0x80, 0x00, 0x7f, 0xc3,
0xc0, 0xf8, 0xff, 0xe0, 0x01, 0xff, 0xc7, 0xc0, 0xf8, 0x7f, 0xfe, 0x1f, 0xff, 0x87, 0xc0, 0xfc,
0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0xe0, 0x7f, 0xff, 0x81,
0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0};
static const unsigned char PROGMEM logo_bmp2[] =
{// 'face_2_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x1f, 0xfe, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0xff, 0xff,
0xc1, 0xff, 0xc0, 0xff, 0x83, 0xff, 0xff, 0xf0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x1f, 0xff, 0xff, 0xfe, 0x1f, 0xc0, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xf8,
0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf1, 0xff, 0xff,
0xff, 0xff, 0xe3, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xf1, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0,
0xcf, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0x8f, 0xfe, 0x1f, 0xff, 0x1f, 0xfc, 0x40, 0x8f, 0xfc,
0x1f, 0xfe, 0x0f, 0xfc, 0x40, 0x9f, 0xfc, 0x0f, 0xfe, 0x0f, 0xfe, 0x40, 0x1f, 0xfc, 0x1f, 0xfe,
0x0f, 0xfe, 0x00, 0x1f, 0xfe, 0x1f, 0xff, 0x1f, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x40, 0x8f, 0xf1, 0xff, 0xff, 0xe3, 0xfc, 0x40,
0x8f, 0xf0, 0xff, 0xff, 0xc3, 0xfc, 0x40, 0xcf, 0xf8, 0x7f, 0xff, 0x87, 0xfc, 0xc0, 0xc7, 0xfc,
0x1f, 0xfe, 0x0f, 0xf8, 0xc0, 0xc7, 0xfe, 0x07, 0xf8, 0x1f, 0xf8, 0xc0, 0xe3, 0xff, 0x80, 0x00,
0x7f, 0xf1, 0xc0, 0xe1, 0xff, 0xe0, 0x01, 0xff, 0xe1, 0xc0, 0xf1, 0xff, 0xfc, 0x0f, 0xff, 0xe3,
0xc0, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xfc,
0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xfe, 0x1f, 0xff, 0xff, 0xfe, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x83, 0xff, 0xff, 0xf0, 0x7f, 0xc0, 0xff, 0xe0, 0xff, 0xff, 0xc1,
0xff, 0xc0, 0xff, 0xf0, 0x1f, 0xfe, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0
};
static const unsigned char PROGMEM logo_bmp3[] =
{// 'face_3_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x07, 0xf8, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0x3f, 0xff,
0x01, 0xff, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xfc, 0x1f, 0xff, 0xff, 0xfe, 0x0f, 0xc0, 0xf8,
0x3f, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf0, 0xff, 0xff,
0xff, 0xff, 0xc3, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xf1, 0xc0, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0,
0xc7, 0xf8, 0x7f, 0xff, 0x87, 0xf8, 0xc0, 0x87, 0xf0, 0x7f, 0xff, 0x83, 0xf8, 0x40, 0x8f, 0xf0,
0x3f, 0xff, 0x03, 0xfc, 0x40, 0x8f, 0xf0, 0x3f, 0xff, 0x03, 0xfc, 0x40, 0x0f, 0xf0, 0x7f, 0xff,
0x83, 0xfc, 0x00, 0x1f, 0xf8, 0xff, 0xff, 0xc7, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x40, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x40,
0x87, 0xfe, 0x00, 0x00, 0x1f, 0xf8, 0x40, 0xc7, 0xfc, 0x00, 0x00, 0x0f, 0xf8, 0xc0, 0xc7, 0xfc,
0x00, 0x00, 0x0f, 0xf8, 0xc0, 0xc3, 0xfe, 0x00, 0x00, 0x1f, 0xf0, 0xc0, 0xe3, 0xff, 0xff, 0xff,
0xff, 0xf1, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc3,
0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xfc,
0x1f, 0xff, 0xff, 0xfe, 0x0f, 0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0xe0, 0x3f, 0xff, 0x01,
0xff, 0xc0, 0xff, 0xf0, 0x07, 0xf8, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0
};
static const unsigned char PROGMEM logo_bmp4[] =
{// 'face_4_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x07, 0xf8, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0x3f, 0xff,
0x01, 0xff, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xfc, 0x1f, 0xff, 0xff, 0xfe, 0x0f, 0xc0, 0xf8,
0x3f, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf0, 0xff, 0xff,
0xff, 0xff, 0xc3, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xf1, 0xc0, 0xc3, 0xfe, 0x7f, 0xff, 0x9f, 0xf0, 0xc0, 0xc7, 0xfc, 0x1f, 0xfe, 0x0f, 0xf8, 0xc0,
0xc7, 0xf8, 0x0f, 0xfc, 0x07, 0xf8, 0xc0, 0x87, 0xf8, 0x0f, 0xfc, 0x07, 0xf8, 0x40, 0x8f, 0xf8,
0x0f, 0xfc, 0x07, 0xfc, 0x40, 0x8f, 0xf8, 0x0f, 0xfc, 0x07, 0xfc, 0x40, 0x0f, 0xfc, 0x1f, 0xfe,
0x0e, 0xfc, 0x00, 0x1f, 0xfe, 0x7f, 0xff, 0x9c, 0x7e, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x7e,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xf0, 0x3e, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x1e, 0x00, 0x1f,
0xff, 0xff, 0xff, 0xe3, 0x1e, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe3, 0x0e, 0x00, 0x1f, 0xff, 0xf8,
0x07, 0xe3, 0x0e, 0x00, 0x1f, 0xff, 0xe0, 0x01, 0xe0, 0x1e, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x60,
0x1c, 0x00, 0x8f, 0xff, 0x03, 0xf0, 0x30, 0x3c, 0x40, 0x8f, 0xfe, 0x0f, 0xfc, 0x1f, 0xfc, 0x40,
0x87, 0xfc, 0x3f, 0xff, 0x0f, 0xf8, 0x40, 0xc7, 0xfc, 0x7f, 0xff, 0x8f, 0xf8, 0xc0, 0xc7, 0xf8,
0x7f, 0xff, 0x87, 0xf8, 0xc0, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf0, 0xc0, 0xe3, 0xf8, 0xff, 0xff,
0xc7, 0xf1, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc3,
0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xfc,
0x1f, 0xff, 0xff, 0xfe, 0x0f, 0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0xe0, 0x3f, 0xff, 0x01,
0xff, 0xc0, 0xff, 0xf0, 0x07, 0xf8, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0
};
static const unsigned char PROGMEM logo_bmp5[] =
{// 'face_5_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0x7f, 0xff,
0x81, 0xff, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xfc, 0x3f, 0x1f, 0xff, 0x3f, 0x0f, 0xc0, 0xf8,
0x7f, 0x1f, 0xff, 0x1f, 0x87, 0xc0, 0xf8, 0xfe, 0x1f, 0xff, 0x0f, 0xc7, 0xc0, 0xf0, 0xe0, 0x3f,
0xff, 0x81, 0xc3, 0xc0, 0xe1, 0xe0, 0x7f, 0xff, 0xc0, 0xe1, 0xc0, 0xe3, 0xe1, 0xff, 0xff, 0xe1,
0xf1, 0xc0, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0,
0xc7, 0xfd, 0xff, 0xff, 0xef, 0xf8, 0xc0, 0x8f, 0xf8, 0x7f, 0xff, 0x87, 0xfc, 0x40, 0x8f, 0xf8,
0x3f, 0xff, 0x07, 0xfc, 0x40, 0x8f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x40, 0x1f, 0xff, 0x03, 0xf0,
0x3f, 0xfe, 0x00, 0x1f, 0xff, 0xc3, 0xf0, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0x03, 0xf0, 0x3f, 0xfe,
0x00, 0x1f, 0xfe, 0x0f, 0xfc, 0x1f, 0xfe, 0x00, 0x1f, 0xf8, 0x1f, 0xfe, 0x07, 0xfe, 0x00, 0x1f,
0xf8, 0x7f, 0xff, 0x87, 0xfe, 0x00, 0x1f, 0xfd, 0xff, 0xff, 0xef, 0xfe, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xf0, 0x03, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xc0, 0x00, 0xff,
0xfe, 0x00, 0x8f, 0xff, 0x80, 0x00, 0x7f, 0xfc, 0x40, 0x8f, 0xff, 0x07, 0xf8, 0x3f, 0xfc, 0x40,
0x8f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x40, 0xc7, 0xfc, 0x3f, 0xff, 0x0f, 0xf8, 0xc0, 0xc7, 0xf8,
0x7f, 0xff, 0x87, 0xf8, 0xc0, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf0, 0xc0, 0xe3, 0xf8, 0xc0, 0x00,
0xc7, 0xf1, 0xc0, 0xe1, 0xf0, 0x00, 0x00, 0x07, 0xe1, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x03, 0xc3,
0xc0, 0xf8, 0xf8, 0x7f, 0xff, 0x87, 0xc7, 0xc0, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xfc,
0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0xe0, 0x7f, 0xff, 0x81,
0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0
};
static const unsigned char PROGMEM logo_bmp6[] =
{// 'face_6_0_Resize Image', 50x50px
0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xfc,
0x00, 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xe0, 0x7f, 0xff,
0x81, 0xff, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0x07, 0xff, 0xff, 0xf8, 0x3f,
0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xf8,
0x7f, 0xff, 0xff, 0xff, 0x87, 0xc0, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf0, 0xff, 0xff,
0xff, 0xff, 0xc3, 0xc0, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xc0, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xf1, 0xc0, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0,
0xc7, 0xf9, 0xe7, 0xf9, 0xe7, 0xf8, 0xc0, 0x8f, 0xf0, 0xc3, 0xf0, 0xc3, 0xfc, 0x40, 0x8f, 0xf8,
0x03, 0xf0, 0x07, 0xfc, 0x40, 0x8f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x40, 0x1f, 0xfe, 0x0f, 0xfc,
0x1f, 0xfe, 0x00, 0x1f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfe, 0x00, 0x1f, 0xf8, 0x07, 0xf8, 0x07, 0xfe,
0x00, 0x1f, 0xf0, 0xc3, 0xf0, 0xc3, 0xfe, 0x00, 0x1f, 0xf9, 0xe3, 0xf1, 0xe7, 0xfe, 0x00, 0x1f,
0xfd, 0xff, 0xff, 0xef, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x40, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x40,
0x8f, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x40, 0xc7, 0xff, 0xff, 0xc3, 0xc3, 0xf8, 0xc0, 0xc7, 0xff,
0xff, 0xc7, 0xc7, 0xf8, 0xc0, 0xc3, 0xff, 0xff, 0xc7, 0xc7, 0xf0, 0xc0, 0xe3, 0xff, 0xff, 0xc7,
0xc7, 0xf1, 0xc0, 0xe1, 0xff, 0xff, 0xc3, 0xc7, 0xe1, 0xc0, 0xf0, 0xff, 0xff, 0xe3, 0x87, 0xc3,
0xc0, 0xf8, 0xff, 0xff, 0xe0, 0x0f, 0xc7, 0xc0, 0xf8, 0x7f, 0xff, 0xf0, 0x0f, 0x87, 0xc0, 0xfc,
0x3f, 0xff, 0xfc, 0x3f, 0x0f, 0xc0, 0xfe, 0x0f, 0xff, 0xff, 0xfc, 0x1f, 0xc0, 0xff, 0x07, 0xff,
0xff, 0xf8, 0x3f, 0xc0, 0xff, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xc0, 0xff, 0xe0, 0x7f, 0xff, 0x81,
0xff, 0xc0, 0xff, 0xf0, 0x0f, 0xfc, 0x03, 0xff, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0xc0,
0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xc0
};
void setup() {
Serial.begin(9600);
// 設定LED腳位為輸出模式
for (int i = 0; i < 3; i++) {
pinMode(ledTaiNan[i], OUTPUT);
}
// 連接WiFi
connectWiFi();
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay(2000); // Pause for 2 seconds
display.clearDisplay(); //清除畫面
}
void loop() {
fetchDataAndUpdateLED();
DateTime now = rtc.now();
display.clearDisplay(); //清除畫面
display.setTextSize(1); //設置文字大小
display.setTextColor(1); //設置顏色
display.setCursor(0,0); //設置起始座標
display.print(now.year(), DEC);
display.print('/');
display.print(now.month(), DEC);
display.print('/');
display.print(now.day(), DEC);
display.print(" (");
display.print(daysOfTheWeek[now.dayOfTheWeek()]);
display.print(") ");
display.print(now.hour(), DEC);
display.print(':');
display.print(now.minute(), DEC);
display.print(':');
display.print(now.second(), DEC);
display.setCursor(0,48);
TempAndHumidity data = dhtSensor.getTempAndHumidity();
display.println("T:" + String(data.temperature, 2) + "°C");
display.println("H:" + String(data.humidity, 1) + "%");
display.println("---");
if (lastPm25 >= 0 && lastPm25 <= 50) {
display.drawBitmap(70,17,logo_bmp1,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉1
display.display();
} else if (lastPm25 <= 100) {
display.drawBitmap(70,17,logo_bmp2,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉2
display.display();
} else if (lastPm25 <= 150) {
display.drawBitmap(70,17,logo_bmp3,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉3
display.display();
} else if (lastPm25 <= 200) {
display.drawBitmap(70,17,logo_bmp4,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉4
display.display();
} else if (lastPm25 <= 300) {
display.drawBitmap(70,17,logo_bmp5,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉5
display.display();
} else {
display.drawBitmap(70,17,logo_bmp6,LOGO_WIDTH,LOGO_HEIGHT,1); // 臉6
display.display();
}
}
// 連接WiFi
void connectWiFi() {
WiFi.mode(WIFI_STA);
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println("\nConnected to WiFi");
}
// 抓取臺南站資料並更新LED
void fetchDataAndUpdateLED() {
HTTPClient http;
http.begin("https://data.moenv.gov.tw/api/v2/aqx_p_02?api_key=e8dd42e6-9b8b-43f8-991e-b3dee723a52d&limit=1000&sort=datacreationdate%20desc&format=JSON");
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
DynamicJsonDocument doc(16384);
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
for (JsonObject record : doc["records"].as<JsonArray>()) {
const char* site = record["site"];
const char* pm25Str = record["pm25"];
// 只處理臺南站的資料
if (site && pm25Str && strcmp(site, "臺南") == 0) {
int pm25 = atoi(pm25Str);
// 更新LED顏色,但不熄滅
updateLED(pm25);
// 如果PM2.5值有變化,則顯示結果
if (pm25 != lastPm25) {
Serial.print("Site: ");
Serial.print(site);
Serial.print(", PM2.5: ");
Serial.println(pm25);
}
lastPm25 = pm25;
}
}
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
// 根據PM2.5值控制LED顏色
void updateLED(int pm25) {
// 根據PM2.5值設定LED顏色
if (pm25 >= 0 && pm25 <= 50) {
setColor(ledTaiNan, 0, 255, 0); // 綠色
} else if (pm25 <= 100) {
setColor(ledTaiNan, 255, 255, 0); // 黃色
} else if (pm25 <= 150) {
setColor(ledTaiNan, 255, 165, 0); // 橙色
} else if (pm25 <= 200) {
setColor(ledTaiNan, 255, 0, 0); // 紅色
} else if (pm25 <= 300) {
setColor(ledTaiNan, 128, 0, 128); // 紫色
} else {
setColor(ledTaiNan, 139, 0, 0); // 暗紅色
}
}
// 設定LED顏色
void setColor(int* ledPins, int red, int green, int blue) {
for (int i = 0; i < 3; i++) {
analogWrite(ledPins[i], (i == 0) ? red : ((i == 1) ? green : blue));
}
}