#include <ESP8266.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);
#define EspSerial Serial1
#define UARTSPEED 115200
#define SSID F("WIFI名称")
#define PASSWORD F("WIFI密码")
#define HOST_NAME F("api.openweathermap.org")
#define HOST_PORT (80)
#define SUN 0
#define SUN_CLOUD 1
#define CLOUD 2
#define RAIN 3
#define THUNDER 4
#define SNOW 5
#define MIST 6
#define MOON 7
unsigned long lastConnectionTime = 3600000; //openweather每天免费查询6次,那么四小时查一次吧。1秒 = 1000 ms(),4小时 = 4 * 60 * 60 * 1000 = 14400000。
const unsigned long postingInterval = 3600000; // 一小时查一下吧,1小时= 3600000。
static const byte GETDATA[] PROGMEM = {
"GET /data/2.5/forecast?id=城市ID&APPID=****密钥**** HTTP/1.0\r\nHost: api.openweathermap.org\r\nConnection: close\r\n\r\n"
};
ESP8266 wifi(&EspSerial);
//https://openweathermap.org/weather-conditions
uint8_t getSymbol(String weather_icon)
{
// clear sky
if (weather_icon == "01d")
return SUN;
if (weather_icon == "01n")
return MOON;
//few clouds
if (weather_icon == "02d" || weather_icon == "03d" || weather_icon == "04d")
return SUN_CLOUD;
//broken clouds
if (weather_icon == "02n" || weather_icon == "03n" || weather_icon == "04n")
return CLOUD;
//shower rain
if (weather_icon == "10d" || weather_icon == "10n")
return RAIN;
//rain
if (weather_icon == "09d" || weather_icon == "09n")
return RAIN;
//thunderstorm
if (weather_icon == "11d" || weather_icon == "11n")
return THUNDER; //雷
//snow
if (weather_icon == "13d" || weather_icon == "13n")
return SNOW;
//mist
if (weather_icon == "50d" || weather_icon == "50n")
return MIST; //雾
}
//https://github.com/olikraus/u8g2/wiki/fntgrpiconic
void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol)
{
switch (symbol)
{
case SUN:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 69);
break;
case SUN_CLOUD:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 65);
break;
case CLOUD:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 64);
break;
case RAIN:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 67);
break;
case THUNDER:
u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t);
u8g2.drawGlyph(x, y, 67);
break;
case SNOW:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 68);
break;
case MIST:
u8g2.setFont(u8g2_font_open_iconic_text_6x_t);
u8g2.drawGlyph(x, y, 64);
break;
case MOON:
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 66);
break;
}
}
void drawWeather(uint8_t symbol, int degree)
{
drawWeatherSymbol(0, 48, symbol);
u8g2.setFont(u8g2_font_logisoso32_tf);
u8g2.setCursor(48 + 3, 42);
u8g2.print(degree);
u8g2.print("°C"); // requires enableUTF8Print()
}
void drawScrollString(int16_t offset, const char *s)
{
static char buf[36]; // should for screen with up to 256 pixel width
size_t len;
size_t char_offset = 0;
u8g2_uint_t dx = 0;
size_t visible = 0;
len = strlen(s);
if (offset < 0)
{
char_offset = (-offset) / 8;
dx = offset + char_offset * 8;
if (char_offset >= u8g2.getDisplayWidth() / 8)
return;
visible = u8g2.getDisplayWidth() / 8 - char_offset + 1;
strncpy(buf, s, visible);
buf[visible] = '\0';
u8g2.setFont(u8g2_font_8x13_mf);
u8g2.drawStr(char_offset * 8 - dx, 62, buf);
}
else
{
char_offset = offset / 8;
if (char_offset >= len)
return; // nothing visible
dx = offset - char_offset * 8;
visible = len - char_offset;
if (visible > u8g2.getDisplayWidth() / 8 + 1)
visible = u8g2.getDisplayWidth() / 8 + 1;
strncpy(buf, s + char_offset, visible);
buf[visible] = '\0';
u8g2.setFont(u8g2_font_8x13_mf);
u8g2.drawStr(-dx, 62, buf);
}
}
void draw(const char *s, uint8_t symbol, int degree)
{
int16_t offset = -(int16_t)u8g2.getDisplayWidth();
int16_t len = strlen(s);
for (;;)
{
u8g2.firstPage();
do
{
drawWeather(symbol, degree);
drawScrollString(offset, s);
} while (u8g2.nextPage());
delay(20);
offset += 2;
if (offset > len * 8 + 1)
break;
}
}
void setup()
{
Serial.begin(115200);
while (!Serial)
;
Serial.print(F("setup begin\r\n"));
delay(100);
WifiInit(EspSerial, UARTSPEED);
Serial.print(F("FW Version:"));
Serial.println(wifi.getVersion().c_str());
if (wifi.setOprToStationSoftAP())
{
Serial.print(F("to station + softap ok\r\n"));
}
else
{
Serial.print(F("to station + softap err\r\n"));
}
if (wifi.joinAP(SSID, PASSWORD))
{
Serial.print(F("Join AP success\r\n"));
Serial.print(F("IP:"));
Serial.println(wifi.getLocalIP().c_str());
}
else
{
Serial.print(F("Join AP failure\r\n"));
}
if (wifi.disableMUX())
{
Serial.print(F("single ok\r\n"));
}
else
{
Serial.print(F("single err\r\n"));
}
Serial.print(F("setup end\r\n"));
u8g2.begin();
u8g2.enableUTF8Print();
}
void loop()
{
if (millis() - lastConnectionTime > postingInterval) {
lastConnectionTime = (signed long) millis();
if (wifi.createTCP(HOST_NAME, HOST_PORT))
{
Serial.print(F("create tcp ok\r\n"));
}
else
{
Serial.print(F("create tcp err\r\n"));
}
wifi.sendFromFlash(GETDATA, sizeof(GETDATA));
}
unsigned int i = 0; //timeout counter
int n = 0; // char counter
while (!EspSerial.find("["))
{
}
char json[374] = {};
while (i < 374)
{
if (EspSerial.available())
{
char c = EspSerial.read();
json[n] = c;
n++;
if (c == '[')
{
json[n - 1] = ' ';
}
if (c == ']')
{
json[n - 1] = '}';
break;
}
i = 0;
}
i++;
}
//{"dt":1567317600,"main":{"temp":296.45,"temp_min":294.9,"temp_max":296.45,"pressure":1014.49,"sea_level":1014.49,"grnd_level":1015.02,"humidity":89,"temp_kf":1.55},"weather": {"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}}
//Serial.print(json);
//Serial.println();
delay(500);
if (wifi.releaseTCP()) {
Serial.print(F("release tcp ok\r\n"));
} else {
Serial.print(F("release tcp err\r\n"));
}
//https://arduinojson.org/v6/assistant/
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8) + 150;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, json);
JsonObject main = doc["main"];
float main_temp = main["temp"]; // 296.45
float main_temp_min = main["temp_min"]; // 294.9
float main_temp_max = main["temp_max"]; // 296.45
float main_pressure = main["pressure"]; // 1014.49
float main_sea_level = main["sea_level"]; // 1014.49
float main_grnd_level = main["grnd_level"]; // 1015.02
int main_humidity = main["humidity"]; // 89
float main_temp_kf = main["temp_kf"]; // 1.55
JsonObject weather = doc["weather"];
int weather_id = weather["id"]; // 501
String weather_main = weather["main"]; // "Rain"
String weather_description = weather["description"]; // "moderate rain"
String weather_icon = weather["icon"]; // "10d"
int Temp = main_temp - 273.15;
uint8_t symbol = getSymbol(weather_icon);
draw("Best Wishes For You!", symbol, Temp); //礼多人不怪 :)
}