264 lines
8.2 KiB
C++
264 lines
8.2 KiB
C++
#include "Network.h"
|
|
|
|
#include <WiFi.h>
|
|
#include <WiFiClientSecure.h>
|
|
#include <HTTPClient.h>
|
|
|
|
#define ARDUINOJSON_DECODE_UNICODE 1
|
|
#include <ArduinoJson.h>
|
|
|
|
// 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<JsonArray>();
|
|
|
|
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<char *>(), 30);
|
|
utf8_to_latin9(calName[i], calName[i], 30);
|
|
strncpy(calStart[i], row["start"].as<char *>(), 25);
|
|
strncpy(calTitle[i], row["title"].as<char *>(), 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);
|
|
}
|