293 lines
7.7 KiB
C++
293 lines
7.7 KiB
C++
#include "freertos/portable.h"
|
|
#include "alarm.h"
|
|
#include "Times.h"
|
|
#include <HTTPClient.h>
|
|
#include <iostream>
|
|
#include <ArduinoJson.h>
|
|
|
|
class ServerConnector
|
|
{
|
|
private:
|
|
AlarmStatus *status;
|
|
long lastUpdate;
|
|
// WiFiClient wifiClient;
|
|
// CardReader *_cardReader;
|
|
WiegandReader *_cardReader;
|
|
|
|
const String AUTHORIZED_ENTRANCE = "AUTHORIZE_ENTRANCE";
|
|
const String ServerAddress = "alarm.int.francelsoft.com";
|
|
// const String ServerAddress = "10.88.88.169:9003";
|
|
const String EVEN_TYPE_FIRED = "Fired";
|
|
const String EVENT_TYPE_EVENT_UPDATE = "EventUpdate";
|
|
const String EVENT_TYPE_UPDATE = "Update";
|
|
|
|
const String FIELD_DISARM = "disarm";
|
|
const String FIELD_ALLOWED_CARDS = "cards";
|
|
|
|
int failedAttempts;
|
|
bool running;
|
|
|
|
// long lastHeapSize=0;
|
|
// long initHeapSize=0;
|
|
|
|
void HandTask()
|
|
{
|
|
// if(initHeapSize == 0)
|
|
// {
|
|
// initHeapSize=xPortGetFreeHeapSize();
|
|
// }
|
|
// long currentHeapSize=0;
|
|
running = true;
|
|
for (;;)
|
|
{
|
|
// every 15 seconds ask for update: DISSARM & CARDS
|
|
unsigned long currentMillis = millis();
|
|
if (lastUpdate + FromSeconds(15) < currentMillis)
|
|
{
|
|
lastUpdate = currentMillis;
|
|
// currentHeapSize= xPortGetFreeHeapSize();
|
|
// if(abs(currentHeapSize - lastHeapSize) > 32)
|
|
// {
|
|
// Serial.print("[MEMORY] xPortGetFreeHeapSize: "); Serial.print(currentHeapSize);
|
|
// Serial.print( "| Total Variation: "); Serial.print(currentHeapSize - initHeapSize);
|
|
// Serial.print(" | Variation: "); Serial.println(currentHeapSize - lastHeapSize);
|
|
// lastHeapSize=currentHeapSize;
|
|
// }
|
|
|
|
|
|
if(failedAttempts == 5)
|
|
{
|
|
Serial.println("[HTTP] 5 fail connections, restarting thread.");
|
|
failedAttempts=6;
|
|
running=false;
|
|
vTaskDelete(NULL);
|
|
return;
|
|
}
|
|
|
|
if(!CheckWifiConnection()){
|
|
Serial.println("[HTTP] could not recconect, trying later");
|
|
continue;
|
|
}
|
|
RequestUpdate();
|
|
}
|
|
|
|
if (!status->sendNotif && !status->isFired)
|
|
{
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
continue;
|
|
}
|
|
if (status->sendNotif)
|
|
{
|
|
status->eventId = currentMillis;
|
|
}
|
|
SendAlarm();
|
|
status->sendNotif = false;
|
|
vTaskDelay(FromSeconds(3) / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
bool CheckWifiConnection()
|
|
{
|
|
|
|
if(failedAttempts >= 10)
|
|
{
|
|
Serial.println("[HTTP] Too many faliures, restarting system");
|
|
ESP.restart();
|
|
}
|
|
|
|
if(WiFi.status() == WL_CONNECTED){
|
|
return true;
|
|
}
|
|
|
|
Serial.println("[HTTP] Reconnecting to WiFi...");
|
|
WiFi.disconnect();
|
|
WiFi.reconnect();
|
|
return (WiFi.status() == WL_CONNECTED);
|
|
|
|
}
|
|
|
|
void SendAlarm()
|
|
{
|
|
String eventtype = status->sendNotif ? EVEN_TYPE_FIRED : EVENT_TYPE_EVENT_UPDATE;
|
|
String url = "http://" + ServerAddress + "/?eventId=" + String(status->eventId) + "&eventType=" + eventtype + "&eventData=t";
|
|
Serial.println("[HTTP] Contacting Alarm Server: " + url);
|
|
String response = MakeHttpCall(url);
|
|
if (response == "")
|
|
{
|
|
Serial.println("[HTTP] Alarm Server not recheable");
|
|
return;
|
|
}
|
|
|
|
if (response == AUTHORIZED_ENTRANCE)
|
|
{
|
|
// Todo Extract to Disarm method
|
|
Serial.println("[HTTP] Entrace authorized by server.");
|
|
status->isFired = false;
|
|
status->isArmed = status->doorStatus == DOOR_CLOSED;
|
|
}
|
|
}
|
|
|
|
void RequestUpdate()
|
|
{
|
|
StaticJsonDocument<200> docStatus;
|
|
docStatus["doorStatus"] = status->doorStatus;
|
|
docStatus["armed"] = status->isArmed;
|
|
docStatus["fireing"] = status->isFired;
|
|
docStatus["lastUser"] = status->userAllowed;
|
|
docStatus["lastEntrance"] = status->lastEntrance;
|
|
docStatus["millis"] = millis();
|
|
|
|
String jsonString;
|
|
serializeJson(docStatus, jsonString);
|
|
|
|
String encodedJson = standardUrlEncode(jsonString);
|
|
|
|
String url = "http://" + ServerAddress + "/?eventId=0&eventType=" + EVENT_TYPE_UPDATE + "&eventData=" + encodedJson;
|
|
|
|
// Serial.println(url);
|
|
|
|
|
|
String response = MakeHttpCall(url);
|
|
if (response == "")
|
|
{
|
|
Serial.println("[HTTP] Update Server not recheable");
|
|
return;
|
|
}
|
|
|
|
JsonDocument doc;
|
|
deserializeJson(doc, response);
|
|
|
|
DeserializationError error = deserializeJson(doc, response);
|
|
|
|
if (error)
|
|
{
|
|
Serial.print("[HTTP] Serialize error: ");
|
|
Serial.println(error.c_str());
|
|
return;
|
|
}
|
|
|
|
if (doc[FIELD_DISARM].is<bool>() && doc[FIELD_DISARM])
|
|
{
|
|
// disarm requested
|
|
// Todo Extract to Disarm method, and add to alarm.h
|
|
// same in card reader
|
|
Serial.println("[HTTP] Disarm request by server");
|
|
disarm(status);
|
|
}
|
|
|
|
// Serial.print(FIELD_ALLOWED_CARDS);
|
|
int cardsNo = doc[FIELD_ALLOWED_CARDS].size();
|
|
|
|
for (int i = 0; i < cardsNo; i++)
|
|
{
|
|
_cardReader->AddUser(doc[FIELD_ALLOWED_CARDS][i]["id"], doc[FIELD_ALLOWED_CARDS][i]["name"]);
|
|
}
|
|
}
|
|
|
|
String MakeHttpCall(String url)
|
|
{
|
|
HTTPClient http;
|
|
http.setReuse(false);
|
|
|
|
// if (!http.begin(wifiClient, url))
|
|
if (!http.begin(url))
|
|
{
|
|
failedAttempts= failedAttempts + 1;
|
|
Serial.println("[HTTP] not able to start http call");
|
|
http.end();
|
|
return "";
|
|
}
|
|
|
|
int httpCode = http.GET();
|
|
// httpCode will be negative on error
|
|
|
|
// Serial.printf("[HTTP] wifi.available: %d, connected: %d \r\n", wifiClient.available(), wifiClient.connected());
|
|
// Serial.printf("[HTTP] http.connected: %d \r\n", http.connected());
|
|
|
|
|
|
if (httpCode <= 0)
|
|
{
|
|
failedAttempts= failedAttempts + 1;
|
|
Serial.printf("[HTTP] Failed connetion - code: %d , error: %s\r\n", httpCode, http.errorToString(httpCode).c_str());
|
|
|
|
http.end();
|
|
return "";
|
|
}
|
|
|
|
// HTTP header has been send and Server response header has been handled
|
|
// Serial.printf("[HTTPS] GET Finished... code: %d\n", httpCode);
|
|
// file found at server
|
|
if (httpCode != HTTP_CODE_OK)
|
|
{
|
|
failedAttempts= failedAttempts + 1;
|
|
Serial.println("[HTTP] Server responded non 200 code");
|
|
http.end();
|
|
return "";
|
|
}
|
|
|
|
// print server response payload
|
|
failedAttempts=0;
|
|
|
|
String payload = http.getString();
|
|
http.end();
|
|
return payload;
|
|
}
|
|
|
|
String standardUrlEncode(const String &str) {
|
|
String encoded = "";
|
|
char c;
|
|
char code0;
|
|
char code1;
|
|
for (size_t i = 0; i < str.length(); i++) {
|
|
c = str.charAt(i);
|
|
// Check if character is unreserved per RFC 3986
|
|
if ((c >= 'A' && c <= 'Z') ||
|
|
(c >= 'a' && c <= 'z') ||
|
|
(c >= '0' && c <= '9') ||
|
|
c == '-' || c == '_' || c == '.' || c == '~') {
|
|
encoded += c;
|
|
} else {
|
|
encoded += '%';
|
|
code0 = (c >> 4) & 0xF;
|
|
code1 = c & 0xF;
|
|
encoded += (code0 < 10) ? char(code0 + '0') : char(code0 - 10 + 'A');
|
|
encoded += (code1 < 10) ? char(code1 + '0') : char(code1 - 10 + 'A');
|
|
}
|
|
}
|
|
return encoded;
|
|
}
|
|
|
|
public:
|
|
|
|
ServerConnector(AlarmStatus *statusObj, WiegandReader *cardReader)
|
|
{
|
|
status = statusObj;
|
|
running = false;
|
|
// wifiClient = new WiFiClient();
|
|
_cardReader = cardReader;
|
|
failedAttempts=0;
|
|
}
|
|
|
|
bool IsRunning()
|
|
{
|
|
return running;
|
|
}
|
|
|
|
void StartNotifierAsync()
|
|
{
|
|
running = true;
|
|
BaseType_t xReturned;
|
|
TaskHandle_t xHandle = NULL;
|
|
xReturned = xTaskCreate(this->asynTask, "sendNotif", 3000, (void *)this, 2, &xHandle);
|
|
failedAttempts=0;
|
|
Serial.print("Start: "); Serial.println(xReturned == pdPASS ? "Pass" : "Not pass");
|
|
Serial.print("Status: "); Serial.println(eTaskGetState(xHandle));
|
|
}
|
|
|
|
static void asynTask(void *pvParameter)
|
|
{
|
|
ServerConnector *serverInstance = (ServerConnector *)pvParameter;
|
|
serverInstance->HandTask();
|
|
}
|
|
};
|