#include "Network.h" #include #include #include #define ARDUINOJSON_DECODE_UNICODE 1 #include // Static Json from ArduinoJson library StaticJsonDocument<6000> doc; void Network::begin() { byte TryCounter = 0; // Initiating wifi, like in BasicHttpClient example WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while ((WiFi.status() != WL_CONNECTED) && (TryCounter < 10)) { delay(1000); TryCounter++; } // Find internet time setTime(); // Update calendar setCalendar(); } // Gets time from ntp server void Network::getTime(int *timeDigits) { struct tm timeinfo; time_t nowSecs = time(nullptr); setenv("TZ", timeZone, 1); tzset(); localtime_r(&nowSecs, &timeinfo); // fill in the digits timeDigits[0] = timeinfo.tm_min % 10; //minutes (units) timeDigits[1] = timeinfo.tm_min / 10; //minutes (tens) timeDigits[2] = timeinfo.tm_hour % 10; //hours (units) timeDigits[3] = timeinfo.tm_hour / 10; //hours (tens) } // Function to get calendar from web void Network::setCalendar() { // Http object used to make get request HTTPClient http; http.getStream().setNoDelay(true); http.getStream().setTimeout(10); // Initiate http http.begin(calendarURL); // Actually do request int httpCode = http.GET(); if (httpCode == 200) { int32_t len = http.getSize(); if (len > 0) { // Try parsing JSON object DeserializationError error = deserializeJson(doc, http.getStream()); JsonArray arr = doc.as(); if (!error) { // delete array in RTC because a possible smaller new array for (int i = 0; i < 5; ++i) { calName[i][0] = '\0'; calStart[i][0] = '\0'; calTitle[i][0] = '\0'; } int i = 0; for (JsonArray::iterator it=arr.begin(); it!=arr.end(); ++it) { JsonObject row = *it; strncpy(calName[i], row["calendar"].as(), 30); utf8_to_latin9(calName[i], calName[i], 30); strncpy(calStart[i], row["start"].as(), 25); strncpy(calTitle[i], row["title"].as(), 80); utf8_to_latin9(calTitle[i], calTitle[i], 80); if (++i >= 5) break; } } } } // Clear document and end http doc.clear(); http.end(); } void Network::off() { WiFi.disconnect(true); WiFi.mode(WIFI_OFF); } void Network::setTime() { byte TryCounter = 0; // Used for setting correct time configTime(0, 0, "de.pool.ntp.org", "time.nist.gov"); delay(2000); // wait 2s to (re)sync time // if time is already set in RTC, // the loop below doesn't wait for sync // because the time value is valid time_t nowSecs = time(nullptr); while ((nowSecs < 8 * 3600 * 2)&& (TryCounter < 120)) { delay(500); // yield(); nowSecs = time(nullptr); TryCounter++; } } /* UTF-8 to ISO-8859-1/ISO-8859-15 mapper. * Return 0..255 for valid ISO-8859-15 code points, 256 otherwise. */ static inline unsigned int to_latin9(const unsigned int code) { /* Code points 0 to U+00FF are the same in both. */ if (code < 256U) return code; switch (code) { case 0x0152U: return 188U; /* U+0152 = 0xBC: OE ligature */ case 0x0153U: return 189U; /* U+0153 = 0xBD: oe ligature */ case 0x0160U: return 166U; /* U+0160 = 0xA6: S with caron */ case 0x0161U: return 168U; /* U+0161 = 0xA8: s with caron */ case 0x0178U: return 190U; /* U+0178 = 0xBE: Y with diaresis */ case 0x017DU: return 180U; /* U+017D = 0xB4: Z with caron */ case 0x017EU: return 184U; /* U+017E = 0xB8: z with caron */ case 0x20ACU: return 164U; /* U+20AC = 0xA4: Euro */ default: return 256U; } } /* Convert an UTF-8 string to ISO-8859-15. * All invalid sequences are ignored. * Note: output == input is allowed, * but input < output < input + length * is not. * Output has to have room for (length+1) chars, including the trailing NUL byte. */ size_t Network::utf8_to_latin9(char *const output, const char *const input, const size_t length) { unsigned char *out = (unsigned char *)output; const unsigned char *in = (const unsigned char *)input; const unsigned char *const end = (const unsigned char *)input + length; unsigned int c; while (in < end) if (*in < 128) *(out++) = *(in++); /* Valid codepoint */ else if (*in < 192) in++; /* 10000000 .. 10111111 are invalid */ else if (*in < 224) { /* 110xxxxx 10xxxxxx */ if (in + 1 >= end) break; if ((in[1] & 192U) == 128U) { c = to_latin9( (((unsigned int)(in[0] & 0x1FU)) << 6U) | ((unsigned int)(in[1] & 0x3FU)) ); if (c < 256) *(out++) = c; } in += 2; } else if (*in < 240) { /* 1110xxxx 10xxxxxx 10xxxxxx */ if (in + 2 >= end) break; if ((in[1] & 192U) == 128U && (in[2] & 192U) == 128U) { c = to_latin9( (((unsigned int)(in[0] & 0x0FU)) << 12U) | (((unsigned int)(in[1] & 0x3FU)) << 6U) | ((unsigned int)(in[2] & 0x3FU)) ); if (c < 256) *(out++) = c; } in += 3; } else if (*in < 248) { /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (in + 3 >= end) break; if ((in[1] & 192U) == 128U && (in[2] & 192U) == 128U && (in[3] & 192U) == 128U) { c = to_latin9( (((unsigned int)(in[0] & 0x07U)) << 18U) | (((unsigned int)(in[1] & 0x3FU)) << 12U) | (((unsigned int)(in[2] & 0x3FU)) << 6U) | ((unsigned int)(in[3] & 0x3FU)) ); if (c < 256) *(out++) = c; } in += 4; } else if (*in < 252) { /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (in + 4 >= end) break; if ((in[1] & 192U) == 128U && (in[2] & 192U) == 128U && (in[3] & 192U) == 128U && (in[4] & 192U) == 128U) { c = to_latin9( (((unsigned int)(in[0] & 0x03U)) << 24U) | (((unsigned int)(in[1] & 0x3FU)) << 18U) | (((unsigned int)(in[2] & 0x3FU)) << 12U) | (((unsigned int)(in[3] & 0x3FU)) << 6U) | ((unsigned int)(in[4] & 0x3FU)) ); if (c < 256) *(out++) = c; } in += 5; } else if (*in < 254) { /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (in + 5 >= end) break; if ((in[1] & 192U) == 128U && (in[2] & 192U) == 128U && (in[3] & 192U) == 128U && (in[4] & 192U) == 128U && (in[5] & 192U) == 128U) { c = to_latin9( (((unsigned int)(in[0] & 0x01U)) << 30U) | (((unsigned int)(in[1] & 0x3FU)) << 24U) | (((unsigned int)(in[2] & 0x3FU)) << 18U) | (((unsigned int)(in[3] & 0x3FU)) << 12U) | (((unsigned int)(in[4] & 0x3FU)) << 6U) | ((unsigned int)(in[5] & 0x3FU)) ); if (c < 256) *(out++) = c; } in += 6; } else in++; /* 11111110 and 11111111 are invalid */ /* Terminate the output string. */ *out = '\0'; return (size_t)(out - (unsigned char *)output); }