不管是深圳还是香港,一到夏天就没命的下雨,说来就来的雨又说停就停。让人觉得整个岭南地区是不是就只分旱季和雨季。
于是就想有个分钟级的天气预报,普通的app还得用看手机,因为工作的原因,有时候会很久都碰不到手机。于是祭出了吃灰一段时间的ESP8266,自己写一个分钟级的天气检测。

硬件:
ESP8266,带0.91英寸屏幕(128x32,heltec版本)
软件:
Arduino IDE,ArduinoJson

考虑到ESP8266性能太弱,爬网页拿天气数据不太现实,所以就直接用API。最开始用的是高德地图提供的,但是有几个缺点:

  • 30分钟更新一次
  • 最小提供区域是区级
  • 根本不准

于是就去找专业公司,彩云和和风都可以并且免费提供一定的额度。其中,彩云的审核是人工的,当时急着做就直接用和风的api了,正在更新博客的时候收到邮件通知彩云通过审核了。和风的有以下特点:

  • api限制是每日1000次
  • 支持经纬度
  • 实时天气
  • 数据信息更全

放图,看一下最终的效果。第一行是天气信息,第二行分别是温度和降水量。

photo_2020-06-08_18-59-35.jpg

源码

附上源代码,万一有其他人要用。折腾json就花了半天的功夫,c++在便捷性上确实有点拉跨。

/**
    Weather OLED
    Created on: June 7, 2020
    copyright@PA.CI

*/

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include <ESP8266WiFiMulti.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include "heltec.h" // alias for `#include "SSD1306Wire.h"`

const uint8_t fingerprint[20] = {0x02, 0x5f, 0x4b, 0xea, 0x55, 0xb5, 0x64, 0xda, 0xd8, 0xc9, 0xc9, 0x78, 0x0e, 0x3C, 0x7d, 0xd5, 0xe3, 0x8f, 0xe9, 0x4f};
ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);
  for (uint8_t t = 4; t > 0; t--) {
//    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("ssid", "passwd");
}

void loop() {
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
    client->setFingerprint(fingerprint);
    HTTPClient https;
//    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "key and parameters")) {  // api for the weather and key, parameters
//      Serial.print("[HTTPS] GET...\n");
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        //        HTTP header has been send and Server response header has been handled
//        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          //          Serial.println(payload);
          //go to https://arduinojson.org/v6/assistant/ for modify
          const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(13) + 350;
          DynamicJsonDocument doc(capacity);
          deserializeJson(doc, payload);
          String precipitation = doc["HeWeather6"][0]["now"]["pcpn"].as<char*>();
          String weather = doc["HeWeather6"][0]["now"]["cond_txt"].as<char*>();
          String temperate = doc["HeWeather6"][0]["now"]["tmp"].as<char*>();
//          Serial.print(precipitation);
//          Serial.print(weather);

            // OLED screen
          Heltec.begin(true /*DisplayEnable Enable*/, true /*Serial Enable*/);
          Heltec.display->init();
          Heltec.display->flipScreenVertically();
          Heltec.display->setFont(ArialMT_Plain_10);
          Heltec.display->drawString(15, 2, weather);
          Heltec.display->drawString(15, 17, temperate + "C" + "  " + precipitation + "mm");
          Heltec.display->display();
          //          Serial.println();
        }
      } else {
//        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
//      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }
  //  Serial.println("Wait 10min before next round...");
  delay(600000);
}

标签: 喝水

添加新评论