732 lines
17 KiB
C++
732 lines
17 KiB
C++
/******************************************************************************
|
|
* Freematics Hub client and Traccar client implementations
|
|
* Works with Freematics ONE+
|
|
* Developed by Stanley Huang <stanley@freematics.com.au>
|
|
* Distributed under BSD license
|
|
* Visit https://freematics.com/products for hardware information
|
|
* Visit https://hub.freematics.com to view live and history telemetry data
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include <FreematicsPlus.h>
|
|
#include "telestore.h"
|
|
#include "telemesh.h"
|
|
#include "teleclient.h"
|
|
#include "config.h"
|
|
|
|
#if SERVER_ENCRYPTION_ENABLE == 1
|
|
#include "telecrypt.h"
|
|
#endif
|
|
|
|
extern int16_t rssi;
|
|
extern char devid[];
|
|
extern char vin[];
|
|
extern GPS_DATA* gd;
|
|
extern char isoTime[];
|
|
|
|
CBuffer::CBuffer(uint8_t* mem)
|
|
{
|
|
m_data = mem;
|
|
purge();
|
|
}
|
|
|
|
void CBuffer::add(uint16_t pid, uint8_t type, void* values, int bytes, uint8_t count)
|
|
{
|
|
if (offset < BUFFER_LENGTH - sizeof(ELEMENT_HEAD) - bytes) {
|
|
ELEMENT_HEAD hdr = {pid, type, count};
|
|
*(ELEMENT_HEAD*)(m_data + offset) = hdr;
|
|
offset += sizeof(ELEMENT_HEAD);
|
|
memcpy(m_data + offset, values, bytes);
|
|
offset += bytes;
|
|
total++;
|
|
} else {
|
|
Serial.println("FULL");
|
|
}
|
|
}
|
|
|
|
void CBuffer::purge()
|
|
{
|
|
state = BUFFER_STATE_EMPTY;
|
|
timestamp = 0;
|
|
offset = 0;
|
|
total = 0;
|
|
}
|
|
|
|
void CBuffer::serialize(CStorage& store)
|
|
{
|
|
uint16_t of = 0;
|
|
for (int n = 0; n < total && of < offset; n++) {
|
|
ELEMENT_HEAD* hdr = (ELEMENT_HEAD*)(m_data + of);
|
|
of += sizeof(ELEMENT_HEAD);
|
|
switch (hdr->type) {
|
|
case ELEMENT_UINT8:
|
|
store.log(hdr->pid, (uint8_t*)(m_data + of), hdr->count);
|
|
of += (uint16_t)hdr->count * sizeof(uint8_t);
|
|
break;
|
|
case ELEMENT_UINT16:
|
|
store.log(hdr->pid, (uint16_t*)(m_data + of), hdr->count);
|
|
of += (uint16_t)hdr->count * sizeof(uint16_t);
|
|
break;
|
|
case ELEMENT_UINT32:
|
|
store.log(hdr->pid, (uint32_t*)(m_data + of), hdr->count);
|
|
of += (uint16_t)hdr->count * sizeof(uint32_t);
|
|
break;
|
|
case ELEMENT_INT32:
|
|
store.log(hdr->pid, (int32_t*)(m_data + of), hdr->count);
|
|
of += (uint16_t)hdr->count * sizeof(int32_t);
|
|
break;
|
|
case ELEMENT_FLOAT:
|
|
store.log(hdr->pid, (float*)(m_data + of), hdr->count);
|
|
of += (uint16_t)hdr->count * sizeof(float);
|
|
break;
|
|
case ELEMENT_FLOAT_D1:
|
|
store.log(hdr->pid, (float*)(m_data + of), hdr->count, "%.1f");
|
|
of += (uint16_t)hdr->count * sizeof(float);
|
|
break;
|
|
case ELEMENT_FLOAT_D2:
|
|
store.log(hdr->pid, (float*)(m_data + of), hdr->count, "%.2f");
|
|
of += (uint16_t)hdr->count * sizeof(float);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBufferManager::init()
|
|
{
|
|
total = BUFFER_SLOTS;
|
|
#if BOARD_HAS_PSRAM
|
|
slots = (CBuffer**)heap_caps_malloc(BUFFER_SLOTS * sizeof(void*), MALLOC_CAP_SPIRAM);
|
|
#else
|
|
slots = (CBuffer**)malloc(BUFFER_SLOTS * sizeof(void*));
|
|
#endif
|
|
for (int n = 0; n < BUFFER_SLOTS; n++) {
|
|
void* mem;
|
|
#if BOARD_HAS_PSRAM
|
|
mem = heap_caps_malloc(BUFFER_LENGTH, MALLOC_CAP_SPIRAM);
|
|
#else
|
|
mem = malloc(BUFFER_LENGTH);
|
|
#endif
|
|
if (!mem) {
|
|
Serial.println("OUT OF RAM");
|
|
total = n;
|
|
break;
|
|
}
|
|
slots[n] = new CBuffer((uint8_t*)mem);
|
|
}
|
|
assert(total > 0);
|
|
}
|
|
|
|
void CBufferManager::purge()
|
|
{
|
|
for (int n = 0; n < total; n++) slots[n]->purge();
|
|
}
|
|
|
|
CBuffer* CBufferManager::getFree()
|
|
{
|
|
if (last) {
|
|
CBuffer* slot = last;
|
|
last = 0;
|
|
if (slot->state == BUFFER_STATE_EMPTY) return slot;
|
|
}
|
|
uint32_t ts = 0xffffffff;
|
|
int m = 0;
|
|
// search for free slot, if none, mark the oldest one
|
|
for (int n = 0; n < total; n++) {
|
|
if (slots[n]->state == BUFFER_STATE_EMPTY) {
|
|
return slots[n];
|
|
} else if (slots[n]->state == BUFFER_STATE_FILLED && slots[n]->timestamp < ts) {
|
|
m = n;
|
|
ts = slots[n]->timestamp;
|
|
}
|
|
}
|
|
// dispose oldest data when buffer is full
|
|
while (slots[m]->state == BUFFER_STATE_LOCKED) delay(1);
|
|
slots[m]->purge();
|
|
return slots[m];
|
|
}
|
|
|
|
CBuffer* CBufferManager::getOldest()
|
|
{
|
|
uint32_t ts = 0xffffffff;
|
|
int m = -1;
|
|
for (int n = 0; n < total; n++) {
|
|
if (slots[n]->state == BUFFER_STATE_FILLED && slots[n]->timestamp < ts) {
|
|
m = n;
|
|
ts = slots[n]->timestamp;
|
|
}
|
|
}
|
|
if (m >= 0) {
|
|
slots[m]->state = BUFFER_STATE_LOCKED;
|
|
return slots[m];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
CBuffer* CBufferManager::getNewest()
|
|
{
|
|
uint32_t ts = 0;
|
|
int m = -1;
|
|
for (int n = 0; n < total; n++) {
|
|
if (slots[n]->state == BUFFER_STATE_FILLED && slots[n]->timestamp > ts) {
|
|
m = n;
|
|
ts = slots[n]->timestamp;
|
|
}
|
|
}
|
|
if (m >= 0) {
|
|
slots[m]->state = BUFFER_STATE_LOCKED;
|
|
return slots[m];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CBufferManager::free(CBuffer* slot)
|
|
{
|
|
slot->purge();
|
|
last = slot;
|
|
}
|
|
|
|
void CBufferManager::printStats()
|
|
{
|
|
int bytes = 0;
|
|
int count = 0;
|
|
int samples = 0;
|
|
for (int n = 0; n < total; n++) {
|
|
if (slots[n]->state != BUFFER_STATE_FILLED) continue;
|
|
bytes += slots[n]->offset;
|
|
samples += slots[n]->total;
|
|
count++;
|
|
}
|
|
if (slots) {
|
|
Serial.print("[BUF] ");
|
|
Serial.print(samples);
|
|
Serial.print(" samples | ");
|
|
Serial.print(bytes);
|
|
Serial.print(" bytes | ");
|
|
Serial.print(count);
|
|
Serial.print('/');
|
|
Serial.println(total);
|
|
}
|
|
}
|
|
|
|
bool TeleClientUDP::verifyChecksum(char* data)
|
|
{
|
|
uint8_t sum = 0;
|
|
char *s = strrchr(data, '*');
|
|
if (!s) return false;
|
|
for (char *p = data; p < s; p++) sum += *p;
|
|
if (hex2uint8(s + 1) == sum) {
|
|
*s = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TeleClientUDP::notify(byte event, const char* payload)
|
|
{
|
|
char buf[48];
|
|
char cache[128];
|
|
CStorageRAM netbuf;
|
|
netbuf.init(cache, 128);
|
|
netbuf.header(devid);
|
|
netbuf.dispatch(buf, sprintf(buf, "EV=%X", (unsigned int)event));
|
|
netbuf.dispatch(buf, sprintf(buf, "TS=%lu", millis()));
|
|
netbuf.dispatch(buf, sprintf(buf, "ID=%s", devid));
|
|
if (rssi) {
|
|
netbuf.dispatch(buf, sprintf(buf, "SSI=%d", (int)rssi));
|
|
}
|
|
if (vin[0]) {
|
|
netbuf.dispatch(buf, sprintf(buf, "VIN=%s", vin));
|
|
}
|
|
if (payload) {
|
|
netbuf.dispatch(payload, strlen(payload));
|
|
}
|
|
netbuf.tailer();
|
|
//Serial.println(netbuf.buffer());
|
|
for (byte attempts = 0; attempts < 3; attempts++) {
|
|
// send notification datagram
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
#if SERVER_ENCRYPTION_ENABLE == 1
|
|
char *orig_send_buf = netbuf.buffer();
|
|
unsigned int orig_send_buf_len = netbuf.length();
|
|
unsigned char encrypted_buf[12 + orig_send_buf_len + 16];
|
|
encrypt_string((unsigned char *)orig_send_buf, orig_send_buf_len, encrypted_buf);
|
|
if (!wifi.send((const char *)encrypted_buf, sizeof(encrypted_buf))) break;
|
|
#else
|
|
if (!wifi.send(netbuf.buffer(), netbuf.length())) break;
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#if SERVER_ENCRYPTION_ENABLE == 1
|
|
char *orig_send_buf = netbuf.buffer();
|
|
unsigned int orig_send_buf_len = netbuf.length();
|
|
unsigned char encrypted_buf[12 + orig_send_buf_len + 16];
|
|
encrypt_string((unsigned char *)orig_send_buf, orig_send_buf_len, encrypted_buf);
|
|
if (!cell.send((const char *)encrypted_buf, sizeof(encrypted_buf))) break;
|
|
#else
|
|
if (!cell.send(netbuf.buffer(), netbuf.length())) break;
|
|
#endif
|
|
}
|
|
if (event == EVENT_ACK) return true; // no reply for ACK
|
|
char *data = 0;
|
|
int bytesRecv = 0;
|
|
// receive reply
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
data = cell.getBuffer();
|
|
bytesRecv = wifi.receive(data, RECV_BUF_SIZE - 1);
|
|
if (bytesRecv > 0) {
|
|
data[bytesRecv] = 0;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
data = cell.receive(&bytesRecv);
|
|
}
|
|
if (!data || bytesRecv == 0) {
|
|
Serial.println("[UDP] Timeout");
|
|
continue;
|
|
}
|
|
rxBytes += bytesRecv;
|
|
|
|
// decrypt received data
|
|
#if SERVER_ENCRYPTION_ENABLE == 1
|
|
char decrypted_data[bytesRecv - 12 - 16 + 1]; // +1 for null-terminator
|
|
decrypt_string((unsigned char *)data, bytesRecv, (unsigned char *)decrypted_data);
|
|
data = decrypted_data;
|
|
bytesRecv = strlen(decrypted_data);
|
|
#endif
|
|
// verify checksum
|
|
if (!verifyChecksum(data)) {
|
|
Serial.print("[UDP] Checksum mismatch:");
|
|
Serial.println(data);
|
|
continue;
|
|
}
|
|
char pattern[16];
|
|
sprintf(pattern, "EV=%u", event);
|
|
if (!strstr(data, pattern)) {
|
|
Serial.print("[UDP] Invalid reply: ");
|
|
Serial.println(data);
|
|
continue;
|
|
}
|
|
if (event == EVENT_LOGIN) {
|
|
// extract info from server response
|
|
char *p = strstr(data, "TM=");
|
|
if (p) {
|
|
// set local time from server
|
|
unsigned long tm = atol(p + 3);
|
|
struct timeval tv = { .tv_sec = (time_t)tm, .tv_usec = 0 };
|
|
settimeofday(&tv, NULL);
|
|
}
|
|
p = strstr(data, "SN=");
|
|
if (p) {
|
|
char *q = strchr(p, ',');
|
|
if (q) *q = 0;
|
|
}
|
|
feedid = hex2uint16(data);
|
|
login = true;
|
|
} else if (event == EVENT_LOGOUT) {
|
|
login = false;
|
|
}
|
|
// success
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TeleClientUDP::connect(bool quick)
|
|
{
|
|
byte event = login ? EVENT_RECONNECT : EVENT_LOGIN;
|
|
bool success = false;
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
if (quick) return wifi.open(SERVER_HOST, SERVER_PORT);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
cell.close();
|
|
if (quick) {
|
|
return cell.open(0, 0);
|
|
}
|
|
}
|
|
|
|
packets = 0;
|
|
|
|
// connect to telematics server
|
|
for (byte attempts = 0; attempts < 3; attempts++) {
|
|
Serial.print(event == EVENT_LOGIN ? "LOGIN(" : "RECONNECT(");
|
|
Serial.print(SERVER_HOST);
|
|
Serial.print(':');
|
|
Serial.print(SERVER_PORT);
|
|
Serial.println(")...");
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
if (!wifi.open(SERVER_HOST, SERVER_PORT)) {
|
|
Serial.println("[WIFI] Unable to connect");
|
|
delay(1000);
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (!cell.open(SERVER_HOST, SERVER_PORT)) {
|
|
if (!cell.check()) break;
|
|
Serial.println("[NET] Unable to connect");
|
|
delay(3000);
|
|
continue;
|
|
}
|
|
}
|
|
// log in or reconnect to Freematics Hub
|
|
if (!notify(event)) {
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
wifi.close();
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (!cell.check()) break;
|
|
cell.close();
|
|
}
|
|
Serial.println("[NET] Server timeout");
|
|
continue;
|
|
}
|
|
success = true;
|
|
break;
|
|
}
|
|
if (event == EVENT_LOGIN) startTime = millis();
|
|
if (success) {
|
|
lastSyncTime = millis();
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool TeleClientUDP::ping()
|
|
{
|
|
bool success = false;
|
|
for (byte n = 0; n < 3 && !success; n++) {
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
success = wifi.open(SERVER_HOST, SERVER_PORT);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
success = cell.open(SERVER_HOST, SERVER_PORT);
|
|
}
|
|
if (success) {
|
|
if ((success = notify(EVENT_PING))) break;
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
wifi.close();
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
cell.close();
|
|
}
|
|
delay(1000);
|
|
}
|
|
}
|
|
if (success) lastSyncTime = millis();
|
|
return success;
|
|
}
|
|
|
|
bool TeleClientUDP::transmit(const char* packetBuffer, unsigned int packetSize)
|
|
{
|
|
#if ENABLE_WIFI
|
|
// transmit data via wifi
|
|
if (wifi.connected()) {
|
|
if (wifi.send(packetBuffer, packetSize)) {
|
|
txBytes += packetSize;
|
|
txCount++;
|
|
Serial.print("[WIFI] ");
|
|
Serial.print(packetSize);
|
|
Serial.println(" bytes sent");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
// transmit data via cellular
|
|
if (++packets >= 64) {
|
|
cell.close();
|
|
cell.open(0, 0);
|
|
packets = 0;
|
|
}
|
|
Serial.print("[CELL] ");
|
|
Serial.print(packetSize);
|
|
Serial.println(" bytes being sent");
|
|
if (cell.send(packetBuffer, packetSize)) {
|
|
txBytes += packetSize;
|
|
txCount++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TeleClientUDP::inbound()
|
|
{
|
|
// check incoming datagram
|
|
do {
|
|
int len = 0;
|
|
char *data = 0;
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
data = cell.getBuffer();
|
|
len = wifi.receive(data, RECV_BUF_SIZE - 1, 10);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
data = cell.receive(&len, 50);
|
|
}
|
|
if (!data || len == 0) break;
|
|
data[len] = 0;
|
|
|
|
#if SERVER_ENCRYPTION_ENABLE == 1
|
|
char decrypted_data[len - 12 - 16 + 1];
|
|
decrypt_string((unsigned char *)data, len, (unsigned char *)decrypted_data);
|
|
data = decrypted_data;
|
|
len = strlen(decrypted_data);
|
|
#endif
|
|
|
|
Serial.print("[UDP] ");
|
|
Serial.println(data);
|
|
rxBytes += len;
|
|
if (!verifyChecksum(data)) {
|
|
Serial.print("[UDP] Checksum mismatch:");
|
|
Serial.println(data);
|
|
break;
|
|
}
|
|
char *p = strstr(data, "EV=");
|
|
if (!p) break;
|
|
int eventID = atoi(p + 3);
|
|
switch (eventID) {
|
|
case EVENT_SYNC:
|
|
feedid = hex2uint16(data);
|
|
Serial.print("[UDP] FEED ID:");
|
|
Serial.println(feedid);
|
|
break;
|
|
}
|
|
lastSyncTime = millis();
|
|
} while(0);
|
|
}
|
|
|
|
void TeleClientUDP::shutdown()
|
|
{
|
|
if (login) {
|
|
notify(EVENT_LOGOUT);
|
|
login = false;
|
|
Serial.println("[NET] Logout");
|
|
}
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected()) {
|
|
wifi.end();
|
|
Serial.println("[WIFI] Deactivated");
|
|
return;
|
|
}
|
|
#endif
|
|
cell.end();
|
|
Serial.println("[CELL] Deactivated");
|
|
}
|
|
|
|
bool TeleClientHTTP::notify(byte event, const char* payload)
|
|
{
|
|
char url[256];
|
|
snprintf(url, sizeof(url), "%s/notify/%s?EV=%u&SSI=%d&VIN=%s", SERVER_PATH, devid,
|
|
(unsigned int)event, (int)rssi, vin);
|
|
if (event == EVENT_LOGOUT) login = false;
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
return wifi.send(METHOD_GET, url, true) && wifi.receive(cell.getBuffer(), RECV_BUF_SIZE - 1) && wifi.code() == 200;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
return cell.send(METHOD_GET, url, true) && cell.receive() && cell.code() == 200;
|
|
}
|
|
}
|
|
|
|
bool TeleClientHTTP::transmit(const char* packetBuffer, unsigned int packetSize)
|
|
{
|
|
#if ENABLE_WIFI
|
|
if ((wifi.connected() && wifi.state() != HTTP_CONNECTED) || cell.state() != HTTP_CONNECTED) {
|
|
#else
|
|
if (cell.state() != HTTP_CONNECTED) {
|
|
#endif
|
|
// reconnect if disconnected
|
|
if (!connect(true)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
char url[256];
|
|
bool success = false;
|
|
int len;
|
|
#if SERVER_METHOD == PROTOCOL_METHOD_GET
|
|
if (gd && gd->ts) {
|
|
len = snprintf(url, sizeof(url), "%s/push?id=%s×tamp=%s&lat=%f&lon=%f&altitude=%d&speed=%f&heading=%d",
|
|
SERVER_PATH, devid, isoTime,
|
|
gd->lat, gd->lng, (int)gd->alt, gd->speed, (int)gd->heading);
|
|
} else {
|
|
len = snprintf(url, sizeof(url), "%s/push?id=%s", SERVER_PATH, devid);
|
|
}
|
|
success = cell.send(METHOD_GET, url, true);
|
|
#else
|
|
len = snprintf(url, sizeof(url), "%s/post/%s", SERVER_PATH, devid);
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected()) {
|
|
Serial.print("[WIFI] ");
|
|
Serial.println(url);
|
|
success = wifi.send(METHOD_POST, url, true, packetBuffer, packetSize);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Serial.print("[CELL] ");
|
|
Serial.println(url);
|
|
success = cell.send(METHOD_POST, url, true, packetBuffer, packetSize);
|
|
}
|
|
len += packetSize;
|
|
#endif
|
|
if (!success) {
|
|
Serial.println("Connection closed");
|
|
return false;
|
|
} else {
|
|
txBytes += len;
|
|
txCount++;
|
|
}
|
|
|
|
// check response
|
|
int recvBytes = 0;
|
|
char* content = 0;
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected())
|
|
{
|
|
content = wifi.receive(cell.getBuffer(), RECV_BUF_SIZE - 1, &recvBytes);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
content = cell.receive(&recvBytes);
|
|
}
|
|
if (!content) {
|
|
// close connection on receiving timeout
|
|
Serial.println("No HTTP response");
|
|
return false;
|
|
}
|
|
Serial.print("[HTTP] ");
|
|
Serial.println(content);
|
|
#if ENABLE_WIFI
|
|
if ((wifi.connected() && wifi.code() == 200) || cell.code() == 200) {
|
|
#else
|
|
if (cell.code() == 200) {
|
|
#endif
|
|
// successful
|
|
lastSyncTime = millis();
|
|
rxBytes += recvBytes;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TeleClientHTTP::connect(bool quick)
|
|
{
|
|
if (!quick) {
|
|
#if ENABLE_WIFI
|
|
if (!wifi.connected()) cell.init();
|
|
#else
|
|
cell.init();
|
|
#endif
|
|
} else {
|
|
#if ENABLE_WIFI
|
|
if (!wifi.connected()) cell.close();
|
|
#else
|
|
cell.close();
|
|
#endif
|
|
}
|
|
|
|
// connect to HTTP server
|
|
bool success = false;
|
|
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected()) success = wifi.open(SERVER_HOST, SERVER_PORT);
|
|
#endif
|
|
if (!success) {
|
|
for (byte attempts = 0; !success && attempts < 3; attempts++) {
|
|
success = cell.open(SERVER_HOST, SERVER_PORT);
|
|
if (!success) {
|
|
if (!cell.check()) break;
|
|
cell.close();
|
|
cell.init();
|
|
}
|
|
}
|
|
}
|
|
if (!success) {
|
|
Serial.println("[CELL] Unable to connect");
|
|
return false;
|
|
}
|
|
if (quick) return true;
|
|
if (!login) {
|
|
Serial.print("LOGIN(");
|
|
Serial.print(SERVER_HOST);
|
|
Serial.print(':');
|
|
Serial.print(SERVER_PORT);
|
|
Serial.println(")...");
|
|
// log in or reconnect to Freematics Hub
|
|
if (notify(EVENT_LOGIN)) {
|
|
lastSyncTime = millis();
|
|
login = true;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TeleClientHTTP::ping()
|
|
{
|
|
return connect();
|
|
}
|
|
|
|
void TeleClientHTTP::shutdown()
|
|
{
|
|
if (login) {
|
|
notify(EVENT_LOGOUT);
|
|
login = false;
|
|
Serial.println("[NET] Logout");
|
|
}
|
|
#if ENABLE_WIFI
|
|
if (wifi.connected()) {
|
|
wifi.end();
|
|
Serial.println("[WIFI] Deactivated");
|
|
return;
|
|
}
|
|
#endif
|
|
cell.close();
|
|
cell.end();
|
|
Serial.println("[CELL] Deactivated");
|
|
}
|