123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- Weather Access API
- Information provided by the Hong Kong Observatory open data API
- */
- //Scheduler entry point, update today weather information (executed per hr)
- void todayWeatherUpdateCallback() {
- updateCurrentWeatherInfo();
- renderHomepageWeatherInfo();
- }
- //Scheduler entry point, updated every 6 hr
- void weatherForcastCallback() {
- updateAndRenderForcastInfo();
- }
- //Current weather info
- const char* rhurl = "https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=rhrread&lang=en";
- //Weather forcast info
- const char* wfurl = "https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=fnd&lang=en";
- /*
- Weather Forcast Loaders
- */
- bool updateAndRenderForcastInfo() {
- Serial.println("Updating weather forcast info...");
- WiFiClientSecure httpsClient; // Use WiFiClientSecure for HTTPS
- httpsClient.setInsecure(); // Ignore SSL certificate verification (for simplicity)
- if (httpsClient.connect("data.weather.gov.hk", 443)) {
- Serial.println("Downloading forcast info");
- httpsClient.print(String("GET ") + wfurl + " HTTP/1.1\r\n" +
- "Host: data.weather.gov.hk\r\n" +
- "Connection: close\r\n\r\n");
- String response = "";
- //Skip through the headers
- while (httpsClient.connected()) {
- String line = httpsClient.readStringUntil('\n');
- if (line == "\r") {
- break;
- }
- }
- //Read the JSON body
- String line = "";
- while (httpsClient.available()) {
- line = httpsClient.readStringUntil('\n'); //Read Line by Line
- response += line;
- }
- //Trim the first unwannted byte and the last
- int startTrimPos = response.indexOf("{");
- int lastTrimPos = response.lastIndexOf("}");
- response = response.substring(startTrimPos, lastTrimPos + 1);
- //Serial.println(response);
- if (response.length() < 10){
- changePage("error");
- sendCommand("t1.txt=\"Invalid resp: " + response + "\"");
- delay(10000);
- changePage("home");
- return false;
- }
-
- // Build the filter
- StaticJsonDocument<1024> filter;
- for (int i = 0; i < 7; i++) {
- filter["weatherForecast"][i]["week"] = true;
- filter["weatherForecast"][i]["forecastMintemp"]["value"] = true;
- filter["weatherForecast"][i]["forecastMaxtemp"]["value"] = true;
- filter["weatherForecast"][i]["forecastMaxrh"]["value"] = true;
- filter["weatherForecast"][i]["ForecastIcon"] = true;
- }
- // Parse JSON data
- StaticJsonDocument<5120> jsonDoc;
- auto error = deserializeJson(jsonDoc, response, DeserializationOption::Filter(filter));
- if (error) {
- Serial.print(F("deserializeJson() failed with code "));
- Serial.println(error.c_str());
- return false;
- }
- //serializeJsonPretty(jsonDoc, Serial);
- //Render the weather forcast onto the HMI
- for (int i = 0; i < 7; i++) {
- //Get day of week
- String dow = jsonDoc["weatherForecast"][i]["week"];
- dow = dow.substring(0, 3);
- //Get min-max temp
- int minTemp = jsonDoc["weatherForecast"][i]["forecastMintemp"]["value"];
- int maxTemp = jsonDoc["weatherForecast"][i]["forecastMaxtemp"]["value"];
- int maxRh = jsonDoc["weatherForecast"][i]["forecastMaxrh"]["value"];
- //Get forcast icon
- int forcastIcon = jsonDoc["weatherForecast"][i]["ForecastIcon"];
- renderForcastField(String(i), dow, minTemp, maxTemp, maxRh, forcastIcon);
- }
- }
- return true;
- }
- /*
- Current Weather Loaders
- */
- //Render the homepage weather info from the buffered information
- void renderHomepageWeatherInfo() {
- if (currentPage == 0) {
- printIntCommand("home.temp.txt=", currentTemp);
- printIntCommand("home.humd.txt=", currentHumd);
- printIntCommand("home.rain.txt=", currentRain);
- //Change the main weather icon
- if (isNight()) {
- if (currentIsRaining) {
- sendCommand("home.wicon.pic=11");
- } else {
- sendCommand("home.wicon.pic=7");
- }
- } else {
- if (currentIsRaining) {
- sendCommand("home.wicon.pic=11");
- } else {
- sendCommand("home.wicon.pic=6");
- }
- }
- }
- }
- void updateCurrentWeatherInfo() {
- WiFiClientSecure httpsClient; // Use WiFiClientSecure for HTTPS
- httpsClient.setInsecure(); // Ignore SSL certificate verification (for simplicity)
-
- if (httpsClient.connect("data.weather.gov.hk", 443)) {
- Serial.println("Downloading current weather info");
- httpsClient.print(String("GET ") + rhurl + " HTTP/1.1\r\n" +
- "Host: data.weather.gov.hk\r\n" +
- "Connection: close\r\n\r\n");
- String response = "";
- //Skip through the headers
- while (httpsClient.connected()) {
- String line = httpsClient.readStringUntil('\n');
- if (line == "\r") {
- break;
- }
- }
- //Read the JSON body
- String line;
- while (httpsClient.available()) {
- line = httpsClient.readStringUntil('\n'); //Read Line by Line
- response += line;
- }
- //Trim the first unwannted byte and the last
- int startTrimPos = response.indexOf("{");
- int lastTrimPos = response.lastIndexOf("}");
- response = response.substring(startTrimPos, lastTrimPos + 1);
- //Serial.println(response);
-
- // Build the filter
- StaticJsonDocument<1024> filter;
- filter["temperature"]["data"][0]["value"] = true;
- filter["humidity"]["data"][0]["value"] = true;
- filter["rainfall"]["data"][0]["max"] = true;
- filter["rainfall"]["data"][0]["main"] = true;
-
- // Parse JSON data
- /*
- DynamicJsonDocument jsonDoc(8192); // Change the size according to your JSON data
- auto error = deserializeJson(jsonDoc, response);
- if (error) {
- Serial.print(F("deserializeJson() failed with code "));
- Serial.println(error.c_str());
- return;
- }
- */
- // Parse JSON data
- StaticJsonDocument<4096> jsonDoc;
- auto error = deserializeJson(jsonDoc, response, DeserializationOption::Filter(filter));
- if (error) {
- Serial.print(F("deserializeJson() failed with code "));
- Serial.println(error.c_str());
- return;
- }
-
- // Access and return the temperature value
- currentTemp = jsonDoc["temperature"]["data"][19]["value"];
- currentHumd = jsonDoc["humidity"]["data"][0]["value"];
- currentRain = jsonDoc["rainfall"]["data"][16]["max"];
- currentIsRaining = String(jsonDoc["rainfall"]["data"][16]["main"]) == "TRUE";
- // Serial debug prints
- Serial.println(int(jsonDoc["temperature"]["data"][19]["value"]));
- Serial.println(int(jsonDoc["humidity"]["data"][0]["value"]));
- Serial.println(int(jsonDoc["rainfall"]["data"][16]["max"]));
- Serial.println(String(jsonDoc["rainfall"]["data"][16]["main"]));
- } else {
- Serial.println("Failed to connect to server");
- }
- }
|