今日得閒繼續玩,上天文台搵埋濕度/溫度放入個 Display。本來還想搵埋酷熱/寒冷/火災/暴雨/風球之類的警告 ...
C_Law 發表於 2021-6-5 17:30

師兄請教一下,小弟正想試下整個香港地區溫度,用你上面個天文台api。
請問有冇參考連結例程可以用到香港地區data,改小小就用得。我用D1mini的

謝謝

via HKEPC IR Pro 3.6.1 - iOS(3.0.0)

TOP

本帖最後由 C_Law 於 2021-6-13 02:35 編輯
師兄請教一下,小弟正想試下整個香港地區溫度,用你上面個天文台api。
請問有冇參考連結例程可以用到香港 ...
royc 發表於 2021/6/10 11:10


以下係我玩緊個鐘的部份 Code,可以用 rhrread 搵到:
閃電
分區氣溫
天文台濕度

以及用 warnsum 搵到
風球
紅黑黃雨
雷暴警告
寒冷/酷熱警告
紅/黃火災警告

上載到 ESP8266 前要先修改 PortNo, WiFi 的 SSID/PASSWORD。
Oooops~~~~這裡貼 Code 自動幫我刪除了一部份斜楝!照抄以下出來用係會錯,等我諗諗再 Post 過。
(好似改返正)
  1. #ifndef UNIT_TEST
  2. #include <Arduino.h>
  3. #endif
  4. #include <ESP8266WiFi.h>
  5. #include <ESP8266WiFiMulti.h>
  6. #include <ESP8266WebServer.h>
  7. #include <ESP8266mDNS.h>
  8. #include <WiFiClient.h>
  9. #include <ESP8266HTTPClient.h>

  10. // some parameters used for WiFi
  11. const unsigned int PortNo = 80;
  12. const char* SSID1 = "yourSSID1";               // SSID and Password for WiFi connection
  13. const char* PW1 = "yourPASSWORD1";
  14. const char* SSID2 = "yourSSID2";
  15. const char* PW2 = "yourPASSWORD2";
  16. const char* SSID3 = "yourSSID3";
  17. const char* PW3 = "yourPASSWORD3";

  18. const uint16_t LED = 2;       // OnChipLED(Pull_Up)=D4 for D1 mini
  19. const bool LEDon = false;     // false for Pull_Up, otherwise true

  20. // some variables for weather
  21. String weatherJSON;
  22. String TempC;
  23. String MaxMinTempC;
  24. String HumPercent;
  25. String WTCSGNL;  // Tropical Cyclone Warning Signal: None, TC1, TC3, TC8xx, TC9, TC10
  26. bool Lightning;
  27. bool WTS = false; //Thunderstorm warning
  28. int wFire;  // Fire warning: 0,1,2=Normal, Yellow, Red
  29. int wCH;    // Cold/Hot warning: 0,1,2,=Normal,Cold,Hot
  30. int wRAIN;  // Rain warning: 0,1,2,3=None,Amber,Red,Black

  31. ESP8266WiFiMulti wifiMulti;
  32. ESP8266WebServer server(PortNo);

  33. void setup() {
  34.   pinMode(LED, OUTPUT);
  35.   digitalWrite(LED, LEDon);
  36.   
  37.   Serial.begin(115200);
  38.   Serial.println("");
  39.   
  40.   WiFi.mode(WIFI_STA);
  41.   wifiMulti.addAP(SSID1, PW1);
  42.   wifiMulti.addAP(SSID2, PW2);
  43.   wifiMulti.addAP(SSID3, PW3);
  44.   
  45.   // waiting for WiFi connection
  46.   while (wifiMulti.run() != WL_CONNECTED) {
  47.     delay(500);
  48.   }
  49.   
  50.   Serial.println("");
  51.   Serial.print("Connected to: ");
  52.   Serial.println(WiFi.SSID());
  53.   Serial.print("IP address: ");
  54.   Serial.println(WiFi.localIP().toString());
  55.   Serial.print("Port no.: ");
  56.   Serial.println(PortNo);
  57.   digitalWrite(LED, !LEDon);
  58.   
  59.   server.on("/", handleRoot);
  60.   server.on("/rhrread", handleRhrread);
  61.   server.on("/warnsum", handleWarnSum);
  62.   server.on("/rhrread2", handleRhrread2);
  63.   server.on("/warnsum2", handleWarnSum2);
  64.   server.onNotFound(handleNotFound);
  65.   server.begin();
  66. }

  67. void loop() {
  68.   server.handleClient();
  69. }

  70. void handleRoot() {
  71.   String message = "";
  72.   message = "<HTML>\n" \
  73.             "  <HEAD>\n" \
  74.             "    <TITLE>Get weather information by ESP8266</TITLE>\n" \
  75.             "  </HEAD>\n" \
  76.             "  <body>\n" \
  77.             "    Get weather information by ESP8266<p>\n";
  78.   message += "  </body>\n" \
  79.              "</HTLM>";
  80.   server.send(200, "text/html", message);
  81. }

  82. void handleRhrread() {
  83.   String message = "";
  84.   if (GetJson("rhrread")){
  85.     int StartPos = 0;
  86.     int EndPos = weatherJSON.length() - 1;
  87.     int ResultStart = 0;
  88.     int ResultEnd = EndPos;
  89.     String sTemp;
  90.     String Location;
  91.     message = weatherJSON;
  92.         
  93.     // Get Lightning warning for "Hong Kong and Kowloon"
  94.     Location = "Hong Kong and Kowloon";
  95.     StartPos = 0;
  96.     EndPos = weatherJSON.length() - 1;
  97.     ResultStart = StartPos;
  98.     ResultEnd = EndPos;
  99.     Lightning = false;
  100.     if (GetJsonRange("\"lightning\":{", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  101.       StartPos = ResultStart;
  102.       EndPos = ResultEnd;
  103.       if (GetJsonRange("\"" + Location + "\",\"occur\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  104.         Lightning = (weatherJSON.substring(ResultStart, ResultEnd) == "true");
  105.       }
  106.     }
  107.     message += "\n\rLightning=";
  108.     if (Lightning) message += "true";
  109.     else message += "false";
  110.    
  111.     // Get "Kowloon City" temperture
  112.     Location = "Kowloon City";
  113.     StartPos = 0;
  114.     EndPos = weatherJSON.length() - 1;
  115.     TempC = "";
  116.     if (GetJsonRange("\"temperature\":{\"data\":[", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  117.       StartPos = ResultStart;
  118.       EndPos = ResultEnd;
  119.       if (GetJsonRange("\"" + Location + "\",\"value\":", ",", StartPos, EndPos, &ResultStart, &ResultEnd)){
  120.         TempC = weatherJSON.substring(ResultStart, ResultEnd) + "C";
  121.       }
  122.     }
  123.     message += "\n\rTempC=" + TempC;
  124.    
  125.     // Get Humidity
  126.     StartPos = 0;
  127.     EndPos = weatherJSON.length() - 1;
  128.     ResultStart = StartPos;
  129.     ResultEnd = EndPos;
  130.     if (GetJsonRange("\"humidity\":{", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  131.       StartPos = ResultStart;
  132.       EndPos = ResultEnd;
  133.       if (GetJsonRange("\"value\":", ",", StartPos, EndPos, &ResultStart, &ResultEnd)){
  134.         HumPercent = weatherJSON.substring(ResultStart, ResultEnd) + "%";
  135.       }
  136.     }
  137.     message += "\n\rHumidity=" +HumPercent;
  138.   }
  139.   
  140.   server.send(200, "text/plain", message);
  141. }

  142. void handleRhrread2() {
  143.   String message = "";
  144.   if (true){
  145.     weatherJSON = "{\"lightning\":{\"data\":[{\"place\":\"Lantau\",\"occur\":\"true\"},{\"place\":\"Hong Kong and Kowloon\",\"occur\":\"true\"}],\"startTime\":\"2021-06-11T18:45:00+08:00\",\"endTime\":\"2021-06-11T19:45:00+08:00\"},\"rainfall\":{\"data\":[{\"unit\":\"mm\",\"place\":\"Central &amp; Western District\",\"max\":9,\"min\":1,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Eastern District\",\"max\":8,\"min\":1,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Kwai Tsing\",\"max\":2,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Islands District\",\"max\":12,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"North District\",\"max\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Sai Kung\",\"max\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Sha Tin\",\"max\":1,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Southern District\",\"max\":15,\"min\":7,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Tai Po\",\"max\":1,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Tsuen Wan\",\"max\":2,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Tuen Mun\",\"max\":3,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Wan Chai\",\"max\":10,\"min\":5,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Yuen Long\",\"max\":2,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Yau Tsim Mong\",\"max\":4,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Sham Shui Po\",\"max\":2,\"min\":1,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Kowloon City\",\"max\":1,\"min\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Wong Tai Sin\",\"max\":0,\"main\":\"FALSE\"},{\"unit\":\"mm\",\"place\":\"Kwun Tong\",\"max\":1,\"min\":0,\"main\":\"FALSE\"}],\"startTime\":\"2021-06-11T18:45:00+08:00\",\"endTime\":\"2021-06-11T19:45:00+08:00\"},\"icon\":[64],\"iconUpdateTime\":\"2021-06-11T20:25:00+08:00\",\"uvindex\":\"\",\"updateTime\":\"2021-06-11T20:26:00+08:00\",\"temperature\":{\"data\":[{\"place\":\"King's Park\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Hong Kong Observatory\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Wong Chuk Hang\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Ta Kwu Ling\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Lau Fau Shan\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Tai Po\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Sha Tin\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Tuen Mun\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Tseung Kwan O\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Sai Kung\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Cheung Chau\",\"value\":26,\"unit\":\"C\"},{\"place\":\"Chek Lap Kok\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Tsing Yi\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Shek Kong\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Tsuen Wan Ho Koon\",\"value\":26,\"unit\":\"C\"},{\"place\":\"Tsuen Wan Shing Mun Valley\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Hong Kong Park\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Shau Kei Wan\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Kowloon City\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Happy Valley\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Wong Tai Sin\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Stanley\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Kwun Tong\",\"value\":27,\"unit\":\"C\"},{\"place\":\"Sham Shui Po\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Kai Tak Runway Park\",\"value\":28,\"unit\":\"C\"},{\"place\":\"Yuen Long Park\",\"value\":29,\"unit\":\"C\"},{\"place\":\"Tai Mei Tuk\",\"value\":29,\"unit\":\"C\"}],\"recordTime\":\"2021-06-11T20:00:00+08:00\"},\"warningMessage\":[\"The Tropical Cyclone Signal No. 1 has been issued.\",\"The Amber Rainstorm Warning Signal was issued at 8:25 p.m.\",\"The Thunderstorm Warning has been issued. It will remain effective until 11:00 p.m. today. Occasional thunderstorms are expected to occur over Hong Kong.\"],\"mintempFrom00To09\":\"\",\"rainfallFrom00To12\":\"\",\"rainfallLastMonth\":\"\",\"rainfallJanuaryToLastMonth\":\"\",\"tcmessage\":[\"Here is the information on Tropical Depression:\nLocation: 18.3 degrees north, 112.3 degrees east; Maximum sustained wind near its centre: 45 km\/h.\"],\"humidity\":{\"recordTime\":\"2021-06-11T20:00:00+08:00\",\"data\":[{\"unit\":\"percent\",\"value\":88,\"place\":\"Hong Kong Observatory\"}]}}";
  146.     int StartPos = 0;
  147.     int EndPos = weatherJSON.length() - 1;
  148.     int ResultStart = 0;
  149.     int ResultEnd = EndPos;
  150.     String sTemp;
  151.     String Location;
  152.     message = weatherJSON;
  153.         
  154.     // Get Lightning warning for "Hong Kong and Kowloon"
  155.     Location = "Hong Kong and Kowloon";
  156.     StartPos = 0;
  157.     EndPos = weatherJSON.length() - 1;
  158.     ResultStart = StartPos;
  159.     ResultEnd = EndPos;
  160.     Lightning = false;
  161.     if (GetJsonRange("\"lightning\":{", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  162.       StartPos = ResultStart;
  163.       EndPos = ResultEnd;
  164.       if (GetJsonRange("\"" + Location + "\",\"occur\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  165.         Lightning = (weatherJSON.substring(ResultStart, ResultEnd) == "true");
  166.       }
  167.     }
  168.     message += "\n\rLightning=";
  169.     if (Lightning) message += "true";
  170.     else message += "false";
  171.    
  172.     // Get "Kowloon City" temperture
  173.     Location = "Kowloon City";
  174.     StartPos = 0;
  175.     EndPos = weatherJSON.length() - 1;
  176.     TempC = "";
  177.     if (GetJsonRange("\"temperature\":{\"data\":[", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  178.       StartPos = ResultStart;
  179.       EndPos = ResultEnd;
  180.       if (GetJsonRange("\"" + Location + "\",\"value\":", ",", StartPos, EndPos, &ResultStart, &ResultEnd)){
  181.         TempC = weatherJSON.substring(ResultStart, ResultEnd) + "C";
  182.       }
  183.     }
  184.     message += "\n\rTempC=" + TempC;
  185.    
  186.     // Get Humidity
  187.     StartPos = 0;
  188.     EndPos = weatherJSON.length() - 1;
  189.     ResultStart = StartPos;
  190.     ResultEnd = EndPos;
  191.     if (GetJsonRange("\"humidity\":{", "]", StartPos, EndPos, &ResultStart, &ResultEnd)){
  192.       StartPos = ResultStart;
  193.       EndPos = ResultEnd;
  194.       if (GetJsonRange("\"value\":", ",", StartPos, EndPos, &ResultStart, &ResultEnd)){
  195.         HumPercent = weatherJSON.substring(ResultStart, ResultEnd) + "%";
  196.       }
  197.     }
  198.     message += "\n\rHumidity=" +HumPercent;
  199.   }
  200.   
  201.   server.send(200, "text/plain", message);
  202. }

  203. void handleWarnSum() {
  204.   String message ="";
  205.   if (GetJson("warnsum")) {
  206.     int StartPos = 0;
  207.     int EndPos = weatherJSON.length() - 1;
  208.     int ResultStart = 0;
  209.     int ResultEnd = EndPos;
  210.     String sTemp;
  211.    
  212.     // Check WRAIN
  213.     wRAIN = 0;
  214.     if (GetJsonRange("\"WRAIN\":{", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  215.       StartPos = ResultStart;
  216.       EndPos = ResultEnd;
  217.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  218.         sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  219.         if ((sTemp != "CANCEL") && (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd))){
  220.           sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  221.           if (sTemp == "WRAINA") wRAIN = 1;
  222.           else if (sTemp == "WRAINR") wRAIN = 2;
  223.           else if (sTemp == "WRAINB") wRAIN = 3;
  224.         }
  225.       }
  226.     }
  227.     message = "\n\r\n\rwRAIN=";
  228.     message += wRAIN;
  229.    
  230.     // Check Thunderstorm warning WTS
  231.     StartPos = 0;
  232.     EndPos = weatherJSON.length() - 1;
  233.     WTS = false;
  234.     if (GetJsonRange("\"WTS\":{", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  235.       StartPos = ResultStart;
  236.       EndPos = ResultEnd;
  237.       
  238.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  239.         sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  240.         if (sTemp != "CANCEL") WTS = true;
  241.       }
  242.     }
  243.     message += "\n\rWTS=";
  244.     if (WTS) message += "true";
  245.     else message += "false";
  246.    
  247.     // Check Tropical Cyclone Warning Signal WTCSGNL
  248.     StartPos = 0;
  249.     EndPos = weatherJSON.length() - 1;
  250.     WTCSGNL = "None";
  251.     if (GetJsonRange("\"WTCSGNL\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  252.       StartPos = ResultStart;
  253.       EndPos = ResultEnd;
  254.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  255.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") {
  256.           if (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  257.             WTCSGNL = weatherJSON.substring(ResultStart, ResultEnd);
  258.           }
  259.         }
  260.       }
  261.     }
  262.     message += "\n\rWTCSGNL=" + WTCSGNL;
  263.    
  264.     // Check WHOT
  265.     wCH = 0;
  266.     StartPos = 0;
  267.     EndPos = weatherJSON.length() - 1;
  268.     if (GetJsonRange("\"WHOT\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  269.       StartPos = ResultStart;
  270.       EndPos = ResultEnd;
  271.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  272.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") wCH = 2;
  273.       }
  274.     }
  275.    
  276.     // Check WCOLD
  277.     StartPos = 0;
  278.     EndPos = weatherJSON.length() - 1;
  279.     // wCH already reset before WHOT check, no need to reset in here
  280.     if (GetJsonRange("\"COLD\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  281.       StartPos = ResultStart;
  282.       EndPos = ResultEnd;
  283.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  284.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") wCH = 1;
  285.       }
  286.     }
  287.     message += "\n\rwCH=";
  288.     message += wCH;
  289.    
  290.     // Get WFIRE
  291.     StartPos = 0;
  292.     EndPos = weatherJSON.length() - 1;
  293.     wFire = 0;
  294.     if (GetJsonRange("\"WFIRE\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  295.       StartPos = ResultStart;
  296.       EndPos = ResultEnd;
  297.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  298.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") {
  299.           if (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  300.             sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  301.             if (sTemp == "WFIREY") wFire = 1;      // yellow
  302.             else if (sTemp == "WFIRER") wFire = 2; // red
  303.           }
  304.         }
  305.       }
  306.     }
  307.     message += "\n\rwFire=";
  308.     message += wFire;
  309.   }
  310.   
  311.   message = weatherJSON + message;
  312.   server.send(200, "text/plain", message);
  313. }

  314. void handleWarnSum2() {
  315.   String message ="";
  316.   if (true) {
  317.     weatherJSON = "{\"WRAIN\":{\"name\":\"Rainstorm Warning Signal\",\"code\":\"WRAINA\",\"type\":\"Amber\",\"actionCode\":\"ISSUE\",\"issueTime\":\"2021-06-11T20:25:00+08:00\",\"updateTime\":\"2021-06-11T20:25:00+08:00\"},\"WTS\":{\"name\":\"Thunderstorm Warning\",\"code\":\"WTS\",\"actionCode\":\"UPDATE\",\"issueTime\":\"2021-06-11T18:35:00+08:00\",\"expireTime\":\"2021-06-11T23:00:00+08:00\",\"updateTime\":\"2021-06-11T21:10:00+08:00\"},\"WTCSGNL\":{\"name\":\"Tropical Cyclone Warning Signal\",\"code\":\"TC1\",\"actionCode\":\"ISSUE\",\"type\":\"Standby Signal No. 1\",\"issueTime\":\"2021-06-11T16:15:00+08:00\",\"updateTime\":\"2021-06-11T16:15:00+08:00\"}}";
  318.     int StartPos = 0;
  319.     int EndPos = weatherJSON.length() - 1;
  320.     int ResultStart = 0;
  321.     int ResultEnd = EndPos;
  322.     String sTemp;
  323.    
  324.     // Check WRAIN
  325.     wRAIN = 0;
  326.     if (GetJsonRange("\"WRAIN\":{", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  327.       StartPos = ResultStart;
  328.       EndPos = ResultEnd;
  329.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  330.         sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  331.         if ((sTemp != "CANCEL") && (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd))){
  332.           sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  333.           if (sTemp == "WRAINA") wRAIN = 1;
  334.           else if (sTemp == "WRAINR") wRAIN = 2;
  335.           else if (sTemp == "WRAINB") wRAIN = 3;
  336.         }
  337.       }
  338.     }
  339.     message = "\n\r\n\rwRAIN=";
  340.     message += wRAIN;
  341.    
  342.     // Check Thunderstorm warning WTS
  343.     StartPos = 0;
  344.     EndPos = weatherJSON.length() - 1;
  345.     WTS = false;
  346.     if (GetJsonRange("\"WTS\":{", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  347.       StartPos = ResultStart;
  348.       EndPos = ResultEnd;
  349.       
  350.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  351.         sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  352.         if (sTemp != "CANCEL") WTS = true;
  353.       }
  354.     }
  355.     message += "\n\rWTS=";
  356.     if (WTS) message += "true";
  357.     else message += "false";
  358.    
  359.     // Check Tropical Cyclone Warning Signal WTCSGNL
  360.     StartPos = 0;
  361.     EndPos = weatherJSON.length() - 1;
  362.     WTCSGNL = "None";
  363.     if (GetJsonRange("\"WTCSGNL\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  364.       StartPos = ResultStart;
  365.       EndPos = ResultEnd;
  366.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  367.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") {
  368.           if (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  369.             WTCSGNL = weatherJSON.substring(ResultStart, ResultEnd);
  370.           }
  371.         }
  372.       }
  373.     }
  374.     message += "\n\rWTCSGNL=" + WTCSGNL;
  375.    
  376.     // Check WHOT
  377.     wCH = 0;
  378.     StartPos = 0;
  379.     EndPos = weatherJSON.length() - 1;
  380.     if (GetJsonRange("\"WHOT\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  381.       StartPos = ResultStart;
  382.       EndPos = ResultEnd;
  383.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  384.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") wCH = 2;
  385.       }
  386.     }
  387.    
  388.     // Check WCOLD
  389.     StartPos = 0;
  390.     EndPos = weatherJSON.length() - 1;
  391.     // wCH already reset before WHOT check, no need to reset in here
  392.     if (GetJsonRange("\"COLD\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  393.       StartPos = ResultStart;
  394.       EndPos = ResultEnd;
  395.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  396.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") wCH = 1;
  397.       }
  398.     }
  399.     message += "\n\rwCH=";
  400.     message += wCH;
  401.    
  402.     // Get WFIRE
  403.     StartPos = 0;
  404.     EndPos = weatherJSON.length() - 1;
  405.     wFire = 0;
  406.     if (GetJsonRange("\"WFIRE\":{\"", "}", StartPos, EndPos, &ResultStart, &ResultEnd)){
  407.       StartPos = ResultStart;
  408.       EndPos = ResultEnd;
  409.       if (GetJsonRange("\"actionCode\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  410.         if (weatherJSON.substring(ResultStart, ResultEnd) != "CANCEL") {
  411.           if (GetJsonRange("\"code\":\"", "\"", StartPos, EndPos, &ResultStart, &ResultEnd)){
  412.             sTemp = weatherJSON.substring(ResultStart, ResultEnd);
  413.             if (sTemp == "WFIREY") wFire = 1;      // yellow
  414.             else if (sTemp == "WFIRER") wFire = 2; // red
  415.           }
  416.         }
  417.       }
  418.     }
  419.     message += "\n\rwFire=";
  420.     message += wFire;
  421.   }
  422.   
  423.   message = weatherJSON + message;
  424.   server.send(200, "text/plain", message);
  425. }

  426. void handleNotFound() {
  427.   String message = "File Not Found\n\n";
  428.   message += "URI: ";
  429.   message += server.uri();
  430.   message += "\nMethod: ";
  431.   message += (server.method() == HTTP_GET)?"GET":"POST";
  432.   message += "\nArguments: ";
  433.   message += server.args();
  434.   message += "\n";
  435.   for (uint8_t i = 0; i < server.args(); i++)
  436.     message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  437.   server.send(404, "text/plain", message);
  438. }

  439. bool GetJson(String dataType){
  440.   /*
  441.     dataType can be: rhrread, warnsum, fnd...etc
  442.   */
  443.   bool Result = false;
  444.   HTTPClient http;
  445.   WiFiClientSecure client;
  446.   client.setInsecure(); // use with caution
  447.   weatherJSON = "";     // clear previous JSON
  448.   
  449.   http.begin(client, "https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=" + dataType + "&lang=en");
  450.   if (http.GET() == HTTP_CODE_OK) {
  451.     weatherJSON = http.getString();
  452.     Result = true;
  453.   }
  454.   return Result;
  455. }

  456. bool GetJsonRange(String StartString, String EndString, int StartPos, int EndPos, int *SectionStart, int *SectionEnd) {
  457.   bool Good = true;
  458.   int ResultStart = StartPos;
  459.   int ResultEnd = EndPos;
  460.   String message = "";
  461.   // initial check
  462.   if ((StartString == "") || (EndString =="")) Good = false;
  463.   if (!Good || (StartPos < 0) || (StartPos > weatherJSON.length() - 1)) Good = false;
  464.   if (!Good || (EndPos <= StartPos) || (EndPos > weatherJSON.length() -1)) Good = false;
  465.   
  466.   if (Good) {
  467.     ResultStart = weatherJSON.indexOf(StartString, StartPos);
  468.     if (ResultStart < 0) Good =false;
  469.     else {
  470.       ResultStart += StartString.length();
  471.       if (ResultStart > EndPos) Good =false;
  472.       else {
  473.         ResultEnd = weatherJSON.indexOf(EndString, ResultStart);
  474.         if (ResultEnd > EndPos) Good = false;
  475.       }
  476.     }
  477.   }
  478.   if (Good) {
  479.     *SectionStart = ResultStart;
  480.     *SectionEnd = ResultEnd;
  481.   }
  482.   return Good;
  483. }
複製代碼
.

好似寫了好多行,實際有百幾行係重複 ,handleRhrread 和 handleWarnsum 以及 handleRhrread2 和 handleWarnsum2 基本上係一樣,分別只係前者會即時上天文台下載資料,而後者是我用來做測試,用了昨晚又一號風球、又黃雨、又雷暴……etc 的時候下載資料。

上載及連到 WiFi 後(LED 會熄),可以用以用 Web browser 經以下網址讀取資料:
http://ip-address:PortNo/xxxx

ip-address 係 Router 派給 ESP8266 的 ip
PortNo 係程式開頭由你自定的 Port number
xxxx 可以係 rhrread 或 warnsum。(以及 rhrread2 或 warnsum2)

主要係經 GetJson() 去下載天文台的 JSON 檔。

至於由 JSON 搵出想要的資料,應該係有 Library 去解讀內容,但我懶得睇 Library 的說明,寧願自己寫,我用 GetJsonRange() 去搵我想要的數值。

例如搵九龍城氣溫,氣溫必定係以下一段之內:
"temperature":{"data":[{...},{...},...{九龍城資料},...{...}]}
我先用 GetJsonRange() 去搵 "temperature":{"data":[ 以及 ] 的位置(ResultStart, ResultEnd)。

然後係上次搵到的範圍內再搵九龍城資料,這資料會類似係:
{"place":"Kowloon City","value":28,"unit":"C"}
而溫度就夾係 "place":"Kowloon City","value": 同後面的逗號之間,可以再用 GetJsonRange() 去搵這兩個位置,最後就可以用substring 從 weatherJSON 之中抽出溫度數值(String)。

不過有些資料,例如暴雨警告,除了搵 WRAIN 同個 code 之外,還是睇埋 actionCode 是否 CANCEL。

TOP

本帖最後由 marlin12 於 2021-6-13 15:38 編輯

有時間的話,可以試用ArduinoJson v6。
這個程式庫是雙向的,可以把陣列(array)轉為JSON,或者JSON轉為陣列。

ArduinoJson

Deserialize with ArduinoJson (JSON轉array)

還有ArduinoJson Assistant,教埋你點用。
只需要揀啱Processor(ESP8266)、Mode(Deserialize)、Input Type(String),然後放你個JSON字串入去,相關的程式便會自動產生出來。

TOP

有時間的話,可以試用ArduinoJson v6。
這個程式庫是雙向的,可以把陣列(array)轉為JSON,或者JSON轉為陣列 ...
marlin12 發表於 2021/6/13 12:22


Thx~~~

其實我都有裝 ArduinoJson,不過無心機睇 Tutorial,我見天文台幾個 JSON 的結構不是太複雜,就嘗試寫 GetJsonRange() 玩下先。

TOP

多謝各位師兄資料,都要時間消代一下。
Thanks

via HKEPC IR Pro 3.6.1 - iOS(3.0.0)

TOP

厲害, 結果看似簡單, 原來寫碼要這麼長

TOP

厲害, 結果看似簡單, 原來寫碼要這麼長
xiao 發表於 2021/6/16 09:16


其實我無學過 C++,亂寫一通 ,識寫應該可以寫得簡潔好多!

大致上完成我心目中想做的事。係差在不知怎去整黑雨警告,事關不想睇電視時被個鐘的光度吸引了視線,所以個鐘用黑色做底色,但黑底加個黑色雨字就即係無字!不想雨字改其他顏色,唯有係個雨字加底色,但試了好組合,還未試到個效果好的底色可以配到黃/紅黑。暫時用個「雨」字頂檔,遲下得閒會畫公仔。
LCD_Clock20210618a.jpg

ps.個 LCD 內置字庫同畫圖指令,話就話有 64 色可揀,但好多色重複,實際可用顏色其實好小。

TOP