#include "freertos/portable.h" #include "alarm.h" #include "Times.h" #include #include #include class ServerConnector { private: AlarmStatus *status; long lastUpdate; // WiFiClient wifiClient; CardReader *_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() && 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"); status->isArmed = false; status->isFired = false; status->lastEntrance = millis(); } // 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, CardReader *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(); } };