FamilyPlanner/Network.cpp

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);
}