查看: 3467|回复: 0

Arduinojson 6解析openweather制作气象台历(下)

[复制链接]

签到天数: 124 天

[LV.7]常住居民III

发表于 2019-9-22 23:19 | 显示全部楼层 |阅读模式
本帖最后由 topdog 于 2020-2-21 00:23 编辑

网站介绍图标和气候状态的关系见 https://openweathermap.org/weather-conditions 就是用解析出来的icon来将u8g2lib里面自带的图标对应起来。
u8g2lib里面自带的图标介绍:https://github.com/olikraus/u8g2/wiki/fntgrpiconic 这样我们就不需要再费力地用软件转化了。
这里还要介绍一个使用Arduinojson6的小技巧,点击打开链接 https://arduinojson.org/v6/assistant/ 这是arduinojson官方提供的小助手,把已经截取的字符串黏贴到input区域,网站就会给出记忆体长度和解析出的结构,你再把parsing program黏贴到IDE程序里面。是不是很方便呀!
还要注意的就是延时,不能过于频繁登录openweather查询,最好间隔四小时。长时间延时用delay()不科学。Arduino应用millis函数可获取机器运行的时间长度,单位ms。系统最长的记录时间为9小时22分,如果超出时间将从0开始。函数返回值为unsigned long型,无参数。假设延时一小时,1秒 = 1000 ms(毫秒),1小时= 60*60*1000=3600000。
millis()五十天会溢出一次,这里使用signed long强制置零。
unsigned long lastConnectionTime = 3600000;      
const unsigned long postingInterval =  3600000;  
(millis() - lastConnectionTime > postingInterval)
lastConnectionTime = (signed long) millis();


arduinojson助手.JPG
最终效果图:
IMG_20190922_215450.jpg

程序如下:
#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); //礼多人不怪 :)   

}
(完)

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

热门推荐

点灯科技的blink库有没有设备到设备间分享数据功能啊
点灯科技的blink库有没有
请问下,点灯科技的blink库里有没有接受其他设备的函数程序啊? 我想设计4个8266设
OLED 128*64自制可达10000000个选项的菜单(已更新)
OLED 128*64自制可达10000
OLED 128*64自制可达10000000个选项的菜单 温馨提示: 建议占个楼再食用本帖子
DIY炫彩灯带,竟如此简单,更有硬件开发工具免费领!
DIY炫彩灯带,竟如此简单
什么是涂鸦Arduino SDK? Arduino 是全球最流行的开源硬件平台,涂鸦官方推出的 Ardui
ESP8266利用Blinker、小爱同学和本地按钮控制4路开关
ESP8266利用Blinker、小爱
案例介绍:小爱同学(安卓、苹果、小爱音响均可)控制4路开关 硬件需求:ESP8266 node
Seeeduion XIAO
Seeeduion XIAO
请问有那位大神用Seeeduion XIAO做过HID设备吗 求教程 网上有些说要用 TinyUSB来做 不
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表