設定某一地區,並透過json解析其AQI值顯示在OLED。範例檔:「8.OPENDATA_OLED.ino」。

程式碼

//https://t.ly/86qm
//幾個重要的地方
//1. 原本使用httpclient就改成WiFiClientSecure
//2. 不知道是不是內容較多,原本使用client.readstring會讀取不完整,因此改成一行一行讀取client.readStringUntil('\\n')

#include <WiFiClientSecure.h>
#include <ArduinoJson.h>//使用JSON函式庫
#include "Wire.h"  //i2c 21或22接腳
#include "U8g2lib.h" //請下載u8g2程式庫

//OLED 螢幕解析度為128*64
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

char SSID[] = "test"; //請修改為您連線的網路名稱
char PASSWORD[] = "12345678"; //請修改為您連線的網路密碼
char host[] = "data.epa.gov.tw";
//申請API key 環保署: <https://data.epa.gov.tw/api-term>
char url[] = "/api/v2/aqx_p_432?offset=0&limit=1000&format=json&api_key=自己申請的API KEY";  // Server URL

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  //連線到指定的WiFi SSID
  Serial.print("Connecting Wifi: ");
  Serial.println(SSID);
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  //連線成功,顯示取得的IP
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
  //client.setInsecure(); //若使用ESP32 1.0.6核心須加上這句避免SSL問題

  u8g2.begin();//初始化
  u8g2.enableUTF8Print();//啟用 UTF8字集
  u8g2.setFont(u8g2_font_unifont_t_chinese1);//設定使用中文字形
  u8g2.setDrawColor(1);//設定顏色,我們是單色只有1
  u8g2.setFontPosTop();//座標從上開始
  u8g2.setFontDirection(0);//0不旋轉、1->90、2->180、3->270
}

void loop() {
  Serial.println("啟動網頁連線");
  if (client.connect(host, 443)) {
    Serial.println("連線成功,開始讀取內容");
    // Make a HTTP request:
    client.print("GET "); client.print(url); client.println(" HTTP/1.0"); //1.1改成1.0
    client.print("Host: "); client.println(host);//
    client.println("Connection: close");
    client.println();
    //等候回應
    delay(2000);

    Serial.println("\\n讀取表頭");
    while (client.connected()) {
      String line = client.readStringUntil('\\n');
      Serial.println(line);
      if (line == "\\r") {
        Serial.println("\\n表頭結束");
        break;
      }
    }

    String payload = "";

    Serial.println("\\n讀取原始內容---------");
    while (client.connected()) {
      client.setTimeout(1000);
      //一次讀取一句,如果只使用readString會讀取不完
      String line = client.readStringUntil('\\n');
      //去除空白字元
      line.trim(); line.replace("\\r\\n", "");
      //Serial.print(line);
      payload += line ;
    }
    Serial.println("\\n原始內容結束----------");

    payload = "[" + payload + "]"; //將JSON物件轉換成JSON陣列
    Serial.println("\\nPayload=");
    Serial.println(payload);
    //JSON解析
    DynamicJsonDocument AQJarray(50000);
    deserializeJson(AQJarray, payload);//解析payload為JSON Array格式
    Serial.println("一共有 " + String(AQJarray[0]["fields"].size()) + " 欄位");
    Serial.println("一共有 " + String(AQJarray[0]["records"].size()) + " 站所");
    for (int i = 0; i <= AQJarray[0]["records"].size(); i++) {
      //尋找siteid=54的左營所
      if (AQJarray[0]["records"][i]["siteid"] == "54") {
        String Str_AQIValue = AQJarray[0]["records"][i]["aqi"];
        String Str_Sitename = AQJarray[0]["records"][i]["sitename"];
        String Str_Pubishtime = AQJarray[0]["records"][i]["publishtime"];
        Serial.println(Str_Sitename + "AQI: " + Str_AQIValue);
        //int Int_AQIValue = Str_AQIValue.toInt(); //轉整數給後續判斷用

        u8g2.clear();//顯示前清除螢幕
        u8g2.setCursor(0, 20);//移動游標
        u8g2.print(String(Str_Sitename).c_str());   //寫入文字
        u8g2.print(String("AQI:").c_str()); //c_str將String字串轉為OLED可以使用的character字元
        u8g2.print(String(Str_AQIValue).c_str());

        u8g2.setCursor(0, 40);//移動游標
        /*這一段是用來顯示更新的次數
          u8g2.print(String("目前數字:").c_str());//寫入文字
          u8g2.print(String(i).c_str());//寫入文字
        */

        //u8g2.print(String("更新時間:").c_str());   //寫入文字
        u8g2.print(String(Str_Pubishtime).c_str()); //c_str將String字串轉為OLED可以使用的character字元

        u8g2.drawLine(0, 11, 90, 11);//劃線從0,11->90,60
        u8g2.drawLine(0, 60, 90, 60);//劃線從0,60->90,60

        u8g2.sendBuffer();//送到螢幕顯示
      }
    }

    Serial.println("完成,關閉連線...");
    client.stop();//斷線,否則只能傳5次
  }
  else {
    Serial.println("連線失敗...請再重試一次");
  }
  delay(300000);
}

範例結果

342984982_557963319730527_585764161046736190_n.jpg

下一節