查看: 3546|回复: 0

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

[复制链接]

签到天数: 168 天

[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); //礼多人不怪 :)   

}
(完)

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

本版积分规则

热门推荐

智能“百味”勺子开发实战营,为你的生活添滋味!
智能“百味”勺子开发实战
想不想拥有一把神奇的“百味”勺子,把索然无味的食物变出酸甜苦辣咸的丰富滋味
20sffactory 三自由度3D打印机械手臂 - 高速移动
20sffactory 三自由度3D打
这款机械臂作者没有给他起名字,用作者的名字来命名. 目前为止,生态最好,做的最完
多位数码管显示项目——以TM1650为例
多位数码管显示项目——以
以下是用搭载TM1650的4位数码管,显示电位器所代表0到1023的模拟信号数值 示意图:
新手小白付费拜师求教:TM1650四位时钟数码管的具体用法
新手小白付费拜师求教:TM
从淘宝购买的TM16504位数码管的时钟模块,卖家给了程序,但是完全不会用。求一位老师
【Arduino】168种传感器模块系列实验(76)---TTL转RS-485模块
【Arduino】168种传感器模
37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表