From 24c0b2c4a27ebe5c5475e93d798c5496957a0bcb Mon Sep 17 00:00:00 2001 From: AIS IoT Platform Integration <113405874+AIS-DeviceIntegration@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:01:13 +0700 Subject: [PATCH 1/3] Delete src/utils directory --- src/utils/Attribute_MQTT_core.cpp | 13 - src/utils/Attribute_MQTT_core.h | 74 - src/utils/BuiltinSensor.cpp | 233 -- src/utils/BuiltinSensor.h | 44 - src/utils/FileSystem.cpp | 164 -- src/utils/FileSystem.h | 26 - src/utils/MAGELLAN_MQTT_device_core.cpp | 2892 ----------------------- src/utils/MAGELLAN_MQTT_device_core.h | 309 --- src/utils/manageConfigOTAFile.cpp | 320 --- src/utils/manageConfigOTAFile.h | 35 - src/utils/utility.cpp | 78 - src/utils/utility.h | 17 - 12 files changed, 4205 deletions(-) delete mode 100644 src/utils/Attribute_MQTT_core.cpp delete mode 100644 src/utils/Attribute_MQTT_core.h delete mode 100644 src/utils/BuiltinSensor.cpp delete mode 100644 src/utils/BuiltinSensor.h delete mode 100644 src/utils/FileSystem.cpp delete mode 100644 src/utils/FileSystem.h delete mode 100644 src/utils/MAGELLAN_MQTT_device_core.cpp delete mode 100644 src/utils/MAGELLAN_MQTT_device_core.h delete mode 100644 src/utils/manageConfigOTAFile.cpp delete mode 100644 src/utils/manageConfigOTAFile.h delete mode 100644 src/utils/utility.cpp delete mode 100644 src/utils/utility.h diff --git a/src/utils/Attribute_MQTT_core.cpp b/src/utils/Attribute_MQTT_core.cpp deleted file mode 100644 index 620c52d..0000000 --- a/src/utils/Attribute_MQTT_core.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/* -library version: v2.6.1 -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 1 november 2022. -Released for private usage. -*/ -#include "Attribute_MQTT_core.h" - -BuiltinSensor mySensor; -utility utls; -FileSystem fileSys; -manageConfigOTAFile configOTAFile; \ No newline at end of file diff --git a/src/utils/Attribute_MQTT_core.h b/src/utils/Attribute_MQTT_core.h deleted file mode 100644 index 9b2cdf5..0000000 --- a/src/utils/Attribute_MQTT_core.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -library version: v2.6.1 -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 1 september 2022. -Released for private usage. -*/ -#ifndef ATTRIBUTE_CORE_H -#define ATTRIBUTE_CORE_H -#include -#include -#include "../PubSubClient.h" -#include "../ArduinoJson-v6.18.3.h" -#include "./FileSystem.h" -#include "./BuiltinSensor.h" -#include "./manageConfigOTAFile.h" -#define useGSMClient 0 -#define useExternalClient 1 -#include "SPIFFS.h" - -class Attribute_MQTT_core -{ -public: - static boolean isBypassAutoUpdate; - static boolean usingCheckUpdate; - static boolean checkFirmwareUptodate; - static boolean isFirmwareUptodate; - static boolean flagAutoOTA; - static unsigned long prv_cb_timeout_millis; - static unsigned int timeout_req_download_fw; - static boolean checkTimeout_request_download_fw; - static boolean remind_Event_GET_FW_infoOTA; - static boolean triggerRemainOTA; - static boolean triggerRemainSub; - static boolean remain_ota_fw_info_match; - static String valid_remain_fw_name; - static unsigned int valid_remain_fw_size; - static boolean flag_remain_ota; - static boolean ctrl_regis_key; - static boolean ctrl_regis_pta; - static boolean ctrl_regis_json; - static boolean conf_regis_key; - static boolean conf_regis_pta; - static boolean conf_regis_json; - static boolean resp_regis; - static boolean ctrl_jsonOBJ; - static boolean conf_jsonOBJ; - static boolean using_Checksum; - static boolean useAdvanceCallback; - static String ext_Token; - static String ext_EndPoint; - static int clientNetInterface; - static Client *ClientNET; - static PubSubClient *mqtt_client; //MQTT Client - static unsigned int fw_count_chunk; - static unsigned int fw_total_size; - static unsigned int chunk_size; - static unsigned int default_chunk_size; - static unsigned int totalChunk; - static unsigned int current_chunk; - static unsigned int current_size; - static size_t incomingChunkSize; - static size_t calculate_chunkSize; - static boolean inProcessOTA; - static boolean startReqDownloadOTA; - static String sensorJSON_str; - static String clientConfigJSON_str; - static boolean useBuiltInSensor; - static StaticJsonDocument<512> docClientConf; - static DynamicJsonDocument *adjDoc; - static DynamicJsonDocument *docSensor; -}; -extern Attribute_MQTT_core attr; -#endif \ No newline at end of file diff --git a/src/utils/BuiltinSensor.cpp b/src/utils/BuiltinSensor.cpp deleted file mode 100644 index 9a15587..0000000 --- a/src/utils/BuiltinSensor.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include "./BuiltinSensor.h" - -int cnt_initGPS = 0; -int timeoutInitGPS = 300; // 30 sec 300 * 100 ms = 3000 ms - -void BuiltinSensor::gps_begin() -{ - if(attr.clientNetInterface == useExternalClient) - { - while (!GSM.begin()) - { - Serial.println(F("# Try to connect GPS...")); - } - } - while (!GPS.begin()) - { - if (cnt_initGPS >= timeoutInitGPS) - { - Serial.println(F("GPS Setup timeout exist from initial GPS...")); - break; - } - Serial.println(F("GPS Setup fail")); - delay(100); - cnt_initGPS++; - } -} - -void BuiltinSensor::begin() -{ - Wire.begin(); - SHT40.begin(); - gps_begin(); -} - -info_gps BuiltinSensor::getGPS_info() -{ - info_gps buffer_infoGPS; - if (!attr.useBuiltInSensor) - { - Serial.println(F("# Please allow \"true\" useBuiltinSensor in begin function")); - buffer_infoGPS.latitude = 0.00000f; - buffer_infoGPS.longitude = 0.00000f; - buffer_infoGPS.altitude = 0.00000f; - buffer_infoGPS.speed = 0.00000f; - buffer_infoGPS.course = 0.00000f; - return buffer_infoGPS; - } - if (GPS.available()) - { - buffer_infoGPS.latitude = GPS.latitude(); - buffer_infoGPS.longitude = GPS.longitude(); - buffer_infoGPS.altitude = GPS.altitude(); - buffer_infoGPS.speed = GPS.speed(); - buffer_infoGPS.course = GPS.course(); - } - else - { - Serial.println("# GPS not ready"); - buffer_infoGPS.latitude = 0.00000f; - buffer_infoGPS.longitude = 0.00000f; - buffer_infoGPS.altitude = 0.00000f; - buffer_infoGPS.speed = 0.00000f; - buffer_infoGPS.course = 0.00000f; - } - return buffer_infoGPS; -} - -float BuiltinSensor::readLatitude() -{ - float _lat = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLatitude\" allow \"true\" useBuiltinSensor in begin function")); - return _lat; - } - else - { - _lat = getGPS_info().latitude; - } - return _lat; -} -float BuiltinSensor::readLongitude() -{ - float _lng = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLongitude\" allow \"true\" useBuiltinSensor in begin function")); - return _lng; - } - else - { - _lng = getGPS_info().longitude; - } - return _lng; -} - -String BuiltinSensor::readLocation() -{ - // String _location = "0.000000,0.000000"; - char _location[] = "0.000000,0.000000"; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLocation\" allow \"true\" useBuiltinSensor in begin function")); - return String(_location); - } - else - { - sprintf(_location, "%.4f,%.4f", readLatitude(), readLongitude()); - } - return _location; -} - -float BuiltinSensor::readSpeed() -{ - float _speed = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readSpeed\" allow \"true\" useBuiltinSensor in begin function")); - return _speed; - } - else - { - _speed = getGPS_info().speed; - } - return _speed; -} - -float BuiltinSensor::readAltitude() -{ - float _alt = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readAltitude\" allow \"true\" useBuiltinSensor in begin function")); - return _alt; - } - else - { - _alt = getGPS_info().altitude; - } - return _alt; -} - -float BuiltinSensor::readCourse() -{ - float _course = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readCourse\" allow \"true\" useBuiltinSensor in begin function")); - return _course; - } - else - { - _course = getGPS_info().course; - } - return _course; -} - -float BuiltinSensor::readTemperature() -{ - float temp = -1; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"Temperature\" allow \"true\" useBuiltinSensor in begin function")); - return temp; - } - else - { - temp = SHT40.readTemperature(); - } - return temp; -} -float BuiltinSensor::readHumidity() -{ - float humid = -1; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"Humidity\" allow \"true\" useBuiltinSensor in begin function")); - return humid; - } - else - { - humid = SHT40.readHumidity(); - } - return humid; -} - -boolean BuiltinSensor::GPSavailable() -{ - bool GPS_state = false; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] GPS not available please allow \"true\" useBuiltinSensor in begin function")); - } - else{ - GPS_state = GPS.available(); - // if(!GPS_state) - // { - // // Serial.println(F("# GPS not available please check signal or antenna GPS connect to board")); - // } - } - return GPS_state; -} - -unsigned long BuiltinSensor::getUnixTime() -{ - unsigned long _unix = (long)0000000000; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getUnixTime\" allow \"true\" useBuiltinSensor in begin function")); - return _unix; - } - else - { - if(GPS.available()) - { - tm t; - tm buff_tm = utls.convertUnix(GPS.getTime(), 0); - t.tm_mday = buff_tm.tm_mday; - t.tm_mon = buff_tm.tm_mon -1; - t.tm_year = buff_tm.tm_year; - t.tm_hour = buff_tm.tm_hour; - t.tm_min = buff_tm.tm_min; - t.tm_sec = buff_tm.tm_sec; - t.tm_isdst = -1; - _unix = mktime(&t); - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _unix; -} diff --git a/src/utils/BuiltinSensor.h b/src/utils/BuiltinSensor.h deleted file mode 100644 index 585ca73..0000000 --- a/src/utils/BuiltinSensor.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef BUILTINSENSOR_H -#define BUILTINSENSOR_H - -#include -#include -#include -#include -#include -#include "./Attribute_MQTT_core.h" -#include -#include "./utility.h" -struct info_gps{ - float latitude = 0.0000f; - float longitude = 0.0000f; - float altitude = 0.0000f; - float speed = 0.0000f; - float course = 0.0000f; -}; -class BuiltinSensor: private utility -{ - private: - const int secPerHour = 3600; - void gps_begin(); - int local_timeZone = 7; - info_gps getGPS_info(); - // tm convertUnix(unsigned long unix, int timeZone = 7); - public: - void begin(); - boolean GPSavailable(); - - float readLatitude(); - float readLongitude(); - float readAltitude(); - float readSpeed(); - float readCourse(); - float readTemperature(); - float readHumidity(); - String readLocation(); - unsigned long getUnixTime(); -}; - -extern BuiltinSensor mySensor; - -#endif \ No newline at end of file diff --git a/src/utils/FileSystem.cpp b/src/utils/FileSystem.cpp deleted file mode 100644 index 6e17d34..0000000 --- a/src/utils/FileSystem.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include -#include "./FileSystem.h" -#define DEBUG false //set to true for debug output, false for no debug output -#define DEBUG_SERIAL if(DEBUG)Serial - -void FileSystem::begin(boolean format_if_failed) -{ - if(!SPIFFS.begin(format_if_failed)) - { - DEBUG_SERIAL.println("- FileSystem Mount Failed"); - return; - } - -} -ListFileString FileSystem::listDirectory(const char* dir_name, uint8_t level, fs::FS &fs) -{ - ListFileString list; - DEBUG_SERIAL.printf("Listing directory: %s\r\n", dir_name); - - File root = fs.open(dir_name); - if(!root){ - DEBUG_SERIAL.println("− failed to open directory"); - return list; - } - if(!root.isDirectory()){ - DEBUG_SERIAL.println(" − not a directory"); - return list; - } - - File file = root.openNextFile(); - if(!file) - { - DEBUG_SERIAL.printf("- not found directory in directory: %s\r\n", dir_name); - } - while(file){ - if(file.isDirectory()){ - DEBUG_SERIAL.print(" DIR : "); - DEBUG_SERIAL.println(file.name()); - list.push_back(file.name()); - if(level){ - listDirectory(file.name(), level -1); - } - } - file = root.openNextFile(); - } - return list; -} - -ListFileString FileSystem::listFile(const char* dir_name, fs::FS &fs) -{ - ListFileString list; - DEBUG_SERIAL.printf("Listing File: %s\r\n", dir_name); - - File root = fs.open(dir_name); - if(!root){ - DEBUG_SERIAL.println("− failed to open directory"); - return list; - } - - File file = root.openNextFile(); - if(!file) - { - DEBUG_SERIAL.printf("- not found file in directory: %s\r\n", dir_name); - } - while(file){ - if(!file.isDirectory()){ - DEBUG_SERIAL.print(" FILE: "); - DEBUG_SERIAL.print(file.name()); - list.push_back(file.name()); - DEBUG_SERIAL.print("\tSIZE: "); - DEBUG_SERIAL.println(file.size()); - } - file = root.openNextFile(); - } - return list; -} - -String FileSystem::readFile(const char* path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Reading file: %s\r\n", path); - char *buffer; - File file = fs.open(path); - if(!file || file.isDirectory()) - { - DEBUG_SERIAL.println(F("- faild to open file for reading")); - return "null"; - } - DEBUG_SERIAL.println(F("- read from file:")); - while(file.available()) - { - buffer = new char[file.size() +2]; - strcpy(buffer, file.readString().c_str()); - } - file.close(); - return String(buffer); -} - -boolean FileSystem::writeFile(const char* path, const char * message, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Writing file: %s\r\n", path); - - File file = fs.open(path, FILE_WRITE); - if(!file){ - DEBUG_SERIAL.println("− failed to open file for writing"); - return false; - } - if(file.print(message)){ - DEBUG_SERIAL.println("− file written"); - file.close(); - return true; - }else { - DEBUG_SERIAL.println("− frite failed"); - return false; - } -} - -boolean FileSystem::appendFile(const char* path, const char * message, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Appending to file: %s\r\n", path); - - File file = fs.open(path, FILE_APPEND); - if(!file){ - DEBUG_SERIAL.println("− failed to open file for appending"); - return false; - } - if(file.print(message)){ - DEBUG_SERIAL.println("− message appended"); - file.close(); - return true; - } else { - DEBUG_SERIAL.println("− append failed"); - return false; - } -} - -boolean FileSystem::renameFile(const char* old_path, const char * new_path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Renaming file %s to %s\r\n", old_path, new_path); - if (fs.rename(old_path, new_path)) { - DEBUG_SERIAL.println("− file renamed"); - return true; - } else { - DEBUG_SERIAL.println("− rename failed"); - return false; - } -} - -boolean FileSystem::deleteFile(const char* path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Deleting file: %s\r\n", path); - if(fs.remove(path)){ - DEBUG_SERIAL.println("− file deleted"); - return true; - } else { - DEBUG_SERIAL.println("− delete failed"); - return false; - } -} - -boolean FileSystem::isFileExist(const char* path, fs::FS &fs) -{ - return fs.exists(path); -} - diff --git a/src/utils/FileSystem.h b/src/utils/FileSystem.h deleted file mode 100644 index 72f6469..0000000 --- a/src/utils/FileSystem.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FILESYSTEM_H -#define FILESYSTEM_H -#include -#include "SPIFFS.h" -#include "FS.h" -#include - -typedef std::vector ListFileString; - -class FileSystem -{ -private: - -public: - void begin(boolean format_if_failed = true); - ListFileString listDirectory(const char* dir_name, uint8_t level, fs::FS &fs = SPIFFS); - ListFileString listFile(const char* dir_name, fs::FS &fs = SPIFFS); - String readFile(const char* path, fs::FS &fs = SPIFFS); //limit filesize can read 60081 can't 63207 - boolean writeFile(const char* path, const char * message, fs::FS &fs = SPIFFS); - boolean appendFile(const char* path, const char * message, fs::FS &fs = SPIFFS); - boolean renameFile(const char* old_path, const char * new_path, fs::FS &fs = SPIFFS); - boolean deleteFile(const char* path, fs::FS &fs = SPIFFS); - boolean isFileExist(const char* path, fs::FS &fs = SPIFFS); -}; -extern FileSystem fileSys; -#endif \ No newline at end of file diff --git a/src/utils/MAGELLAN_MQTT_device_core.cpp b/src/utils/MAGELLAN_MQTT_device_core.cpp deleted file mode 100644 index d28ade7..0000000 --- a/src/utils/MAGELLAN_MQTT_device_core.cpp +++ /dev/null @@ -1,2892 +0,0 @@ -/* -Copyright (c) 2020, Advanced Wireless Network -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Magellan_4GBoard v2.6.1 AIS 4G Board. -support SIMCOM SIM7600E(AIS 4G Board) - -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 1 december 2022. -Released for private usage. -*/ - -#include "MAGELLAN_MQTT_device_core.h" - -StaticJsonDocument<512> intern_docJSON; -boolean Attribute_MQTT_core::isBypassAutoUpdate = false; // false = autoUpdate, true = unuse autoUpdate -boolean Attribute_MQTT_core::usingCheckUpdate = false; -boolean Attribute_MQTT_core::checkFirmwareUptodate = false; -boolean Attribute_MQTT_core::isFirmwareUptodate = false; -boolean Attribute_MQTT_core::flagAutoOTA = true; -size_t Attribute_MQTT_core::calculate_chunkSize = 0; //calculate part size from clientBuffer -size_t Attribute_MQTT_core::incomingChunkSize = 0; -unsigned int Attribute_MQTT_core::fw_total_size = 0; -unsigned int Attribute_MQTT_core::fw_count_chunk = 0; -unsigned int Attribute_MQTT_core::chunk_size = 0; -unsigned int Attribute_MQTT_core::totalChunk = 0; -unsigned int Attribute_MQTT_core::current_chunk = 0; -unsigned int Attribute_MQTT_core::current_size = 0; -unsigned int Attribute_MQTT_core::default_chunk_size = 4096; -int Attribute_MQTT_core::clientNetInterface; -Client *Attribute_MQTT_core::ClientNET = NULL; -PubSubClient *Attribute_MQTT_core::mqtt_client = NULL; //MQTT Client -boolean Attribute_MQTT_core::ctrl_regis_key = false; -boolean Attribute_MQTT_core::ctrl_regis_pta = false; -boolean Attribute_MQTT_core::ctrl_regis_json = false; -boolean Attribute_MQTT_core::conf_regis_key = false; -boolean Attribute_MQTT_core::conf_regis_pta = false; -boolean Attribute_MQTT_core::conf_regis_json = false; -boolean Attribute_MQTT_core::resp_regis = false; -boolean Attribute_MQTT_core::ctrl_jsonOBJ = false; -boolean Attribute_MQTT_core::conf_jsonOBJ = false; -boolean Attribute_MQTT_core::using_Checksum = false; -boolean Attribute_MQTT_core::useAdvanceCallback = false; -String Attribute_MQTT_core::ext_Token; -String Attribute_MQTT_core::ext_EndPoint; -boolean Attribute_MQTT_core::inProcessOTA = false; -boolean Attribute_MQTT_core::useBuiltInSensor = false; -boolean Attribute_MQTT_core::remain_ota_fw_info_match = false; -boolean Attribute_MQTT_core::flag_remain_ota = false; -String Attribute_MQTT_core::valid_remain_fw_name = ""; -unsigned int Attribute_MQTT_core::valid_remain_fw_size = 0; -boolean Attribute_MQTT_core::triggerRemainOTA = true; -boolean Attribute_MQTT_core::triggerRemainSub = true; -boolean Attribute_MQTT_core::remind_Event_GET_FW_infoOTA = false; -boolean Attribute_MQTT_core::startReqDownloadOTA = false; -boolean Attribute_MQTT_core::checkTimeout_request_download_fw = false; -unsigned int Attribute_MQTT_core::timeout_req_download_fw = 180000; -unsigned long Attribute_MQTT_core::prv_cb_timeout_millis = 0; -StaticJsonDocument<512> Attribute_MQTT_core::docClientConf; -DynamicJsonDocument *Attribute_MQTT_core::adjDoc = new DynamicJsonDocument(256); -DynamicJsonDocument *Attribute_MQTT_core::docSensor = new DynamicJsonDocument(1024); - -OTA_INFO MAGELLAN_MQTT_device_core::OTA_info; - -boolean attemp_download_1 = false; -boolean attemp_download_2 = false; - -String b2str(byte* payload, unsigned int length) // convert byte* to String -{ - char buffer_payload[length+1] = {0}; - memcpy(buffer_payload, (char*)payload, length); - return String(buffer_payload); -} - -typedef struct -{ - String registerKey; - ctrl_handleCallback ctrl_key_callback; - ctrl_Json_handleCallback ctrl_Json_callback; - ctrl_PTAhandleCallback ctrl_pta_callback; - ctrl_JsonOBJ_handleCallback ctrl_obj_callback; - - conf_handleCallback conf_key_callback; - conf_Json_handleCallback conf_json_callback; - conf_PTAhandleCallback conf_pta_callback; - conf_JsonOBJ_handleCallback conf_obj_callback; - resp_callback resp_h_callback; - - void *next; - unsigned int Event; - unsigned int RESP_Events; - -} regisAPI; - -regisAPI *_startRegis = NULL; //buffer callback -regisAPI *_startRegisPTA = NULL; //buffer callback -regisAPI *_startRegisJSON = NULL; //buffer callback -regisAPI *_startRegisConf = NULL; //buffer callback -regisAPI *_startRegisPTAConf = NULL; //buffer callback -regisAPI *_startRegisJSONConf = NULL; //buffer callback -regisAPI *_startRESP = NULL; - -regisAPI *_startOBJ_CTRL = NULL; -regisAPI *_startOBJ_CONF = NULL; - -boolean ext_useAdvanceCallback = false; - - -Centric centric; - -void (*cb_internal)(EVENTS events, char*); - -JsonObject deJson(String jsonContent) -{ - JsonObject buffer; - intern_docJSON.clear(); - if(jsonContent != NULL && jsonContent != "clear") - { - DeserializationError error = deserializeJson(intern_docJSON, jsonContent); - buffer = intern_docJSON.as(); - if(error) - Serial.println("# Error to DeserializeJson Control"); - } - return buffer; -} - -String deControl(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta ; - if( statusCode == "20000") - { - if(jsonContent.indexOf("Delta") != -1) - { - buffDelta = buffdoc["Delta"].as(); - content = buffDelta; - } - else if(jsonContent.indexOf("Sensor") != -1) - { - buffDelta = buffdoc["Sensor"].as(); - content = buffDelta; - } - } - return content; -} - -String deConfig(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta ; - if( statusCode == "20000") - { - if(jsonContent.indexOf("Config") != -1) - { - buffDelta = buffdoc["Config"].as(); - content = buffDelta; - } - } - return content; -} -/////////// Feature OTA function none member in class ////////////////////// -boolean pubClientConfig(String payload) //for external function member -{ - String topic = "api/v2/thing/"+ attr.ext_Token +"/config/persist"; - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), payload.c_str()); - bool _debug_ = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Save ClientConfig: "+ _debug_); - Serial.println("# Payload: "+ payload); - return Pub_status; -} - -boolean sub_InfoOTA() -{ - String topic = "api/v2/thing/"+ attr.ext_Token+"/firmwareinfo/resp"; - boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Subscribe Firmware Information: "+ Debug); - return Sub_status; -} - -boolean unsub_InfoOTA() -{ - String topic = "api/v2/thing/"+attr.ext_Token+"/firmwareinfo/resp"; - boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Firmware Information: "+ Debug); - return Sub_status; -} - -boolean pub_Info() -{ - String topic = "api/v2/thing/"+attr.ext_Token+"/firmwareinfo/req"; - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); - // Serial.println(topic); - String Debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Firmware Information: "+ Debug); - return Pub_status; -} - -boolean sub_DownloadOTA() -{ - String topic = "api/v2/thing/"+attr.ext_Token+"/firmwaredownload/resp/+"; - boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Subscribe Firmware Download: "+ Debug); - return Sub_status; -} - -boolean unsub_DownloadOTA() -{ - String topic = "api/v2/thing/"+attr.ext_Token+"/firmwaredownload/resp/+"; - boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Firmware Download: "+ Debug); - return Sub_status; -} - -boolean pub_Download(unsigned int fw_chunk, size_t chunk_size) -{ - if(fw_chunk == 0) - { - attr.startReqDownloadOTA = true; - } - attr.checkTimeout_request_download_fw = true; - String topic = "api/v2/thing/"+attr.ext_Token+"/firmwaredownload/req/"+String(fw_chunk)+"?filesize="+String(chunk_size); - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); - // Serial.println(topic); - String Debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("------------------------------>")); - Serial.println("# ->Request Firmware Download on chunk: "+String(fw_chunk)+" Status: "+ Debug); - Serial.println("# ->Chunk size request: "+String(chunk_size)); - return Pub_status; -} - -boolean pub_UpdateProgress(String FOTA_State, String description) -{ - delay(3000); - String topic = "api/v2/thing/"+attr.ext_Token+"/fotaupdateprogress/req/?FOTAState="+FOTA_State; - boolean Pub_status = false; - if(description.indexOf("description") != -1) - { - Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); - Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); - Serial.println(F("-------------------------------")); - Serial.println("# STATE OTA Description: "+ description); - Serial.println(F("-------------------------------")); - } - else{ - Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); - Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); - } - - String Debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Update Progress OTA state discription: \""+ FOTA_State +"\" Status: "+ Debug); - return Pub_status; -} - -boolean check_remain_fw_isMatch(String validate_fw_name,unsigned int validate_fw_size, String descriptionWhenFail) -{ - - if(MAGELLAN_MQTT_device_core::OTA_info.firmwareName == validate_fw_name && - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize == validate_fw_size) - { - Serial.println(F("# Check firmware information incoming is match OTA still working")); - return true; - } - else - { - Serial.println(F("# Check firmware information does not match after reconnect")); - // pub_UpdateProgress("FAILED","{\"description\":\""+descriptionWhenFail+"\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\""+descriptionWhenFail+"(version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - // readFS_pubClientConfig(); - - return false; - } -} - -void checkUpdate(String topic, String payload) -{ - if(topic.indexOf("/firmwareinfo/resp") != -1) - { - Serial.println(F("========================")); - Serial.println(F("# Check incoming firmware update")); - if(payload != "{}" && payload.indexOf("20000") != -1) - { - JsonObject fw_doc = deJson(payload); - String name = fw_doc["namefirmware"]; - unsigned int size = fw_doc["sizefirmware"]; - String version = fw_doc["versionfirmware"]; - String c_sum = fw_doc["checksum"]; - String al_c_sum = fw_doc["checksumAlgorithm"]; - attr.valid_remain_fw_name = name; - attr.valid_remain_fw_size = size; - if(name == "null" && size <= 0) - { - Serial.println(F("# [warning]Firmware Information is wrong or empty!")); - } - else{ - attr.checkFirmwareUptodate = configOTAFile.compareFirmwareIsUpToDate(fw_doc); - - MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; - MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; - MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; - - if(attr.checkFirmwareUptodate) - { - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = UP_TO_DATE; - } - else{ - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = OUT_OF_DATE; - } - attr.usingCheckUpdate = false; - } - } - } -} - -void save_fw_info(String topic, String payload) -{ - // Serial.println("-save_fw_info: "+payload); - if(topic.indexOf("/firmwareinfo/resp") != -1) - { - Serial.println(F("=======================")); - Serial.println(F("# Detect incoming Firmware Information")); - if(payload != "{}" && payload.indexOf("20000") != -1) - { - JsonObject fw_doc = deJson(payload); - String name = fw_doc["namefirmware"]; - unsigned int size = fw_doc["sizefirmware"]; - String version = fw_doc["versionfirmware"]; - String c_sum = fw_doc["checksum"]; - String al_c_sum = fw_doc["checksumAlgorithm"]; - attr.valid_remain_fw_name = name; - attr.valid_remain_fw_size = size; - if(name == "null" && size <= 0) - { - Serial.println(F("# [warning]Firmware Information is wrong or empty!")); - } - else // validate data pass - { - if((attr.inProcessOTA) && (attr.flag_remain_ota)) // inprocess but remain connect with broker - { - attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, - attr.valid_remain_fw_size, "firmware information not match after reconnect"); - - attr.flag_remain_ota = false; - Serial.println(F("=======================")); - Serial.println(F("# Validate from reconnect Firmware OTA Information #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("=======================")); - if(!attr.remain_ota_fw_info_match) - { - Serial.println(F("# [ERROR] Device must restart because firmware change #")); - Serial.println(F("# firmware not match validate OTA information after reconnect")); - delay(5000); - ESP.restart(); - } - else - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - } - else if((attr.inProcessOTA) && (!attr.triggerRemainOTA)) // inprocess get info fw - { - attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, - attr.valid_remain_fw_size, "user change firmware version while device in OTA process "); - if(!attr.remain_ota_fw_info_match) - { - Serial.println(F("=======================")); - Serial.println(F("# Firmware OTA Information Incoming While inProcessOTA #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("# [ERROR] Device must restart because firmware change #")); - // pub_UpdateProgress("FAILED","{\"description\":\"user change firmware version while device in process OTA\"}"); - Serial.println(F("=======================")); - delay(5000); - ESP.restart(); - } - } - - if(!attr.inProcessOTA) // first get info and save to variable - { - attr.isFirmwareUptodate = configOTAFile.compareFirmwareOTA(fw_doc); - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = ((attr.isFirmwareUptodate == true)? UP_TO_DATE : OUT_OF_DATE); - // MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; - MAGELLAN_MQTT_device_core::OTA_info.firmwareName = configOTAFile.readSpacificFromConfFile("namefirmware"); - // MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; - size_t buffReadSizefirmware = configOTAFile.readSpacificFromConfFile("sizefirmware").toInt(); - attr.fw_total_size = buffReadSizefirmware; - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = buffReadSizefirmware; - // MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; - MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = configOTAFile.readSpacificFromConfFile("versionfirmware"); - // MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksum = configOTAFile.readSpacificFromConfFile("checksum"); - // MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = configOTAFile.readSpacificFromConfFile("checksumAlgorithm"); - - unsigned int b_cal_chunk_todo = (attr.fw_total_size / attr.chunk_size) +1; - // MAGELLAN_MQTT_device_core::OTA_info.totalChunk = b_cal_chunk_todo; - attr.totalChunk = b_cal_chunk_todo; - - if(!attr.isFirmwareUptodate) - { - Serial.println("# Estimate OTA toltal request chunk : "+String(attr.totalChunk)); - pub_UpdateProgress("INITIALIZE","{\"description\":\"Initialize firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ - " size: "+ String(attr.fw_total_size)+"\"}"); - MAGELLAN_MQTT_device_core::OTA_info.isReadyOTA = true; - Serial.println(F("========================================")); - Serial.println(F("# Firmware OTA information available #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("========================================")); - - // save Client config when firmware change and file ota config change - // readFS_pubClientConfig(); - - attr.remind_Event_GET_FW_infoOTA = false; - } - } - } - } - else - { - Serial.println(F("# Fail to get firmware Information or you don't have firmware OTA")); - Serial.println("# Detail: "+payload); - } - } -} - - -String ERORRdescriptionUpdate() -{ - switch (Update.getError()) - { - case 0: - return "UPDATE_ERROR_OK"; - break; - case 1: - return "UPDATE_ERROR_WRITE"; - break; - case 2: - return "UPDATE_ERROR_ERASE"; - break; - case 3: - return "UPDATE_ERROR_READ"; - break; - case 4: - return "UPDATE_ERROR_SPACE"; - break; - case 5: - return "UPDATE_ERROR_SIZE"; - break; - case 6: - return "UPDATE_ERROR_STREAM"; - break; - case 7: - return "UPDATE_ERROR_MD5"; - break; - case 8: - return "UPDATE_ERROR_MAGIC_BYTE"; - break; - case 9: - return "UPDATE_ERROR_ACTIVATE{firmware is mismatch this board}"; - break; - case 10: - return "UPDATE_ERROR_NO_PARTITION"; - break; - case 11: - return "UPDATE_ERROR_BAD_ARGUMENT"; - break; - case 12: - return "UPDATE_ERROR_ABORT"; - break; - default: - return "ERROR_UNKNOWN"; - break; - } -} - -void validate_lostOTA_Data_incoming() -{ - if(attr.current_chunk+1 < attr.totalChunk) - { - if(attr.incomingChunkSize < attr.chunk_size) - { - Serial.println(F("# [Warning]Lost some data while in process OTA")); - Serial.println(F("# [Warning]Device must restart")); - // pub_UpdateProgress("FAILED","{\"description\":\"Data incoming lost or incorrect\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\"Data incoming lost or incorrect (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - delay(5000); - ESP.restart(); - } - } -} - -void updateFirmware(uint8_t *data, size_t len) -{ - Update.write(data, len); - attr.current_size += len; - attr.incomingChunkSize = (int)len; - Serial.println("# <-Incoming chunk size: "+String(attr.incomingChunkSize)); - unsigned int calc_percent = map(attr.current_size, 0, attr.fw_total_size, 0, 100); - Serial.println("# <-Current firmware size: "+ String(attr.current_size)+"/"+String(attr.fw_total_size)+ " => ["+String(calc_percent)+" %]"); - validate_lostOTA_Data_incoming(); - if (attr.current_size != attr.fw_total_size) - { - return; - } - - if(Update.end(true)) - { - // pub_UpdateProgress("DOWNLOADED","{\"description\":\"Download firmware name: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareName)+ - // " size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)+"\"}"); - pub_UpdateProgress("DOWNLOADED",""); - if(attr.using_Checksum) - { - // pub_UpdateProgress("VERIFIED","{\"description\":\"verify checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum+"\"}"); - pub_UpdateProgress("VERIFIED",""); - } - Serial.println(F("-------------------------------")); - Serial.println(F("# OTA done!")); - if (Update.isFinished()) - { - // pub_UpdateProgress("UPDATED","{\"description\":\"firmware name: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareName)+" size: " - // +String(attr.fw_total_size)+" version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - // pub_UpdateProgress("UPDATED","{\"description\":\""+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion)+"\"}"); - pub_UpdateProgress("UPDATED", ""); - Serial.println(F("# Update successfully completed. Rebooting.")); - configOTAFile.saveSuccessOrFail("done"); - - String readfileConfig = configOTAFile.readConfigFileOTA(); - configOTAFile.saveLastedOTA(readfileConfig); - - String fw_infoInFIleSys; - JsonObject fw_last = configOTAFile.readObjectLastedOTA(); - int bufferFW_size = fw_last["sizefirmware"]; - - fw_last.remove("namefirmware"); - fw_last.remove("sizefirmware"); - fw_last.remove("checksumAlgorithm"); - String bufferFW_v = fw_last["versionfirmware"]; - fw_last["firmwareVersion"] = bufferFW_v; - fw_last.remove("versionfirmware"); - serializeJson(fw_last, fw_infoInFIleSys); - - if(fw_infoInFIleSys.indexOf("null") == -1) - { - pubClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config - { - pubClientConfig(fw_infoInFIleSys); - } - - else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) - { - pubClientConfig(fw_infoInFIleSys); - } - - // Serial.println("#Debug: "+ configOTAFile.readConfigFileOTA()); - Serial.println(F("# Safety mode GSM shutdown!")); - GSM.shutdown(); - delay(10000); - ESP.restart(); - } - else - { - // pub_UpdateProgress("FAILED","{\"description\":\"something_went_wrong\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\"something_went_wrong (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - - Serial.println(F("# Update not finished? Something went wrong!")); - configOTAFile.saveSuccessOrFail("fail"); - - // readFS_pubClientConfig(); - } - } - else - { - String error_des = ERORRdescriptionUpdate(); - Serial.println("# OTA Fail Error Occurred. Error #: " + error_des+ " # Error Enum {"+String(Update.getError())+"}"); - // pub_UpdateProgress("FAILED","{\"description\":\""+ error_des +"\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\""+ error_des +" (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - // readFS_pubClientConfig(); - } - delay(5000); - ESP.restart(); -} - -void hook_FW_download(String topic, uint8_t* payload, unsigned int length) -{ - // Serial.println("Debug in HOOK topic: "+String(topic)); - // Serial.println("Debug in HOOK length: "+String(length)); - if(topic.indexOf("/firmwaredownload/resp/") != -1) - { - int index = topic.indexOf("/resp/"); - String crrnt_part = topic.substring(index+6); //crrnt_part is part start from index 0 - attr.current_chunk = crrnt_part.toInt(); - // MAGELLAN_MQTT_device_core::OTA_info.currentChunk = attr.current_chunk+1; - Serial.println(F("<--------------------------------")); - Serial.println("# <-Firmware current chunk: "+ String(attr.current_chunk+1)+"/"+ String(attr.totalChunk)); - if(length > 0 && (attr.fw_count_chunk <= attr.totalChunk)) - { - attr.checkTimeout_request_download_fw = false; - attr.prv_cb_timeout_millis = millis(); - updateFirmware(payload, length); - attr.fw_count_chunk++; - attemp_download_1 = false; - attemp_download_2 = false; - - pub_Download(attr.fw_count_chunk, attr.chunk_size); - - if(!attr.inProcessOTA) - { - // pub_UpdateProgress("DOWNLOADING","{\"description\":\"Downloading firmware name: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareName)+ - // " size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)+"\"}"); - pub_UpdateProgress("DOWNLOADING", "{\"description\":\"downloading firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ - " size: "+ String(attr.fw_total_size)+"\"}"); - } - attr.inProcessOTA = true; - MAGELLAN_MQTT_device_core::OTA_info.inProcessOTA = attr.inProcessOTA; - } - if(attr.fw_count_chunk == attr.totalChunk) - { - if(attr.current_size != attr.fw_total_size) - { - Serial.println(F("#[Warning] Complete Request chunk but lost or incorrect DATA from OTA")); - Serial.println(F("#[Warning] Must restart board")); - // pub_UpdateProgress("FAILED","{\"description\":\"Complete Request total of chunk but lost or incorrect DATA from OTA\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\"Complete request total of chunk but lost or incorrect DATA from OTA (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - // readFS_pubClientConfig(); - - delay(3000); - ESP.restart(); - } - } - } -} - -/////////// Feature OTA function none member inclass ////////////////////// - -void msgCallback_internalHandler(char * topic, byte* payload, unsigned int length) -{ - String action = "ERROR"; - unsigned int buffEvent = ERROR; - String b_topic = String(topic); - String _payload = b2str(payload, length); - String key = "null"; //if this topic is'nt PLAINTEXT - String code = "0"; - - EVENTS intern_EVENT; - intern_EVENT.RESP = "EMPTY"; - - regisAPI *handleRegisPTA = _startRegisPTA; - regisAPI *handleRegisJSON = _startRegisJSON; - regisAPI *handleRegisJSON_CTRL_OBJ = _startOBJ_CTRL; - regisAPI *handleRegisKEY = _startRegis; - - regisAPI *handleRegisPTAConf = _startRegisPTAConf; - regisAPI *handleRegisJSONConf = _startRegisJSONConf; - regisAPI *handleRegisJSON_CONF_OBJ = _startOBJ_CONF; - regisAPI *handleRegisKEYConf = _startRegisConf; - - regisAPI *handleRESP = _startRESP; - //OTA Feature ///////////////// - if((attr.usingCheckUpdate) && (!attr.inProcessOTA)) - { - checkUpdate(b_topic, _payload); - } - else if(!attr.usingCheckUpdate && attr.flagAutoOTA) - { - save_fw_info(b_topic, _payload); - } - hook_FW_download(b_topic, payload, length); - /////////////////////////////// - char * b_payload = (char *)_payload.c_str(); //payload for advance_cb and endpoint centric - - if(b_topic.indexOf("/auth/resp/") != -1) - { - buffEvent = TOKEN; - action = "TOKEN"; - attr.ext_Token = *&_payload; - } - if(b_topic.indexOf("/delta/resp/pta") != -1) - { - int indexfound2 = String(b_topic).indexOf("="); - String keyOnTopic = b_topic.substring(indexfound2+1); - key = keyOnTopic; - buffEvent = CONTROL_PLAINTEXT; - action = "CONTROL_PLAINTEXT"; - - if((_payload == "40300" || (_payload =="40400") && (_payload.length() == 5))) - { - code = _payload; - intern_EVENT.RESP ="FAIL"; - } - else{ - code = "20000"; - intern_EVENT.RESP ="SUCCESS"; - } - - if(attr.ctrl_regis_key) - { - while (handleRegisKEY != NULL) - { - if(handleRegisKEY->registerKey == key){ - break; - } - else{ - handleRegisKEY = (regisAPI *)handleRegisKEY->next; - } - } - if(handleRegisKEY != NULL) - { - if(handleRegisKEY->registerKey == key) - { - handleRegisKEY->ctrl_key_callback(_payload); - } - } - } - if(attr.ctrl_regis_pta) - { - while (handleRegisPTA != NULL) - { - if(handleRegisPTA->Event == buffEvent){ - break; - } - else{ - handleRegisPTA = (regisAPI *)handleRegisPTA->next; - } - } - if(handleRegisPTA != NULL) - { - handleRegisPTA->ctrl_pta_callback(key, _payload); - } - } - } - - else if(b_topic.indexOf("/delta/resp") != -1) - { - buffEvent = CONTROL_JSON; - action = "CONTROL_JSON"; - - if(_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.indexOf("\":\"")+8); - intern_EVENT.RESP ="SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()+8); - intern_EVENT.RESP ="FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - - if(attr.ctrl_regis_json) - { - while (handleRegisJSON != NULL) - { - if(handleRegisJSON->Event == buffEvent){ - break; - } - else{ - handleRegisJSON = (regisAPI *)handleRegisJSON->next; - } - } - if(handleRegisJSON != NULL) - { - handleRegisJSON->ctrl_Json_callback(_payload); - } - } - - if(attr.ctrl_jsonOBJ) - { - while (handleRegisJSON_CTRL_OBJ != NULL) - { - if(handleRegisJSON_CTRL_OBJ->Event == buffEvent){ - break; - } - else{ - handleRegisJSON_CTRL_OBJ = (regisAPI *)handleRegisJSON_CTRL_OBJ->next; - } - } - if(handleRegisJSON_CTRL_OBJ != NULL) - { - // Serial.println(_payload); - String buffDocs = deControl(_payload); - // Serial.println(buffDocs); - JsonObject Docs = deJson(buffDocs); - handleRegisJSON_CTRL_OBJ->ctrl_obj_callback(Docs); - } - } - } - - if(b_topic.indexOf("/config/resp/pta/?config=") != -1) - { - int indexfound2 = String(b_topic).indexOf("="); - String keyOnTopic = b_topic.substring(indexfound2+1); - key = keyOnTopic; - buffEvent = CONFIG_PLAINTEXT; - action = "CONFIG_PLAINTEXT"; - - if((_payload == "40300" || (_payload =="40400") && (_payload.length() == 5))) - { - code = _payload; - intern_EVENT.RESP ="FAIL"; - } - else{ - code = "20000"; - intern_EVENT.RESP ="SUCCESS"; - } - - if(attr.conf_regis_key) - { - while (handleRegisKEYConf != NULL) - { - if(handleRegisKEYConf->registerKey == key){ - break; - } - else{ - handleRegisKEYConf = (regisAPI *)handleRegisKEYConf->next; - } - } - if(handleRegisKEYConf != NULL) - { - if(handleRegisKEYConf->registerKey == key) - { - handleRegisKEYConf->conf_key_callback(_payload); - } - } - } - - if(attr.conf_regis_pta) - { - while (handleRegisJSON != NULL) - { - if(handleRegisPTAConf->Event == buffEvent){ - break; - } - else{ - handleRegisPTAConf = (regisAPI *)handleRegisPTAConf->next; - } - } - if(handleRegisPTAConf != NULL) - { - handleRegisPTAConf->conf_pta_callback(key, _payload); - } - } - - } - else if(b_topic.indexOf("/config/resp") != -1) - { - buffEvent = CONFIG_JSON; - action = "CONFIG_JSON"; - - if(_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.indexOf("\":\"")+8); - intern_EVENT.RESP ="SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()+8); - intern_EVENT.RESP ="FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - - if(attr.conf_regis_json) - { - while (handleRegisJSONConf != NULL) - { - if(handleRegisJSONConf->Event == buffEvent){ - break; - } - else{ - handleRegisJSONConf = (regisAPI *)handleRegisJSONConf->next; - } - } - if(handleRegisJSONConf != NULL) - { - handleRegisJSONConf->conf_json_callback(_payload); - } - } - - if(attr.conf_jsonOBJ) - { - while (handleRegisJSON_CONF_OBJ != NULL) - { - if(handleRegisJSON_CONF_OBJ->Event == buffEvent){ - break; - } - else{ - handleRegisJSON_CONF_OBJ = (regisAPI *)handleRegisJSON_CONF_OBJ->next; - } - } - if(handleRegisJSON_CONF_OBJ != NULL) - { - // Serial.println(_payload); - String buffDocs = deConfig(_payload); - // Serial.println(buffDocs); - JsonObject Docs = deJson(buffDocs); - handleRegisJSON_CONF_OBJ->conf_obj_callback(Docs); - } - } - } - - if(b_topic.indexOf("dateTime") != -1) - { - buffEvent = UNIXTIME; - action = "UNIXTIME"; - } - if(b_topic.indexOf("/report/resp/pta/?") != -1) - { - buffEvent = RESP_REPORT_PLAINTEXT; - action = "RESP_REPORT_PLAINTEXT"; - int indexfound2 = String(b_topic).indexOf("="); - String keyOnTopic = b_topic.substring(indexfound2+1); - key = keyOnTopic; - if(_payload.indexOf("20000") != -1) - { - code = _payload; - intern_EVENT.RESP ="SUCCESS"; - } - else{ - code = _payload; - intern_EVENT.RESP ="FAIL"; - } - } - else if (b_topic.indexOf("/report/resp") != -1) - { - buffEvent = RESP_REPORT_JSON; - action = "RESP_REPORT_JSON"; - - if(_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()+8); - intern_EVENT.RESP ="SUCCESS"; - } - else - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()+8); - intern_EVENT.RESP ="FAIL"; - } - } - - if(b_topic.indexOf("/heartbeat/resp/pta") != -1) - { - buffEvent = RESP_HEARTBEAT_PLAINTEXT; - action = "RESP_HEARTBEAT_PLAINTEXT"; - - if(_payload.indexOf("20000") != -1) - { - code = _payload; - intern_EVENT.RESP ="SUCCESS"; - } - else{ - code = _payload; - intern_EVENT.RESP ="FAIL"; - } - - - } - else if(b_topic.indexOf("/heartbeat/resp") != -1) - { - buffEvent = RESP_HEARTBEAT_JSON; - action = "RESP_HEARTBEAT_JSON"; - - if(_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()-2); - intern_EVENT.RESP ="SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()-2); - intern_EVENT.RESP ="FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - } - if(b_topic.indexOf("/report/timestamp/resp") != -1) - { - buffEvent = RESP_REPORT_TIMESTAMP; - action = "RESP_REPORT_TIMESTAMP"; - if(_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()-2); - intern_EVENT.RESP ="SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"")+3, _payload.length()-2); - intern_EVENT.RESP ="FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - } - if(b_topic.indexOf("/server/destination/response") != -1) - { - buffEvent = GET_ENDPOINT; - action = "GET_ENDPOINT"; - attr.ext_EndPoint = b_payload; - } - // Serial.println("#INSIDE "); - // Serial.println(action); - // Serial.println(_payload); - // Serial.println("#INSIDE "); - - intern_EVENT.CODE = code.toInt(); - intern_EVENT.Topic = b_topic; - intern_EVENT.Payload = _payload; - intern_EVENT.PayloadLength = length; - intern_EVENT.Action = action; - intern_EVENT.Key = key; - - if(ext_useAdvanceCallback) //routing to onMessage Callback when use setMessageListener(Callback) - { - cb_internal(intern_EVENT, b_payload); - } - - if(attr.resp_regis) - { - while (handleRESP != NULL) - { - if(handleRESP->Event == buffEvent){ - break; - } - else{ - handleRESP = (regisAPI *)handleRESP->next; - } - } - // Serial.println("# IN RESP :"+ String(handleRESP->Event)); - // Serial.println("# IN RESP2 :"+ String(buffEvent)); - if(handleRESP != NULL) - { - if(handleRESP->Event == buffEvent) - { - handleRESP->resp_h_callback(intern_EVENT); - } - } - } - // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Action); - // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Payload); -} - -MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core(Client& client) -{ - prev_time = millis(); - now_time = millis(); - HB_prev_time = millis(); - HB_now_time = millis(); - - attr.clientNetInterface = useExternalClient; - Client *newClient = &client; - attr.ClientNET = *&newClient; - attr.mqtt_client = new PubSubClient(*attr.ClientNET); - this->client = *&attr.mqtt_client; -} - -MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core() -{ - prev_time = millis(); - now_time = millis(); - HB_prev_time = millis(); - HB_now_time = millis(); - - attr.clientNetInterface = useGSMClient; - this->gsm_client = new GSMClient; - attr.ClientNET= *&gsm_client; - attr.mqtt_client = new PubSubClient(*attr.ClientNET); - this->client = *&attr.mqtt_client; -} - -String MAGELLAN_MQTT_device_core::getHostName() -{ - return this->host; -} - -void MAGELLAN_MQTT_device_core::setMQTTBufferSize(uint16_t sizeBuffer) -{ - // Serial.println(F("# SetBufferSize: ")); - // Serial.println(sizeBuffer); - this->_default_bufferSize = sizeBuffer; -} - -void MAGELLAN_MQTT_device_core::setAuthMagellan(String _thingIden, String _thingSecret, String _imei) -{ - Serial.println(F("#====== Setting Magellan Authentication =======")); - if(!(CheckString_isDigit(_thingIden) && CheckString_isDigit(_thingSecret))) - { - Serial.print(F("# ERROR Can't connect to Magellan")); - Serial.print(F("# Parameter from you setting invalid \n [thingIdentify]=> ")); - Serial.print(_thingIden); - Serial.print(F(" [thingSecret]=> ")); - Serial.println(_thingSecret); - Serial.println(F("# Invalid Parameter!! Please check [thingIdentify] and [thingSecret]")); - while (true) - { - Serial.print("."); - delay(300); - this->cnt_fail++; - if(cnt_fail >= 100) //timeout Restart board 30 sec - { - ESP.restart(); - } - } - } - this->thingIden = _thingIden; - this->thingSecret = _thingSecret; - this->imei = _imei; - // Serial.println(F("#Set Auth Success")); - // Serial.println(thingIden); - // Serial.println(thingSecret); - // Serial.println(imei); -} - -void getRadio() -{ - if(attr.clientNetInterface == useGSMClient) - { - Serial.println(F("#========= Radio Quality information ==========")); - Serial.println("Signal Strength: "+String(Network.getSignalStrength())); - Serial.println(F("#==============================================")); - } -} - -void MAGELLAN_MQTT_device_core::initialBoard() -{ - delay(1000); - setAuthMagellan(GSM.getICCID(), GSM.getIMSI(), GSM.getIMEI()); - Serial.println(F("#====== Initializing Board =======")); - Serial.println("ICCID: "+String(thingIden)); - Serial.println("IMSI: "+String(thingSecret)); - Serial.println("IMEI: "+String(imei)); - Serial.println(F("#=================================")); -} - -void MAGELLAN_MQTT_device_core::getBoardInfo() -{ - Serial.println(F("#====== Board information =========")); - Serial.println("ICCID: "+String(thingIden)); - Serial.println("IMSI: "+String(thingSecret)); - Serial.println("IMEI: "+String(imei)); - getRadio(); - Serial.println(F("#=================================")); -} - -String MAGELLAN_MQTT_device_core::getICCID() -{ - return this->thingIden; -} - -String MAGELLAN_MQTT_device_core::getIMEI() -{ - return this->imei; -} - -String MAGELLAN_MQTT_device_core::getIMSI() -{ - return this->thingSecret; -} - -String MAGELLAN_MQTT_device_core::readToken() -{ - return this->token; -} - -boolean MAGELLAN_MQTT_device_core::CheckString_isDigit(String valid_payload) -{ - for(byte i = 0; i < valid_payload.length(); i++) - { - if(!isDigit(valid_payload.charAt(i))) return false; - } - return true; -} - -boolean MAGELLAN_MQTT_device_core::CheckString_isDouble(String valid_payload) -{ - char* input = (char*)valid_payload.c_str(); - char* end; - strtod(input, &end); - if(* input == '\0') - { - return false; - } - if(end == input || *end != '\0') - { - return false; - } - return true; -} - -// void MAGELLAN_MQTT_device_core::setCallback(void(callback(char*, byte*, unsigned int))) -// { -// this->client->setCallback(callback); -// } - -void MAGELLAN_MQTT_device_core::setCallback_msgHandle() -{ - this->client->setCallback(msgCallback_internalHandler); -} - -void MAGELLAN_MQTT_device_core::setMessageListener(void(* callback)(EVENTS, char*)) -{ - attr.useAdvanceCallback = true; - if(callback) - cb_internal = callback; -} - -void MAGELLAN_MQTT_device_core::reconnect() -{ - while (!isConnected()) - { - Serial.print(F("Device Disconected from Magellan...")); - checkConnection(); - if(flagToken) - { - Serial.print(F("# Remain Subscribes list\n")); - attr.triggerRemainSub = true; - - attr.triggerRemainOTA = true; - if(!attr.flagAutoOTA) - { - sub_InfoOTA(); - } - - } - } -} - -boolean MAGELLAN_MQTT_device_core::acceptEndPoint(String payload) -{ - boolean acceptStatus = false; - if(payload.length() >= 10) - { - const char* buff_payload = payload.c_str(); - JsonObject getCetric = deJson(buff_payload); - - String buf1 = getCetric["ServerDestinationInfo"]; - String buf2 = getCetric["OperationStatus"]; - // Serial.println("buf1 :"+ buf1); - if(buf2.indexOf("20000") != -1) - { - JsonObject getCetric2 = deJson(buf1); - String buff_ip = getCetric2["ServerIP"]; - String buff_domain = getCetric2["ServerDomain"]; - String buff_port = getCetric2["ServerPort"]; - centric.endPoint_DOMAIN = buff_domain; - centric.endPoint_IP = buff_ip; - centric.endPoint_PORT = buff_port; - acceptStatus = true; - Serial.println(F("## NEW ZONE AVAILABLE #######")); - Serial.println("# Centric IP >>: " + centric.endPoint_IP); - Serial.println("# Centric Domain >>: " + centric.endPoint_DOMAIN); - Serial.println("# Centric Port >>: " + String(centric.endPoint_PORT)); - Serial.println(F("#############################")); - cnt_attempt = 0; - } - else - { - Serial.println(F("# Fail to Get Endpoint form centric")); - Serial.println(F("# Please check the thing device is activated")); - Serial.print(F("# response: ")); - Serial.println(payload); - } - } - return acceptStatus; -} - - -void MAGELLAN_MQTT_device_core::acceptToken(String payload) -{ - if(payload.length() >= 36) - { - this->flagToken = true; - this->token = payload; - Serial.println("# Thingtoken: " + token); - } -} - -void MAGELLAN_MQTT_device_core::acceptToken(EVENTS event) -{ - String _payload = event.Payload; - if((event.Topic == "api/v2/thing/" + String(thingIden) + "/" + String(thingSecret) + "/auth/resp/pta") && !flagToken) - { - if(_payload.length() >= 36) - { - this->flagToken = true; - this->token = _payload; - Serial.println("# Token >> :" + token); - } - } -} - -// String MAGELLAN_MQTT_device_core::byteToString(byte* payload, unsigned int length_payload) -// { -// char buffer_payload[length_payload+1] = {0}; -// memcpy(buffer_payload, (char*)payload, length_payload); -// return String(buffer_payload); -// } - -String MAGELLAN_MQTT_device_core::byteToString(byte* payload, unsigned int length_payload) -{ - return b2str(payload, length_payload); -} - - -void MAGELLAN_MQTT_device_core::loop() -{ - this->client->loop(); - reconnect(); -} - -void MAGELLAN_MQTT_device_core::reconnectMagellan() -{ - while (!isConnected()) - { - srand( time(NULL) ); - int randnum = rand() % 10000; //generate number concat in Client id - int randnum_2 = rand() % 10000; //generate number concat in Client id - String client_idBuff = client_id +"_"+String(randnum)+"_"+String(randnum_2); - Serial.println(F("Attempting MQTT connection ...")); - this->client->setServer(this->host.c_str(), this->port); - this->client->setCallback(msgCallback_internalHandler); - Serial.println("Connecting Magellan on: "+ String(this->host) + ", Port: "+ String(this->port)); - if(this->client->connect(client_idBuff.c_str(), this->thingIden.c_str(), this->thingSecret.c_str())) - { - Serial.println("Client id: "+ client_idBuff +" is connected"); - recon_attempt = 0; - } - else - { - Serial.print(F("failed, reconnect =")); - Serial.print(this->client->state()); - Serial.println(F(" try again in 5 seconds")); - if(!flagToken) - { - Serial.println(F("# Please check the thing device is activated ")); - } - delay(5000); - recon_attempt++; - Serial.print(F("# attempt connect on :")); - Serial.println(String(recon_attempt)+ " times"); - if(recon_attempt >= MAXrecon_attempt) - { - Serial.println(" attempt to connect more than "+String(MAXrecon_attempt)+ " Restart Board"); - ESP.restart(); - } - } - } - thingRegister(); -} - -void MAGELLAN_MQTT_device_core::checkConnection() -{ - if(!isConnected()) - { - reconnectMagellan(); - } -} - - -void MAGELLAN_MQTT_device_core::magellanCentric(const char* _host, int _port) -{ - if(!isConnected()) - { - while (!isConnected()) - { - srand( time(NULL) ); - int randnum = rand() % 10000; //generate number concat in Client id - int randnum_2 = rand() % 10000; //generate number concat in Client id - String client_idBuff = client_id +"_"+String(randnum)+"_"+String(randnum_2); - Serial.println(F("#Attempting connection ...")); - this->client->setServer(_host, _port); - this->client->setCallback(msgCallback_internalHandler); - Serial.println("Connecting Magellan on: "+ String(this->host) + ", Port: "+ String(this->port)); - String thisIdenCentric = "Centric."+thingIden; - if(this->client->connect(client_idBuff.c_str(), thisIdenCentric.c_str(), this->thingSecret.c_str())) - { - Serial.println("Client id : "+ client_idBuff +" is connected"); - recon_attempt = 0; - } - - else - { - Serial.print(F("failed, reconnect =")); - Serial.print(this->client->state()); - Serial.println(F(" try again in 5 seconds")); - Serial.print(F("Count Attemp Reconnect: ")); - recon_attempt++; - Serial.println(recon_attempt); - delay(5000); - if(recon_attempt >= MAXrecon_attempt) - { - Serial.println(" attempt to connect more than: "+String(MAXrecon_attempt)+ " Restart Board"); - ESP.restart(); - } - } - } - getEndPoint(); - } -} - -void MAGELLAN_MQTT_device_core::getEndPoint() -{ - Serial.println(F("# REQUEST ENDPOINT")); - while (!flagRegisterEndPoint ) - { - String topic = "api/v2/things/"+this->thingIden+"/"+this->thingSecret+"/server/destination/response"; - this->flagRegisterEndPoint = this->client->subscribe(topic.c_str()); - Serial.println("# Register destination server: "+String(flagRegisterEndPoint)); - } - while (!flagGetEndPoint) - { - this->client->loop(); - // Serial.println("Pub"); - this->requestEndpoint(); - if(attr.ext_EndPoint.length() >= 10) - { - // Serial.println(ext_EndPoint); - flagGetEndPoint = acceptEndPoint(attr.ext_EndPoint); - } - delay(5000); - } - if(flagGetEndPoint) - { - Serial.println(F("# Disconnect from Centric")); - this->client->disconnect(); - Serial.println(F("# Connect to new zone")); - srand( time(NULL) ); - int randnum = rand() % 10000; //generate number concat in Client id - int randnum_2 = rand() % 10000; //generate number concat in Client id - String client_idBuff = client_id +"_"+String(randnum)+"_"+String(randnum_2); - this->beginCustom(client_idBuff, true, centric.endPoint_IP, (centric.endPoint_PORT).toInt(), this->_default_bufferSize); - } -} - -bool MAGELLAN_MQTT_device_core::isConnected() -{ - return this->client->connected(); -} - -void MAGELLAN_MQTT_device_core::beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] "+ String(lib_version) +" ==================="); - if(attr.clientNetInterface == useGSMClient) - { - Serial.println("# AIS 4G Board"); - while(!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if(attr.clientNetInterface == useExternalClient) - { - Serial.println("# External Client"); - } - if(builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - delay(5000); - getRadio(); - this->host = _host; - this->port = _port; - this->client_id = _client_id; - if(bufferSize > _default_OverBufferSize) - { - Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); - Serial.println(); - this->setBufferSize(_default_OverBufferSize); - attr.calculate_chunkSize = _default_bufferSize/2; - } - else - { - this->setBufferSize(bufferSize); - attr.calculate_chunkSize = bufferSize/2; - } - checkConnection(); - -} - -void MAGELLAN_MQTT_device_core::beginCentric() -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] "+ String(lib_version) +" ==================="); - if(attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while(!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if(attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - Serial.println(F("# Connect to Centric")); - delay(5000); - getRadio(); - this->host = hostCentric; - this->port = mgPort; - this->client_id = this->getICCID(); //auto_assigned Client ID with ThingIdent - setBufferSize(_default_bufferSize); - magellanCentric(); -} - -void MAGELLAN_MQTT_device_core::begin(boolean builtInSensor) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] "+ String(lib_version) +" ==================="); - if(attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while(!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if(attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - if(builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - getRadio(); - delay(5000); - String _host = _host_production; - - this->host = _host; - this->port = mgPort; - this->client_id = getICCID(); //auto_assigned Client ID with ICCID - setBufferSize(_default_bufferSize); - checkConnection(); - -} - -void MAGELLAN_MQTT_device_core::begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone, uint16_t bufferSize, boolean builtInSensor) -{ - setAuthMagellan(_thingIden, _thingSencret, _imei); - Serial.print(F("ThingIdentify: ")); - Serial.println(_thingIden); - Serial.print(F("ThingSecret: ")); - Serial.println(_thingSencret); - Serial.print(F("IMEI: ")); - Serial.println(_imei); - begin(_thingIden, builtInSensor, Zone, bufferSize); -} - -void MAGELLAN_MQTT_device_core::begin(String _client_id, boolean builtInSensor, unsigned int Zone, uint16_t bufferSize) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] "+ String(lib_version) +" ==================="); - if(attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while(!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - - else if(attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - - if(builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - getRadio(); - delay(5000); - String _host = _host_production; - switch (Zone) - { - case Production: - _host = _host_production; - break; - default: - _host = _host_production; - Serial.println(F("# OUT OF LENGTH ZONE MOVE TO Production")); - break; - } - this->host = _host; - this->port = mgPort; - this->client_id = _client_id; - if(bufferSize > _default_OverBufferSize) - { - Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); - Serial.println(); - this->setBufferSize(_default_OverBufferSize); - attr.calculate_chunkSize = _default_bufferSize/2; - } - else - { - this->setBufferSize(bufferSize); - attr.calculate_chunkSize = bufferSize/2; - } - checkConnection(); -} - -boolean MAGELLAN_MQTT_device_core::registerToken() -{ - String topic = "api/v2/thing/" + this->thingIden + "/" + this->thingSecret + "/auth/resp/pta"; - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println(F("# Register Token to magellan")); - Serial.println("# Register Token Status: "+ _debug); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::report(String payload) -{ - - String topic = "api/v2/thing/" + token + "/report/persist"; - boolean Pub_status = client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Report JSON: "+ _debug); - Serial.println("# Payload: "+ payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::report(String key, String value) -{ - String topic = "api/v2/thing/"+ token +"/report/persist/pta/?sensor="+ key; - boolean Pub_status = client->publish(topic.c_str(), value.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Report Plaintext: "+ _debug); - Serial.println("# [key]: "+ key); - Serial.println("# [value]: "+ value); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportSensor() -{ - String bufferPlayload = buildSensorJSON(*attr.docSensor); - boolean Pub_status = false; - if(bufferPlayload.indexOf("null") == -1) - { - Pub_status = report(bufferPlayload); - clearSensorBuffer(*attr.docSensor); - } - else - { - Serial.println(F("# Can't reportSensor Because Not set function \"void addSensor(key,value)\" before reportSensor")); - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::ACKControl(String key, String value) -{ - String topic = "api/v2/thing/"+ token +"/report/persist/pta/?sensor="+ key; - boolean Pub_status = this->client->publish(topic.c_str(), value.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# ACKNOWNLEDGE Control Plaintext: "+ _debug); - Serial.println("# [key]: "+ key); - Serial.println("# [value]: "+ value); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::ACKControl(String payload) -{ - String topic = "api/v2/thing/" + token + "/report/persist"; - boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# ACKNOWNLEDGE Control JSON: "+ _debug); - Serial.println("# Payload: "+ payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type) -{ - boolean Pub_status = false; - String topic_ = "api/v2/thing/"+ token +"/report/timestamp/persist"; - if(timestamp != NULL && JSONpayload != NULL) - { - String payload_ = "[{\"UNIXTS\":"+ timestamp+ ",\"Sensor\":"+ JSONpayload +"}]"; - Pub_status = this->client->publish(topic_.c_str(), payload_.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println("# Report with timestamp: "+ _debug); - Serial.println("# Payload: "+ payload_); - return Pub_status; - } - else{ - Serial.println(F("# Report with timestamp: Failure")); - Serial.println(F("# Error Empty timestamp or payload")); - - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportClientConfig(String payload) -{ - String topic = "api/v2/thing/"+ token +"/config/persist"; - boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Save ClientConfig: "+ _debug); - Serial.println("# Payload: "+ payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::requestEndpoint() -{ - boolean Pub_status = false; - if(!flagGetEndPoint) - { - if(cnt_attempt >= limit_attempt) - { - Serial.println("Device Attempt to request ENDPOINT more than "+String(limit_attempt)+" time. restart board"); - delay(1000); - ESP.restart(); - } - if(millis() - previouseMillis > 10000) - { - previouseMillis = millis(); - String topic = "api/v2/things/" + thingIden + "/" + thingSecret + "/server/destination/request"; - Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.print("# Request Endpoint: "+ _debug); - if(cnt_attempt > 0) - { - Serial.print(" Attempt >> " + String(cnt_attempt -1) + " time"); - } - Serial.println(); - cnt_attempt++; - } - } - return Pub_status; -} - - -boolean MAGELLAN_MQTT_device_core::requestToken() -{ - boolean Pub_status = false; - if(!flagToken) - { - if(cnt_attempt >= limit_attempt) - { - Serial.println("Device Attempt to request token more than "+String(limit_attempt)+" time. restart board"); - delay(1000); - ESP.restart(); - } - if(millis() - previouseMillis > 10000) - { - previouseMillis = millis(); - String topic = "api/v2/thing/" + thingIden + "/" + thingSecret + "/auth/req"; - Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - // Serial.println("topic :" + topic); - Serial.print("# Request Token: "+ _debug); - if(cnt_attempt > 0) - { - Serial.print(" Attempt >> " + String(cnt_attempt -1) + " time"); - } - Serial.println(); - cnt_attempt++; - } - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::setBufferSize(uint16_t size) -{ - Serial.println("# set BufferSize: "+String(size)); - return this->client->setBufferSize(size); -} - -boolean MAGELLAN_MQTT_device_core::heartbeat() -{ - String topic = "api/v2/thing/"+ token +"/heartbeat"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Heartbeat Trigger: "+ _debug); - return Pub_status; -} - -void MAGELLAN_MQTT_device_core::heartbeat(unsigned int triger_ms) -{ - HB_threshold_ms = triger_ms; - HB_now_time = millis(); - unsigned long different_ms = HB_now_time - HB_prev_time; - if(different_ms >= HB_threshold_ms) - { - heartbeat(); - HB_prev_time = HB_now_time; - } -} - -void MAGELLAN_MQTT_device_core::setManualToken(String _token) -{ - Serial.println(F("# SET MANUAL TOKEN =====")); - Serial.println("#Token: "+_token); - if(_token.length() >= 36) - { - token = _token; - acceptToken(token); - } -} - -boolean MAGELLAN_MQTT_device_core::reqControlJSON() -{ - - String topic = "api/v2/thing/"+ token +"/delta/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Control [Json]: "+ _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqControl(String key) -{ - String topic = "api/v2/thing/"+ token +"/delta/req/?sensor="+key; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Control Plaintext by [Key]: \""+key+"\": "+ _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqConfigJSON() -{ - String topic = "api/v2/thing/"+ token +"/config/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Config [Json]: "+ _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqConfig(String key) -{ - String topic = "api/v2/thing/"+ token +"/config/req/?config="+ key; //fact C c - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Config Plaintext [Key]: \""+ key+"\": "+ _debug); - return Pub_status; -} - -void MAGELLAN_MQTT_device_core::getControl(String key, ctrl_handleCallback ctrl_callback) -{ - attr.ctrl_regis_key = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_PLAINTEXT; - newRegis->registerKey = key; - newRegis->ctrl_key_callback = ctrl_callback; - newRegis->next = NULL; - - if (_startRegis != NULL) { - regisAPI *focusRegis = _startRegis; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegis = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getControl(ctrl_PTAhandleCallback ctrl_pta_callback) -{ - attr.ctrl_regis_pta = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_PLAINTEXT; - newRegis->ctrl_pta_callback = ctrl_pta_callback; - newRegis->next = NULL; - - if (_startRegisPTA != NULL) { - regisAPI *focusRegis = _startRegisPTA; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegisPTA = newRegis; - } -} - - -void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_Json_handleCallback ctrl_json_callback) -{ - attr.ctrl_regis_json = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_JSON; - newRegis->ctrl_Json_callback = ctrl_json_callback; - newRegis->next = NULL; - - if (_startRegisJSON != NULL) { - regisAPI *focusRegis = _startRegisJSON; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegisJSON = newRegis; - } -} - - -void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb) -{ - attr.ctrl_jsonOBJ = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_JSON; - newRegis->ctrl_obj_callback = jsonOBJ_cb; - newRegis->next = NULL; - - if (_startOBJ_CTRL != NULL) { - regisAPI *focusRegis = _startOBJ_CTRL; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startOBJ_CTRL = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfig(String key, conf_handleCallback _conf_callback) -{ - attr.conf_regis_key = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_PLAINTEXT; - newRegis->registerKey = key; - newRegis->conf_key_callback = _conf_callback; - newRegis->next = NULL; - - if (_startRegisConf != NULL) { - regisAPI *focusRegis = _startRegisConf; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegisConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfig(conf_PTAhandleCallback conf_pta_callback) -{ - attr.conf_regis_pta = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_PLAINTEXT; - newRegis->conf_pta_callback = conf_pta_callback; - newRegis->next = NULL; - - if (_startRegisPTAConf != NULL) { - regisAPI *focusRegis = _startRegisPTAConf; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegisPTAConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfigJSON(conf_Json_handleCallback conf_json_callback) -{ - attr.conf_regis_json = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_JSON; - newRegis->conf_json_callback = conf_json_callback; - newRegis->next = NULL; - - if (_startRegisJSONConf != NULL) { - regisAPI *focusRegis = _startRegisJSONConf; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRegisJSONConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb) -{ - attr.conf_jsonOBJ = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_JSON; - newRegis->conf_obj_callback = jsonOBJ_cb; - newRegis->next = NULL; - - if (_startOBJ_CONF != NULL) { - regisAPI *focusRegis = _startOBJ_CONF; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startOBJ_CONF = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getRESP(unsigned int resp_event, resp_callback resp_cb) -{ - attr.resp_regis = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = resp_event; - newRegis->resp_h_callback = resp_cb; - newRegis->next = NULL; - - if (_startRESP != NULL) { - regisAPI *focusRegis = _startRESP; - while (focusRegis->next != NULL) { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } else { - _startRESP = newRegis; - } -} - -boolean MAGELLAN_MQTT_device_core:: registerResponseReport(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/report/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/report/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/"+ token +"/report/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP Report: "+ _debug); - Serial.println("# Subscribe Response Report: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} - - -boolean MAGELLAN_MQTT_device_core:: registerResponseReportTimestamp() -{ - String topic = "api/v2/thing/"+ token +"/report/timestamp/resp"; - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP ReportTimestamp: "+ _debug); - Serial.println("# Subscribe Response ReportTimestamp: "+ _debug); - return Sub_status; -} - - -boolean MAGELLAN_MQTT_device_core:: registerResponseHeartbeat(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/heartbeat/resp/pta"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/heartbeat/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/"+ token +"/heartbeat/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP Heartbeat: "+ _debug); - Serial.println("# Subscribe Response Heartbeat: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerConfig(String key) -{ - String topic = "api/v2/thing/"+ token +"/config/resp/pta/?config="+ key; //fact C c - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - // Serial.println("# Register Server Config [Key]: \""+key+"\" Register: "+ _debug); - Serial.println("# Subscribe ServerConfig [Key]: \""+key+"\" Subscribe: "+ _debug); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerConfig(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/config/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/config/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/"+ token +"/config/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# Register Server Config: "+ _debug); - Serial.println("# Subscribe ServerConfig: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::getTimestamp() -{ - String topic = "api/v2/server/dateTime/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Get ServerTime Request: "+ _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerTimestamp(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/server/dateTime/resp/pta"; - break; - case 1: - topic = "api/v2/server/dateTime/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/server/dateTime/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - Serial.println(F("# Subscribe Timestamp magellan")); - // Serial.println(F("# RegisterTimestamp magellan")); - Serial.println("# Subscribe ServerTime: "+ _debug); - // Serial.println("# RegisterTimestamp: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerControl(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/delta/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/delta/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/"+ token +"/delta/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl: "+ _debug); - Serial.println("# Subscribe Control: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerControl(String key) -{ - String topic = "api/v2/thing/"+ token +"/delta/resp/pta/?sensor="+ key; //fact S s - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(topic); - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl [Key]: \""+key+"\" Register: "+ _debug); - Serial.println("# Subscribe Control [Key]: \""+key+"\" Subscribe: "+ _debug); - return Sub_status; -} - -void MAGELLAN_MQTT_device_core::thingRegister() -{ - while (!flagRegisterToken) - { - this->flagRegisterToken = registerToken(); - } - while (!flagToken) - { - loop(); - requestToken(); - if(attr.ext_Token.length() >= 30) - { - token = attr.ext_Token; - acceptToken(token); - } - } -} - -void MAGELLAN_MQTT_device_core::registerList(func_callback_registerList cb_regisList) -{ - if(attr.triggerRemainSub) - { - if(attr.inProcessOTA) - { - Serial.println(F("# Subscribes List is terminated when Inprocess OTA")); - } - else - { - Serial.println(F("# Subscribes List")); - cb_regisList(); - if(!attr.flagAutoOTA) - { - sub_InfoOTA(); - } - } - attr.triggerRemainSub = false; - Serial.println(F("#============================")); - } -} - -void MAGELLAN_MQTT_device_core::interval_ms(unsigned long ms, func_callback_ms cb_ms) -{ - threshold_ms = ms; - now_time = millis(); - unsigned long different_ms = now_time - prev_time; - if(different_ms >= threshold_ms) - { - prev_time = millis(); - cb_ms(); - } -} - -JsonObject MAGELLAN_MQTT_device_core::deserialJson(String jsonContent) -{ - JsonObject buffer; - if(jsonContent != NULL && jsonContent != "clear") - { - DeserializationError error = deserializeJson(docJson, jsonContent); - buffer = docJson.as(); - if(error) - Serial.println("# Error to DeserializeJson Control"); - } - return buffer; -} - -String MAGELLAN_MQTT_device_core::deserialControlJSON(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deserialJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta ; - if( statusCode == "20000") - { - if(jsonContent.indexOf("Delta") != -1) - { - buffDelta = buffdoc["Delta"].as(); - content = buffDelta; - } - else if(jsonContent.indexOf("Sensor") != -1) - { - buffDelta = buffdoc["Sensor"].as(); - content = buffDelta; - } - } - return content; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, String value, JsonDocument &ref_docs) -{ - int len = value.length(); - char * c_value = new char[len +1]; - std::copy(value.begin(), value.end(), c_value); - c_value[len] = '\0'; - ref_docs[key] = c_value; - delete[] c_value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, const char* value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, int value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, float value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, boolean value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, String value, JsonDocument &ref_docs) -{ - int len = value.length(); - char * c_value = new char[len +1]; - std::copy(value.begin(), value.end(), c_value); - c_value[len] = '\0'; - ref_docs[key] = c_value; - delete[] c_value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, const char* value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+value); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, int value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, float value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, boolean value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::remove(String key, JsonDocument &ref_docs) -{ - Serial.println("Remove [Key]: "+key); - ref_docs.remove(key); -} - -boolean MAGELLAN_MQTT_device_core::findKey(String key, JsonDocument &ref_docs) -{ - return ref_docs.containsKey(key); -} - -String MAGELLAN_MQTT_device_core::buildSensorJSON(JsonDocument &ref_docs) -{ - String bufferJsonStr; - // Serial.println("# [Build JSON Key is]: "+ String(ref_docs.size()) +" key"); - size_t mmr_usage = ref_docs.memoryUsage(); - size_t max_size = ref_docs.memoryPool().capacity(); - size_t safety_size = max_size * (0.97); - // Serial.println("Safety size: "+String(safety_size)); - if(mmr_usage >= safety_size) - { - bufferJsonStr = "null"; - Serial.println("# [Overload memory toJSONString] *Maximum Safety Memory size to use is: "+String(safety_size)); - } - else - { - serializeJson(ref_docs, bufferJsonStr); - Serial.println("# [to JSON String Key is]: "+ String(ref_docs.size()) +" key"); - } - - - Serial.println("# MemoryUsage: "+ String(mmr_usage)+"/"+String(safety_size)+" from("+String(ref_docs.memoryPool().capacity())+")"); - return bufferJsonStr; -} - -void MAGELLAN_MQTT_device_core::adjustBufferSensor(size_t sizeJSONbuffer) -{ - attr.docSensor = new DynamicJsonDocument(sizeJSONbuffer); -} - -int MAGELLAN_MQTT_device_core::readBufferSensor(JsonDocument &ref_docs) -{ - return ref_docs.memoryPool().capacity(); -} - -void MAGELLAN_MQTT_device_core::clearSensorBuffer(JsonDocument &ref_docs) -{ - Serial.println(F("# [Clear Json buffer]")); - ref_docs.clear(); - Serial.println(F("-------------------------------")); -} - -boolean MAGELLAN_MQTT_device_core::registerInfoOTA() -{ - return sub_InfoOTA(); -} - -boolean MAGELLAN_MQTT_device_core::unregisterInfoOTA() -{ - return unsub_InfoOTA(); -} - -boolean MAGELLAN_MQTT_device_core::requestFW_Info() -{ - return pub_Info(); -} - -boolean MAGELLAN_MQTT_device_core::registerDownloadOTA() -{ - return sub_DownloadOTA(); -} - -boolean MAGELLAN_MQTT_device_core::unregisterDownloadOTA() -{ - return unsub_DownloadOTA(); -} - -boolean MAGELLAN_MQTT_device_core::requestFW_Download(unsigned int fw_chunk, size_t chunk_size) -{ - return pub_Download(fw_chunk, chunk_size); -} - -boolean MAGELLAN_MQTT_device_core::updateProgressOTA(String OTA_state,String description) -{ - return pub_UpdateProgress(OTA_state, description); -} - -void MAGELLAN_MQTT_device_core::activeOTA(size_t chunk_size, boolean useChecksum) -{ - Serial.println(F("#============================")); - Serial.println(F("# Activated OTA")); - Update.begin(UPDATE_SIZE_UNKNOWN); - attr.using_Checksum = useChecksum; - String isC_sum = (attr.using_Checksum == true) ? "ENABLE":"DISABLE"; - Serial.println(F(" ")); - Serial.print(isC_sum); - Serial.println(F(" Checksum FirmwareOTA")); - // Serial.println(*attr.chunk_size); - if(chunk_size > 4096) - { - Serial.print(F("# [Warning] Chunk Size Maximun is 4096 (use Default \"")); - Serial.print(attr.default_chunk_size); - Serial.println(F("\")")); - setChunkSize(attr.default_chunk_size); - } - else{ - setChunkSize(chunk_size); - } - configOTAFile.beginFileSystem(true); - if(!configOTAFile.checkFileOTA()) - { - configOTAFile.createConfigFileOTA(); - } - - if(!configOTAFile.checkLastedOTA()) - { - configOTAFile.createLastedOTA(); - if(configOTAFile.checkFileOTA()) - { - String fw_infoInFIleSys = configOTAFile.readLastedOTA(); - } - } - else{ - String fw_infoInFIleSys; - JsonObject fw_last = configOTAFile.readObjectLastedOTA(); - int bufferFW_size = fw_last["sizefirmware"]; - - fw_last.remove("namefirmware"); - fw_last.remove("sizefirmware"); - fw_last.remove("checksumAlgorithm"); - String bufferFW_v = fw_last["versionfirmware"]; - fw_last["firmwareVersion"] = bufferFW_v; - fw_last.remove("versionfirmware"); - serializeJson(fw_last, fw_infoInFIleSys); - if(fw_infoInFIleSys.indexOf("null") == -1) - { - this->reportClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config - { - this->reportClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) - { - this->reportClientConfig(fw_infoInFIleSys); - } - } -} -void MAGELLAN_MQTT_device_core::setChecksum(String md5Checksum) -{ - Serial.println("# Set Checksum md5: "+md5Checksum+" Status:"+(Update.setMD5(md5Checksum.c_str()) == true? " Success":" Fail")); -} - -void MAGELLAN_MQTT_device_core::setChunkSize(size_t chunkSize) -{ - attr.chunk_size = chunkSize; - Serial.println("# Set Chunk size: "+String(attr.chunk_size)); -} - -void checkTimeoutReq_fw_download() -{ - if(attr.checkTimeout_request_download_fw) - { - unsigned long differentTime = millis() - attr.prv_cb_timeout_millis; - if(differentTime > 60000 && !attemp_download_1) - { - Serial.println("#Attemp resume download 1 after checktimeout 1 minute"); - pub_Download(attr.fw_count_chunk, attr.chunk_size); - attemp_download_1 = true; - } - if(differentTime > 120000 && !attemp_download_2) - { - Serial.println("#Attemp resume download 2 after checktimeout 2 minute"); - pub_Download(attr.fw_count_chunk, attr.chunk_size); - attemp_download_2 = true; - } - if(differentTime > attr.timeout_req_download_fw) - { - // pub_UpdateProgress("FAILED","{\"description\":\"Timeout from request firmware download\",\"errordescription\":\""+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+"\"}"); - pub_UpdateProgress("FAILED","{\"errordescription\":\"Timeout from request firmware download (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - // readFS_pubClientConfig(); - - Serial.println("#device must restart timeout from request firmware dowload "+String(attr.timeout_req_download_fw/60000)+" minute"); - delay(5000); - ESP.restart(); - } - // Serial.println("Counting Timeout: "+String(diferentTime/1000)); - } - else{ - attr.prv_cb_timeout_millis = millis(); - } -} - -unsigned long prv_mills_usingCheckOTA = 0; -void checkTimeoutCheckUpdate() -{ - if(attr.usingCheckUpdate) - { - unsigned long differentTime = millis() - prv_mills_usingCheckOTA; - if(differentTime > 15000) - { - attr.usingCheckUpdate = false; - } - } - else if(!attr.usingCheckUpdate) - { - prv_mills_usingCheckOTA = millis(); - } -} - -boolean remind_unsub_when_inProcessOTA = false; -unsigned long prv_mills_pubinfo = 0; -void MAGELLAN_MQTT_device_core::handleOTA(boolean OTA_after_getInfo) -{ - checkTimeoutReq_fw_download(); - checkTimeoutCheckUpdate(); - if(attr.triggerRemainOTA) - { - - Serial.println(F("# Active handleOTA")); - registerInfoOTA(); - if(attr.flagAutoOTA) - registerDownloadOTA(); - Serial.println(F("#============================")); - - if(attr.inProcessOTA) //if get fw in hook fw will auto count and request dowload fw - { - attr.flag_remain_ota = true; - attr.remain_ota_fw_info_match = false; - - if(!attr.remain_ota_fw_info_match) - { - if(millis() - prv_mills_pubinfo > 5000) - { - pub_Info(); - prv_mills_pubinfo = millis(); - } - } - else if(attr.remain_ota_fw_info_match) // remain get firmware - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - } - if(attr.startReqDownloadOTA && !attr.inProcessOTA) //if get part 0 fail but start ota still work when reconnect - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - attr.triggerRemainOTA = false; - } - if((attr.fw_total_size > 0) && !(attr.remind_Event_GET_FW_infoOTA)) - { - // Serial.println(F("=======================")); - // Serial.println(F("# Firmware OTA Information Available #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.fw_name); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.fw_totalSize)); - // Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.fw_version); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.algorithm_check_sum); - // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.check_sum); - // Serial.println(F("=======================")); - if(attr.using_Checksum && !attr.isFirmwareUptodate) - { - if(MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "md5" || MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "MD5") - setChecksum(MAGELLAN_MQTT_device_core::OTA_info.checksum); - else{ - Serial.println(F("#[Warning] Can't set checksum because algorithm checksum is not \"md5\"")); - Serial.println(F("#[Warning] But OTA Process still working without checksum ")); - attr.using_Checksum = false; - } - } - if(OTA_after_getInfo && !attr.isFirmwareUptodate) //auto request OTA after get fw information - { - pub_Download(0, attr.chunk_size); - } - attr.remind_Event_GET_FW_infoOTA = true; - } - if(attr.inProcessOTA && ! remind_unsub_when_inProcessOTA) - { - Serial.println(F("=================================================")); - Serial.println(F("# Inprocess OTA terminate other incoming message")); - Serial.println(F("# Unsubscribe unuse function")); - if(attr.ctrl_regis_key || attr.ctrl_regis_pta) - { - unregisterControl(PLAINTEXT); - } - if(attr.ctrl_jsonOBJ || attr.ctrl_regis_json) - { - unregisterControl(JSON); - } - if(attr.conf_regis_key || attr.conf_regis_pta) - { - unregisterConfig(PLAINTEXT); - } - if(attr.conf_jsonOBJ || attr.conf_regis_json) - { - unregisterConfig(JSON); - } - if(attr.resp_regis) - { - unregisterResponseHeartbeat(PLAINTEXT); - unregisterResponseHeartbeat(JSON); - unregisterResponseReport(PLAINTEXT); - unregisterResponseReport(JSON); - unregisterResponseReportTimestamp(); - unregisterTimestamp(PLAINTEXT); - unregisterTimestamp(JSON); - } - remind_unsub_when_inProcessOTA = true; - Serial.println(F("=================================================")); - } -} -////////////////// Unsub /////////// -boolean MAGELLAN_MQTT_device_core::unregisterControl(int format){ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/delta/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/delta/resp"; - break; - default: - topic = "api/v2/thing/"+ token +"/delta/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl: "+ _debug); - Serial.println("# Unsubscribe Control: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterControl(String key){ - String topic = "api/v2/thing/"+ token +"/delta/resp/pta/?sensor="+ key; //fact S s - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(topic); - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Control [Key]: \""+key+"\" Unsubscribe: "+ _debug); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterConfig(int format){ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/config/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/config/resp"; - break; - default: - topic = "api/v2/thing/"+ token +"/config/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerConfig: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterConfig(String key){ - String topic = "api/v2/thing/"+ token +"/config/resp/pta/?config="+ key; //fact C c - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerConfig [Key]: \""+key+"\" Unsubscribe: "+ _debug); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterTimestamp(int format){ - String topic; - switch (format) - { - case 0: - topic = "api/v2/server/dateTime/resp/pta"; - break; - case 1: - topic = "api/v2/server/dateTime/resp"; - break; - default: - topic = "api/v2/server/dateTime/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerTime: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterResponseReport(int format){ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/report/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/report/resp"; - break; - default: - topic = "api/v2/thing/"+ token +"/report/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response Report: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} -boolean MAGELLAN_MQTT_device_core::unregisterResponseReportTimestamp(){ - String topic = "api/v2/thing/"+ token +"/report/timestamp/resp"; - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response ReportTimestamp: "+ _debug); - return Sub_status; -} -boolean MAGELLAN_MQTT_device_core::unregisterResponseHeartbeat(int format){ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/"+ token +"/heartbeat/resp/pta"; - break; - case 1: - topic = "api/v2/thing/"+ token +"/heartbeat/resp"; - break; - default: - topic = "api/v2/thing/"+ token +"/heartbeat/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true)? "Success" : "Failure"; - String respType = (format == 0)? "Plaintext":"JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response Heartbeat: "+ _debug); - Serial.println("# Response type: "+ respType); - return Sub_status; -} -////////////////// Unsub ////////// - diff --git a/src/utils/MAGELLAN_MQTT_device_core.h b/src/utils/MAGELLAN_MQTT_device_core.h deleted file mode 100644 index 37d38ae..0000000 --- a/src/utils/MAGELLAN_MQTT_device_core.h +++ /dev/null @@ -1,309 +0,0 @@ -/* -Copyright (c) 2020, Advanced Wireless Network -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Magellan_4GBoard v2.6.1 AIS 4G Board. -support SIMCOM SIM7600E(AIS 4G Board) - -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 9 december 2022. -Released for private usage. -*/ -#ifndef MAGELLAN_MQTT_DEVICE_CORE_h -#define MAGELLAN_MQTT_DEVICE_CORE_h - -#include -#include "../PubSubClient.h" -#include "../ArduinoJson-v6.18.3.h" -#include -#include -#include -#include -#include -#include "Attribute_MQTT_core.h" -#include "BuiltinSensor.h" - -// #define Dev_version "v2.6.1" -#define lib_version "v1.1.1" - -#define PLAINTEXT 0 //Plaintext -#define JSON 1 //Json - -#define ERROR 0 -#define TOKEN 1 -#define CONTROL_JSON 2 -#define CONTROL_PLAINTEXT 3 -#define CONFIG_JSON 4 -#define CONFIG_PLAINTEXT 5 -#define UNIXTIME 6 -#define UTCTIME 7 -#define RESP_REPORT_JSON 8 -#define RESP_REPORT_PLAINTEXT 9 -#define RESP_REPORT_TIMESTAMP 10 -#define RESP_HEARTBEAT_JSON 11 -#define RESP_HEARTBEAT_PLAINTEXT 12 -#define GET_ENDPOINT 13 - -#define mgPort 1883 -#define hostCentric "centric-magellan.ais.co.th" -//for define mode Timestamp -#define SET_UNIXTS 0 -#define SET_UTC 1 - -#define Production 1 -#define Staging 2 -#define IoT 3 - -#define _host_production "magellan.ais.co.th" - -#define defaultBuffer 1024 -#define defaultOTABuffer 8192 -#define _default_OverBufferSize 8192 - -#define UNKNOWN -1 -#define OUT_OF_DATE 0 -#define UP_TO_DATE 1 -typedef struct { - // unsigned int Type; - String Topic; - String Key; - String Action; - String Payload; - String RESP; - unsigned int CODE; - unsigned int PayloadLength; -}EVENTS; - -typedef struct { - String endPoint_IP; - String endPoint_DOMAIN; - String endPoint_PORT; -}Centric; - -typedef struct { - boolean isReadyOTA = false; - int firmwareIsUpToDate = -1; - boolean inProcessOTA = false; - unsigned int firmwareTotalSize = 0; - String firmwareName = "UNKNOWN"; - String firmwareVersion = "UNKNOWN"; - String checksum = "UNKNOWN"; - String checksumAlgorithm = "UNKNOWN"; -}OTA_INFO; - -typedef std::function ctrl_handleCallback; -typedef std::function ctrl_Json_handleCallback; -typedef std::function ctrl_JsonOBJ_handleCallback; -typedef std::function conf_handleCallback; -typedef std::function conf_Json_handleCallback; -typedef std::function conf_JsonOBJ_handleCallback; - -typedef std::function ctrl_PTAhandleCallback; -typedef std::function conf_PTAhandleCallback; -typedef std::function resp_callback; -// typedef std::function resp_callback; - -typedef std::function func_callback_registerList; - - - -//Client Internet interface connection -#define useGSMClient 0 -#define useExternalClient 1 - -// #define subRemainCallback std::function subRemain - -typedef std::function func_callback_ms; - -class MAGELLAN_MQTT_device_core -{ -public: - MAGELLAN_MQTT_device_core(Client& client); // for customize client internet interface - MAGELLAN_MQTT_device_core(); // for GSM client internet interface - boolean flagToken = false; - String client_id; - void setAuthMagellan(String _thingIden, String _thingSecret, String _imei = "none"); // add on - void begin(boolean builtInSensor = false); - void begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone = Production, uint16_t bufferSize = 1024, boolean builtInSensor = true); - void beginCentric(); - void beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize); // - void begin(String _client_id, boolean buildInSensor = true, unsigned int Zone = Production, uint16_t bufferSize = 1024); // - String getHostName(); // - void getBoardInfo(); // - String getIMEI(); - String getIMSI(); - String getICCID(); - String readToken(); - - void magellanCentric(const char* _host = hostCentric, int _port = mgPort); //add on - boolean reportSensor(); - boolean report(String payload); // - boolean report(String key, String value); // - boolean registerResponseReport(int format = JSON); - boolean registerResponseReportTimestamp(); - boolean registerResponseHeartbeat(int format = JSON); - boolean reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type = SET_UNIXTS); // Json Payload - boolean heartbeat(); // - void heartbeat(unsigned int triger_ms); // - boolean registerConfig(int format = JSON); // PTA and JSON - boolean registerConfig(String key);// - boolean registerControl(int format = JSON); // - boolean registerControl(String key); // - boolean registerTimestamp(int format = JSON); // - boolean reqControl(String key); - boolean reqControlJSON(); - - ////// unsub //////////////// - boolean unregisterControl(int format = JSON); // - boolean unregisterControl(String key); // - boolean unregisterConfig(int format = JSON); // PTA and JSON - boolean unregisterConfig(String key); // - boolean unregisterTimestamp(int format = JSON); // - boolean unregisterResponseReport(int format = JSON); - boolean unregisterResponseReportTimestamp(); - boolean unregisterResponseHeartbeat(int format = JSON); - ////// unsub //////////////// - - void getControl(String key, ctrl_handleCallback ctrl_callback); - void getControl(ctrl_PTAhandleCallback ctrl_pta_callback); - void getControlJSON(ctrl_Json_handleCallback ctrl_json_callback); - void getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb); - - void getConfig(String key, conf_handleCallback _conf_callback); - void getConfig(conf_PTAhandleCallback conf_pta_callback); - void getConfigJSON(conf_Json_handleCallback conf_json_callback); - void getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb); - void getRESP(unsigned int resp_event ,resp_callback resp_cb); - - boolean getTimestamp(); // - boolean reqConfigJSON(); // - boolean reqConfig(String key); // - boolean reportClientConfig(String payload); // - boolean isConnected(); - void loop(); // - void setMessageListener(void(*callback)(EVENTS, char*)); - - void setManualToken(String _token); - void acceptToken(EVENTS event); - - boolean ACKControl(String key, String value); - boolean ACKControl(String payload); - - void interval_ms(unsigned long ms, func_callback_ms cb_ms); - void registerList(func_callback_registerList cb_regisList); - - // interface MAGELLANJSON - StaticJsonDocument<256> docJson; - - String deserialControlJSON(String jsonContent); - JsonObject deserialJson(String jsonContent); - void addSensor(String key, String value, JsonDocument &ref_docs); - void addSensor(String key, const char* value, JsonDocument &ref_docs); - void addSensor(String key, int value, JsonDocument &ref_docs); - void addSensor(String key, float value, JsonDocument &ref_docs); - void addSensor(String key, boolean value, JsonDocument &ref_docs); - void updateSensor(String key, String value, JsonDocument &ref_docs); - void updateSensor(String key, const char* value, JsonDocument &ref_docs); - void updateSensor(String key, int value, JsonDocument &ref_docs); - void updateSensor(String key, float value, JsonDocument &ref_docs); - void updateSensor(String key, boolean value, JsonDocument &ref_docs); - String buildSensorJSON(JsonDocument &ref_docs); - void remove(String key, JsonDocument &ref_docs); - boolean findKey(String key, JsonDocument &ref_docs); - void adjustBufferSensor(size_t sizeJSONbuffer); - int readBufferSensor(JsonDocument &ref_docs); - void clearSensorBuffer(JsonDocument &ref_docs); - - void setMQTTBufferSize(uint16_t size); - boolean CheckString_isDigit(String valid_payload); // - boolean CheckString_isDouble(String valid_payload); // - - //OTA Feature// - void activeOTA(size_t part_size, boolean useChecksum = true); - void handleOTA(boolean OTA_after_getInfo = true); - boolean registerInfoOTA(); - boolean registerDownloadOTA(); - boolean unregisterInfoOTA(); - boolean unregisterDownloadOTA(); - boolean updateProgressOTA(String OTA_state, String description); - boolean requestFW_Info(); - boolean requestFW_Download(unsigned int fw_part, size_t part_size); - void setChecksum(String md5Checksum); - void setChunkSize(size_t Chunksize); - static OTA_INFO OTA_info; - /////////////// - -private: - int _default_bufferSize = 1024; - // BuiltinSensor mySensor; - void reconnect(); //add on - void checkConnection(); // - void getEndPoint(); //get end point from centric - boolean acceptEndPoint(String payload); //get end point from centric - void thingRegister(); // - void acceptToken(String payload); // - boolean setBufferSize(uint16_t size); // default 256 (uplink 128 + downlink 128) - String byteToString(byte* payload, unsigned int length_payload); // convert byte* to string - void setCallback_msgHandle(); - void initialBoard(); // - unsigned long previouseMillis = 0; // - boolean flagRegisterEndPoint= false; // - boolean flagGetEndPoint = false; // - boolean flagRegisterToken = false; // - boolean flagReportRetry = false; - boolean flagAuthMagellan = false; - - boolean registerToken(); // - boolean requestToken(); // - boolean requestEndpoint(); // - void reconnectMagellan(); // - int limit_attempt = 11; // 11 -> for atempt 10 request token - int cnt_attempt = 0; // - int recon_attempt = 0; - int MAXrecon_attempt = 10; - unsigned long prev_time; - unsigned long now_time; - unsigned long threshold_ms; - - unsigned long HB_prev_time; - unsigned long HB_now_time; - unsigned long HB_threshold_ms; - - unsigned long cnt_fail = 0; - - String host; - String thingIden; - String thingSecret; - String imei; - String token; - String _debug; - int port; - // boolean useBuiltInSensor = true; -protected: - PubSubClient *client = NULL; - GSMClient *gsm_client = NULL; -}; - -#endif - - diff --git a/src/utils/manageConfigOTAFile.cpp b/src/utils/manageConfigOTAFile.cpp deleted file mode 100644 index 5dfbb6e..0000000 --- a/src/utils/manageConfigOTAFile.cpp +++ /dev/null @@ -1,320 +0,0 @@ -//lasted update 15/11/2022 - check lasted too if state configfile fail, before decide to ota must compare lasted with incoming fw info too -#include "manageConfigOTAFile.h" - -void manageConfigOTAFile::beginFileSystem(boolean formatIfFail) -{ - fileSys.begin(formatIfFail); -} - -boolean manageConfigOTAFile::checkFileOTA() -{ - return fileSys.isFileExist(configOTAFilePath); -} - -boolean manageConfigOTAFile::checkLastedOTA() -{ - return fileSys.isFileExist(lastedOTAPath); -} - - -boolean manageConfigOTAFile::createConfigFileOTA() -{ - String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\",\"status\":\"null\"}"; - return fileSys.writeFile(configOTAFilePath, init_config.c_str()); -} - -boolean manageConfigOTAFile::createLastedOTA() -{ - String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\"}"; - return fileSys.writeFile(lastedOTAPath, init_config.c_str()); -} - -String manageConfigOTAFile::readConfigFileOTA() -{ - return fileSys.readFile(configOTAFilePath); -} - -String manageConfigOTAFile::readLastedOTA() -{ - return fileSys.readFile(lastedOTAPath); -} - -JsonObject manageConfigOTAFile::readObjectConfigFileOTA() -{ - String buffReadConfigOTA = readConfigFileOTA(); - JsonObject buffer; - OTAdoc.clear(); - if(buffReadConfigOTA != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); - buffer = OTAdoc.as(); - if(error) - Serial.println("# Error to DeserializeJson readConfigFileOTA"); - } - return buffer; -} -JsonObject manageConfigOTAFile::readObjectLastedOTA() -{ - String buffReadConfigOTA = readLastedOTA(); - JsonObject buffer; - OTAdoc.clear(); - if(buffReadConfigOTA != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); - buffer = OTAdoc.as(); - if(error) - Serial.println("# Error to DeserializeJson readLastedOTA"); - } - return buffer; -} - -String manageConfigOTAFile::readSpacificFromConfFile(String readKey) -{ - String result = readObjectConfigFileOTA()[readKey.c_str()]; - return result; -} - -boolean manageConfigOTAFile::saveProfileOTA(JsonObject dataOTA, String stateOTA) -{ - OTAdoc.clear(); - if(stateOTA != NULL && dataOTA.size() > 0) - { - OTAdoc = dataOTA; - OTAdoc.remove("Code"); - OTAdoc["status"] = stateOTA.c_str(); - - String contentToWrite; - serializeJson(OTAdoc, contentToWrite); - - bool saveFile = fileSys.writeFile(configOTAFilePath, contentToWrite.c_str()); - if(saveFile) - { - // Serial.println("# New Information OTA: "+contentToWrite); - Serial.println(F("# Save firmware information success!")); - } - return saveFile; - } - else - { - return false; - } -} - -boolean manageConfigOTAFile::saveLastedOTA(String lastedDataOTA) -{ - bool saveFile = false; - JsonObject buffer; - OTAdoc.clear(); - if(lastedDataOTA.c_str() != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, lastedDataOTA.c_str()); - buffer = OTAdoc.as(); - if(error) - { - Serial.println("# Error to DeserializeJson saveLastedOTA"); - return false; - } - else - { - buffer.remove("status"); - String contentLasted; - serializeJson(buffer, contentLasted); - - saveFile = fileSys.writeFile(lastedOTAPath, contentLasted.c_str()); - if(saveFile) - { - // Serial.println("# New Information OTA: "+contentToWrite); - // Serial.println("# saveLastedOTA: "+contentLasted); - Serial.println(F("# Save lastedOTA success!")); - } - return saveFile; - } - } - return saveFile; -} - -boolean manageConfigOTAFile::saveSuccessOrFail(String stateOTA) -{ - JsonObject bufferProfile = readObjectConfigFileOTA(); - - StaticJsonDocument<512> docsBuffer = bufferProfile; - bufferProfile.remove("Code"); - docsBuffer["status"] = stateOTA.c_str(); - String ProfileUpdate; - serializeJson(docsBuffer, ProfileUpdate); - return fileSys.writeFile(configOTAFilePath, ProfileUpdate.c_str()); -} - -boolean manageConfigOTAFile::compareFirmwareOTA(JsonObject dataOTA) -{ - JsonObject bufferProfile = readObjectConfigFileOTA(); - String status = readSpacificFromConfFile("status"); - - String readFW_name = bufferProfile["namefirmware"]; - String incomingFW_name = dataOTA["namefirmware"]; - - size_t readFW_size = bufferProfile["sizefirmware"]; - size_t incomingFW_size = dataOTA["sizefirmware"]; - - String readFW_checksum = bufferProfile["checksum"]; - String incomingFW_checksum = dataOTA["checksum"]; - - String readFW_version = bufferProfile["versionfirmware"]; - String incomingFW_version = dataOTA["versionfirmware"]; - - String readFW_csAlg = bufferProfile["checksumAlgorithm"]; - String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; - - String readFW_cs = bufferProfile["checksum"]; - String incomingFW_cs = dataOTA["checksum"]; - - // Lasted check - JsonObject buffLasted = readObjectLastedOTA(); - - String LastedFW_name = buffLasted["namefirmware"]; - size_t LastedFW_Size = buffLasted["sizefirmware"]; - String LastedFW_checksum = buffLasted["checksum"]; - // Lasted check - if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") - { - Serial.println(F("")); - Serial.println(F("# Device is unknow version in file system")); - Serial.println(F("# Save firmware information")); - Serial.println("# ======== Information OTA ========"); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - // Serial.println("# firmware checksumAlgorithm: "+ incomingFW_csAlg); - Serial.println("# firmware checksum: "+ incomingFW_checksum); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && - readFW_checksum == incomingFW_checksum) - { - if(status == "done") - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# Firmware device version: "+ incomingFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else if(status == "fail" && !(LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) - { - Serial.println(F("")); - Serial.println(F("#[OTA Failed] Try to OTA firmware again")); - Serial.println(F("# ======== Information OTA ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - else{ - Serial.println(F("")); - Serial.println(F("# Keep going to OTA firmware again")); - Serial.println(F("# ======== Information OTA ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - Serial.println(F("")); - return false; //false mean firmware not match - } - } - else{ // fw not match incoming != file => new version - if(status == "done") - { - Serial.println(F("")); - Serial.println(F("# Device have new version")); - Serial.println(F("# ======== Information OTA change ========")); - // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); - // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - else if(status != "done" && (LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# Firmware device version: "+ incomingFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else{ - Serial.println(F("")); - Serial.println("# Previous version OTA does not success status is: \""+ status +"\"# but have new version"); - Serial.println(F("# ======== Information OTA change ========")); - // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); - // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - } -} - -boolean manageConfigOTAFile::compareFirmwareIsUpToDate(JsonObject dataOTA) -{ - JsonObject buffLastedOTA = readObjectLastedOTA(); - - String readFW_name = buffLastedOTA["namefirmware"]; - String incomingFW_name = dataOTA["namefirmware"]; - - size_t readFW_size = buffLastedOTA["sizefirmware"]; - size_t incomingFW_size = dataOTA["sizefirmware"]; - - String readFW_checksum = buffLastedOTA["checksum"]; - String incomingFW_checksum = dataOTA["checksum"]; - - String readFW_version = buffLastedOTA["versionfirmware"]; - String incomingFW_version = dataOTA["versionfirmware"]; - - String readFW_csAlg = buffLastedOTA["checksumAlgorithm"]; - String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; - - String readFW_cs = buffLastedOTA["checksum"]; - String incomingFW_cs = dataOTA["checksum"]; - - if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is out of date ========")); - Serial.println(F("# ======== Device unknown version ========")); - Serial.println("# New version is available: "+ incomingFW_version); - Serial.println(F("# ========================================")); - Serial.println(F("")); - return false; - } - if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && - readFW_checksum == incomingFW_checksum) - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - Serial.println("# Firmware device version: "+ readFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else{ - Serial.println(F("")); - Serial.println(F("# ======== Firmware is out of date ========")); - Serial.println(F("# ======== NEW firmware available ========")); - Serial.println("# New version is available: "+ incomingFW_version); - Serial.println("# Firmware device version: "+ readFW_version); - Serial.println(F("# ========================================")); - Serial.println(F("")); - return false; - } -} \ No newline at end of file diff --git a/src/utils/manageConfigOTAFile.h b/src/utils/manageConfigOTAFile.h deleted file mode 100644 index bae8fac..0000000 --- a/src/utils/manageConfigOTAFile.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MANAGECONFIGOTAFILE_H -#define MANAGECONFIGOTAFILE_H -#include -#include "SPIFFS.h" -#include "FS.h" -#include -#include "FileSystem.h" -#include "../ArduinoJson-v6.18.3.h" -// typedef std::vector ListFileString; - -class manageConfigOTAFile -{ -private: - const char* configOTAFilePath = "/configOTAFile.json"; - const char* lastedOTAPath = "/lastedOTAFile.json"; - StaticJsonDocument<512> OTAdoc; -public: - void beginFileSystem(boolean formatIfFail = true); - boolean checkFileOTA(); - boolean checkLastedOTA(); - boolean createConfigFileOTA(); - boolean createLastedOTA(); - String readConfigFileOTA(); - String readLastedOTA(); - JsonObject readObjectConfigFileOTA(); - JsonObject readObjectLastedOTA(); - String readSpacificFromConfFile(String readKey); - boolean saveProfileOTA(JsonObject dataOTA, String stateOTA); - boolean saveLastedOTA(String lastedDataOTA); - boolean saveSuccessOrFail(String stateOTA); - boolean compareFirmwareOTA(JsonObject dataOTA); - boolean compareFirmwareIsUpToDate(JsonObject dataOTA); -}; -extern manageConfigOTAFile configOTAFile; -#endif \ No newline at end of file diff --git a/src/utils/utility.cpp b/src/utils/utility.cpp deleted file mode 100644 index 49f81b2..0000000 --- a/src/utils/utility.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include "./utility.h" - - tm utility::convertUnix(unsigned long unix, int timeZone) - { - time_t timestamp = unix + (timeZone * 60 * 60); - tm *local_time = gmtime(×tamp); - return *local_time; - } - - String utility::toDateTimeString(unsigned long unixtTime, int timeZone) - { - tm buff_tm = utls.convertUnix(unixtTime, timeZone); - char dateSTR[] = "00/00/0000 00:00:00"; - if(buff_tm.tm_year < 1900) - { - sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year + 1900, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); - } - else - { - sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); - } - return String(dateSTR); - } - - String utility::toUniversalTime(unsigned long unixtTime, int timeZone) - { - tm buff_tm = convertUnix(unixtTime, timeZone); - char _utc[] = "0000-00-00T00:00:00"; - char _lc[] = "00:00"; - char _lc_h[] = "00"; - String result = "0000-00-00T00:00:00+00:00"; - sprintf(_utc, "%04i-%02i-%02iT%02i:%02i:%02i", buff_tm.tm_year + 1900, buff_tm.tm_mon +1, buff_tm.tm_mday, - buff_tm.tm_hour,buff_tm.tm_min, buff_tm.tm_sec); - if(timeZone >= 0) - { - sprintf(_lc_h, "%02i", timeZone); - sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); - } - else{ - sprintf(_lc_h, "%03i", timeZone); - sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); - } - result = String(_utc) + String(_lc); - return result; - } - - unsigned long utility::toUnix(tm time_) - { - unsigned long _unix = (long)0000000000; - tm t; - t.tm_mday = time_.tm_mday; - t.tm_mon = time_.tm_mon; - if(time_.tm_year < 1900) - { - t.tm_year = time_.tm_year; - } - else - { - t.tm_year = time_.tm_year -1900; - } - t.tm_hour = time_.tm_hour; - t.tm_min = time_.tm_min; - t.tm_sec = time_.tm_sec; - t.tm_isdst = -1; - _unix = mktime(&t); - return _unix; - } - - boolean utility::StringIsDigit(String validate_str) - { - for(byte i = 0; i < validate_str.length(); i++) - { - if(!isDigit(validate_str.charAt(i))) return false; - } - return true; - } \ No newline at end of file diff --git a/src/utils/utility.h b/src/utils/utility.h deleted file mode 100644 index 186559d..0000000 --- a/src/utils/utility.h +++ /dev/null @@ -1,17 +0,0 @@ - -#ifndef UTILITY_H -#define UTILITY_H -#include - class utility - { - private: - - public: - String toDateTimeString(unsigned long unixtTime, int timeZone); - String toUniversalTime(unsigned long unixtTime, int timeZone); - unsigned long toUnix(tm time_); - tm convertUnix(unsigned long unix, int timeZone); - boolean StringIsDigit(String validate_str); - }; - extern utility utls; -#endif \ No newline at end of file From 222e5fa91259939353ea9291c8e6f753250da02e Mon Sep 17 00:00:00 2001 From: AIS IoT Platform Integration <113405874+AIS-DeviceIntegration@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:05:48 +0700 Subject: [PATCH 2/3] Delete utils directory --- utils/Attribute_MQTT_core.cpp | 14 - utils/Attribute_MQTT_core.h | 92 - utils/BuiltinSensor.cpp | 481 ----- utils/BuiltinSensor.h | 61 - utils/FileSystem.cpp | 209 -- utils/FileSystem.h | 28 - utils/MAGELLAN_MQTT_device_core.cpp | 3068 --------------------------- utils/MAGELLAN_MQTT_device_core.h | 313 --- utils/manageConfigOTAFile.cpp | 326 --- utils/manageConfigOTAFile.h | 35 - utils/utility.cpp | 78 - utils/utility.h | 17 - 12 files changed, 4722 deletions(-) delete mode 100644 utils/Attribute_MQTT_core.cpp delete mode 100644 utils/Attribute_MQTT_core.h delete mode 100644 utils/BuiltinSensor.cpp delete mode 100644 utils/BuiltinSensor.h delete mode 100644 utils/FileSystem.cpp delete mode 100644 utils/FileSystem.h delete mode 100644 utils/MAGELLAN_MQTT_device_core.cpp delete mode 100644 utils/MAGELLAN_MQTT_device_core.h delete mode 100644 utils/manageConfigOTAFile.cpp delete mode 100644 utils/manageConfigOTAFile.h delete mode 100644 utils/utility.cpp delete mode 100644 utils/utility.h diff --git a/utils/Attribute_MQTT_core.cpp b/utils/Attribute_MQTT_core.cpp deleted file mode 100644 index e5151f8..0000000 --- a/utils/Attribute_MQTT_core.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* -library version: v2.5.3 -Author:Worawit Sayned (POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 1 september 2022. -Released for private usage. -*/ -#include "Attribute_MQTT_core.h" - -BuiltinSensor mySensor; -utility utls; -StorageMemory ext_mem; -FileSystem fileSys; -manageConfigOTAFile configOTAFile; \ No newline at end of file diff --git a/utils/Attribute_MQTT_core.h b/utils/Attribute_MQTT_core.h deleted file mode 100644 index a1b6db3..0000000 --- a/utils/Attribute_MQTT_core.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 16 february 2023. -Released for private usage. -*/ -#ifndef ATTRIBUTE_CORE_H -#define ATTRIBUTE_CORE_H -#include -#include -#include "../PubSubClient.h" -#include "../ArduinoJson-v6.18.3.h" -#include "./StorageMemory.h" -#include "./FileSystem.h" -#include "./BuiltinSensor.h" -#include "./manageConfigOTAFile.h" -#define useGSMClient 0 -#define useExternalClient 1 -#include "SPIFFS.h" - -#define _major_ver 1 -#define _feature_ver 2 -#define _enhance_ver 0 -#define lib_ver "v"+String(_major_ver) +"."+ String(_feature_ver)+"."+String(_enhance_ver) - -class Attribute_MQTT_core -{ -public: - static boolean isBypassAutoUpdate; - static boolean usingCheckUpdate; - static boolean checkFirmwareUptodate; - static boolean isFirmwareUptodate; - static boolean flagAutoOTA; - static unsigned long prv_cb_timeout_millis; - static unsigned int timeout_req_download_fw; - static boolean checkTimeout_request_download_fw; - static boolean remind_Event_GET_FW_infoOTA; - static boolean triggerRemainOTA; - static boolean triggerRemainSub; - static boolean remain_ota_fw_info_match; - static String valid_remain_fw_name; - static unsigned int valid_remain_fw_size; - static boolean flag_remain_ota; - static boolean ctrl_regis_key; - static boolean ctrl_regis_pta; - static boolean ctrl_regis_json; - static boolean conf_regis_key; - static boolean conf_regis_pta; - static boolean conf_regis_json; - static boolean resp_regis; - static boolean ctrl_jsonOBJ; - static boolean conf_jsonOBJ; - static boolean using_Checksum; - static boolean useAdvanceCallback; - static String ext_Token; - static String ext_EndPoint; - static int clientNetInterface; - static Client *ClientNET; - static PubSubClient *mqtt_client; //MQTT Client - static unsigned int fw_count_chunk; - static unsigned int fw_total_size; - static unsigned int chunk_size; - static unsigned int default_chunk_size; - static unsigned int totalChunk; - static unsigned int current_chunk; - static unsigned int current_size; - static size_t incomingChunkSize; - static size_t calculate_chunkSize; - static boolean inProcessOTA; - static boolean startReqDownloadOTA; - static String sensorJSON_str; - static String clientConfigJSON_str; - static boolean useBuiltInSensor; - static StaticJsonDocument<512> docClientConf; - static DynamicJsonDocument *adjDoc; - static DynamicJsonDocument *docSensor; - //1.2.0 - static boolean checkUpdate_inside; - static unsigned int delayCheckUpdate_inside; - static unsigned int delayRequest_download; - static size_t buffer_JSON_bufferSize; - static size_t max_payload_report; - static int matchMsgId_cb; - static int matchMsgId_send; - static int maxRetransmit; - - static boolean isMatchMsgId; - static boolean reqRetransmit; - -}; -extern Attribute_MQTT_core attr; -#endif \ No newline at end of file diff --git a/utils/BuiltinSensor.cpp b/utils/BuiltinSensor.cpp deleted file mode 100644 index f11be75..0000000 --- a/utils/BuiltinSensor.cpp +++ /dev/null @@ -1,481 +0,0 @@ -#include -#include "./BuiltinSensor.h" - -int cnt_initGPS = 0; -int timeoutInitGPS = 300; // 30 sec 300 * 100 ms = 3000 ms - -void BuiltinSensor::gps_begin() -{ - if(attr.clientNetInterface == useExternalClient) - { - while (!GSM.begin()) - { - Serial.println(F("# Try to connect GPS...")); - } - } - while (!GPS.begin()) - { - if (cnt_initGPS >= timeoutInitGPS) - { - Serial.println(F("GPS Setup timeout exist from initial GPS...")); - break; - } - Serial.println(F("GPS Setup fail")); - delay(100); - cnt_initGPS++; - } -} - -void BuiltinSensor::begin() -{ - Wire.begin(); - SHT40.begin(); - gps_begin(); -} - -info_gps BuiltinSensor::getGPS_info() -{ - info_gps buffer_infoGPS; - if (!attr.useBuiltInSensor) - { - Serial.println(F("# Please allow \"true\" useBuiltinSensor in begin function")); - buffer_infoGPS.latitude = 0.00000f; - buffer_infoGPS.longitude = 0.00000f; - buffer_infoGPS.altitude = 0.00000f; - buffer_infoGPS.speed = 0.00000f; - buffer_infoGPS.course = 0.00000f; - return buffer_infoGPS; - } - if (GPS.available()) - { - buffer_infoGPS.latitude = GPS.latitude(); - buffer_infoGPS.longitude = GPS.longitude(); - buffer_infoGPS.altitude = GPS.altitude(); - buffer_infoGPS.speed = GPS.speed(); - buffer_infoGPS.course = GPS.course(); - } - else - { - Serial.println("# GPS not ready"); - buffer_infoGPS.latitude = 0.00000f; - buffer_infoGPS.longitude = 0.00000f; - buffer_infoGPS.altitude = 0.00000f; - buffer_infoGPS.speed = 0.00000f; - buffer_infoGPS.course = 0.00000f; - } - return buffer_infoGPS; -} - -float BuiltinSensor::readLatitude() -{ - float _lat = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLatitude\" allow \"true\" useBuiltinSensor in begin function")); - return _lat; - } - else - { - _lat = getGPS_info().latitude; - } - return _lat; -} -float BuiltinSensor::readLongitude() -{ - float _lng = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLongitude\" allow \"true\" useBuiltinSensor in begin function")); - return _lng; - } - else - { - _lng = getGPS_info().longitude; - } - return _lng; -} - -String BuiltinSensor::readLocation() -{ - // String _location = "0.000000,0.000000"; - char _location[] = "0.000000,0.000000"; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readLocation\" allow \"true\" useBuiltinSensor in begin function")); - return String(_location); - } - else - { - sprintf(_location, "%.4f,%.4f", readLatitude(), readLongitude()); - } - return _location; -} - -float BuiltinSensor::readSpeed() -{ - float _speed = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readSpeed\" allow \"true\" useBuiltinSensor in begin function")); - return _speed; - } - else - { - _speed = getGPS_info().speed; - } - return _speed; -} - -float BuiltinSensor::readAltitude() -{ - float _alt = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readAltitude\" allow \"true\" useBuiltinSensor in begin function")); - return _alt; - } - else - { - _alt = getGPS_info().altitude; - } - return _alt; -} - -float BuiltinSensor::readCourse() -{ - float _course = 0.000000f; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"readCourse\" allow \"true\" useBuiltinSensor in begin function")); - return _course; - } - else - { - _course = getGPS_info().course; - } - return _course; -} - -float BuiltinSensor::readTemperature() -{ - float temp = -1; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"Temperature\" allow \"true\" useBuiltinSensor in begin function")); - return temp; - } - else - { - temp = SHT40.readTemperature(); - } - return temp; -} -float BuiltinSensor::readHumidity() -{ - float humid = -1; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"Humidity\" allow \"true\" useBuiltinSensor in begin function")); - return humid; - } - else - { - humid = SHT40.readHumidity(); - } - return humid; -} - -boolean BuiltinSensor::GPSavailable() -{ - bool GPS_state = false; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] GPS not available please allow \"true\" useBuiltinSensor in begin function")); - } - else{ - GPS_state = GPS.available(); - if(!GPS_state) - { - // Serial.println(F("# GPS not available please check signal or antenna GPS connect to board")); - } - } - return GPS_state; -} - -void BuiltinSensor::setLocalTimeZone(int timeZone) -{ - char _lc[] = "00:00"; - char _lc_h[] = "00"; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't set \"setLocalTimeZone\" allow \"true\" useBuiltinSensor in begin function")); - } - else{ - this->local_timeZone = timeZone; - if(local_timeZone >= 0) - { - sprintf(_lc_h, "%02i", local_timeZone); - sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); - } - else - { - sprintf(_lc_h, "%03i", local_timeZone); - sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); - } - Serial.println("# Setting local timezone on GPS GMT: " + String(_lc)); - } -} - -// tm BuiltinSensor::utls.convertUnix(unsigned long unix, int timeZone) -// { -// time_t timestamp = unix + (timeZone * secPerHour); -// tm *local_time = gmtime(×tamp); -// return *local_time; -// } - -int BuiltinSensor::getDay() -{ - int _day = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getDay\" allow \"true\" useBuiltinSensor in begin function")); - return _day; - } - else - { - if(GPS.available()) - { - _day = utls.convertUnix(GPS.getTime(), local_timeZone).tm_mday; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - - return _day; -} - -String BuiltinSensor::getDayToString() -{ - return String(getDay()); -} - -int BuiltinSensor::getMonth() -{ - int _month = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getMonth\" allow \"true\" useBuiltinSensor in begin function")); - return _month; - } - else - { - if(GPS.available()) - { - _month = utls.convertUnix(GPS.getTime(), local_timeZone).tm_mon; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _month; -} - -String BuiltinSensor::getMonthToString() -{ - return String(getMonth()); -} - -int BuiltinSensor::getYear() -{ - int _year = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getYear\" allow \"true\" useBuiltinSensor in begin function")); - return _year; - } - else - { - if(GPS.available()) - { - _year = utls.convertUnix(GPS.getTime(), local_timeZone).tm_year + 1900; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _year; -} - -String BuiltinSensor::getYearToString() -{ - return String(getYear()); -} - -int BuiltinSensor::getHour() -{ - int _hour = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getHour\" allow \"true\" useBuiltinSensor in begin function")); - return _hour; - } - else - { - if(GPS.available()) - { - - _hour = utls.convertUnix(GPS.getTime(), local_timeZone).tm_hour; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _hour; -} - -String BuiltinSensor::getHourToString() -{ - return String(getHour()); -} - -int BuiltinSensor::getMinute() -{ - int _minute = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getMinute\" allow \"true\" useBuiltinSensor in begin function")); - return _minute; - } - else - { - if(GPS.available()) - { - _minute = utls.convertUnix(GPS.getTime(), local_timeZone).tm_min; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _minute; -} - -String BuiltinSensor::getMinuteToString() -{ - return String(getMinute()); -} - -int BuiltinSensor::getSecond() -{ - int _sec = 0; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getSecond\" allow \"true\" useBuiltinSensor in begin function")); - return _sec; - } - else - { - if(GPS.available()) - { - _sec = utls.convertUnix(GPS.getTime(), local_timeZone).tm_sec; - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _sec; -} - -String BuiltinSensor::getSecondToString() -{ - return String(getSecond()); -} - -String BuiltinSensor::getDateTimeString() -{ - tm buff_tm = utls.convertUnix(GPS.getTime(), local_timeZone); - char dateSTR[] = "00/00/0000 00:00:00"; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getDateTimeString\" allow \"true\" useBuiltinSensor in begin function")); - return String(dateSTR); - } - else - { - if(GPS.available()) - { - sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon, buff_tm.tm_year + 1900, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return String(dateSTR); -} - -String BuiltinSensor::getUniversalTime() -{ - tm buff_tm = utls.convertUnix(GPS.getTime(), local_timeZone); - char _utc[] = "0000-00-00T00:00:00"; - char _lc[] = "00:00"; - char _lc_h[] = "00"; - String result = "0000-00-00T00:00:00+00:00"; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getUniversalTime\" allow \"true\" useBuiltinSensor in begin function")); - return result; - } - else - { - if(GPS.available()) - { - sprintf(_utc, "%04i-%02i-%02iT%02i:%02i:%02i", buff_tm.tm_year + 1900, buff_tm.tm_mon, buff_tm.tm_mday, - buff_tm.tm_hour,buff_tm.tm_min, buff_tm.tm_sec); - - if(local_timeZone >= 0) - { - sprintf(_lc_h, "%02i", local_timeZone); - sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); - } - else{ - sprintf(_lc_h, "%03i", local_timeZone); - sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); - } - result = String(_utc) + String(_lc); - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return result; -} - -unsigned long BuiltinSensor::getUnixTime() -{ - unsigned long _unix = (long)0000000000; - if (!attr.useBuiltInSensor) - { - Serial.println(F("#[Warning] Can't read \"getUnixTime\" allow \"true\" useBuiltinSensor in begin function")); - return _unix; - } - else - { - if(GPS.available()) - { - tm t; - tm buff_tm = utls.convertUnix(GPS.getTime(), 0); - t.tm_mday = buff_tm.tm_mday; - t.tm_mon = buff_tm.tm_mon -1; - t.tm_year = buff_tm.tm_year; - t.tm_hour = buff_tm.tm_hour; - t.tm_min = buff_tm.tm_min; - t.tm_sec = buff_tm.tm_sec; - t.tm_isdst = -1; - _unix = mktime(&t); - } - else{ - Serial.println(F("# GPS not ready")); - } - } - return _unix; -} diff --git a/utils/BuiltinSensor.h b/utils/BuiltinSensor.h deleted file mode 100644 index 7620337..0000000 --- a/utils/BuiltinSensor.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef BUILTINSENSOR_H -#define BUILTINSENSOR_H - -#include -#include -#include -#include -#include -#include "./Attribute_MQTT_core.h" -#include -#include "./utility.h" -struct info_gps{ - float latitude = 0.0000f; - float longitude = 0.0000f; - float altitude = 0.0000f; - float speed = 0.0000f; - float course = 0.0000f; -}; -class BuiltinSensor: private utility -{ - private: - const int secPerHour = 3600; - void gps_begin(); - int local_timeZone = 7; - info_gps getGPS_info(); - // tm convertUnix(unsigned long unix, int timeZone = 7); - public: - void begin(); - boolean GPSavailable(); - - float readLatitude(); - float readLongitude(); - float readAltitude(); - float readSpeed(); - float readCourse(); - float readTemperature(); - float readHumidity(); - String readLocation(); - - void setLocalTimeZone(int timeZone); - int getDay(); - String getDayToString(); - int getMonth(); - String getMonthToString(); - int getYear(); - String getYearToString(); - int getHour(); - String getHourToString(); - int getMinute(); - String getMinuteToString(); - int getSecond(); - String getSecondToString(); - String getDateTimeString();//* - String getUniversalTime();//* - unsigned long getUnixTime(); //* - -}; - -extern BuiltinSensor mySensor; - -#endif \ No newline at end of file diff --git a/utils/FileSystem.cpp b/utils/FileSystem.cpp deleted file mode 100644 index 4600a49..0000000 --- a/utils/FileSystem.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include "./FileSystem.h" -#define DEBUG false //set to true for debug output, false for no debug output -#define DEBUG_SERIAL if(DEBUG)Serial - -void FileSystem::begin(boolean format_if_failed) -{ - if(!SPIFFS.begin(format_if_failed)) - { - DEBUG_SERIAL.println("- FileSystem Mount Failed"); - return; - } - -} -ListFileString FileSystem::listDirectory(const char* dir_name, uint8_t level, fs::FS &fs) -{ - ListFileString list; - DEBUG_SERIAL.printf("Listing directory: %s\r\n", dir_name); - - File root = fs.open(dir_name); - if(!root){ - DEBUG_SERIAL.println("− failed to open directory"); - return list; - } - if(!root.isDirectory()){ - DEBUG_SERIAL.println(" − not a directory"); - return list; - } - - File file = root.openNextFile(); - if(!file) - { - DEBUG_SERIAL.printf("- not found directory in directory: %s\r\n", dir_name); - } - while(file){ - if(file.isDirectory()){ - DEBUG_SERIAL.print(" DIR : "); - DEBUG_SERIAL.println(file.name()); - list.push_back(file.name()); - if(level){ - listDirectory(file.name(), level -1); - } - } - file = root.openNextFile(); - } - return list; -} - -ListFileString FileSystem::listFile(const char* dir_name, fs::FS &fs) -{ - ListFileString list; - DEBUG_SERIAL.printf("Listing File: %s\r\n", dir_name); - - File root = fs.open(dir_name); - if(!root){ - DEBUG_SERIAL.println("− failed to open directory"); - return list; - } - - File file = root.openNextFile(); - if(!file) - { - DEBUG_SERIAL.printf("- not found file in directory: %s\r\n", dir_name); - } - while(file){ - if(!file.isDirectory()){ - DEBUG_SERIAL.print(" FILE: "); - DEBUG_SERIAL.print(file.name()); - list.push_back(file.name()); - DEBUG_SERIAL.print("\tSIZE: "); - DEBUG_SERIAL.println(file.size()); - } - file = root.openNextFile(); - } - return list; -} - -String FileSystem::readBigFile(const char* path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Reading file: %s\r\n", path); - String _read_buffer; - File file = fs.open(path); - if(!file || file.isDirectory()) - { - DEBUG_SERIAL.println(F("- faild to open file for reading")); - return "null"; - } - - DEBUG_SERIAL.println("- read from file size:"+String(file.size())); - while(file.available()) - { - char buff[65000]; - int l = file.readBytesUntil('\n', buff, sizeof(buff)); - buff[l] = 0; - _read_buffer.concat(buff); - - } - return _read_buffer; -} - -ListFileString FileSystem::readLargeFile(const char* path, fs::FS &fs) -{ - ListFileString list; - DEBUG_SERIAL.printf("Reading file: %s\r\n", path); - char* buffer; - String _read_buffer; - File file = fs.open(path); - if(!file || file.isDirectory()) - { - DEBUG_SERIAL.println(F("- faild to open file for reading")); - return list; - } - - DEBUG_SERIAL.println("- read from file size:"+String(file.size())); - while(file.available()) - { - list.push_back(file.readStringUntil('\n').c_str()); - } - file.close(); - return list; -} - -String FileSystem::readFile(const char* path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Reading file: %s\r\n", path); - char *buffer; - File file = fs.open(path); - if(!file || file.isDirectory()) - { - DEBUG_SERIAL.println(F("- faild to open file for reading")); - return "null"; - } - DEBUG_SERIAL.println(F("- read from file:")); - while(file.available()) - { - buffer = new char[file.size() +2]; - strcpy(buffer, file.readString().c_str()); - } - file.close(); - return String(buffer); -} - -boolean FileSystem::writeFile(const char* path, const char * message, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Writing file: %s\r\n", path); - - File file = fs.open(path, FILE_WRITE); - if(!file){ - DEBUG_SERIAL.println("− failed to open file for writing"); - return false; - } - if(file.print(message)){ - DEBUG_SERIAL.println("− file written"); - file.close(); - return true; - }else { - DEBUG_SERIAL.println("− frite failed"); - return false; - } -} - -boolean FileSystem::appendFile(const char* path, const char * message, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Appending to file: %s\r\n", path); - - File file = fs.open(path, FILE_APPEND); - if(!file){ - DEBUG_SERIAL.println("− failed to open file for appending"); - return false; - } - if(file.print(message)){ - DEBUG_SERIAL.println("− message appended"); - file.close(); - return true; - } else { - DEBUG_SERIAL.println("− append failed"); - return false; - } -} - -boolean FileSystem::renameFile(const char* old_path, const char * new_path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Renaming file %s to %s\r\n", old_path, new_path); - if (fs.rename(old_path, new_path)) { - DEBUG_SERIAL.println("− file renamed"); - return true; - } else { - DEBUG_SERIAL.println("− rename failed"); - return false; - } -} - -boolean FileSystem::deleteFile(const char* path, fs::FS &fs) -{ - DEBUG_SERIAL.printf("Deleting file: %s\r\n", path); - if(fs.remove(path)){ - DEBUG_SERIAL.println("− file deleted"); - return true; - } else { - DEBUG_SERIAL.println("− delete failed"); - return false; - } -} - -boolean FileSystem::isFileExist(const char* path, fs::FS &fs) -{ - return fs.exists(path); -} - diff --git a/utils/FileSystem.h b/utils/FileSystem.h deleted file mode 100644 index 5f8e7dc..0000000 --- a/utils/FileSystem.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FILESYSTEM_H -#define FILESYSTEM_H -#include -#include "SPIFFS.h" -#include "FS.h" -#include - -typedef std::vector ListFileString; - -class FileSystem -{ -private: - -public: - void begin(boolean format_if_failed = true); - ListFileString listDirectory(const char* dir_name, uint8_t level, fs::FS &fs = SPIFFS); - ListFileString listFile(const char* dir_name, fs::FS &fs = SPIFFS); - String readFile(const char* path, fs::FS &fs = SPIFFS); //limit filesize can read 60081 can't 63207 - String readBigFile(const char* path, fs::FS &fs = SPIFFS); - ListFileString readLargeFile(const char* path, fs::FS &fs = SPIFFS); - boolean writeFile(const char* path, const char * message, fs::FS &fs = SPIFFS); - boolean appendFile(const char* path, const char * message, fs::FS &fs = SPIFFS); - boolean renameFile(const char* old_path, const char * new_path, fs::FS &fs = SPIFFS); - boolean deleteFile(const char* path, fs::FS &fs = SPIFFS); - boolean isFileExist(const char* path, fs::FS &fs = SPIFFS); -}; -extern FileSystem fileSys; -#endif \ No newline at end of file diff --git a/utils/MAGELLAN_MQTT_device_core.cpp b/utils/MAGELLAN_MQTT_device_core.cpp deleted file mode 100644 index dc9ab85..0000000 --- a/utils/MAGELLAN_MQTT_device_core.cpp +++ /dev/null @@ -1,3068 +0,0 @@ -/* -Copyright (c) 2020, Advanced Wireless Network -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -support SIMCOM SIM7600E(AIS 4G Board) - -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 22 may 2023. -Released for private usage. -*/ - -#include "MAGELLAN_MQTT_device_core.h" -StaticJsonDocument<512> intern_docJSON; -boolean Attribute_MQTT_core::isBypassAutoUpdate = false; // false = autoUpdate, true = unuse autoUpdate -boolean Attribute_MQTT_core::usingCheckUpdate = false; -boolean Attribute_MQTT_core::checkFirmwareUptodate = false; -boolean Attribute_MQTT_core::isFirmwareUptodate = false; -boolean Attribute_MQTT_core::flagAutoOTA = true; -size_t Attribute_MQTT_core::calculate_chunkSize = 0; // calculate part size from clientBuffer -size_t Attribute_MQTT_core::incomingChunkSize = 0; -unsigned int Attribute_MQTT_core::fw_total_size = 0; -unsigned int Attribute_MQTT_core::fw_count_chunk = 0; -unsigned int Attribute_MQTT_core::chunk_size = 0; -unsigned int Attribute_MQTT_core::totalChunk = 0; -unsigned int Attribute_MQTT_core::current_chunk = 0; -unsigned int Attribute_MQTT_core::current_size = 0; -unsigned int Attribute_MQTT_core::default_chunk_size = 4096; -int Attribute_MQTT_core::clientNetInterface; -Client *Attribute_MQTT_core::ClientNET = NULL; -PubSubClient *Attribute_MQTT_core::mqtt_client = NULL; // MQTT Client -boolean Attribute_MQTT_core::ctrl_regis_key = false; -boolean Attribute_MQTT_core::ctrl_regis_pta = false; -boolean Attribute_MQTT_core::ctrl_regis_json = false; -boolean Attribute_MQTT_core::conf_regis_key = false; -boolean Attribute_MQTT_core::conf_regis_pta = false; -boolean Attribute_MQTT_core::conf_regis_json = false; -boolean Attribute_MQTT_core::resp_regis = false; -boolean Attribute_MQTT_core::ctrl_jsonOBJ = false; -boolean Attribute_MQTT_core::conf_jsonOBJ = false; -boolean Attribute_MQTT_core::using_Checksum = false; -boolean Attribute_MQTT_core::useAdvanceCallback = false; -String Attribute_MQTT_core::ext_Token; -String Attribute_MQTT_core::ext_EndPoint; -boolean Attribute_MQTT_core::inProcessOTA = false; -boolean Attribute_MQTT_core::useBuiltInSensor = false; -boolean Attribute_MQTT_core::remain_ota_fw_info_match = false; -boolean Attribute_MQTT_core::flag_remain_ota = false; -String Attribute_MQTT_core::valid_remain_fw_name = ""; -unsigned int Attribute_MQTT_core::valid_remain_fw_size = 0; -boolean Attribute_MQTT_core::triggerRemainOTA = true; -boolean Attribute_MQTT_core::triggerRemainSub = true; -boolean Attribute_MQTT_core::remind_Event_GET_FW_infoOTA = false; -boolean Attribute_MQTT_core::startReqDownloadOTA = false; -boolean Attribute_MQTT_core::checkTimeout_request_download_fw = false; -unsigned int Attribute_MQTT_core::timeout_req_download_fw = 180000; -unsigned long Attribute_MQTT_core::prv_cb_timeout_millis = 0; -StaticJsonDocument<512> Attribute_MQTT_core::docClientConf; -DynamicJsonDocument *Attribute_MQTT_core::adjDoc = new DynamicJsonDocument(256); -DynamicJsonDocument *Attribute_MQTT_core::docSensor = new DynamicJsonDocument(1024); -// 1.1.2 -unsigned int Attribute_MQTT_core::delayRequest_download = 0; -boolean Attribute_MQTT_core::checkUpdate_inside = false; -unsigned int Attribute_MQTT_core::delayCheckUpdate_inside = 60000; -size_t Attribute_MQTT_core::buffer_JSON_bufferSize = 1024; -size_t Attribute_MQTT_core::max_payload_report = 50000; -int Attribute_MQTT_core::matchMsgId_cb = -1; -int Attribute_MQTT_core::matchMsgId_send = -1; -int Attribute_MQTT_core::maxRetransmit = 5; -boolean Attribute_MQTT_core::isMatchMsgId = false; -boolean Attribute_MQTT_core::reqRetransmit = false; - -OTA_INFO MAGELLAN_MQTT_device_core::OTA_info; -func_callback_registerList MAGELLAN_MQTT_device_core::duplicate_subs_list; - -boolean attemp_download_1 = false; -boolean attemp_download_2 = false; - -String b2str(byte *payload, unsigned int length) // convert byte* to String -{ - char buffer_payload[length + 1] = {0}; - memcpy(buffer_payload, (char *)payload, length); - return String(buffer_payload); -} - -typedef struct -{ - String registerKey; - ctrl_handleCallback ctrl_key_callback; - ctrl_Json_handleCallback ctrl_Json_callback; - ctrl_PTAhandleCallback ctrl_pta_callback; - ctrl_JsonOBJ_handleCallback ctrl_obj_callback; - - conf_handleCallback conf_key_callback; - conf_Json_handleCallback conf_json_callback; - conf_PTAhandleCallback conf_pta_callback; - conf_JsonOBJ_handleCallback conf_obj_callback; - resp_callback resp_h_callback; - - void *next; - unsigned int Event; - unsigned int RESP_Events; - -} regisAPI; - -regisAPI *_startRegis = NULL; // buffer callback -regisAPI *_startRegisPTA = NULL; // buffer callback -regisAPI *_startRegisJSON = NULL; // buffer callback -regisAPI *_startRegisConf = NULL; // buffer callback -regisAPI *_startRegisPTAConf = NULL; // buffer callback -regisAPI *_startRegisJSONConf = NULL; // buffer callback -regisAPI *_startRESP = NULL; - -regisAPI *_startOBJ_CTRL = NULL; -regisAPI *_startOBJ_CONF = NULL; - -boolean ext_useAdvanceCallback = false; - -Centric centric; - -void (*cb_internal)(EVENTS events, char *); - -JsonObject deJson(String jsonContent) -{ - JsonObject buffer; - intern_docJSON.clear(); - if (jsonContent != NULL && jsonContent != "clear") - { - DeserializationError error = deserializeJson(intern_docJSON, jsonContent); - buffer = intern_docJSON.as(); - if (error) - Serial.println("# Error to DeserializeJson Control"); - } - return buffer; -} - -String deControl(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta; - if (statusCode == "20000") - { - if (jsonContent.indexOf("Delta") != -1) - { - buffDelta = buffdoc["Delta"].as(); - content = buffDelta; - } - else if (jsonContent.indexOf("Sensor") != -1) - { - buffDelta = buffdoc["Sensor"].as(); - content = buffDelta; - } - } - return content; -} - -String deConfig(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta; - if (statusCode == "20000") - { - if (jsonContent.indexOf("Config") != -1) - { - buffDelta = buffdoc["Config"].as(); - content = buffDelta; - } - } - return content; -} -/////////// Feature OTA function none member in class ////////////////////// -boolean pubClientConfig(String payload) // for external function member -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/config/persist"; - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), payload.c_str()); - bool _debug_ = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Save ClientConfig: " + _debug_); - Serial.println("# [Clientconfigs]: " + payload); - return Pub_status; -} - - -boolean sub_InfoOTA() -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/resp"; - boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Subscribe Firmware Information: " + Debug); - return Sub_status; -} - -boolean unsub_InfoOTA() -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/resp"; - boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Firmware Information: " + Debug); - return Sub_status; -} - -boolean pub_Info() -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/req"; - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); - // Serial.println(topic); - String Debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Firmware Information: " + Debug); - return Pub_status; -} - -boolean sub_DownloadOTA() -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/resp/+"; - boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Subscribe Firmware Download: " + Debug); - return Sub_status; -} - -boolean unsub_DownloadOTA() -{ - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/resp/+"; - boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); - // Serial.println(topic); - String Debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Firmware Download: " + Debug); - return Sub_status; -} - -boolean pub_Download(unsigned int fw_chunk, size_t chunk_size) -{ - if (fw_chunk == 0) - { - attr.startReqDownloadOTA = true; - } - attr.checkTimeout_request_download_fw = true; - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/req/" + String(fw_chunk) + "?filesize=" + String(chunk_size); - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); - // Serial.println(topic); - String Debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("------------------------------>")); - Serial.println("# ->Request Firmware Download on chunk: " + String(fw_chunk) + " Status: " + Debug); - Serial.println("# ->Chunk size request: " + String(chunk_size)); - return Pub_status; -} -// pre ver.1.1.2 -boolean pub_Download(unsigned int fw_chunk, size_t chunk_size, String versionName) -{ - if (fw_chunk == 0) - { - attr.startReqDownloadOTA = true; - } - attr.checkTimeout_request_download_fw = true; - String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/req/" + String(fw_chunk) + "?filesize=" + String(chunk_size); - String payload = "{\"FirmwareVersion\" : \"" + versionName + "\"}"; - boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), payload.c_str()); - // Serial.println(topic); - String Debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("------------------------------>")); - Serial.println("# ->Request Firmware Download by version name \"" + versionName + "\"on chunk: " + String(fw_chunk) + " Status: " + Debug); - Serial.println("# ->Chunk size request: " + String(chunk_size)); - return Pub_status; -} - -boolean pub_UpdateProgress(String FOTA_State, String description) -{ - delay(3000); - String topic = "api/v2/thing/" + attr.ext_Token + "/fotaupdateprogress/req/?FOTAState=" + FOTA_State; - boolean Pub_status = false; - if (description.indexOf("description") != -1 || description.indexOf("Version") != -1) - { - Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); - Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); - Serial.println(F("-------------------------------")); - Serial.println("# STATE OTA Description: " + description); - Serial.println(F("-------------------------------")); - } - else - { - Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); - Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); - } - - String Debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Update Progress OTA state discription: \"" + FOTA_State + "\" Status: " + Debug); - return Pub_status; -} - -boolean check_remain_fw_isMatch(String validate_fw_name, unsigned int validate_fw_size, String descriptionWhenFail) -{ - - if (MAGELLAN_MQTT_device_core::OTA_info.firmwareName == validate_fw_name && - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize == validate_fw_size) - { - Serial.println(F("# Check firmware information incoming is match OTA still working")); // re new description - return true; - } - else - { - Serial.println(F("# Check firmware information does not match after reconnect")); - // pub_UpdateProgress("FAILED","{\"errordescription\":\""+descriptionWhenFail+"(version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " " + descriptionWhenFail + "\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - - - return false; - } -} - -void checkUpdate(String topic, String payload) -{ - if (topic.indexOf("/firmwareinfo/resp") != -1) - { - Serial.println(F("========================")); - Serial.println(F("# Check incoming firmware update")); - if (payload != "{}" && payload.indexOf("20000") != -1) - { - JsonObject fw_doc = deJson(payload); - String name = fw_doc["namefirmware"]; - unsigned int size = fw_doc["sizefirmware"]; - String version = fw_doc["versionfirmware"]; - String c_sum = fw_doc["checksum"]; - String al_c_sum = fw_doc["checksumAlgorithm"]; - attr.valid_remain_fw_name = name; - attr.valid_remain_fw_size = size; - if (name == "null" && size <= 0) - { - Serial.println(F("# [warning]Firmware Information is wrong or empty!")); - } - else - { - attr.checkFirmwareUptodate = configOTAFile.compareFirmwareIsUpToDate(fw_doc); - - MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; - MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; - MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; - - if (attr.checkFirmwareUptodate) - { - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = UP_TO_DATE; - } - else - { - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = OUT_OF_DATE; - } - attr.usingCheckUpdate = false; - } - } - } -} - -void save_fw_info(String topic, String payload) -{ - // Serial.println("-save_fw_info: "+payload); - if (topic.indexOf("/firmwareinfo/resp") != -1) - { - Serial.println(F("=======================")); - Serial.println(F("# Detect incoming Firmware Information")); - if (payload != "{}" && payload.indexOf("20000") != -1) - { - JsonObject fw_doc = deJson(payload); - String name = fw_doc["namefirmware"]; - unsigned int size = fw_doc["sizefirmware"]; - String version = fw_doc["versionfirmware"]; - String c_sum = fw_doc["checksum"]; - String al_c_sum = fw_doc["checksumAlgorithm"]; - attr.valid_remain_fw_name = name; - attr.valid_remain_fw_size = size; - if (name == "null" && size <= 0) - { - Serial.println(F("# [warning]Firmware Information is wrong or empty!")); - } - else // validate data pass - { - if ((attr.inProcessOTA) && (attr.flag_remain_ota)) // inprocess but remain connect with broker - { - attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, - attr.valid_remain_fw_size, "is mismatch from server"); // OTA renew description - - attr.flag_remain_ota = false; - Serial.println(F("=======================")); - Serial.println(F("# Validate from reconnect Firmware OTA Information #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("=======================")); - if (!attr.remain_ota_fw_info_match) - { - Serial.println(F("# [ERROR] Device must restart because firmware change #")); - Serial.println(F("# firmware not match validate OTA information after reconnect")); - delay(5000); - ESP.restart(); - } - else - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - } - else if ((attr.inProcessOTA) && (!attr.triggerRemainOTA)) // inprocess get info fw - { - attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, - attr.valid_remain_fw_size, "is obsolete"); // re new OTA description - if (!attr.remain_ota_fw_info_match) - { - Serial.println(F("=======================")); - Serial.println(F("# Firmware OTA Information Incoming While inProcessOTA #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - Serial.println(" ->Firmware checksum: " + MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("# [ERROR] Device must restart because firmware change #")); - Serial.println(F("=======================")); - delay(5000); - ESP.restart(); - } - } - - if (!attr.inProcessOTA) // first get info and save to variable - { - attr.isFirmwareUptodate = configOTAFile.compareFirmwareOTA(fw_doc); - - MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = ((attr.isFirmwareUptodate == true) ? UP_TO_DATE : OUT_OF_DATE); - // MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; - MAGELLAN_MQTT_device_core::OTA_info.firmwareName = configOTAFile.readSpacificFromConfFile("namefirmware"); - // MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; - size_t buffReadSizefirmware = configOTAFile.readSpacificFromConfFile("sizefirmware").toInt(); - attr.fw_total_size = buffReadSizefirmware; - MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = buffReadSizefirmware; - // MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; - MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = configOTAFile.readSpacificFromConfFile("versionfirmware"); - // MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksum = configOTAFile.readSpacificFromConfFile("checksum"); - // MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; - MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = configOTAFile.readSpacificFromConfFile("checksumAlgorithm"); - - unsigned int b_cal_chunk_todo = (attr.fw_total_size / attr.chunk_size) + 1; - - // ver 1.1.2 UPDATED - if (attr.isFirmwareUptodate == UP_TO_DATE) - { - JsonObject infoCurrentFW = configOTAFile.readObjectLastedOTA(); - String fw_ver = infoCurrentFW["versionfirmware"]; - String fw_size = infoCurrentFW["sizefirmware"]; - // pub_UpdateProgress("UPDATED","{\"description\":\"Device already uptodate firmware version: "+ - // String(fw_ver)+ - // " firmware size: "+String(fw_size)+"\"}"); - pub_UpdateProgress("UPDATED", "{\"description\":\"Firmware " + String(fw_ver) + " is Up to Date\",\"Version\":\"" + fw_ver + "\"}"); - } - // ver 1.1.2 UPDATED - - attr.totalChunk = b_cal_chunk_todo; - - if (!attr.isFirmwareUptodate) - { - Serial.println("# Estimate OTA toltal request chunk : " + String(attr.totalChunk)); - // pub_UpdateProgress("INITIALIZE","{\"description\":\"Initialize firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ - // " size: "+ String(attr.fw_total_size)+"\"}"); - pub_UpdateProgress("INITIALIZE", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); - MAGELLAN_MQTT_device_core::OTA_info.isReadyOTA = true; - Serial.println(F("========================================")); - Serial.println(F("# Firmware OTA information available #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); - Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); - Serial.println(" ->Firmware checksum: " + MAGELLAN_MQTT_device_core::OTA_info.checksum); - Serial.println(F("========================================")); - - // save Client config when firmware change and file ota config change - - - attr.remind_Event_GET_FW_infoOTA = false; - } - } - } - } - else - { - Serial.println(F("# Fail to get firmware Information or you don't have firmware OTA")); - Serial.println("# Detail: " + payload); - } - } -} - -String ERORRdescriptionUpdate() -{ - switch (Update.getError()) - { - case 0: - return "UPDATE_ERROR_OK"; - break; - case 1: - return "UPDATE_ERROR_WRITE"; - break; - case 2: - return "UPDATE_ERROR_ERASE"; - break; - case 3: - return "UPDATE_ERROR_READ"; - break; - case 4: - return "UPDATE_ERROR_SPACE"; - break; - case 5: - return "UPDATE_ERROR_SIZE"; - break; - case 6: - return "UPDATE_ERROR_STREAM"; - break; - case 7: - return "UPDATE_ERROR_MD5"; - break; - case 8: - return "UPDATE_ERROR_MAGIC_BYTE"; - break; - case 9: - return "UPDATE_ERROR_ACTIVATE{firmware is mismatch this board}"; - break; - case 10: - return "UPDATE_ERROR_NO_PARTITION"; - break; - case 11: - return "UPDATE_ERROR_BAD_ARGUMENT"; - break; - case 12: - return "UPDATE_ERROR_ABORT"; - break; - default: - return "ERROR_UNKNOWN"; - break; - } -} - -void validate_lostOTA_Data_incoming() -{ - if (attr.current_chunk + 1 < attr.totalChunk) - { - if (attr.incomingChunkSize < attr.chunk_size) - { - Serial.println(F("# [Warning]Lost some data while in process OTA")); - Serial.println(F("# [Warning]Device must restart")); - // pub_UpdateProgress("FAILED","{\"errordescription\":\"Data incoming lost or incorrect (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is incorrect or lost data\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - - - delay(5000); - ESP.restart(); - } - } -} - -void updateFirmware(uint8_t *data, size_t len) -{ - Update.write(data, len); - attr.current_size += len; - attr.incomingChunkSize = (int)len; - Serial.println("# <-Incoming chunk size: " + String(attr.incomingChunkSize)); - unsigned int calc_percent = map(attr.current_size, 0, attr.fw_total_size, 0, 100); - Serial.println("# <-Current firmware size: " + String(attr.current_size) + "/" + String(attr.fw_total_size) + " => [" + String(calc_percent) + " %]"); - validate_lostOTA_Data_incoming(); - if (attr.current_size != attr.fw_total_size) - { - return; - } - - if (Update.end(true)) - { - // pub_UpdateProgress("DOWNLOADED",""); - pub_UpdateProgress("DOWNLOADED", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); - if (attr.using_Checksum) - { - pub_UpdateProgress("VERIFIED", ""); - } - Serial.println(F("-------------------------------")); - Serial.println(F("# OTA done!")); - if (Update.isFinished()) - { - Serial.println(F("# Update successfully completed. Rebooting.")); - configOTAFile.saveSuccessOrFail("done"); - - String readfileConfig = configOTAFile.readConfigFileOTA(); - configOTAFile.saveLastedOTA(readfileConfig); - - String fw_infoInFIleSys; - JsonObject fw_last = configOTAFile.readObjectLastedOTA(); - int bufferFW_size = fw_last["sizefirmware"]; - - fw_last.remove("namefirmware"); - fw_last.remove("sizefirmware"); - fw_last.remove("checksumAlgorithm"); - String bufferFW_v = fw_last["versionfirmware"]; - - pub_UpdateProgress("UPDATED", "{\"Version\":\"" + bufferFW_v + "\"}"); - - fw_last["firmwareVersion"] = bufferFW_v; - fw_last.remove("versionfirmware"); - serializeJson(fw_last, fw_infoInFIleSys); - - if (fw_infoInFIleSys.indexOf("null") == -1) - { - pubClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config - { - pubClientConfig(fw_infoInFIleSys); - } - - else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) - { - pubClientConfig(fw_infoInFIleSys); - } - - // Serial.println("#Debug: "+ configOTAFile.readConfigFileOTA()); - Serial.println(F("# Safety mode GSM shutdown!")); - GSM.shutdown(); - delay(5000); - ESP.restart(); - } - else - { - // pub_UpdateProgress("FAILED","{\"errordescription\":\"something_went_wrong (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " Something went wrong (UNKNOWN ERROR)\"}"); - - Serial.println(F("# Update not finished? Something went wrong!")); - configOTAFile.saveSuccessOrFail("fail"); - } - } - else - { - String error_des = ERORRdescriptionUpdate(); - Serial.println("# OTA Fail Error Occurred. Error #: " + error_des + " # Error Enum {" + String(Update.getError()) + "}"); - // pub_UpdateProgress("FAILED","{\"errordescription\":\""+ error_des +" (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " : " + error_des + "\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - - } - delay(5000); - ESP.restart(); -} - -void hook_FW_download(String topic, uint8_t *payload, unsigned int length) -{ - // Serial.println("Debug in HOOK topic: "+String(topic)); - // Serial.println("Debug in HOOK length: "+String(length)); - if (topic.indexOf("/firmwaredownload/resp/") != -1) - { - int index = topic.indexOf("/resp/"); - String crrnt_part = topic.substring(index + 6); // crrnt_part is part start from index 0 - attr.current_chunk = crrnt_part.toInt(); - // MAGELLAN_MQTT_device_core::OTA_info.currentChunk = attr.current_chunk+1; - Serial.println(F("<--------------------------------")); - Serial.println("# <-Firmware current chunk: " + String(attr.current_chunk + 1) + "/" + String(attr.totalChunk)); - if (length > 0 && (attr.fw_count_chunk <= attr.totalChunk)) - { - attr.checkTimeout_request_download_fw = false; - attr.prv_cb_timeout_millis = millis(); - updateFirmware(payload, length); - attr.fw_count_chunk++; - attemp_download_1 = false; - attemp_download_2 = false; - - if (attr.delayRequest_download > 0) - { - delay(attr.delayRequest_download); - Serial.println("# Using delay download every chunk in: " + String(attr.delayRequest_download) + " ms."); - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - else - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - - if (!attr.inProcessOTA) - { - // pub_UpdateProgress("DOWNLOADING", "{\"description\":\"downloading firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ - // " size: "+ String(attr.fw_total_size)+"\"}"); - pub_UpdateProgress("DOWNLOADING", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); - } - attr.inProcessOTA = true; - MAGELLAN_MQTT_device_core::OTA_info.inProcessOTA = attr.inProcessOTA; - } - if (attr.fw_count_chunk == attr.totalChunk) - { - if (attr.current_size != attr.fw_total_size) - { - Serial.println(F("#[Warning] Complete Request chunk but lost or incorrect DATA from OTA")); - Serial.println(F("#[Warning] Must restart board")); - // pub_UpdateProgress("FAILED","{\"errordescription\":\"Complete request total of chunk but lost or incorrect DATA from OTA (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloaded firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is incorrect or lost data\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - delay(3000); - ESP.restart(); - } - } - } -} - -/////////// Feature OTA function none member inclass ////////////////////// - -// ver.1.1.2 -// @attention function compare between MsgId_cb(RCV from cb) and MsgId_send when using reqRetransmission -void checkRequestRetransmit() -{ - if (attr.reqRetransmit) - { - attr.isMatchMsgId = (attr.matchMsgId_send == attr.matchMsgId_cb) ? true : false; - if (attr.isMatchMsgId) - { - Serial.print(F("\n# ========================================\n")); - Serial.println("# Received MsgId: " + String(attr.matchMsgId_send) + " retransmit from server"); - Serial.print(F("# ========================================\n\n")); - - attr.reqRetransmit = false; - } - } -} - -void msgCallback_internalHandler(char *topic, byte *payload, unsigned int length) -{ - String action = "ERROR"; - unsigned int buffEvent = ERROR; - String b_topic = String(topic); - String _payload = b2str(payload, length); - String key = "null"; // if this topic is'nt PLAINTEXT - String code = "0"; - int _MsgId = -1; - - EVENTS intern_EVENT; - intern_EVENT.RESP = "EMPTY"; - - regisAPI *handleRegisPTA = _startRegisPTA; - regisAPI *handleRegisJSON = _startRegisJSON; - regisAPI *handleRegisJSON_CTRL_OBJ = _startOBJ_CTRL; - regisAPI *handleRegisKEY = _startRegis; - - regisAPI *handleRegisPTAConf = _startRegisPTAConf; - regisAPI *handleRegisJSONConf = _startRegisJSONConf; - regisAPI *handleRegisJSON_CONF_OBJ = _startOBJ_CONF; - regisAPI *handleRegisKEYConf = _startRegisConf; - - regisAPI *handleRESP = _startRESP; - // OTA Feature ///////////////// - if ((attr.usingCheckUpdate) && (!attr.inProcessOTA)) - { - checkUpdate(b_topic, _payload); - } - else if (!attr.usingCheckUpdate && attr.flagAutoOTA) - { - save_fw_info(b_topic, _payload); - } - hook_FW_download(b_topic, payload, length); - /////////////////////////////// - char *b_payload = (char *)_payload.c_str(); // payload for advance_cb and endpoint centric - - if (b_topic.indexOf("/auth/resp/") != -1) - { - buffEvent = TOKEN; - action = "TOKEN"; - attr.ext_Token = *&_payload; - } - if (b_topic.indexOf("/delta/resp/pta") != -1) - { - int indexfound2 = String(b_topic).indexOf("="); - String keyOnTopic = b_topic.substring(indexfound2 + 1); - key = keyOnTopic; - buffEvent = CONTROL_PLAINTEXT; - action = "CONTROL_PLAINTEXT"; - - if ((_payload == "40300" || (_payload == "40400") && (_payload.length() == 5))) - { - code = _payload; - intern_EVENT.RESP = "FAIL"; - } - else - { - code = "20000"; - intern_EVENT.RESP = "SUCCESS"; - } - - if (attr.ctrl_regis_key) - { - while (handleRegisKEY != NULL) - { - if (handleRegisKEY->registerKey == key) - { - break; - } - else - { - handleRegisKEY = (regisAPI *)handleRegisKEY->next; - } - } - if (handleRegisKEY != NULL) - { - if (handleRegisKEY->registerKey == key) - { - handleRegisKEY->ctrl_key_callback(_payload); - } - } - } - if (attr.ctrl_regis_pta) - { - while (handleRegisPTA != NULL) - { - if (handleRegisPTA->Event == buffEvent) - { - break; - } - else - { - handleRegisPTA = (regisAPI *)handleRegisPTA->next; - } - } - if (handleRegisPTA != NULL) - { - handleRegisPTA->ctrl_pta_callback(key, _payload); - } - } - } - - else if (b_topic.indexOf("/delta/resp") != -1) - { - buffEvent = CONTROL_JSON; - action = "CONTROL_JSON"; - - if (_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.indexOf("\":\"") + 8); - intern_EVENT.RESP = "SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); - intern_EVENT.RESP = "FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - - if (attr.ctrl_regis_json) - { - while (handleRegisJSON != NULL) - { - if (handleRegisJSON->Event == buffEvent) - { - break; - } - else - { - handleRegisJSON = (regisAPI *)handleRegisJSON->next; - } - } - if (handleRegisJSON != NULL) - { - handleRegisJSON->ctrl_Json_callback(_payload); - } - } - - if (attr.ctrl_jsonOBJ) - { - while (handleRegisJSON_CTRL_OBJ != NULL) - { - if (handleRegisJSON_CTRL_OBJ->Event == buffEvent) - { - break; - } - else - { - handleRegisJSON_CTRL_OBJ = (regisAPI *)handleRegisJSON_CTRL_OBJ->next; - } - } - if (handleRegisJSON_CTRL_OBJ != NULL) - { - // Serial.println(_payload); - String buffDocs = deControl(_payload); - // Serial.println(buffDocs); - JsonObject Docs = deJson(buffDocs); - handleRegisJSON_CTRL_OBJ->ctrl_obj_callback(Docs); - } - } - } - - if (b_topic.indexOf("/config/resp/pta/?config=") != -1) - { - int indexfound2 = String(b_topic).indexOf("="); - String keyOnTopic = b_topic.substring(indexfound2 + 1); - key = keyOnTopic; - buffEvent = CONFIG_PLAINTEXT; - action = "CONFIG_PLAINTEXT"; - - if ((_payload == "40300" || (_payload == "40400") && (_payload.length() == 5))) - { - code = _payload; - intern_EVENT.RESP = "FAIL"; - } - else - { - code = "20000"; - intern_EVENT.RESP = "SUCCESS"; - } - - if (attr.conf_regis_key) - { - while (handleRegisKEYConf != NULL) - { - if (handleRegisKEYConf->registerKey == key) - { - break; - } - else - { - handleRegisKEYConf = (regisAPI *)handleRegisKEYConf->next; - } - } - if (handleRegisKEYConf != NULL) - { - if (handleRegisKEYConf->registerKey == key) - { - handleRegisKEYConf->conf_key_callback(_payload); - } - } - } - - if (attr.conf_regis_pta) - { - while (handleRegisJSON != NULL) - { - if (handleRegisPTAConf->Event == buffEvent) - { - break; - } - else - { - handleRegisPTAConf = (regisAPI *)handleRegisPTAConf->next; - } - } - if (handleRegisPTAConf != NULL) - { - handleRegisPTAConf->conf_pta_callback(key, _payload); - } - } - } - else if (b_topic.indexOf("/config/resp") != -1) - { - buffEvent = CONFIG_JSON; - action = "CONFIG_JSON"; - - if (_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.indexOf("\":\"") + 8); - intern_EVENT.RESP = "SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); - intern_EVENT.RESP = "FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - - if (attr.conf_regis_json) - { - while (handleRegisJSONConf != NULL) - { - if (handleRegisJSONConf->Event == buffEvent) - { - break; - } - else - { - handleRegisJSONConf = (regisAPI *)handleRegisJSONConf->next; - } - } - if (handleRegisJSONConf != NULL) - { - handleRegisJSONConf->conf_json_callback(_payload); - } - } - - if (attr.conf_jsonOBJ) - { - while (handleRegisJSON_CONF_OBJ != NULL) - { - if (handleRegisJSON_CONF_OBJ->Event == buffEvent) - { - break; - } - else - { - handleRegisJSON_CONF_OBJ = (regisAPI *)handleRegisJSON_CONF_OBJ->next; - } - } - if (handleRegisJSON_CONF_OBJ != NULL) - { - // Serial.println(_payload); - String buffDocs = deConfig(_payload); - // Serial.println(buffDocs); - JsonObject Docs = deJson(buffDocs); - handleRegisJSON_CONF_OBJ->conf_obj_callback(Docs); - } - } - } - - if (b_topic.indexOf("dateTime") != -1) - { - buffEvent = UNIXTIME; - action = "UNIXTIME"; - } - if (b_topic.indexOf("/report/resp/pta/?") != -1) - { - buffEvent = RESP_REPORT_PLAINTEXT; - action = "RESP_REPORT_PLAINTEXT"; - - int valid_found_only_msgId = b_topic.indexOf("?id="); // only id - int valid_sensor = b_topic.indexOf("?sensor="); // focus only sensor - int valid_msgId = b_topic.indexOf("&id="); // start with key sensor and id - - if (valid_found_only_msgId != -1) // found only msg id {?id} - { - int indexfound = valid_found_only_msgId; - String msgIdOnTopic = b_topic.substring(indexfound + 4); - _MsgId = msgIdOnTopic.toInt(); - } - - if (valid_msgId != -1) // found MsgId - { - int indexfoundKey = valid_sensor; - int indexfoundId = valid_msgId; - String keyOnTopic = b_topic.substring(indexfoundKey + 8, indexfoundId); - String msgIdOnTopic = b_topic.substring(indexfoundId + 4); - // Serial.println("_payload: "+_payload); - // Serial.println("MsgIdontopic: "+msgIdOnTopic); - key = keyOnTopic; - _MsgId = msgIdOnTopic.toInt(); - } - else if (valid_msgId == -1 && valid_sensor != -1) // not found MsgId , found only key sensor - { - String keyOnTopic = b_topic.substring(valid_sensor + 8); - key = keyOnTopic; - _MsgId = -1; - } - - if (_payload.indexOf("20000") != -1) - { - code = _payload; - intern_EVENT.RESP = "SUCCESS"; - } - else - { - code = _payload; - intern_EVENT.RESP = "FAIL"; - } - } - else if (b_topic.indexOf("/report/resp") != -1) - { - buffEvent = RESP_REPORT_JSON; - action = "RESP_REPORT_JSON"; - - JsonObject OBJ_report_resp = deJson(_payload); - String _code = OBJ_report_resp["Code"]; - - if (_code != "null") - { - code = _code; - } - - if (_payload.indexOf("id") != -1) - { - String _msg_id = OBJ_report_resp["id"]; - if (_msg_id != "null") - { - _MsgId = _msg_id.toInt(); - } - } - else - { - _MsgId = -1; - } - - if (_payload.indexOf("20000") != -1) - { - // code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); - intern_EVENT.RESP = "SUCCESS"; - } - else - { - // code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); - intern_EVENT.RESP = "FAIL"; - } - } - - if (b_topic.indexOf("/heartbeat/resp/pta") != -1) - { - buffEvent = RESP_HEARTBEAT_PLAINTEXT; - action = "RESP_HEARTBEAT_PLAINTEXT"; - - if (_payload.indexOf("20000") != -1) - { - code = _payload; - intern_EVENT.RESP = "SUCCESS"; - } - else - { - code = _payload; - intern_EVENT.RESP = "FAIL"; - } - } - else if (b_topic.indexOf("/heartbeat/resp") != -1) - { - buffEvent = RESP_HEARTBEAT_JSON; - action = "RESP_HEARTBEAT_JSON"; - - if (_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); - intern_EVENT.RESP = "SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); - intern_EVENT.RESP = "FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - } - if (b_topic.indexOf("/report/timestamp/resp") != -1) - { - buffEvent = RESP_REPORT_TIMESTAMP; - action = "RESP_REPORT_TIMESTAMP"; - if (_payload.indexOf("20000") != -1) - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); - intern_EVENT.RESP = "SUCCESS"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - else - { - code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); - intern_EVENT.RESP = "FAIL"; - // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); - } - } - if (b_topic.indexOf("/server/destination/response") != -1) - { - buffEvent = GET_ENDPOINT; - action = "GET_ENDPOINT"; - attr.ext_EndPoint = b_payload; - } - // Serial.println("#INSIDE "); - // Serial.println(action); - // Serial.println(_payload); - // Serial.println("#INSIDE "); - - intern_EVENT.CODE = code.toInt(); - intern_EVENT.Topic = b_topic; - intern_EVENT.Payload = _payload; - intern_EVENT.PayloadLength = length; - intern_EVENT.Action = action; - intern_EVENT.Key = key; - intern_EVENT.MsgId = _MsgId; - attr.matchMsgId_cb = intern_EVENT.MsgId; - checkRequestRetransmit(); - - if (ext_useAdvanceCallback) // routing to onMessage Callback when use setMessageListener(Callback) - { - cb_internal(intern_EVENT, b_payload); - } - - if (attr.resp_regis) - { - while (handleRESP != NULL) - { - if (handleRESP->Event == buffEvent) - { - break; - } - else - { - handleRESP = (regisAPI *)handleRESP->next; - } - } - // Serial.println("# IN RESP :"+ String(handleRESP->Event)); - // Serial.println("# IN RESP2 :"+ String(buffEvent)); - if (handleRESP != NULL) - { - if (handleRESP->Event == buffEvent) - { - handleRESP->resp_h_callback(intern_EVENT); - } - } - } - // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Action); - // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Payload); -} - -MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core(Client &client) -{ - prev_time = 0; - now_time = millis(); - HB_prev_time = 0; - HB_now_time = millis(); - - attr.clientNetInterface = useExternalClient; - Client *newClient = &client; - attr.ClientNET = *&newClient; - attr.mqtt_client = new PubSubClient(*attr.ClientNET); - this->client = *&attr.mqtt_client; - // duplicate_subs_list = NULL; -} - -MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core() -{ - prev_time = 0; - now_time = millis(); - HB_prev_time = 0; - HB_now_time = millis(); - - attr.clientNetInterface = useGSMClient; - this->gsm_client = new GSMClient; - attr.ClientNET = *&gsm_client; - attr.mqtt_client = new PubSubClient(*attr.ClientNET); - this->client = *&attr.mqtt_client; - // duplicate_subs_list = NULL; -} - -String MAGELLAN_MQTT_device_core::getHostName() -{ - return this->host; -} - -void MAGELLAN_MQTT_device_core::setMQTTBufferSize(uint16_t sizeBuffer) -{ - // Serial.println(F("# SetBufferSize: ")); - // Serial.println(sizeBuffer); - this->_default_bufferSize = sizeBuffer; -} - -void MAGELLAN_MQTT_device_core::setAuthMagellan(String _thingIden, String _thingSecret, String _imei) -{ - Serial.println(F("#====== Setting Magellan Authentication =======")); - if (!(CheckString_isDigit(_thingIden) && CheckString_isDigit(_thingSecret))) - { - Serial.print(F("# ERROR Can't connect to Magellan")); - Serial.print(F("# Parameter from you setting invalid \n [thingIdentify]=> ")); - Serial.print(_thingIden); - Serial.print(F(" [thingSecret]=> ")); - Serial.println(_thingSecret); - Serial.println(F("# Invalid Parameter!! Please check [thingIdentify] and [thingSecret]")); - while (true) - { - Serial.print("."); - delay(300); - this->cnt_fail++; - if (cnt_fail >= 100) // timeout Restart board 30 sec - { - ESP.restart(); - } - } - } - this->thingIden = _thingIden; - this->thingSecret = _thingSecret; - this->imei = _imei; - // Serial.println(F("#Set Auth Success")); - // Serial.println(thingIden); - // Serial.println(thingSecret); - // Serial.println(imei); -} - -void getRadio() -{ - if (attr.clientNetInterface == useGSMClient) - { - Serial.println(F("#========= Radio Quality information ==========")); - Serial.println("Signal Strength: " + String(Network.getSignalStrength())); - Serial.println(F("#==============================================")); - } -} - -void MAGELLAN_MQTT_device_core::initialBoard() -{ - delay(1000); - setAuthMagellan(GSM.getICCID(), GSM.getIMSI(), GSM.getIMEI()); - Serial.println(F("#====== Initializing Board =======")); - Serial.println("ICCID: " + String(thingIden)); - Serial.println("IMSI: " + String(thingSecret)); - Serial.println("IMEI: " + String(imei)); - Serial.println(F("#=================================")); -} - -void MAGELLAN_MQTT_device_core::getBoardInfo() -{ - Serial.println(F("#====== Board information =========")); - Serial.println("ICCID: " + String(thingIden)); - Serial.println("IMSI: " + String(thingSecret)); - Serial.println("IMEI: " + String(imei)); - getRadio(); - Serial.println(F("#=================================")); -} - -String MAGELLAN_MQTT_device_core::getICCID() -{ - return this->thingIden; -} - -String MAGELLAN_MQTT_device_core::getIMEI() -{ - return this->imei; -} - -String MAGELLAN_MQTT_device_core::getIMSI() -{ - return this->thingSecret; -} - -String MAGELLAN_MQTT_device_core::readToken() -{ - return this->token; -} - -boolean MAGELLAN_MQTT_device_core::CheckString_isDigit(String valid_payload) -{ - for (byte i = 0; i < valid_payload.length(); i++) - { - if (!isDigit(valid_payload.charAt(i))) - return false; - } - return true; -} - -boolean MAGELLAN_MQTT_device_core::CheckString_isDouble(String valid_payload) -{ - char *input = (char *)valid_payload.c_str(); - char *end; - strtod(input, &end); - if (*input == '\0') - { - return false; - } - if (end == input || *end != '\0') - { - return false; - } - return true; -} - -// void MAGELLAN_MQTT_device_core::setCallback(void(callback(char*, byte*, unsigned int))) -// { -// this->client->setCallback(callback); -// } - -void MAGELLAN_MQTT_device_core::setCallback_msgHandle() -{ - this->client->setCallback(msgCallback_internalHandler); -} - -void MAGELLAN_MQTT_device_core::setMessageListener(void (*callback)(EVENTS, char *)) -{ - attr.useAdvanceCallback = true; - if (callback) - cb_internal = callback; -} - -void MAGELLAN_MQTT_device_core::reconnect() -{ - while (!isConnected()) - { - Serial.print(F("Device Disconected from Magellan...")); - checkConnection(); - if (flagToken) - { - Serial.print(F("# Remain Subscribes list\n")); - attr.triggerRemainSub = true; - - attr.triggerRemainOTA = true; - if (!attr.flagAutoOTA) - { - sub_InfoOTA(); - } - } - } -} - -boolean MAGELLAN_MQTT_device_core::acceptEndPoint(String payload) -{ - boolean acceptStatus = false; - if (payload.length() >= 10) - { - const char *buff_payload = payload.c_str(); - JsonObject getCetric = deJson(buff_payload); - - String buf1 = getCetric["ServerDestinationInfo"]; - String buf2 = getCetric["OperationStatus"]; - // Serial.println("buf1 :"+ buf1); - if (buf2.indexOf("20000") != -1) - { - JsonObject getCetric2 = deJson(buf1); - String buff_ip = getCetric2["ServerIP"]; - String buff_domain = getCetric2["ServerDomain"]; - String buff_port = getCetric2["ServerPort"]; - centric.endPoint_DOMAIN = buff_domain; - centric.endPoint_IP = buff_ip; - centric.endPoint_PORT = buff_port; - acceptStatus = true; - Serial.println(F("## NEW ZONE AVAILABLE #######")); - Serial.println("# Centric IP >>: " + centric.endPoint_IP); - Serial.println("# Centric Domain >>: " + centric.endPoint_DOMAIN); - Serial.println("# Centric Port >>: " + String(centric.endPoint_PORT)); - Serial.println(F("#############################")); - cnt_attempt = 0; - } - else - { - Serial.println(F("# Fail to Get Endpoint form centric")); - Serial.println(F("# Please check the thing device is activated")); - Serial.print(F("# response: ")); - Serial.println(payload); - } - } - return acceptStatus; -} - -void MAGELLAN_MQTT_device_core::acceptToken(String payload) -{ - if (payload.length() >= 36) - { - this->flagToken = true; - this->token = payload; - Serial.println("# Thingtoken: " + token); - } -} - -void MAGELLAN_MQTT_device_core::acceptToken(EVENTS event) -{ - String _payload = event.Payload; - if ((event.Topic == "api/v2/thing/" + String(thingIden) + "/" + String(thingSecret) + "/auth/resp/pta") && !flagToken) - { - if (_payload.length() >= 36) - { - this->flagToken = true; - this->token = _payload; - Serial.println("# Token >> :" + token); - } - } -} - -// String MAGELLAN_MQTT_device_core::byteToString(byte* payload, unsigned int length_payload) -// { -// char buffer_payload[length_payload+1] = {0}; -// memcpy(buffer_payload, (char*)payload, length_payload); -// return String(buffer_payload); -// } - -String MAGELLAN_MQTT_device_core::byteToString(byte *payload, unsigned int length_payload) -{ - return b2str(payload, length_payload); -} - -void MAGELLAN_MQTT_device_core::loop() -{ - this->client->loop(); - reconnect(); -} - -void MAGELLAN_MQTT_device_core::reconnectMagellan() -{ - while (!isConnected()) - { - srand(time(NULL)); - int randnum = rand() % 10000; // generate number concat in Client id - int randnum_2 = rand() % 10000; // generate number concat in Client id - String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); - Serial.println(F("Attempting MQTT connection ...")); - this->client->setServer(this->host.c_str(), this->port); - this->client->setCallback(msgCallback_internalHandler); - Serial.println("Connecting Magellan on: " + String(this->host) + ", Port: " + String(this->port)); - if (this->client->connect(client_idBuff.c_str(), this->thingIden.c_str(), this->thingSecret.c_str())) - { - Serial.println("Client id: " + client_idBuff + " is connected"); - recon_attempt = 0; - } - else - { - Serial.print(F("failed, reconnect =")); - Serial.print(this->client->state()); - Serial.println(F(" try again in 5 seconds")); - if (!flagToken) - { - Serial.println(F("# Please check the thing device is activated ")); - } - delay(5000); - recon_attempt++; - Serial.print(F("# attempt connect on :")); - Serial.println(String(recon_attempt) + " times"); - if (recon_attempt >= MAXrecon_attempt) - { - Serial.println(" attempt to connect more than " + String(MAXrecon_attempt) + " Restart Board"); - ESP.restart(); - } - } - } - thingRegister(); -} - -void MAGELLAN_MQTT_device_core::checkConnection() -{ - if (!isConnected()) - { - reconnectMagellan(); - } -} - -void MAGELLAN_MQTT_device_core::magellanCentric(const char *_host, int _port) -{ - if (!isConnected()) - { - while (!isConnected()) - { - srand(time(NULL)); - int randnum = rand() % 10000; // generate number concat in Client id - int randnum_2 = rand() % 10000; // generate number concat in Client id - String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); - Serial.println(F("#Attempting connection ...")); - this->client->setServer(_host, _port); - this->client->setCallback(msgCallback_internalHandler); - Serial.println("Connecting Magellan on: " + String(this->host) + ", Port: " + String(this->port)); - String thisIdenCentric = "Centric." + thingIden; - if (this->client->connect(client_idBuff.c_str(), thisIdenCentric.c_str(), this->thingSecret.c_str())) - { - Serial.println("Client id : " + client_idBuff + " is connected"); - recon_attempt = 0; - } - - else - { - Serial.print(F("failed, reconnect =")); - Serial.print(this->client->state()); - Serial.println(F(" try again in 5 seconds")); - Serial.print(F("Count Attemp Reconnect: ")); - recon_attempt++; - Serial.println(recon_attempt); - delay(5000); - if (recon_attempt >= MAXrecon_attempt) - { - Serial.println(" attempt to connect more than: " + String(MAXrecon_attempt) + " Restart Board"); - ESP.restart(); - } - } - } - getEndPoint(); - } -} - -void MAGELLAN_MQTT_device_core::getEndPoint() -{ - Serial.println(F("# REQUEST ENDPOINT")); - while (!flagRegisterEndPoint) - { - String topic = "api/v2/things/" + this->thingIden + "/" + this->thingSecret + "/server/destination/response"; - this->flagRegisterEndPoint = this->client->subscribe(topic.c_str()); - Serial.println("# Register destination server: " + String(flagRegisterEndPoint)); - } - while (!flagGetEndPoint) - { - this->client->loop(); - // Serial.println("Pub"); - this->requestEndpoint(); - if (attr.ext_EndPoint.length() >= 10) - { - // Serial.println(ext_EndPoint); - flagGetEndPoint = acceptEndPoint(attr.ext_EndPoint); - } - delay(5000); - } - if (flagGetEndPoint) - { - Serial.println(F("# Disconnect from Centric")); - this->client->disconnect(); - Serial.println(F("# Connect to new zone")); - srand(time(NULL)); - int randnum = rand() % 10000; // generate number concat in Client id - int randnum_2 = rand() % 10000; // generate number concat in Client id - String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); - this->beginCustom(client_idBuff, true, centric.endPoint_IP, (centric.endPoint_PORT).toInt(), this->_default_bufferSize); - } -} - -bool MAGELLAN_MQTT_device_core::isConnected() -{ - return this->client->connected(); -} - -void MAGELLAN_MQTT_device_core::beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); - if (attr.clientNetInterface == useGSMClient) - { - Serial.println("# AIS 4G Board"); - while (!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if ((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if (attr.clientNetInterface == useExternalClient) - { - Serial.println("# External Client"); - } - if (builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - delay(5000); - getRadio(); - this->host = _host; - this->port = _port; - this->client_id = _client_id; - if (bufferSize > _default_OverBufferSize) - { - Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); - Serial.println(); - this->setBufferSize(_default_OverBufferSize); - attr.calculate_chunkSize = _default_bufferSize / 2; - } - else - { - this->setBufferSize(bufferSize); - attr.calculate_chunkSize = bufferSize / 2; - } - checkConnection(); -} - -void MAGELLAN_MQTT_device_core::beginCentric() -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); - if (attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while (!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if ((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if (attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - Serial.println(F("# Connect to Centric")); - delay(5000); - getRadio(); - this->host = hostCentric; - this->port = mgPort; - this->client_id = this->getICCID(); // auto_assigned Client ID with ThingIdent - setBufferSize(_default_bufferSize); - magellanCentric(); -} - -void MAGELLAN_MQTT_device_core::begin(boolean builtInSensor) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); - if (attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while (!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if ((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - else if (attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - if (builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - getRadio(); - delay(5000); - String _host = _host_production; - - this->host = _host; - this->port = mgPort; - this->client_id = getICCID(); // auto_assigned Client ID with ICCID - setBufferSize(_default_bufferSize); - checkConnection(); -} - -void MAGELLAN_MQTT_device_core::begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone, uint16_t bufferSize, boolean builtInSensor) -{ - setAuthMagellan(_thingIden, _thingSencret, _imei); - Serial.print(F("ThingIdentify: ")); - Serial.println(_thingIden); - Serial.print(F("ThingSecret: ")); - Serial.println(_thingSencret); - Serial.print(F("IMEI: ")); - Serial.println(_imei); - begin(_thingIden, builtInSensor, Zone, bufferSize); -} - -void MAGELLAN_MQTT_device_core::begin(String _client_id, boolean builtInSensor, unsigned int Zone, uint16_t bufferSize) -{ - Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); - if (attr.clientNetInterface == useGSMClient) - { - Serial.println(F("# AIS 4G Board")); - while (!GSM.begin()) - { - Serial.println(F("GSM setup fail")); - delay(2000); - } - if ((this->thingIden == NULL) && (this->thingSecret == NULL)) - { - initialBoard(); - // getRadio(); - } - } - - else if (attr.clientNetInterface == useExternalClient) - { - Serial.println(F("# External Client")); - } - - if (builtInSensor) - { - Serial.println(F("# Using Builtin SENSOR")); - attr.useBuiltInSensor = builtInSensor; - mySensor.begin(); - } - getRadio(); - delay(5000); - String _host = _host_production; - switch (Zone) - { - case Production: - _host = _host_production; - break; - default: - _host = _host_production; - Serial.println(F("# OUT OF LENGTH ZONE MOVE TO Production")); - break; - } - this->host = _host; - this->port = mgPort; - this->client_id = _client_id; - if (bufferSize > _default_OverBufferSize) - { - Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); - Serial.println(); - this->setBufferSize(_default_OverBufferSize); - attr.calculate_chunkSize = _default_bufferSize / 2; - } - else - { - this->setBufferSize(bufferSize); - attr.calculate_chunkSize = bufferSize / 2; - } - checkConnection(); -} - -boolean MAGELLAN_MQTT_device_core::registerToken() -{ - String topic = "api/v2/thing/" + this->thingIden + "/" + this->thingSecret + "/auth/resp/pta"; - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println(F("# Register Token to magellan")); - Serial.println("# Register Token Status: " + _debug); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::report(String payload) -{ - - String topic = "api/v2/thing/" + token + "/report/persist"; - boolean Pub_status = client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Report JSON: " + _debug); - Serial.println("# [Sensors]: " + payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::report(String key, String value) -{ - String topic = "api/v2/thing/" + token + "/report/persist/pta/?sensor=" + key; - boolean Pub_status = client->publish(topic.c_str(), value.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Report Plaintext: " + _debug); - Serial.println("# [key]: " + key); - Serial.println("# [value]: " + value); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportSensor() -{ - String bufferPlayload = buildSensorJSON(*attr.docSensor); - boolean Pub_status = false; - if (bufferPlayload.indexOf("null") == -1) - { - Pub_status = report(bufferPlayload); - clearSensorBuffer(*attr.docSensor); - } - else - { - Serial.println(F("# Can't reportSensor Because Not set function \"void addSensor(key,value)\" before reportSensor")); - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::ACKControl(String key, String value) -{ - String topic = "api/v2/thing/" + token + "/report/persist/pta/?sensor=" + key; - boolean Pub_status = this->client->publish(topic.c_str(), value.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# ACKNOWNLEDGE Control Plaintext: " + _debug); - Serial.println("# [key]: " + key); - Serial.println("# [value]: " + value); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::ACKControl(String payload) -{ - String topic = "api/v2/thing/" + token + "/report/persist"; - boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# ACKNOWNLEDGE Control JSON: " + _debug); - Serial.println("# [Sensors]: " + payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type) -{ - boolean Pub_status = false; - String topic_ = "api/v2/thing/" + token + "/report/timestamp/persist"; - if (timestamp != NULL && JSONpayload != NULL) - { - String payload_ = "[{\"UNIXTS\":" + timestamp + ",\"Sensor\":" + JSONpayload + "}]"; - Pub_status = this->client->publish(topic_.c_str(), payload_.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println("# Report with timestamp: " + _debug); - Serial.println("# [Sensors]: " + payload_); - return Pub_status; - } - else - { - Serial.println(F("# Report with timestamp: Failure")); - Serial.println(F("# Error Empty timestamp or Sensor payload")); - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reportClientConfig(String payload) -{ - String topic = "api/v2/thing/" + token + "/config/persist"; - boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Save ClientConfig: " + _debug); - Serial.println("# [ClientConfigs]: " + payload); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::requestEndpoint() -{ - boolean Pub_status = false; - if (!flagGetEndPoint) - { - if (cnt_attempt >= limit_attempt) - { - Serial.println("Device Attempt to request ENDPOINT more than " + String(limit_attempt) + " time. restart board"); - delay(1000); - ESP.restart(); - } - if (millis() - previouseMillis > 10000) - { - previouseMillis = millis(); - String topic = "api/v2/things/" + thingIden + "/" + thingSecret + "/server/destination/request"; - Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.print("# Request Endpoint: " + _debug); - if (cnt_attempt > 0) - { - Serial.print(" Attempt >> " + String(cnt_attempt - 1) + " time"); - } - Serial.println(); - cnt_attempt++; - } - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::requestToken() -{ - boolean Pub_status = false; - if (!flagToken) - { - if (cnt_attempt >= limit_attempt) - { - Serial.println("Device Attempt to request token more than " + String(limit_attempt) + " time. restart board"); - delay(1000); - ESP.restart(); - } - if (millis() - previouseMillis > 10000) - { - previouseMillis = millis(); - String topic = "api/v2/thing/" + thingIden + "/" + thingSecret + "/auth/req"; - Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - // Serial.println("topic :" + topic); - Serial.print("# Request Token: " + _debug); - if (cnt_attempt > 0) - { - Serial.print(" Attempt >> " + String(cnt_attempt - 1) + " time"); - } - Serial.println(); - cnt_attempt++; - } - } - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::setBufferSize(uint16_t size) -{ - Serial.println("# set BufferSize: " + String(size)); - return this->client->setBufferSize(size); -} - -boolean MAGELLAN_MQTT_device_core::heartbeat() -{ - String topic = "api/v2/thing/" + token + "/heartbeat"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Heartbeat Trigger: " + _debug); - return Pub_status; -} - -boolean firstHBdoing = true; -void MAGELLAN_MQTT_device_core::heartbeat(unsigned int triger_ms) -{ - HB_threshold_ms = triger_ms; - HB_now_time = millis(); - unsigned long different_ms = HB_now_time - HB_prev_time; - if (different_ms >= HB_threshold_ms || firstHBdoing) - { - firstHBdoing = false; - heartbeat(); - HB_prev_time = HB_now_time; - } -} - -void MAGELLAN_MQTT_device_core::setManualToken(String _token) -{ - Serial.println(F("# SET MANUAL TOKEN =====")); - Serial.println("#Token: " + _token); - if (_token.length() >= 36) - { - token = _token; - acceptToken(token); - } -} - -boolean MAGELLAN_MQTT_device_core::reqControlJSON() -{ - - String topic = "api/v2/thing/" + token + "/delta/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Control [JSON]: " + _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqControl(String key) -{ - String topic = "api/v2/thing/" + token + "/delta/req/?sensor=" + key; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Control Plaintext by [Key]: \"" + key + "\": " + _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqConfigJSON() -{ - String topic = "api/v2/thing/" + token + "/config/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Config [JSON]: " + _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::reqConfig(String key) -{ - String topic = "api/v2/thing/" + token + "/config/req/?config=" + key; // fact C c - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Request Config Plaintext [Key]: \"" + key + "\": " + _debug); - return Pub_status; -} - -void MAGELLAN_MQTT_device_core::getControl(String key, ctrl_handleCallback ctrl_callback) -{ - attr.ctrl_regis_key = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_PLAINTEXT; - newRegis->registerKey = key; - newRegis->ctrl_key_callback = ctrl_callback; - newRegis->next = NULL; - - if (_startRegis != NULL) - { - regisAPI *focusRegis = _startRegis; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegis = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getControl(ctrl_PTAhandleCallback ctrl_pta_callback) -{ - attr.ctrl_regis_pta = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_PLAINTEXT; - newRegis->ctrl_pta_callback = ctrl_pta_callback; - newRegis->next = NULL; - - if (_startRegisPTA != NULL) - { - regisAPI *focusRegis = _startRegisPTA; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegisPTA = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_Json_handleCallback ctrl_json_callback) -{ - attr.ctrl_regis_json = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_JSON; - newRegis->ctrl_Json_callback = ctrl_json_callback; - newRegis->next = NULL; - - if (_startRegisJSON != NULL) - { - regisAPI *focusRegis = _startRegisJSON; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegisJSON = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb) -{ - attr.ctrl_jsonOBJ = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONTROL_JSON; - newRegis->ctrl_obj_callback = jsonOBJ_cb; - newRegis->next = NULL; - - if (_startOBJ_CTRL != NULL) - { - regisAPI *focusRegis = _startOBJ_CTRL; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startOBJ_CTRL = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfig(String key, conf_handleCallback _conf_callback) -{ - attr.conf_regis_key = true; - - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_PLAINTEXT; - newRegis->registerKey = key; - newRegis->conf_key_callback = _conf_callback; - newRegis->next = NULL; - - if (_startRegisConf != NULL) - { - regisAPI *focusRegis = _startRegisConf; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegisConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfig(conf_PTAhandleCallback conf_pta_callback) -{ - attr.conf_regis_pta = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_PLAINTEXT; - newRegis->conf_pta_callback = conf_pta_callback; - newRegis->next = NULL; - - if (_startRegisPTAConf != NULL) - { - regisAPI *focusRegis = _startRegisPTAConf; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegisPTAConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfigJSON(conf_Json_handleCallback conf_json_callback) -{ - attr.conf_regis_json = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_JSON; - newRegis->conf_json_callback = conf_json_callback; - newRegis->next = NULL; - - if (_startRegisJSONConf != NULL) - { - regisAPI *focusRegis = _startRegisJSONConf; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRegisJSONConf = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb) -{ - attr.conf_jsonOBJ = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = CONFIG_JSON; - newRegis->conf_obj_callback = jsonOBJ_cb; - newRegis->next = NULL; - - if (_startOBJ_CONF != NULL) - { - regisAPI *focusRegis = _startOBJ_CONF; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startOBJ_CONF = newRegis; - } -} - -void MAGELLAN_MQTT_device_core::getRESP(unsigned int resp_event, resp_callback resp_cb) -{ - attr.resp_regis = true; - regisAPI *newRegis = new regisAPI; - newRegis->Event = resp_event; - newRegis->resp_h_callback = resp_cb; - newRegis->next = NULL; - - if (_startRESP != NULL) - { - regisAPI *focusRegis = _startRESP; - while (focusRegis->next != NULL) - { - focusRegis = (regisAPI *)focusRegis->next; - } - focusRegis->next = newRegis; - } - else - { - _startRESP = newRegis; - } -} - -boolean MAGELLAN_MQTT_device_core::registerResponseReport(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/report/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/report/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/" + token + "/report/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP Report: "+ _debug); - Serial.println("# Subscribe Response Report: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerResponseReportTimestamp() -{ - String topic = "api/v2/thing/" + token + "/report/timestamp/resp"; - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP ReportTimestamp: "+ _debug); - Serial.println("# Subscribe Response ReportTimestamp: " + _debug); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerResponseHeartbeat(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/heartbeat/resp/pta"; - break; - case 1: - topic = "api/v2/thing/" + token + "/heartbeat/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/" + token + "/heartbeat/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterRESP Heartbeat: "+ _debug); - Serial.println("# Subscribe Response Heartbeat: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerConfig(String key) -{ - String topic = "api/v2/thing/" + token + "/config/resp/pta/?config=" + key; // fact C c - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - // Serial.println("# Register Server Config [Key]: \""+key+"\" Register: "+ _debug); - Serial.println("# Subscribe ServerConfig [Key]: \"" + key + "\" Subscribe: " + _debug); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerConfig(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/config/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/config/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/" + token + "/config/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# Register Server Config: "+ _debug); - Serial.println("# Subscribe ServerConfig: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::getTimestamp() -{ - String topic = "api/v2/server/dateTime/req"; - boolean Pub_status = this->client->publish(topic.c_str(), " "); - _debug = (Pub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Get ServerTime Request: " + _debug); - return Pub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerTimestamp(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/server/dateTime/resp/pta"; - break; - case 1: - topic = "api/v2/server/dateTime/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/server/dateTime/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - Serial.println(F("# Subscribe Timestamp magellan")); - // Serial.println(F("# RegisterTimestamp magellan")); - Serial.println("# Subscribe ServerTime: " + _debug); - // Serial.println("# RegisterTimestamp: "+ _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerControl(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/delta/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/delta/resp"; - break; - default: - Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); - topic = "api/v2/thing/" + token + "/delta/resp"; - break; - } - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl: "+ _debug); - Serial.println("# Subscribe Control: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} - -boolean MAGELLAN_MQTT_device_core::registerControl(String key) -{ - String topic = "api/v2/thing/" + token + "/delta/resp/pta/?sensor=" + key; // fact S s - boolean Sub_status = this->client->subscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(topic); - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl [Key]: \""+key+"\" Register: "+ _debug); - Serial.println("# Subscribe Control [Key]: \"" + key + "\" Subscribe: " + _debug); - return Sub_status; -} - -void MAGELLAN_MQTT_device_core::thingRegister() -{ - while (!flagRegisterToken) - { - this->flagRegisterToken = registerToken(); - } - while (!flagToken) - { - loop(); - requestToken(); - if (attr.ext_Token.length() >= 30) - { - token = attr.ext_Token; - acceptToken(token); - } - } -} - -void MAGELLAN_MQTT_device_core::registerList(func_callback_registerList cb_regisList) -{ - if (attr.triggerRemainSub) - { - if (attr.inProcessOTA) - { - Serial.println(F("# Subscribes List is terminated when Inprocess OTA")); - } - else - { - Serial.println(F("# Subscribes List")); - cb_regisList(); - if (!attr.flagAutoOTA) - { - sub_InfoOTA(); - } - } - attr.triggerRemainSub = false; - Serial.println(F("#============================")); - } -} - -boolean firstTimedoing = true; -void MAGELLAN_MQTT_device_core::interval_ms(unsigned long ms, func_callback_ms cb_ms) -{ - threshold_ms = ms; - now_time = millis(); - unsigned long different_ms = now_time - prev_time; - if (different_ms >= threshold_ms || firstTimedoing) - { - firstTimedoing = false; - prev_time = millis(); - cb_ms(); - } -} - -JsonObject MAGELLAN_MQTT_device_core::deserialJson(String jsonContent) -{ - JsonObject buffer; - if (jsonContent != NULL && jsonContent != "clear") - { - DeserializationError error = deserializeJson(docJson, jsonContent); - buffer = docJson.as(); - if (error) - Serial.println("# Error to DeserializeJson Control"); - } - return buffer; -} - -String MAGELLAN_MQTT_device_core::deserialControlJSON(String jsonContent) -{ - String content = "40300"; - JsonObject buffdoc = deserialJson(jsonContent); - String statusCode = buffdoc["Code"]; - String buffDelta; - if (statusCode == "20000") - { - if (jsonContent.indexOf("Delta") != -1) - { - buffDelta = buffdoc["Delta"].as(); - content = buffDelta; - } - else if (jsonContent.indexOf("Sensor") != -1) - { - buffDelta = buffdoc["Sensor"].as(); - content = buffDelta; - } - } - return content; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, String value, JsonDocument &ref_docs) -{ - int len = value.length(); - char *c_value = new char[len + 1]; - std::copy(value.begin(), value.end(), c_value); - c_value[len] = '\0'; - ref_docs[key] = c_value; - delete[] c_value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, const char *value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, int value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, float value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::updateSensor(String key, boolean value, JsonDocument &ref_docs) -{ - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, String value, JsonDocument &ref_docs) -{ - int len = value.length(); - char *c_value = new char[len + 1]; - std::copy(value.begin(), value.end(), c_value); - c_value[len] = '\0'; - ref_docs[key] = c_value; - delete[] c_value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, const char *value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+value); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, int value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, float value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::addSensor(String key, boolean value, JsonDocument &ref_docs) -{ - // Serial.println("[Key]: "+key+" [Value]: "+String(value)); - ref_docs[key] = value; -} - -void MAGELLAN_MQTT_device_core::remove(String key, JsonDocument &ref_docs) -{ - Serial.println("Remove [Key]: " + key); - ref_docs.remove(key); -} - -boolean MAGELLAN_MQTT_device_core::findKey(String key, JsonDocument &ref_docs) -{ - return ref_docs.containsKey(key); -} - -String MAGELLAN_MQTT_device_core::buildSensorJSON(JsonDocument &ref_docs) -{ - String bufferJsonStr; - // Serial.println("# [Build JSON Key is]: "+ String(ref_docs.size()) +" key"); - size_t mmr_usage = ref_docs.memoryUsage(); - size_t max_size = ref_docs.memoryPool().capacity(); - size_t safety_size = max_size * (0.97); - // Serial.println("Safety size: "+String(safety_size)); - if (mmr_usage >= safety_size) - { - bufferJsonStr = "null"; - Serial.println("# [Overload memory toJSONString] *Maximum Safety Memory size to use is: " + String(safety_size)); - } - else - { - serializeJson(ref_docs, bufferJsonStr); - Serial.println("# [to JSON String Key is]: " + String(ref_docs.size()) + " key"); - } - - Serial.println("# MemoryUsage: " + String(mmr_usage) + "/" + String(safety_size) + " from(" + String(ref_docs.memoryPool().capacity()) + ")"); - return bufferJsonStr; -} - -void MAGELLAN_MQTT_device_core::adjustBufferSensor(size_t sizeJSONbuffer) -{ - attr.docSensor = new DynamicJsonDocument(sizeJSONbuffer); -} - -int MAGELLAN_MQTT_device_core::readBufferSensor(JsonDocument &ref_docs) -{ - return ref_docs.memoryPool().capacity(); -} - -void MAGELLAN_MQTT_device_core::clearSensorBuffer(JsonDocument &ref_docs) -{ - Serial.println(F("# [Clear JSON buffer]")); - ref_docs.clear(); - Serial.println(F("-------------------------------")); -} - -boolean MAGELLAN_MQTT_device_core::registerInfoOTA() -{ - return sub_InfoOTA(); -} - -boolean MAGELLAN_MQTT_device_core::unregisterInfoOTA() -{ - return unsub_InfoOTA(); -} - -boolean MAGELLAN_MQTT_device_core::requestFW_Info() -{ - return pub_Info(); -} - -boolean MAGELLAN_MQTT_device_core::registerDownloadOTA() -{ - return sub_DownloadOTA(); -} - -boolean MAGELLAN_MQTT_device_core::unregisterDownloadOTA() -{ - return unsub_DownloadOTA(); -} - -boolean MAGELLAN_MQTT_device_core::requestFW_Download(unsigned int fw_chunk, size_t chunk_size) -{ - return pub_Download(fw_chunk, chunk_size); -} - -boolean MAGELLAN_MQTT_device_core::updateProgressOTA(String OTA_state, String description) -{ - return pub_UpdateProgress(OTA_state, description); -} - -void MAGELLAN_MQTT_device_core::activeOTA(size_t chunk_size, boolean useChecksum) -{ - Serial.println(F("#============================")); - Serial.println(F("# Activated OTA")); - Update.begin(UPDATE_SIZE_UNKNOWN); - attr.using_Checksum = useChecksum; - String isC_sum = (attr.using_Checksum == true) ? "ENABLE" : "DISABLE"; - Serial.println(F(" ")); - Serial.print(isC_sum); - Serial.println(F(" Checksum FirmwareOTA")); - // Serial.println(*attr.chunk_size); - if (chunk_size > 4096) - { - Serial.print(F("# [Warning] Chunk Size Maximun is 4096 (use Default \"")); - Serial.print(attr.default_chunk_size); - Serial.println(F("\")")); - setChunkSize(attr.default_chunk_size); - } - else - { - setChunkSize(chunk_size); - } - configOTAFile.beginFileSystem(true); - if (!configOTAFile.checkFileOTA()) - { - configOTAFile.createConfigFileOTA(); - } - - if (!configOTAFile.checkLastedOTA()) - { - configOTAFile.createLastedOTA(); - if (configOTAFile.checkFileOTA()) - { - String fw_infoInFIleSys = configOTAFile.readLastedOTA(); - } - } - else - { - String fw_infoInFIleSys; - JsonObject fw_last = configOTAFile.readObjectLastedOTA(); - int bufferFW_size = fw_last["sizefirmware"]; - - fw_last.remove("namefirmware"); - fw_last.remove("sizefirmware"); - fw_last.remove("checksumAlgorithm"); - String bufferFW_v = fw_last["versionfirmware"]; - fw_last["firmwareVersion"] = bufferFW_v; - fw_last.remove("versionfirmware"); - serializeJson(fw_last, fw_infoInFIleSys); - if (fw_infoInFIleSys.indexOf("null") == -1) - { - this->reportClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config - { - this->reportClientConfig(fw_infoInFIleSys); - } - else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) - { - this->reportClientConfig(fw_infoInFIleSys); - } - } -} -void MAGELLAN_MQTT_device_core::setChecksum(String md5Checksum) -{ - Serial.println("# Set Checksum md5: " + md5Checksum + " Status:" + (Update.setMD5(md5Checksum.c_str()) == true ? " Success" : " Fail")); -} - -void MAGELLAN_MQTT_device_core::setChunkSize(size_t chunkSize) -{ - attr.chunk_size = chunkSize; - Serial.println("# Set Chunk size: " + String(attr.chunk_size)); -} - -void checkTimeoutReq_fw_download() -{ - if (attr.checkTimeout_request_download_fw) - { - unsigned long differentTime = millis() - attr.prv_cb_timeout_millis; - if (differentTime > 60000 && !attemp_download_1) - { - Serial.println("#Attemp resume download 1 after checktimeout 1 minute"); - pub_Download(attr.fw_count_chunk, attr.chunk_size); - attemp_download_1 = true; - } - if (differentTime > 120000 && !attemp_download_2) - { - Serial.println("#Attemp resume download 2 after checktimeout 2 minute"); - pub_Download(attr.fw_count_chunk, attr.chunk_size); - attemp_download_2 = true; - } - if (differentTime > attr.timeout_req_download_fw) - { - // pub_UpdateProgress("FAILED","{\"errordescription\":\"Timeout from request firmware download (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); - pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is timeout on chunk (" + String(attr.current_chunk) + "/" + String(attr.totalChunk) + ")\"}"); - configOTAFile.saveSuccessOrFail("fail"); - - Serial.println("#device must restart timeout from request firmware dowload " + String(attr.timeout_req_download_fw / 60000) + " minute"); - delay(5000); - ESP.restart(); - } - // Serial.println("Counting Timeout: "+String(diferentTime/1000)); - } - else - { - attr.prv_cb_timeout_millis = millis(); - } -} - -unsigned long prv_mills_usingCheckOTA = 0; -void checkTimeoutCheckUpdate() -{ - if (attr.usingCheckUpdate) - { - unsigned long differentTime = millis() - prv_mills_usingCheckOTA; - if (differentTime > 15000) - { - attr.usingCheckUpdate = false; - } - } - else if (!attr.usingCheckUpdate) - { - prv_mills_usingCheckOTA = millis(); - } -} - -boolean remind_unsub_when_inProcessOTA = false; -unsigned long prv_mills_pubinfo = 0; -void MAGELLAN_MQTT_device_core::handleOTA(boolean OTA_after_getInfo) -{ - checkTimeoutReq_fw_download(); - checkTimeoutCheckUpdate(); - if (attr.triggerRemainOTA) - { - - Serial.println(F("# Active handleOTA")); - registerInfoOTA(); - if (attr.flagAutoOTA) - registerDownloadOTA(); - Serial.println(F("#============================")); - - if (attr.inProcessOTA) // if get fw in hook fw will auto count and request dowload fw - { - attr.flag_remain_ota = true; - attr.remain_ota_fw_info_match = false; - - if (!attr.remain_ota_fw_info_match) - { - if (millis() - prv_mills_pubinfo > 5000) - { - pub_Info(); - prv_mills_pubinfo = millis(); - } - } - else if (attr.remain_ota_fw_info_match) // remain get firmware - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - } - if (attr.startReqDownloadOTA && !attr.inProcessOTA) // if get part 0 fail but start ota still work when reconnect - { - pub_Download(attr.fw_count_chunk, attr.chunk_size); - } - attr.triggerRemainOTA = false; - } - if ((attr.fw_total_size > 0) && !(attr.remind_Event_GET_FW_infoOTA)) - { - // Serial.println(F("=======================")); - // Serial.println(F("# Firmware OTA Information Available #")); - // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.fw_name); - // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.fw_totalSize)); - // Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.fw_version); - // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.algorithm_check_sum); - // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.check_sum); - // Serial.println(F("=======================")); - if (attr.using_Checksum && !attr.isFirmwareUptodate) - { - if (MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "md5" || MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "MD5") - setChecksum(MAGELLAN_MQTT_device_core::OTA_info.checksum); - else - { - Serial.println(F("#[Warning] Can't set checksum because algorithm checksum is not \"md5\"")); - Serial.println(F("#[Warning] But OTA Process still working without checksum ")); - attr.using_Checksum = false; - } - } - if (OTA_after_getInfo && !attr.isFirmwareUptodate) // auto request OTA after get fw information - { - pub_Download(0, attr.chunk_size); - } - attr.remind_Event_GET_FW_infoOTA = true; - } - if (attr.inProcessOTA && !remind_unsub_when_inProcessOTA) - { - Serial.println(F("=================================================")); - Serial.println(F("# Inprocess OTA terminate other incoming message")); - Serial.println(F("# Unsubscribe unuse function")); - if (attr.ctrl_regis_key || attr.ctrl_regis_pta) - { - unregisterControl(PLAINTEXT); - } - if (attr.ctrl_jsonOBJ || attr.ctrl_regis_json) - { - unregisterControl(JSON); - } - if (attr.conf_regis_key || attr.conf_regis_pta) - { - unregisterConfig(PLAINTEXT); - } - if (attr.conf_jsonOBJ || attr.conf_regis_json) - { - unregisterConfig(JSON); - } - if (attr.resp_regis) - { - unregisterResponseHeartbeat(PLAINTEXT); - unregisterResponseHeartbeat(JSON); - unregisterResponseReport(PLAINTEXT); - unregisterResponseReport(JSON); - unregisterResponseReportTimestamp(); - unregisterTimestamp(PLAINTEXT); - unregisterTimestamp(JSON); - } - remind_unsub_when_inProcessOTA = true; - Serial.println(F("=================================================")); - } -} -////////////////// Unsub /////////// -boolean MAGELLAN_MQTT_device_core::unregisterControl(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/delta/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/delta/resp"; - break; - default: - topic = "api/v2/thing/" + token + "/delta/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - // Serial.println("# RegisterControl: "+ _debug); - Serial.println("# Unsubscribe Control: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterControl(String key) -{ - String topic = "api/v2/thing/" + token + "/delta/resp/pta/?sensor=" + key; // fact S s - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(topic); - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Control [Key]: \"" + key + "\" Unsubscribe: " + _debug); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterConfig(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/config/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/config/resp"; - break; - default: - topic = "api/v2/thing/" + token + "/config/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerConfig: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterConfig(String key) -{ - String topic = "api/v2/thing/" + token + "/config/resp/pta/?config=" + key; // fact C c - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerConfig [Key]: \"" + key + "\" Unsubscribe: " + _debug); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterTimestamp(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/server/dateTime/resp/pta"; - break; - case 1: - topic = "api/v2/server/dateTime/resp"; - break; - default: - topic = "api/v2/server/dateTime/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe ServerTime: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} // -boolean MAGELLAN_MQTT_device_core::unregisterResponseReport(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/report/resp/pta/+"; - break; - case 1: - topic = "api/v2/thing/" + token + "/report/resp"; - break; - default: - topic = "api/v2/thing/" + token + "/report/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response Report: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} -boolean MAGELLAN_MQTT_device_core::unregisterResponseReportTimestamp() -{ - String topic = "api/v2/thing/" + token + "/report/timestamp/resp"; - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response ReportTimestamp: " + _debug); - return Sub_status; -} -boolean MAGELLAN_MQTT_device_core::unregisterResponseHeartbeat(int format) -{ - String topic; - switch (format) - { - case 0: - topic = "api/v2/thing/" + token + "/heartbeat/resp/pta"; - break; - case 1: - topic = "api/v2/thing/" + token + "/heartbeat/resp"; - break; - default: - topic = "api/v2/thing/" + token + "/heartbeat/resp"; - break; - } - boolean Sub_status = this->client->unsubscribe(topic.c_str()); - _debug = (Sub_status == true) ? "Success" : "Failure"; - String respType = (format == 0) ? "Plaintext" : "JSON"; - Serial.println(F("-------------------------------")); - Serial.println("# Unsubscribe Response Heartbeat: " + _debug); - Serial.println("# Response type: " + respType); - return Sub_status; -} -////////////////// Unsub ////////// diff --git a/utils/MAGELLAN_MQTT_device_core.h b/utils/MAGELLAN_MQTT_device_core.h deleted file mode 100644 index 37c611d..0000000 --- a/utils/MAGELLAN_MQTT_device_core.h +++ /dev/null @@ -1,313 +0,0 @@ -/* -Copyright (c) 2020, Advanced Wireless Network -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -support SIMCOM SIM7600E(AIS 4G Board) - -Author:(POC Device Magellan team) -Create Date: 25 April 2022. -Modified: 22 may 2023. -Released for private usage. -*/ -#ifndef MAGELLAN_MQTT_DEVICE_CORE_h -#define MAGELLAN_MQTT_DEVICE_CORE_h - -#include -#include "../PubSubClient.h" -#include "../ArduinoJson-v6.18.3.h" -#include -#include -#include -#include -#include -#include "Attribute_MQTT_core.h" -#include "BuiltinSensor.h" - -//Response Payload format some function can be set. -#define lib_version lib_ver -#define major_version _major_ver -#define feature_version _feature_ver -#define enhance_version _enhance_ver - -#define PLAINTEXT 0 //Plaintext -#define JSON 1 //Json - -#define ERROR 0 -#define TOKEN 1 -#define CONTROL_JSON 2 -#define CONTROL_PLAINTEXT 3 -#define CONFIG_JSON 4 -#define CONFIG_PLAINTEXT 5 -#define UNIXTIME 6 -#define UTCTIME 7 -#define RESP_REPORT_JSON 8 -#define RESP_REPORT_PLAINTEXT 9 -#define RESP_REPORT_TIMESTAMP 10 -#define RESP_HEARTBEAT_JSON 11 -#define RESP_HEARTBEAT_PLAINTEXT 12 -#define GET_ENDPOINT 13 - -#define mgPort 1883 -#define hostCentric "centric-magellan.ais.co.th" -//for define mode Timestamp -#define SET_UNIXTS 0 -#define SET_UTC 1 - -#define Production 1 -#define Staging 2 -#define IoT 3 - -#define _host_production "magellan.ais.co.th" - -#define defaultBuffer 1024 -#define defaultOTABuffer 8192 -#define _default_OverBufferSize 8192 - -#define UNKNOWN -1 -#define OUT_OF_DATE 0 -#define UP_TO_DATE 1 -typedef struct { - String Topic; - String Key; - String Action; - String Payload; - String RESP; - unsigned int CODE; - unsigned int PayloadLength; - //update 1.2.0 msgId - int MsgId = -1; -}EVENTS; -typedef struct { - String endPoint_IP; - String endPoint_DOMAIN; - String endPoint_PORT; -}Centric; - -typedef struct { - boolean isReadyOTA = false; - int firmwareIsUpToDate = -1; - boolean inProcessOTA = false; - unsigned int firmwareTotalSize = 0; - String firmwareName = "UNKNOWN"; - String firmwareVersion = "UNKNOWN"; - String checksum = "UNKNOWN"; - String checksumAlgorithm = "UNKNOWN"; -}OTA_INFO; - -typedef std::function ctrl_handleCallback; -typedef std::function ctrl_Json_handleCallback; -typedef std::function ctrl_JsonOBJ_handleCallback; -typedef std::function conf_handleCallback; -typedef std::function conf_Json_handleCallback; -typedef std::function conf_JsonOBJ_handleCallback; - -typedef std::function ctrl_PTAhandleCallback; -typedef std::function conf_PTAhandleCallback; -typedef std::function resp_callback; - -typedef std::function func_callback_registerList; - - - -//Client Internet interface connection -#define useGSMClient 0 -#define useExternalClient 1 - -typedef std::function func_callback_ms; - -class MAGELLAN_MQTT_device_core -{ -public: - MAGELLAN_MQTT_device_core(Client& client); // for customize client internet interface - MAGELLAN_MQTT_device_core(); // for GSM client internet interface - boolean flagToken = false; - String client_id; - // String unixtTime; - void setAuthMagellan(String _thingIden, String _thingSecret, String _imei = "none"); // add on - void begin(boolean builtInSensor = false); - void begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone = Production, uint16_t bufferSize = 1024, boolean builtInSensor = true); - void beginCentric(); - void beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize); // - void begin(String _client_id, boolean buildInSensor = true, unsigned int Zone = Production, uint16_t bufferSize = 1024); // - String getHostName(); // - void getBoardInfo(); // - String getIMEI(); - String getIMSI(); - String getICCID(); - String readToken(); - - void magellanCentric(const char* _host = hostCentric, int _port = mgPort); //add on - boolean reportSensor(); - boolean report(String payload); // - boolean report(String key, String value); // - boolean registerResponseReport(int format = JSON); - boolean registerResponseReportTimestamp(); - boolean registerResponseHeartbeat(int format = JSON); - boolean reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type = SET_UNIXTS); // Json Payload - boolean heartbeat(); // - void heartbeat(unsigned int triger_ms); // - boolean registerConfig(int format = JSON); // PTA and JSON - boolean registerConfig(String key);// - boolean registerControl(int format = JSON); // - boolean registerControl(String key); // - boolean registerTimestamp(int format = JSON); // - boolean reqControl(String key); - boolean reqControlJSON(); - - ////// unsub //////////////// - boolean unregisterControl(int format = JSON); // - boolean unregisterControl(String key); // - boolean unregisterConfig(int format = JSON); // PTA and JSON - boolean unregisterConfig(String key); // - boolean unregisterTimestamp(int format = JSON); // - boolean unregisterResponseReport(int format = JSON); - boolean unregisterResponseReportTimestamp(); - boolean unregisterResponseHeartbeat(int format = JSON); - ////// unsub //////////////// - - void getControl(String key, ctrl_handleCallback ctrl_callback); - void getControl(ctrl_PTAhandleCallback ctrl_pta_callback); - void getControlJSON(ctrl_Json_handleCallback ctrl_json_callback); - void getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb); - - void getConfig(String key, conf_handleCallback _conf_callback); - void getConfig(conf_PTAhandleCallback conf_pta_callback); - void getConfigJSON(conf_Json_handleCallback conf_json_callback); - void getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb); - void getRESP(unsigned int resp_event ,resp_callback resp_cb); - - boolean getTimestamp(); // - boolean reqConfigJSON(); // - boolean reqConfig(String key); // - boolean reportClientConfig(String payload); // - boolean isConnected(); - void loop(); // - void setMessageListener(void(*callback)(EVENTS, char*)); - - void setManualToken(String _token); - void acceptToken(EVENTS event); - - boolean ACKControl(String key, String value); - boolean ACKControl(String payload); - - void interval_ms(unsigned long ms, func_callback_ms cb_ms); - void registerList(func_callback_registerList cb_regisList); - - // interface MAGELLANJSON - StaticJsonDocument<256> docJson; - - // StaticJsonDocument<1024> docBuild; - // StaticJsonDocument<512> docClientConf; - - String deserialControlJSON(String jsonContent); - JsonObject deserialJson(String jsonContent); - void addSensor(String key, String value, JsonDocument &ref_docs); - void addSensor(String key, const char* value, JsonDocument &ref_docs); - void addSensor(String key, int value, JsonDocument &ref_docs); - void addSensor(String key, float value, JsonDocument &ref_docs); - void addSensor(String key, boolean value, JsonDocument &ref_docs); - void updateSensor(String key, String value, JsonDocument &ref_docs); - void updateSensor(String key, const char* value, JsonDocument &ref_docs); - void updateSensor(String key, int value, JsonDocument &ref_docs); - void updateSensor(String key, float value, JsonDocument &ref_docs); - void updateSensor(String key, boolean value, JsonDocument &ref_docs); - String buildSensorJSON(JsonDocument &ref_docs); - void remove(String key, JsonDocument &ref_docs); - boolean findKey(String key, JsonDocument &ref_docs); - void adjustBufferSensor(size_t sizeJSONbuffer); - int readBufferSensor(JsonDocument &ref_docs); - void clearSensorBuffer(JsonDocument &ref_docs); - - void setMQTTBufferSize(uint16_t size); - boolean CheckString_isDigit(String valid_payload); // - boolean CheckString_isDouble(String valid_payload); // - - //OTA Feature// - void activeOTA(size_t part_size, boolean useChecksum = true); - void handleOTA(boolean OTA_after_getInfo = true); - boolean registerInfoOTA(); - boolean registerDownloadOTA(); - boolean unregisterInfoOTA(); - boolean unregisterDownloadOTA(); - boolean updateProgressOTA(String OTA_state, String description); - boolean requestFW_Info(); - boolean requestFW_Download(unsigned int fw_part, size_t part_size); - void setChecksum(String md5Checksum); - void setChunkSize(size_t Chunksize); - static OTA_INFO OTA_info; - static func_callback_registerList duplicate_subs_list; //ver.1.2.0 - /////////////// - -private: - int _default_bufferSize = 1024; - // BuiltinSensor mySensor; - void reconnect(); //add on - void checkConnection(); // - void getEndPoint(); //get end point from centric - boolean acceptEndPoint(String payload); //get end point from centric - void thingRegister(); // - void acceptToken(String payload); // - boolean setBufferSize(uint16_t size); // default 256 (uplink 128 + downlink 128) - String byteToString(byte* payload, unsigned int length_payload); // convert byte* to string - void setCallback_msgHandle(); - void initialBoard(); // - unsigned long previouseMillis = 0; // - boolean flagRegisterEndPoint= false; // - boolean flagGetEndPoint = false; // - boolean flagRegisterToken = false; // - boolean flagReportRetry = false; - boolean flagAuthMagellan = false; - - boolean registerToken(); // - boolean requestToken(); // - boolean requestEndpoint(); // - void reconnectMagellan(); // - int limit_attempt = 11; // 11 -> for atempt 10 request token - int cnt_attempt = 0; // - int recon_attempt = 0; - int MAXrecon_attempt = 10; - unsigned long prev_time; - unsigned long now_time; - unsigned long threshold_ms; - - unsigned long HB_prev_time; - unsigned long HB_now_time; - unsigned long HB_threshold_ms; - - unsigned long cnt_fail = 0; - - String host; - String thingIden; - String thingSecret; - String imei; - String token; - String _debug; - int port; - -protected: - PubSubClient *client = NULL; - GSMClient *gsm_client = NULL; -}; - -#endif - - diff --git a/utils/manageConfigOTAFile.cpp b/utils/manageConfigOTAFile.cpp deleted file mode 100644 index e0e1220..0000000 --- a/utils/manageConfigOTAFile.cpp +++ /dev/null @@ -1,326 +0,0 @@ -//lasted update 15/11/2022 - check lasted too if state configfile fail, before decide to ota must compare lasted with incoming fw info too -#include "manageConfigOTAFile.h" - -void manageConfigOTAFile::beginFileSystem(boolean formatIfFail) -{ - fileSys.begin(formatIfFail); -} - -boolean manageConfigOTAFile::checkFileOTA() -{ - return fileSys.isFileExist(configOTAFilePath); -} - -boolean manageConfigOTAFile::checkLastedOTA() -{ - return fileSys.isFileExist(lastedOTAPath); -} - - -boolean manageConfigOTAFile::createConfigFileOTA() -{ - String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\",\"status\":\"null\"}"; - return fileSys.writeFile(configOTAFilePath, init_config.c_str()); -} - -boolean manageConfigOTAFile::createLastedOTA() -{ - String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\"}"; - return fileSys.writeFile(lastedOTAPath, init_config.c_str()); -} - -String manageConfigOTAFile::readConfigFileOTA() -{ - return fileSys.readFile(configOTAFilePath); -} - -String manageConfigOTAFile::readLastedOTA() -{ - return fileSys.readFile(lastedOTAPath); -} - -JsonObject manageConfigOTAFile::readObjectConfigFileOTA() -{ - String buffReadConfigOTA = readConfigFileOTA(); - JsonObject buffer; - OTAdoc.clear(); - if(buffReadConfigOTA != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); - buffer = OTAdoc.as(); - if(error) - Serial.println("# Error to DeserializeJson readConfigFileOTA"); - } - return buffer; -} -JsonObject manageConfigOTAFile::readObjectLastedOTA() -{ - String buffReadConfigOTA = readLastedOTA(); - JsonObject buffer; - OTAdoc.clear(); - if(buffReadConfigOTA != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); - buffer = OTAdoc.as(); - if(error) - Serial.println("# Error to DeserializeJson readLastedOTA"); - } - return buffer; -} - -String manageConfigOTAFile::readSpacificFromConfFile(String readKey) -{ - String result = readObjectConfigFileOTA()[readKey.c_str()]; - return result; -} - -boolean manageConfigOTAFile::saveProfileOTA(JsonObject dataOTA, String stateOTA) -{ - OTAdoc.clear(); - if(stateOTA != NULL && dataOTA.size() > 0) - { - OTAdoc = dataOTA; - OTAdoc.remove("Code"); - OTAdoc["status"] = stateOTA.c_str(); - - String contentToWrite; - serializeJson(OTAdoc, contentToWrite); - - bool saveFile = fileSys.writeFile(configOTAFilePath, contentToWrite.c_str()); - if(saveFile) - { - // Serial.println("# New Information OTA: "+contentToWrite); - Serial.println(F("# Save firmware information success!")); - } - return saveFile; - } - else - { - return false; - } -} - -boolean manageConfigOTAFile::saveLastedOTA(String lastedDataOTA) -{ - -// #ifdef ESP32 -// String buffReadLastedOTA = lastedDataOTA.c_str(); -// #elif defined ESP8266 -// String buffReadLastedOTA = lastedDataOTA; -// #endif - bool saveFile = false; - JsonObject buffer; - OTAdoc.clear(); - if(lastedDataOTA.c_str() != NULL) - { - DeserializationError error = deserializeJson(OTAdoc, lastedDataOTA.c_str()); - buffer = OTAdoc.as(); - if(error) - { - Serial.println("# Error to DeserializeJson saveLastedOTA"); - return false; - } - else - { - buffer.remove("status"); - String contentLasted; - serializeJson(buffer, contentLasted); - - saveFile = fileSys.writeFile(lastedOTAPath, contentLasted.c_str()); - if(saveFile) - { - // Serial.println("# New Information OTA: "+contentToWrite); - // Serial.println("# saveLastedOTA: "+contentLasted); - Serial.println(F("# Save lastedOTA success!")); - } - return saveFile; - } - } - return saveFile; -} - -boolean manageConfigOTAFile::saveSuccessOrFail(String stateOTA) -{ - JsonObject bufferProfile = readObjectConfigFileOTA(); - - StaticJsonDocument<512> docsBuffer = bufferProfile; - bufferProfile.remove("Code"); - docsBuffer["status"] = stateOTA.c_str(); - String ProfileUpdate; - serializeJson(docsBuffer, ProfileUpdate); - return fileSys.writeFile(configOTAFilePath, ProfileUpdate.c_str()); -} - -boolean manageConfigOTAFile::compareFirmwareOTA(JsonObject dataOTA) -{ - JsonObject bufferProfile = readObjectConfigFileOTA(); - String status = readSpacificFromConfFile("status"); - - String readFW_name = bufferProfile["namefirmware"]; - String incomingFW_name = dataOTA["namefirmware"]; - - size_t readFW_size = bufferProfile["sizefirmware"]; - size_t incomingFW_size = dataOTA["sizefirmware"]; - - String readFW_checksum = bufferProfile["checksum"]; - String incomingFW_checksum = dataOTA["checksum"]; - - String readFW_version = bufferProfile["versionfirmware"]; - String incomingFW_version = dataOTA["versionfirmware"]; - - String readFW_csAlg = bufferProfile["checksumAlgorithm"]; - String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; - - String readFW_cs = bufferProfile["checksum"]; - String incomingFW_cs = dataOTA["checksum"]; - - // Lasted check - JsonObject buffLasted = readObjectLastedOTA(); - - String LastedFW_name = buffLasted["namefirmware"]; - size_t LastedFW_Size = buffLasted["sizefirmware"]; - String LastedFW_checksum = buffLasted["checksum"]; - // Lasted check - if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") - { - Serial.println(F("")); - Serial.println(F("# Device is unknow version in file system")); - Serial.println(F("# Save firmware information")); - Serial.println("# ======== Information OTA ========"); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - // Serial.println("# firmware checksumAlgorithm: "+ incomingFW_csAlg); - Serial.println("# firmware checksum: "+ incomingFW_checksum); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && - readFW_checksum == incomingFW_checksum) - { - if(status == "done") - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# Firmware device version: "+ incomingFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else if(status == "fail" && !(LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) - { - Serial.println(F("")); - Serial.println(F("#[OTA Failed] Try to OTA firmware again")); - Serial.println(F("# ======== Information OTA ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - else{ - Serial.println(F("")); - Serial.println(F("# Keep going to OTA firmware again")); - Serial.println(F("# ======== Information OTA ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ incomingFW_version); - Serial.println(F("")); - return false; //false mean firmware not match - } - } - else{ // fw not match incoming != file => new version - if(status == "done") - { - Serial.println(F("")); - Serial.println(F("# Device have new version")); - Serial.println(F("# ======== Information OTA change ========")); - // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); - // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - else if(status != "done" && (LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - // Serial.println("# firmware name: "+ incomingFW_name); - // Serial.println("# firmware size: "+ String(incomingFW_size)); - Serial.println("# Firmware device version: "+ incomingFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else{ - Serial.println(F("")); - Serial.println("# Previous version OTA does not success status is: \""+ status +"\"# but have new version"); - Serial.println(F("# ======== Information OTA change ========")); - // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); - // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); - Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); - Serial.println(F("")); - saveProfileOTA(*&dataOTA, "initialize"); - return false; //false mean firmware not match - } - } -} - -boolean manageConfigOTAFile::compareFirmwareIsUpToDate(JsonObject dataOTA) -{ - JsonObject buffLastedOTA = readObjectLastedOTA(); - - String readFW_name = buffLastedOTA["namefirmware"]; - String incomingFW_name = dataOTA["namefirmware"]; - - size_t readFW_size = buffLastedOTA["sizefirmware"]; - size_t incomingFW_size = dataOTA["sizefirmware"]; - - String readFW_checksum = buffLastedOTA["checksum"]; - String incomingFW_checksum = dataOTA["checksum"]; - - String readFW_version = buffLastedOTA["versionfirmware"]; - String incomingFW_version = dataOTA["versionfirmware"]; - - String readFW_csAlg = buffLastedOTA["checksumAlgorithm"]; - String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; - - String readFW_cs = buffLastedOTA["checksum"]; - String incomingFW_cs = dataOTA["checksum"]; - - if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is out of date ========")); - Serial.println(F("# ======== Device unknown version ========")); - Serial.println("# New version is available: "+ incomingFW_version); - Serial.println(F("# ========================================")); - Serial.println(F("")); - return false; - } - if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && - readFW_checksum == incomingFW_checksum) - { - Serial.println(F("")); - Serial.println(F("# ======== Firmware is up to date ========")); - Serial.println("# Firmware device version: "+ readFW_version); - Serial.println(F("# =========================================")); - Serial.println(F("")); - return true; - } - else{ - Serial.println(F("")); - Serial.println(F("# ======== Firmware is out of date ========")); - Serial.println(F("# ======== NEW firmware available ========")); - Serial.println("# New version is available: "+ incomingFW_version); - Serial.println("# Firmware device version: "+ readFW_version); - Serial.println(F("# ========================================")); - Serial.println(F("")); - return false; - } -} \ No newline at end of file diff --git a/utils/manageConfigOTAFile.h b/utils/manageConfigOTAFile.h deleted file mode 100644 index c7b9946..0000000 --- a/utils/manageConfigOTAFile.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MANAGECONFIGOTAFILE_H -#define MANAGECONFIGOTAFILE_H -#include -#include "SPIFFS.h" -#include "FS.h" -#include -#include "FileSystem.h" -#include "../ArduinoJson-v6.18.3.h" -// typedef std::vector ListFileString; - -class manageConfigOTAFile -{ -private: - const char* configOTAFilePath = "/configOTAFile.json"; - const char* lastedOTAPath = "/lastedOTAFile.json"; - StaticJsonDocument<512> OTAdoc; -public: - void beginFileSystem(boolean formatIfFail = true); - boolean checkFileOTA(); - boolean checkLastedOTA(); - boolean createConfigFileOTA(); - boolean createLastedOTA(); - String readConfigFileOTA(); - String readLastedOTA(); - JsonObject readObjectConfigFileOTA(); - JsonObject readObjectLastedOTA(); - String readSpacificFromConfFile(String readKey); - boolean saveProfileOTA(JsonObject dataOTA, String stateOTA); - boolean saveLastedOTA(String lastedDataOTA); - boolean saveSuccessOrFail(String stateOTA); - boolean compareFirmwareOTA(JsonObject dataOTA); //using for incoming without check update - boolean compareFirmwareIsUpToDate(JsonObject dataOTA); //using when incoming by check update -}; -extern manageConfigOTAFile configOTAFile; -#endif \ No newline at end of file diff --git a/utils/utility.cpp b/utils/utility.cpp deleted file mode 100644 index 49f81b2..0000000 --- a/utils/utility.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include "./utility.h" - - tm utility::convertUnix(unsigned long unix, int timeZone) - { - time_t timestamp = unix + (timeZone * 60 * 60); - tm *local_time = gmtime(×tamp); - return *local_time; - } - - String utility::toDateTimeString(unsigned long unixtTime, int timeZone) - { - tm buff_tm = utls.convertUnix(unixtTime, timeZone); - char dateSTR[] = "00/00/0000 00:00:00"; - if(buff_tm.tm_year < 1900) - { - sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year + 1900, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); - } - else - { - sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); - } - return String(dateSTR); - } - - String utility::toUniversalTime(unsigned long unixtTime, int timeZone) - { - tm buff_tm = convertUnix(unixtTime, timeZone); - char _utc[] = "0000-00-00T00:00:00"; - char _lc[] = "00:00"; - char _lc_h[] = "00"; - String result = "0000-00-00T00:00:00+00:00"; - sprintf(_utc, "%04i-%02i-%02iT%02i:%02i:%02i", buff_tm.tm_year + 1900, buff_tm.tm_mon +1, buff_tm.tm_mday, - buff_tm.tm_hour,buff_tm.tm_min, buff_tm.tm_sec); - if(timeZone >= 0) - { - sprintf(_lc_h, "%02i", timeZone); - sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); - } - else{ - sprintf(_lc_h, "%03i", timeZone); - sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); - } - result = String(_utc) + String(_lc); - return result; - } - - unsigned long utility::toUnix(tm time_) - { - unsigned long _unix = (long)0000000000; - tm t; - t.tm_mday = time_.tm_mday; - t.tm_mon = time_.tm_mon; - if(time_.tm_year < 1900) - { - t.tm_year = time_.tm_year; - } - else - { - t.tm_year = time_.tm_year -1900; - } - t.tm_hour = time_.tm_hour; - t.tm_min = time_.tm_min; - t.tm_sec = time_.tm_sec; - t.tm_isdst = -1; - _unix = mktime(&t); - return _unix; - } - - boolean utility::StringIsDigit(String validate_str) - { - for(byte i = 0; i < validate_str.length(); i++) - { - if(!isDigit(validate_str.charAt(i))) return false; - } - return true; - } \ No newline at end of file diff --git a/utils/utility.h b/utils/utility.h deleted file mode 100644 index 186559d..0000000 --- a/utils/utility.h +++ /dev/null @@ -1,17 +0,0 @@ - -#ifndef UTILITY_H -#define UTILITY_H -#include - class utility - { - private: - - public: - String toDateTimeString(unsigned long unixtTime, int timeZone); - String toUniversalTime(unsigned long unixtTime, int timeZone); - unsigned long toUnix(tm time_); - tm convertUnix(unsigned long unix, int timeZone); - boolean StringIsDigit(String validate_str); - }; - extern utility utls; -#endif \ No newline at end of file From b90a5ae8e40e99194654ddae65b1244f21312d88 Mon Sep 17 00:00:00 2001 From: AIS IoT Platform Integration <113405874+AIS-DeviceIntegration@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:08:08 +0700 Subject: [PATCH 3/3] fix dir lib --- src/utils/Attribute_MQTT_core.cpp | 14 + src/utils/Attribute_MQTT_core.h | 92 + src/utils/BuiltinSensor.cpp | 481 ++++ src/utils/BuiltinSensor.h | 61 + src/utils/FileSystem.cpp | 209 ++ src/utils/FileSystem.h | 28 + src/utils/MAGELLAN_MQTT_device_core.cpp | 3068 +++++++++++++++++++++++ src/utils/MAGELLAN_MQTT_device_core.h | 313 +++ src/utils/StorageMemory.cpp | 154 ++ src/utils/StorageMemory.h | 33 + src/utils/manageConfigOTAFile.cpp | 326 +++ src/utils/manageConfigOTAFile.h | 35 + src/utils/utility.cpp | 78 + src/utils/utility.h | 17 + 14 files changed, 4909 insertions(+) create mode 100644 src/utils/Attribute_MQTT_core.cpp create mode 100644 src/utils/Attribute_MQTT_core.h create mode 100644 src/utils/BuiltinSensor.cpp create mode 100644 src/utils/BuiltinSensor.h create mode 100644 src/utils/FileSystem.cpp create mode 100644 src/utils/FileSystem.h create mode 100644 src/utils/MAGELLAN_MQTT_device_core.cpp create mode 100644 src/utils/MAGELLAN_MQTT_device_core.h create mode 100644 src/utils/StorageMemory.cpp create mode 100644 src/utils/StorageMemory.h create mode 100644 src/utils/manageConfigOTAFile.cpp create mode 100644 src/utils/manageConfigOTAFile.h create mode 100644 src/utils/utility.cpp create mode 100644 src/utils/utility.h diff --git a/src/utils/Attribute_MQTT_core.cpp b/src/utils/Attribute_MQTT_core.cpp new file mode 100644 index 0000000..e5151f8 --- /dev/null +++ b/src/utils/Attribute_MQTT_core.cpp @@ -0,0 +1,14 @@ +/* +library version: v2.5.3 +Author:Worawit Sayned (POC Device Magellan team) +Create Date: 25 April 2022. +Modified: 1 september 2022. +Released for private usage. +*/ +#include "Attribute_MQTT_core.h" + +BuiltinSensor mySensor; +utility utls; +StorageMemory ext_mem; +FileSystem fileSys; +manageConfigOTAFile configOTAFile; \ No newline at end of file diff --git a/src/utils/Attribute_MQTT_core.h b/src/utils/Attribute_MQTT_core.h new file mode 100644 index 0000000..a1b6db3 --- /dev/null +++ b/src/utils/Attribute_MQTT_core.h @@ -0,0 +1,92 @@ +/* +Author:(POC Device Magellan team) +Create Date: 25 April 2022. +Modified: 16 february 2023. +Released for private usage. +*/ +#ifndef ATTRIBUTE_CORE_H +#define ATTRIBUTE_CORE_H +#include +#include +#include "../PubSubClient.h" +#include "../ArduinoJson-v6.18.3.h" +#include "./StorageMemory.h" +#include "./FileSystem.h" +#include "./BuiltinSensor.h" +#include "./manageConfigOTAFile.h" +#define useGSMClient 0 +#define useExternalClient 1 +#include "SPIFFS.h" + +#define _major_ver 1 +#define _feature_ver 2 +#define _enhance_ver 0 +#define lib_ver "v"+String(_major_ver) +"."+ String(_feature_ver)+"."+String(_enhance_ver) + +class Attribute_MQTT_core +{ +public: + static boolean isBypassAutoUpdate; + static boolean usingCheckUpdate; + static boolean checkFirmwareUptodate; + static boolean isFirmwareUptodate; + static boolean flagAutoOTA; + static unsigned long prv_cb_timeout_millis; + static unsigned int timeout_req_download_fw; + static boolean checkTimeout_request_download_fw; + static boolean remind_Event_GET_FW_infoOTA; + static boolean triggerRemainOTA; + static boolean triggerRemainSub; + static boolean remain_ota_fw_info_match; + static String valid_remain_fw_name; + static unsigned int valid_remain_fw_size; + static boolean flag_remain_ota; + static boolean ctrl_regis_key; + static boolean ctrl_regis_pta; + static boolean ctrl_regis_json; + static boolean conf_regis_key; + static boolean conf_regis_pta; + static boolean conf_regis_json; + static boolean resp_regis; + static boolean ctrl_jsonOBJ; + static boolean conf_jsonOBJ; + static boolean using_Checksum; + static boolean useAdvanceCallback; + static String ext_Token; + static String ext_EndPoint; + static int clientNetInterface; + static Client *ClientNET; + static PubSubClient *mqtt_client; //MQTT Client + static unsigned int fw_count_chunk; + static unsigned int fw_total_size; + static unsigned int chunk_size; + static unsigned int default_chunk_size; + static unsigned int totalChunk; + static unsigned int current_chunk; + static unsigned int current_size; + static size_t incomingChunkSize; + static size_t calculate_chunkSize; + static boolean inProcessOTA; + static boolean startReqDownloadOTA; + static String sensorJSON_str; + static String clientConfigJSON_str; + static boolean useBuiltInSensor; + static StaticJsonDocument<512> docClientConf; + static DynamicJsonDocument *adjDoc; + static DynamicJsonDocument *docSensor; + //1.2.0 + static boolean checkUpdate_inside; + static unsigned int delayCheckUpdate_inside; + static unsigned int delayRequest_download; + static size_t buffer_JSON_bufferSize; + static size_t max_payload_report; + static int matchMsgId_cb; + static int matchMsgId_send; + static int maxRetransmit; + + static boolean isMatchMsgId; + static boolean reqRetransmit; + +}; +extern Attribute_MQTT_core attr; +#endif \ No newline at end of file diff --git a/src/utils/BuiltinSensor.cpp b/src/utils/BuiltinSensor.cpp new file mode 100644 index 0000000..f11be75 --- /dev/null +++ b/src/utils/BuiltinSensor.cpp @@ -0,0 +1,481 @@ +#include +#include "./BuiltinSensor.h" + +int cnt_initGPS = 0; +int timeoutInitGPS = 300; // 30 sec 300 * 100 ms = 3000 ms + +void BuiltinSensor::gps_begin() +{ + if(attr.clientNetInterface == useExternalClient) + { + while (!GSM.begin()) + { + Serial.println(F("# Try to connect GPS...")); + } + } + while (!GPS.begin()) + { + if (cnt_initGPS >= timeoutInitGPS) + { + Serial.println(F("GPS Setup timeout exist from initial GPS...")); + break; + } + Serial.println(F("GPS Setup fail")); + delay(100); + cnt_initGPS++; + } +} + +void BuiltinSensor::begin() +{ + Wire.begin(); + SHT40.begin(); + gps_begin(); +} + +info_gps BuiltinSensor::getGPS_info() +{ + info_gps buffer_infoGPS; + if (!attr.useBuiltInSensor) + { + Serial.println(F("# Please allow \"true\" useBuiltinSensor in begin function")); + buffer_infoGPS.latitude = 0.00000f; + buffer_infoGPS.longitude = 0.00000f; + buffer_infoGPS.altitude = 0.00000f; + buffer_infoGPS.speed = 0.00000f; + buffer_infoGPS.course = 0.00000f; + return buffer_infoGPS; + } + if (GPS.available()) + { + buffer_infoGPS.latitude = GPS.latitude(); + buffer_infoGPS.longitude = GPS.longitude(); + buffer_infoGPS.altitude = GPS.altitude(); + buffer_infoGPS.speed = GPS.speed(); + buffer_infoGPS.course = GPS.course(); + } + else + { + Serial.println("# GPS not ready"); + buffer_infoGPS.latitude = 0.00000f; + buffer_infoGPS.longitude = 0.00000f; + buffer_infoGPS.altitude = 0.00000f; + buffer_infoGPS.speed = 0.00000f; + buffer_infoGPS.course = 0.00000f; + } + return buffer_infoGPS; +} + +float BuiltinSensor::readLatitude() +{ + float _lat = 0.000000f; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readLatitude\" allow \"true\" useBuiltinSensor in begin function")); + return _lat; + } + else + { + _lat = getGPS_info().latitude; + } + return _lat; +} +float BuiltinSensor::readLongitude() +{ + float _lng = 0.000000f; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readLongitude\" allow \"true\" useBuiltinSensor in begin function")); + return _lng; + } + else + { + _lng = getGPS_info().longitude; + } + return _lng; +} + +String BuiltinSensor::readLocation() +{ + // String _location = "0.000000,0.000000"; + char _location[] = "0.000000,0.000000"; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readLocation\" allow \"true\" useBuiltinSensor in begin function")); + return String(_location); + } + else + { + sprintf(_location, "%.4f,%.4f", readLatitude(), readLongitude()); + } + return _location; +} + +float BuiltinSensor::readSpeed() +{ + float _speed = 0.000000f; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readSpeed\" allow \"true\" useBuiltinSensor in begin function")); + return _speed; + } + else + { + _speed = getGPS_info().speed; + } + return _speed; +} + +float BuiltinSensor::readAltitude() +{ + float _alt = 0.000000f; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readAltitude\" allow \"true\" useBuiltinSensor in begin function")); + return _alt; + } + else + { + _alt = getGPS_info().altitude; + } + return _alt; +} + +float BuiltinSensor::readCourse() +{ + float _course = 0.000000f; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"readCourse\" allow \"true\" useBuiltinSensor in begin function")); + return _course; + } + else + { + _course = getGPS_info().course; + } + return _course; +} + +float BuiltinSensor::readTemperature() +{ + float temp = -1; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"Temperature\" allow \"true\" useBuiltinSensor in begin function")); + return temp; + } + else + { + temp = SHT40.readTemperature(); + } + return temp; +} +float BuiltinSensor::readHumidity() +{ + float humid = -1; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"Humidity\" allow \"true\" useBuiltinSensor in begin function")); + return humid; + } + else + { + humid = SHT40.readHumidity(); + } + return humid; +} + +boolean BuiltinSensor::GPSavailable() +{ + bool GPS_state = false; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] GPS not available please allow \"true\" useBuiltinSensor in begin function")); + } + else{ + GPS_state = GPS.available(); + if(!GPS_state) + { + // Serial.println(F("# GPS not available please check signal or antenna GPS connect to board")); + } + } + return GPS_state; +} + +void BuiltinSensor::setLocalTimeZone(int timeZone) +{ + char _lc[] = "00:00"; + char _lc_h[] = "00"; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't set \"setLocalTimeZone\" allow \"true\" useBuiltinSensor in begin function")); + } + else{ + this->local_timeZone = timeZone; + if(local_timeZone >= 0) + { + sprintf(_lc_h, "%02i", local_timeZone); + sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); + } + else + { + sprintf(_lc_h, "%03i", local_timeZone); + sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); + } + Serial.println("# Setting local timezone on GPS GMT: " + String(_lc)); + } +} + +// tm BuiltinSensor::utls.convertUnix(unsigned long unix, int timeZone) +// { +// time_t timestamp = unix + (timeZone * secPerHour); +// tm *local_time = gmtime(×tamp); +// return *local_time; +// } + +int BuiltinSensor::getDay() +{ + int _day = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getDay\" allow \"true\" useBuiltinSensor in begin function")); + return _day; + } + else + { + if(GPS.available()) + { + _day = utls.convertUnix(GPS.getTime(), local_timeZone).tm_mday; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + + return _day; +} + +String BuiltinSensor::getDayToString() +{ + return String(getDay()); +} + +int BuiltinSensor::getMonth() +{ + int _month = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getMonth\" allow \"true\" useBuiltinSensor in begin function")); + return _month; + } + else + { + if(GPS.available()) + { + _month = utls.convertUnix(GPS.getTime(), local_timeZone).tm_mon; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _month; +} + +String BuiltinSensor::getMonthToString() +{ + return String(getMonth()); +} + +int BuiltinSensor::getYear() +{ + int _year = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getYear\" allow \"true\" useBuiltinSensor in begin function")); + return _year; + } + else + { + if(GPS.available()) + { + _year = utls.convertUnix(GPS.getTime(), local_timeZone).tm_year + 1900; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _year; +} + +String BuiltinSensor::getYearToString() +{ + return String(getYear()); +} + +int BuiltinSensor::getHour() +{ + int _hour = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getHour\" allow \"true\" useBuiltinSensor in begin function")); + return _hour; + } + else + { + if(GPS.available()) + { + + _hour = utls.convertUnix(GPS.getTime(), local_timeZone).tm_hour; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _hour; +} + +String BuiltinSensor::getHourToString() +{ + return String(getHour()); +} + +int BuiltinSensor::getMinute() +{ + int _minute = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getMinute\" allow \"true\" useBuiltinSensor in begin function")); + return _minute; + } + else + { + if(GPS.available()) + { + _minute = utls.convertUnix(GPS.getTime(), local_timeZone).tm_min; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _minute; +} + +String BuiltinSensor::getMinuteToString() +{ + return String(getMinute()); +} + +int BuiltinSensor::getSecond() +{ + int _sec = 0; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getSecond\" allow \"true\" useBuiltinSensor in begin function")); + return _sec; + } + else + { + if(GPS.available()) + { + _sec = utls.convertUnix(GPS.getTime(), local_timeZone).tm_sec; + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _sec; +} + +String BuiltinSensor::getSecondToString() +{ + return String(getSecond()); +} + +String BuiltinSensor::getDateTimeString() +{ + tm buff_tm = utls.convertUnix(GPS.getTime(), local_timeZone); + char dateSTR[] = "00/00/0000 00:00:00"; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getDateTimeString\" allow \"true\" useBuiltinSensor in begin function")); + return String(dateSTR); + } + else + { + if(GPS.available()) + { + sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon, buff_tm.tm_year + 1900, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return String(dateSTR); +} + +String BuiltinSensor::getUniversalTime() +{ + tm buff_tm = utls.convertUnix(GPS.getTime(), local_timeZone); + char _utc[] = "0000-00-00T00:00:00"; + char _lc[] = "00:00"; + char _lc_h[] = "00"; + String result = "0000-00-00T00:00:00+00:00"; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getUniversalTime\" allow \"true\" useBuiltinSensor in begin function")); + return result; + } + else + { + if(GPS.available()) + { + sprintf(_utc, "%04i-%02i-%02iT%02i:%02i:%02i", buff_tm.tm_year + 1900, buff_tm.tm_mon, buff_tm.tm_mday, + buff_tm.tm_hour,buff_tm.tm_min, buff_tm.tm_sec); + + if(local_timeZone >= 0) + { + sprintf(_lc_h, "%02i", local_timeZone); + sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); + } + else{ + sprintf(_lc_h, "%03i", local_timeZone); + sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); + } + result = String(_utc) + String(_lc); + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return result; +} + +unsigned long BuiltinSensor::getUnixTime() +{ + unsigned long _unix = (long)0000000000; + if (!attr.useBuiltInSensor) + { + Serial.println(F("#[Warning] Can't read \"getUnixTime\" allow \"true\" useBuiltinSensor in begin function")); + return _unix; + } + else + { + if(GPS.available()) + { + tm t; + tm buff_tm = utls.convertUnix(GPS.getTime(), 0); + t.tm_mday = buff_tm.tm_mday; + t.tm_mon = buff_tm.tm_mon -1; + t.tm_year = buff_tm.tm_year; + t.tm_hour = buff_tm.tm_hour; + t.tm_min = buff_tm.tm_min; + t.tm_sec = buff_tm.tm_sec; + t.tm_isdst = -1; + _unix = mktime(&t); + } + else{ + Serial.println(F("# GPS not ready")); + } + } + return _unix; +} diff --git a/src/utils/BuiltinSensor.h b/src/utils/BuiltinSensor.h new file mode 100644 index 0000000..7620337 --- /dev/null +++ b/src/utils/BuiltinSensor.h @@ -0,0 +1,61 @@ +#ifndef BUILTINSENSOR_H +#define BUILTINSENSOR_H + +#include +#include +#include +#include +#include +#include "./Attribute_MQTT_core.h" +#include +#include "./utility.h" +struct info_gps{ + float latitude = 0.0000f; + float longitude = 0.0000f; + float altitude = 0.0000f; + float speed = 0.0000f; + float course = 0.0000f; +}; +class BuiltinSensor: private utility +{ + private: + const int secPerHour = 3600; + void gps_begin(); + int local_timeZone = 7; + info_gps getGPS_info(); + // tm convertUnix(unsigned long unix, int timeZone = 7); + public: + void begin(); + boolean GPSavailable(); + + float readLatitude(); + float readLongitude(); + float readAltitude(); + float readSpeed(); + float readCourse(); + float readTemperature(); + float readHumidity(); + String readLocation(); + + void setLocalTimeZone(int timeZone); + int getDay(); + String getDayToString(); + int getMonth(); + String getMonthToString(); + int getYear(); + String getYearToString(); + int getHour(); + String getHourToString(); + int getMinute(); + String getMinuteToString(); + int getSecond(); + String getSecondToString(); + String getDateTimeString();//* + String getUniversalTime();//* + unsigned long getUnixTime(); //* + +}; + +extern BuiltinSensor mySensor; + +#endif \ No newline at end of file diff --git a/src/utils/FileSystem.cpp b/src/utils/FileSystem.cpp new file mode 100644 index 0000000..4600a49 --- /dev/null +++ b/src/utils/FileSystem.cpp @@ -0,0 +1,209 @@ +#include +#include "./FileSystem.h" +#define DEBUG false //set to true for debug output, false for no debug output +#define DEBUG_SERIAL if(DEBUG)Serial + +void FileSystem::begin(boolean format_if_failed) +{ + if(!SPIFFS.begin(format_if_failed)) + { + DEBUG_SERIAL.println("- FileSystem Mount Failed"); + return; + } + +} +ListFileString FileSystem::listDirectory(const char* dir_name, uint8_t level, fs::FS &fs) +{ + ListFileString list; + DEBUG_SERIAL.printf("Listing directory: %s\r\n", dir_name); + + File root = fs.open(dir_name); + if(!root){ + DEBUG_SERIAL.println("− failed to open directory"); + return list; + } + if(!root.isDirectory()){ + DEBUG_SERIAL.println(" − not a directory"); + return list; + } + + File file = root.openNextFile(); + if(!file) + { + DEBUG_SERIAL.printf("- not found directory in directory: %s\r\n", dir_name); + } + while(file){ + if(file.isDirectory()){ + DEBUG_SERIAL.print(" DIR : "); + DEBUG_SERIAL.println(file.name()); + list.push_back(file.name()); + if(level){ + listDirectory(file.name(), level -1); + } + } + file = root.openNextFile(); + } + return list; +} + +ListFileString FileSystem::listFile(const char* dir_name, fs::FS &fs) +{ + ListFileString list; + DEBUG_SERIAL.printf("Listing File: %s\r\n", dir_name); + + File root = fs.open(dir_name); + if(!root){ + DEBUG_SERIAL.println("− failed to open directory"); + return list; + } + + File file = root.openNextFile(); + if(!file) + { + DEBUG_SERIAL.printf("- not found file in directory: %s\r\n", dir_name); + } + while(file){ + if(!file.isDirectory()){ + DEBUG_SERIAL.print(" FILE: "); + DEBUG_SERIAL.print(file.name()); + list.push_back(file.name()); + DEBUG_SERIAL.print("\tSIZE: "); + DEBUG_SERIAL.println(file.size()); + } + file = root.openNextFile(); + } + return list; +} + +String FileSystem::readBigFile(const char* path, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Reading file: %s\r\n", path); + String _read_buffer; + File file = fs.open(path); + if(!file || file.isDirectory()) + { + DEBUG_SERIAL.println(F("- faild to open file for reading")); + return "null"; + } + + DEBUG_SERIAL.println("- read from file size:"+String(file.size())); + while(file.available()) + { + char buff[65000]; + int l = file.readBytesUntil('\n', buff, sizeof(buff)); + buff[l] = 0; + _read_buffer.concat(buff); + + } + return _read_buffer; +} + +ListFileString FileSystem::readLargeFile(const char* path, fs::FS &fs) +{ + ListFileString list; + DEBUG_SERIAL.printf("Reading file: %s\r\n", path); + char* buffer; + String _read_buffer; + File file = fs.open(path); + if(!file || file.isDirectory()) + { + DEBUG_SERIAL.println(F("- faild to open file for reading")); + return list; + } + + DEBUG_SERIAL.println("- read from file size:"+String(file.size())); + while(file.available()) + { + list.push_back(file.readStringUntil('\n').c_str()); + } + file.close(); + return list; +} + +String FileSystem::readFile(const char* path, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Reading file: %s\r\n", path); + char *buffer; + File file = fs.open(path); + if(!file || file.isDirectory()) + { + DEBUG_SERIAL.println(F("- faild to open file for reading")); + return "null"; + } + DEBUG_SERIAL.println(F("- read from file:")); + while(file.available()) + { + buffer = new char[file.size() +2]; + strcpy(buffer, file.readString().c_str()); + } + file.close(); + return String(buffer); +} + +boolean FileSystem::writeFile(const char* path, const char * message, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Writing file: %s\r\n", path); + + File file = fs.open(path, FILE_WRITE); + if(!file){ + DEBUG_SERIAL.println("− failed to open file for writing"); + return false; + } + if(file.print(message)){ + DEBUG_SERIAL.println("− file written"); + file.close(); + return true; + }else { + DEBUG_SERIAL.println("− frite failed"); + return false; + } +} + +boolean FileSystem::appendFile(const char* path, const char * message, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Appending to file: %s\r\n", path); + + File file = fs.open(path, FILE_APPEND); + if(!file){ + DEBUG_SERIAL.println("− failed to open file for appending"); + return false; + } + if(file.print(message)){ + DEBUG_SERIAL.println("− message appended"); + file.close(); + return true; + } else { + DEBUG_SERIAL.println("− append failed"); + return false; + } +} + +boolean FileSystem::renameFile(const char* old_path, const char * new_path, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Renaming file %s to %s\r\n", old_path, new_path); + if (fs.rename(old_path, new_path)) { + DEBUG_SERIAL.println("− file renamed"); + return true; + } else { + DEBUG_SERIAL.println("− rename failed"); + return false; + } +} + +boolean FileSystem::deleteFile(const char* path, fs::FS &fs) +{ + DEBUG_SERIAL.printf("Deleting file: %s\r\n", path); + if(fs.remove(path)){ + DEBUG_SERIAL.println("− file deleted"); + return true; + } else { + DEBUG_SERIAL.println("− delete failed"); + return false; + } +} + +boolean FileSystem::isFileExist(const char* path, fs::FS &fs) +{ + return fs.exists(path); +} + diff --git a/src/utils/FileSystem.h b/src/utils/FileSystem.h new file mode 100644 index 0000000..5f8e7dc --- /dev/null +++ b/src/utils/FileSystem.h @@ -0,0 +1,28 @@ +#ifndef FILESYSTEM_H +#define FILESYSTEM_H +#include +#include "SPIFFS.h" +#include "FS.h" +#include + +typedef std::vector ListFileString; + +class FileSystem +{ +private: + +public: + void begin(boolean format_if_failed = true); + ListFileString listDirectory(const char* dir_name, uint8_t level, fs::FS &fs = SPIFFS); + ListFileString listFile(const char* dir_name, fs::FS &fs = SPIFFS); + String readFile(const char* path, fs::FS &fs = SPIFFS); //limit filesize can read 60081 can't 63207 + String readBigFile(const char* path, fs::FS &fs = SPIFFS); + ListFileString readLargeFile(const char* path, fs::FS &fs = SPIFFS); + boolean writeFile(const char* path, const char * message, fs::FS &fs = SPIFFS); + boolean appendFile(const char* path, const char * message, fs::FS &fs = SPIFFS); + boolean renameFile(const char* old_path, const char * new_path, fs::FS &fs = SPIFFS); + boolean deleteFile(const char* path, fs::FS &fs = SPIFFS); + boolean isFileExist(const char* path, fs::FS &fs = SPIFFS); +}; +extern FileSystem fileSys; +#endif \ No newline at end of file diff --git a/src/utils/MAGELLAN_MQTT_device_core.cpp b/src/utils/MAGELLAN_MQTT_device_core.cpp new file mode 100644 index 0000000..dc9ab85 --- /dev/null +++ b/src/utils/MAGELLAN_MQTT_device_core.cpp @@ -0,0 +1,3068 @@ +/* +Copyright (c) 2020, Advanced Wireless Network +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +support SIMCOM SIM7600E(AIS 4G Board) + +Author:(POC Device Magellan team) +Create Date: 25 April 2022. +Modified: 22 may 2023. +Released for private usage. +*/ + +#include "MAGELLAN_MQTT_device_core.h" +StaticJsonDocument<512> intern_docJSON; +boolean Attribute_MQTT_core::isBypassAutoUpdate = false; // false = autoUpdate, true = unuse autoUpdate +boolean Attribute_MQTT_core::usingCheckUpdate = false; +boolean Attribute_MQTT_core::checkFirmwareUptodate = false; +boolean Attribute_MQTT_core::isFirmwareUptodate = false; +boolean Attribute_MQTT_core::flagAutoOTA = true; +size_t Attribute_MQTT_core::calculate_chunkSize = 0; // calculate part size from clientBuffer +size_t Attribute_MQTT_core::incomingChunkSize = 0; +unsigned int Attribute_MQTT_core::fw_total_size = 0; +unsigned int Attribute_MQTT_core::fw_count_chunk = 0; +unsigned int Attribute_MQTT_core::chunk_size = 0; +unsigned int Attribute_MQTT_core::totalChunk = 0; +unsigned int Attribute_MQTT_core::current_chunk = 0; +unsigned int Attribute_MQTT_core::current_size = 0; +unsigned int Attribute_MQTT_core::default_chunk_size = 4096; +int Attribute_MQTT_core::clientNetInterface; +Client *Attribute_MQTT_core::ClientNET = NULL; +PubSubClient *Attribute_MQTT_core::mqtt_client = NULL; // MQTT Client +boolean Attribute_MQTT_core::ctrl_regis_key = false; +boolean Attribute_MQTT_core::ctrl_regis_pta = false; +boolean Attribute_MQTT_core::ctrl_regis_json = false; +boolean Attribute_MQTT_core::conf_regis_key = false; +boolean Attribute_MQTT_core::conf_regis_pta = false; +boolean Attribute_MQTT_core::conf_regis_json = false; +boolean Attribute_MQTT_core::resp_regis = false; +boolean Attribute_MQTT_core::ctrl_jsonOBJ = false; +boolean Attribute_MQTT_core::conf_jsonOBJ = false; +boolean Attribute_MQTT_core::using_Checksum = false; +boolean Attribute_MQTT_core::useAdvanceCallback = false; +String Attribute_MQTT_core::ext_Token; +String Attribute_MQTT_core::ext_EndPoint; +boolean Attribute_MQTT_core::inProcessOTA = false; +boolean Attribute_MQTT_core::useBuiltInSensor = false; +boolean Attribute_MQTT_core::remain_ota_fw_info_match = false; +boolean Attribute_MQTT_core::flag_remain_ota = false; +String Attribute_MQTT_core::valid_remain_fw_name = ""; +unsigned int Attribute_MQTT_core::valid_remain_fw_size = 0; +boolean Attribute_MQTT_core::triggerRemainOTA = true; +boolean Attribute_MQTT_core::triggerRemainSub = true; +boolean Attribute_MQTT_core::remind_Event_GET_FW_infoOTA = false; +boolean Attribute_MQTT_core::startReqDownloadOTA = false; +boolean Attribute_MQTT_core::checkTimeout_request_download_fw = false; +unsigned int Attribute_MQTT_core::timeout_req_download_fw = 180000; +unsigned long Attribute_MQTT_core::prv_cb_timeout_millis = 0; +StaticJsonDocument<512> Attribute_MQTT_core::docClientConf; +DynamicJsonDocument *Attribute_MQTT_core::adjDoc = new DynamicJsonDocument(256); +DynamicJsonDocument *Attribute_MQTT_core::docSensor = new DynamicJsonDocument(1024); +// 1.1.2 +unsigned int Attribute_MQTT_core::delayRequest_download = 0; +boolean Attribute_MQTT_core::checkUpdate_inside = false; +unsigned int Attribute_MQTT_core::delayCheckUpdate_inside = 60000; +size_t Attribute_MQTT_core::buffer_JSON_bufferSize = 1024; +size_t Attribute_MQTT_core::max_payload_report = 50000; +int Attribute_MQTT_core::matchMsgId_cb = -1; +int Attribute_MQTT_core::matchMsgId_send = -1; +int Attribute_MQTT_core::maxRetransmit = 5; +boolean Attribute_MQTT_core::isMatchMsgId = false; +boolean Attribute_MQTT_core::reqRetransmit = false; + +OTA_INFO MAGELLAN_MQTT_device_core::OTA_info; +func_callback_registerList MAGELLAN_MQTT_device_core::duplicate_subs_list; + +boolean attemp_download_1 = false; +boolean attemp_download_2 = false; + +String b2str(byte *payload, unsigned int length) // convert byte* to String +{ + char buffer_payload[length + 1] = {0}; + memcpy(buffer_payload, (char *)payload, length); + return String(buffer_payload); +} + +typedef struct +{ + String registerKey; + ctrl_handleCallback ctrl_key_callback; + ctrl_Json_handleCallback ctrl_Json_callback; + ctrl_PTAhandleCallback ctrl_pta_callback; + ctrl_JsonOBJ_handleCallback ctrl_obj_callback; + + conf_handleCallback conf_key_callback; + conf_Json_handleCallback conf_json_callback; + conf_PTAhandleCallback conf_pta_callback; + conf_JsonOBJ_handleCallback conf_obj_callback; + resp_callback resp_h_callback; + + void *next; + unsigned int Event; + unsigned int RESP_Events; + +} regisAPI; + +regisAPI *_startRegis = NULL; // buffer callback +regisAPI *_startRegisPTA = NULL; // buffer callback +regisAPI *_startRegisJSON = NULL; // buffer callback +regisAPI *_startRegisConf = NULL; // buffer callback +regisAPI *_startRegisPTAConf = NULL; // buffer callback +regisAPI *_startRegisJSONConf = NULL; // buffer callback +regisAPI *_startRESP = NULL; + +regisAPI *_startOBJ_CTRL = NULL; +regisAPI *_startOBJ_CONF = NULL; + +boolean ext_useAdvanceCallback = false; + +Centric centric; + +void (*cb_internal)(EVENTS events, char *); + +JsonObject deJson(String jsonContent) +{ + JsonObject buffer; + intern_docJSON.clear(); + if (jsonContent != NULL && jsonContent != "clear") + { + DeserializationError error = deserializeJson(intern_docJSON, jsonContent); + buffer = intern_docJSON.as(); + if (error) + Serial.println("# Error to DeserializeJson Control"); + } + return buffer; +} + +String deControl(String jsonContent) +{ + String content = "40300"; + JsonObject buffdoc = deJson(jsonContent); + String statusCode = buffdoc["Code"]; + String buffDelta; + if (statusCode == "20000") + { + if (jsonContent.indexOf("Delta") != -1) + { + buffDelta = buffdoc["Delta"].as(); + content = buffDelta; + } + else if (jsonContent.indexOf("Sensor") != -1) + { + buffDelta = buffdoc["Sensor"].as(); + content = buffDelta; + } + } + return content; +} + +String deConfig(String jsonContent) +{ + String content = "40300"; + JsonObject buffdoc = deJson(jsonContent); + String statusCode = buffdoc["Code"]; + String buffDelta; + if (statusCode == "20000") + { + if (jsonContent.indexOf("Config") != -1) + { + buffDelta = buffdoc["Config"].as(); + content = buffDelta; + } + } + return content; +} +/////////// Feature OTA function none member in class ////////////////////// +boolean pubClientConfig(String payload) // for external function member +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/config/persist"; + boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), payload.c_str()); + bool _debug_ = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Save ClientConfig: " + _debug_); + Serial.println("# [Clientconfigs]: " + payload); + return Pub_status; +} + + +boolean sub_InfoOTA() +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/resp"; + boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); + // Serial.println(topic); + String Debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Subscribe Firmware Information: " + Debug); + return Sub_status; +} + +boolean unsub_InfoOTA() +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/resp"; + boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); + // Serial.println(topic); + String Debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Firmware Information: " + Debug); + return Sub_status; +} + +boolean pub_Info() +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwareinfo/req"; + boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); + // Serial.println(topic); + String Debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Request Firmware Information: " + Debug); + return Pub_status; +} + +boolean sub_DownloadOTA() +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/resp/+"; + boolean Sub_status = attr.mqtt_client->subscribe(topic.c_str()); + // Serial.println(topic); + String Debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Subscribe Firmware Download: " + Debug); + return Sub_status; +} + +boolean unsub_DownloadOTA() +{ + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/resp/+"; + boolean Sub_status = attr.mqtt_client->unsubscribe(topic.c_str()); + // Serial.println(topic); + String Debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Firmware Download: " + Debug); + return Sub_status; +} + +boolean pub_Download(unsigned int fw_chunk, size_t chunk_size) +{ + if (fw_chunk == 0) + { + attr.startReqDownloadOTA = true; + } + attr.checkTimeout_request_download_fw = true; + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/req/" + String(fw_chunk) + "?filesize=" + String(chunk_size); + boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), " "); + // Serial.println(topic); + String Debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("------------------------------>")); + Serial.println("# ->Request Firmware Download on chunk: " + String(fw_chunk) + " Status: " + Debug); + Serial.println("# ->Chunk size request: " + String(chunk_size)); + return Pub_status; +} +// pre ver.1.1.2 +boolean pub_Download(unsigned int fw_chunk, size_t chunk_size, String versionName) +{ + if (fw_chunk == 0) + { + attr.startReqDownloadOTA = true; + } + attr.checkTimeout_request_download_fw = true; + String topic = "api/v2/thing/" + attr.ext_Token + "/firmwaredownload/req/" + String(fw_chunk) + "?filesize=" + String(chunk_size); + String payload = "{\"FirmwareVersion\" : \"" + versionName + "\"}"; + boolean Pub_status = attr.mqtt_client->publish(topic.c_str(), payload.c_str()); + // Serial.println(topic); + String Debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("------------------------------>")); + Serial.println("# ->Request Firmware Download by version name \"" + versionName + "\"on chunk: " + String(fw_chunk) + " Status: " + Debug); + Serial.println("# ->Chunk size request: " + String(chunk_size)); + return Pub_status; +} + +boolean pub_UpdateProgress(String FOTA_State, String description) +{ + delay(3000); + String topic = "api/v2/thing/" + attr.ext_Token + "/fotaupdateprogress/req/?FOTAState=" + FOTA_State; + boolean Pub_status = false; + if (description.indexOf("description") != -1 || description.indexOf("Version") != -1) + { + Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); + Pub_status = attr.mqtt_client->publish(topic.c_str(), description.c_str()); + Serial.println(F("-------------------------------")); + Serial.println("# STATE OTA Description: " + description); + Serial.println(F("-------------------------------")); + } + else + { + Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); + Pub_status = attr.mqtt_client->publish(topic.c_str(), ""); + } + + String Debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Update Progress OTA state discription: \"" + FOTA_State + "\" Status: " + Debug); + return Pub_status; +} + +boolean check_remain_fw_isMatch(String validate_fw_name, unsigned int validate_fw_size, String descriptionWhenFail) +{ + + if (MAGELLAN_MQTT_device_core::OTA_info.firmwareName == validate_fw_name && + MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize == validate_fw_size) + { + Serial.println(F("# Check firmware information incoming is match OTA still working")); // re new description + return true; + } + else + { + Serial.println(F("# Check firmware information does not match after reconnect")); + // pub_UpdateProgress("FAILED","{\"errordescription\":\""+descriptionWhenFail+"(version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " " + descriptionWhenFail + "\"}"); + configOTAFile.saveSuccessOrFail("fail"); + + + + return false; + } +} + +void checkUpdate(String topic, String payload) +{ + if (topic.indexOf("/firmwareinfo/resp") != -1) + { + Serial.println(F("========================")); + Serial.println(F("# Check incoming firmware update")); + if (payload != "{}" && payload.indexOf("20000") != -1) + { + JsonObject fw_doc = deJson(payload); + String name = fw_doc["namefirmware"]; + unsigned int size = fw_doc["sizefirmware"]; + String version = fw_doc["versionfirmware"]; + String c_sum = fw_doc["checksum"]; + String al_c_sum = fw_doc["checksumAlgorithm"]; + attr.valid_remain_fw_name = name; + attr.valid_remain_fw_size = size; + if (name == "null" && size <= 0) + { + Serial.println(F("# [warning]Firmware Information is wrong or empty!")); + } + else + { + attr.checkFirmwareUptodate = configOTAFile.compareFirmwareIsUpToDate(fw_doc); + + MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; + MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; + MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; + MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; + + if (attr.checkFirmwareUptodate) + { + MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = UP_TO_DATE; + } + else + { + MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = OUT_OF_DATE; + } + attr.usingCheckUpdate = false; + } + } + } +} + +void save_fw_info(String topic, String payload) +{ + // Serial.println("-save_fw_info: "+payload); + if (topic.indexOf("/firmwareinfo/resp") != -1) + { + Serial.println(F("=======================")); + Serial.println(F("# Detect incoming Firmware Information")); + if (payload != "{}" && payload.indexOf("20000") != -1) + { + JsonObject fw_doc = deJson(payload); + String name = fw_doc["namefirmware"]; + unsigned int size = fw_doc["sizefirmware"]; + String version = fw_doc["versionfirmware"]; + String c_sum = fw_doc["checksum"]; + String al_c_sum = fw_doc["checksumAlgorithm"]; + attr.valid_remain_fw_name = name; + attr.valid_remain_fw_size = size; + if (name == "null" && size <= 0) + { + Serial.println(F("# [warning]Firmware Information is wrong or empty!")); + } + else // validate data pass + { + if ((attr.inProcessOTA) && (attr.flag_remain_ota)) // inprocess but remain connect with broker + { + attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, + attr.valid_remain_fw_size, "is mismatch from server"); // OTA renew description + + attr.flag_remain_ota = false; + Serial.println(F("=======================")); + Serial.println(F("# Validate from reconnect Firmware OTA Information #")); + // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); + // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); + Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); + // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); + // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.checksum); + Serial.println(F("=======================")); + if (!attr.remain_ota_fw_info_match) + { + Serial.println(F("# [ERROR] Device must restart because firmware change #")); + Serial.println(F("# firmware not match validate OTA information after reconnect")); + delay(5000); + ESP.restart(); + } + else + { + pub_Download(attr.fw_count_chunk, attr.chunk_size); + } + } + else if ((attr.inProcessOTA) && (!attr.triggerRemainOTA)) // inprocess get info fw + { + attr.remain_ota_fw_info_match = check_remain_fw_isMatch(attr.valid_remain_fw_name, + attr.valid_remain_fw_size, "is obsolete"); // re new OTA description + if (!attr.remain_ota_fw_info_match) + { + Serial.println(F("=======================")); + Serial.println(F("# Firmware OTA Information Incoming While inProcessOTA #")); + // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); + // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); + Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); + // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); + Serial.println(" ->Firmware checksum: " + MAGELLAN_MQTT_device_core::OTA_info.checksum); + Serial.println(F("# [ERROR] Device must restart because firmware change #")); + Serial.println(F("=======================")); + delay(5000); + ESP.restart(); + } + } + + if (!attr.inProcessOTA) // first get info and save to variable + { + attr.isFirmwareUptodate = configOTAFile.compareFirmwareOTA(fw_doc); + + MAGELLAN_MQTT_device_core::OTA_info.firmwareIsUpToDate = ((attr.isFirmwareUptodate == true) ? UP_TO_DATE : OUT_OF_DATE); + // MAGELLAN_MQTT_device_core::OTA_info.firmwareName = name; + MAGELLAN_MQTT_device_core::OTA_info.firmwareName = configOTAFile.readSpacificFromConfFile("namefirmware"); + // MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = size; + size_t buffReadSizefirmware = configOTAFile.readSpacificFromConfFile("sizefirmware").toInt(); + attr.fw_total_size = buffReadSizefirmware; + MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize = buffReadSizefirmware; + // MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = version; + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion = configOTAFile.readSpacificFromConfFile("versionfirmware"); + // MAGELLAN_MQTT_device_core::OTA_info.checksum = c_sum; + MAGELLAN_MQTT_device_core::OTA_info.checksum = configOTAFile.readSpacificFromConfFile("checksum"); + // MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = al_c_sum; + MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm = configOTAFile.readSpacificFromConfFile("checksumAlgorithm"); + + unsigned int b_cal_chunk_todo = (attr.fw_total_size / attr.chunk_size) + 1; + + // ver 1.1.2 UPDATED + if (attr.isFirmwareUptodate == UP_TO_DATE) + { + JsonObject infoCurrentFW = configOTAFile.readObjectLastedOTA(); + String fw_ver = infoCurrentFW["versionfirmware"]; + String fw_size = infoCurrentFW["sizefirmware"]; + // pub_UpdateProgress("UPDATED","{\"description\":\"Device already uptodate firmware version: "+ + // String(fw_ver)+ + // " firmware size: "+String(fw_size)+"\"}"); + pub_UpdateProgress("UPDATED", "{\"description\":\"Firmware " + String(fw_ver) + " is Up to Date\",\"Version\":\"" + fw_ver + "\"}"); + } + // ver 1.1.2 UPDATED + + attr.totalChunk = b_cal_chunk_todo; + + if (!attr.isFirmwareUptodate) + { + Serial.println("# Estimate OTA toltal request chunk : " + String(attr.totalChunk)); + // pub_UpdateProgress("INITIALIZE","{\"description\":\"Initialize firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ + // " size: "+ String(attr.fw_total_size)+"\"}"); + pub_UpdateProgress("INITIALIZE", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); + MAGELLAN_MQTT_device_core::OTA_info.isReadyOTA = true; + Serial.println(F("========================================")); + Serial.println(F("# Firmware OTA information available #")); + // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareName); + // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.firmwareTotalSize)); + Serial.println(" ->Firmware version: " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion); + // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm); + Serial.println(" ->Firmware checksum: " + MAGELLAN_MQTT_device_core::OTA_info.checksum); + Serial.println(F("========================================")); + + // save Client config when firmware change and file ota config change + + + attr.remind_Event_GET_FW_infoOTA = false; + } + } + } + } + else + { + Serial.println(F("# Fail to get firmware Information or you don't have firmware OTA")); + Serial.println("# Detail: " + payload); + } + } +} + +String ERORRdescriptionUpdate() +{ + switch (Update.getError()) + { + case 0: + return "UPDATE_ERROR_OK"; + break; + case 1: + return "UPDATE_ERROR_WRITE"; + break; + case 2: + return "UPDATE_ERROR_ERASE"; + break; + case 3: + return "UPDATE_ERROR_READ"; + break; + case 4: + return "UPDATE_ERROR_SPACE"; + break; + case 5: + return "UPDATE_ERROR_SIZE"; + break; + case 6: + return "UPDATE_ERROR_STREAM"; + break; + case 7: + return "UPDATE_ERROR_MD5"; + break; + case 8: + return "UPDATE_ERROR_MAGIC_BYTE"; + break; + case 9: + return "UPDATE_ERROR_ACTIVATE{firmware is mismatch this board}"; + break; + case 10: + return "UPDATE_ERROR_NO_PARTITION"; + break; + case 11: + return "UPDATE_ERROR_BAD_ARGUMENT"; + break; + case 12: + return "UPDATE_ERROR_ABORT"; + break; + default: + return "ERROR_UNKNOWN"; + break; + } +} + +void validate_lostOTA_Data_incoming() +{ + if (attr.current_chunk + 1 < attr.totalChunk) + { + if (attr.incomingChunkSize < attr.chunk_size) + { + Serial.println(F("# [Warning]Lost some data while in process OTA")); + Serial.println(F("# [Warning]Device must restart")); + // pub_UpdateProgress("FAILED","{\"errordescription\":\"Data incoming lost or incorrect (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is incorrect or lost data\"}"); + configOTAFile.saveSuccessOrFail("fail"); + + + + delay(5000); + ESP.restart(); + } + } +} + +void updateFirmware(uint8_t *data, size_t len) +{ + Update.write(data, len); + attr.current_size += len; + attr.incomingChunkSize = (int)len; + Serial.println("# <-Incoming chunk size: " + String(attr.incomingChunkSize)); + unsigned int calc_percent = map(attr.current_size, 0, attr.fw_total_size, 0, 100); + Serial.println("# <-Current firmware size: " + String(attr.current_size) + "/" + String(attr.fw_total_size) + " => [" + String(calc_percent) + " %]"); + validate_lostOTA_Data_incoming(); + if (attr.current_size != attr.fw_total_size) + { + return; + } + + if (Update.end(true)) + { + // pub_UpdateProgress("DOWNLOADED",""); + pub_UpdateProgress("DOWNLOADED", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); + if (attr.using_Checksum) + { + pub_UpdateProgress("VERIFIED", ""); + } + Serial.println(F("-------------------------------")); + Serial.println(F("# OTA done!")); + if (Update.isFinished()) + { + Serial.println(F("# Update successfully completed. Rebooting.")); + configOTAFile.saveSuccessOrFail("done"); + + String readfileConfig = configOTAFile.readConfigFileOTA(); + configOTAFile.saveLastedOTA(readfileConfig); + + String fw_infoInFIleSys; + JsonObject fw_last = configOTAFile.readObjectLastedOTA(); + int bufferFW_size = fw_last["sizefirmware"]; + + fw_last.remove("namefirmware"); + fw_last.remove("sizefirmware"); + fw_last.remove("checksumAlgorithm"); + String bufferFW_v = fw_last["versionfirmware"]; + + pub_UpdateProgress("UPDATED", "{\"Version\":\"" + bufferFW_v + "\"}"); + + fw_last["firmwareVersion"] = bufferFW_v; + fw_last.remove("versionfirmware"); + serializeJson(fw_last, fw_infoInFIleSys); + + if (fw_infoInFIleSys.indexOf("null") == -1) + { + pubClientConfig(fw_infoInFIleSys); + } + else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config + { + pubClientConfig(fw_infoInFIleSys); + } + + else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) + { + pubClientConfig(fw_infoInFIleSys); + } + + // Serial.println("#Debug: "+ configOTAFile.readConfigFileOTA()); + Serial.println(F("# Safety mode GSM shutdown!")); + GSM.shutdown(); + delay(5000); + ESP.restart(); + } + else + { + // pub_UpdateProgress("FAILED","{\"errordescription\":\"something_went_wrong (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " Something went wrong (UNKNOWN ERROR)\"}"); + + Serial.println(F("# Update not finished? Something went wrong!")); + configOTAFile.saveSuccessOrFail("fail"); + } + } + else + { + String error_des = ERORRdescriptionUpdate(); + Serial.println("# OTA Fail Error Occurred. Error #: " + error_des + " # Error Enum {" + String(Update.getError()) + "}"); + // pub_UpdateProgress("FAILED","{\"errordescription\":\""+ error_des +" (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " : " + error_des + "\"}"); + configOTAFile.saveSuccessOrFail("fail"); + + + } + delay(5000); + ESP.restart(); +} + +void hook_FW_download(String topic, uint8_t *payload, unsigned int length) +{ + // Serial.println("Debug in HOOK topic: "+String(topic)); + // Serial.println("Debug in HOOK length: "+String(length)); + if (topic.indexOf("/firmwaredownload/resp/") != -1) + { + int index = topic.indexOf("/resp/"); + String crrnt_part = topic.substring(index + 6); // crrnt_part is part start from index 0 + attr.current_chunk = crrnt_part.toInt(); + // MAGELLAN_MQTT_device_core::OTA_info.currentChunk = attr.current_chunk+1; + Serial.println(F("<--------------------------------")); + Serial.println("# <-Firmware current chunk: " + String(attr.current_chunk + 1) + "/" + String(attr.totalChunk)); + if (length > 0 && (attr.fw_count_chunk <= attr.totalChunk)) + { + attr.checkTimeout_request_download_fw = false; + attr.prv_cb_timeout_millis = millis(); + updateFirmware(payload, length); + attr.fw_count_chunk++; + attemp_download_1 = false; + attemp_download_2 = false; + + if (attr.delayRequest_download > 0) + { + delay(attr.delayRequest_download); + Serial.println("# Using delay download every chunk in: " + String(attr.delayRequest_download) + " ms."); + pub_Download(attr.fw_count_chunk, attr.chunk_size); + } + else + { + pub_Download(attr.fw_count_chunk, attr.chunk_size); + } + + if (!attr.inProcessOTA) + { + // pub_UpdateProgress("DOWNLOADING", "{\"description\":\"downloading firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+ + // " size: "+ String(attr.fw_total_size)+"\"}"); + pub_UpdateProgress("DOWNLOADING", "{\"description\":\"Firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + "\"}"); + } + attr.inProcessOTA = true; + MAGELLAN_MQTT_device_core::OTA_info.inProcessOTA = attr.inProcessOTA; + } + if (attr.fw_count_chunk == attr.totalChunk) + { + if (attr.current_size != attr.fw_total_size) + { + Serial.println(F("#[Warning] Complete Request chunk but lost or incorrect DATA from OTA")); + Serial.println(F("#[Warning] Must restart board")); + // pub_UpdateProgress("FAILED","{\"errordescription\":\"Complete request total of chunk but lost or incorrect DATA from OTA (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloaded firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is incorrect or lost data\"}"); + configOTAFile.saveSuccessOrFail("fail"); + + delay(3000); + ESP.restart(); + } + } + } +} + +/////////// Feature OTA function none member inclass ////////////////////// + +// ver.1.1.2 +// @attention function compare between MsgId_cb(RCV from cb) and MsgId_send when using reqRetransmission +void checkRequestRetransmit() +{ + if (attr.reqRetransmit) + { + attr.isMatchMsgId = (attr.matchMsgId_send == attr.matchMsgId_cb) ? true : false; + if (attr.isMatchMsgId) + { + Serial.print(F("\n# ========================================\n")); + Serial.println("# Received MsgId: " + String(attr.matchMsgId_send) + " retransmit from server"); + Serial.print(F("# ========================================\n\n")); + + attr.reqRetransmit = false; + } + } +} + +void msgCallback_internalHandler(char *topic, byte *payload, unsigned int length) +{ + String action = "ERROR"; + unsigned int buffEvent = ERROR; + String b_topic = String(topic); + String _payload = b2str(payload, length); + String key = "null"; // if this topic is'nt PLAINTEXT + String code = "0"; + int _MsgId = -1; + + EVENTS intern_EVENT; + intern_EVENT.RESP = "EMPTY"; + + regisAPI *handleRegisPTA = _startRegisPTA; + regisAPI *handleRegisJSON = _startRegisJSON; + regisAPI *handleRegisJSON_CTRL_OBJ = _startOBJ_CTRL; + regisAPI *handleRegisKEY = _startRegis; + + regisAPI *handleRegisPTAConf = _startRegisPTAConf; + regisAPI *handleRegisJSONConf = _startRegisJSONConf; + regisAPI *handleRegisJSON_CONF_OBJ = _startOBJ_CONF; + regisAPI *handleRegisKEYConf = _startRegisConf; + + regisAPI *handleRESP = _startRESP; + // OTA Feature ///////////////// + if ((attr.usingCheckUpdate) && (!attr.inProcessOTA)) + { + checkUpdate(b_topic, _payload); + } + else if (!attr.usingCheckUpdate && attr.flagAutoOTA) + { + save_fw_info(b_topic, _payload); + } + hook_FW_download(b_topic, payload, length); + /////////////////////////////// + char *b_payload = (char *)_payload.c_str(); // payload for advance_cb and endpoint centric + + if (b_topic.indexOf("/auth/resp/") != -1) + { + buffEvent = TOKEN; + action = "TOKEN"; + attr.ext_Token = *&_payload; + } + if (b_topic.indexOf("/delta/resp/pta") != -1) + { + int indexfound2 = String(b_topic).indexOf("="); + String keyOnTopic = b_topic.substring(indexfound2 + 1); + key = keyOnTopic; + buffEvent = CONTROL_PLAINTEXT; + action = "CONTROL_PLAINTEXT"; + + if ((_payload == "40300" || (_payload == "40400") && (_payload.length() == 5))) + { + code = _payload; + intern_EVENT.RESP = "FAIL"; + } + else + { + code = "20000"; + intern_EVENT.RESP = "SUCCESS"; + } + + if (attr.ctrl_regis_key) + { + while (handleRegisKEY != NULL) + { + if (handleRegisKEY->registerKey == key) + { + break; + } + else + { + handleRegisKEY = (regisAPI *)handleRegisKEY->next; + } + } + if (handleRegisKEY != NULL) + { + if (handleRegisKEY->registerKey == key) + { + handleRegisKEY->ctrl_key_callback(_payload); + } + } + } + if (attr.ctrl_regis_pta) + { + while (handleRegisPTA != NULL) + { + if (handleRegisPTA->Event == buffEvent) + { + break; + } + else + { + handleRegisPTA = (regisAPI *)handleRegisPTA->next; + } + } + if (handleRegisPTA != NULL) + { + handleRegisPTA->ctrl_pta_callback(key, _payload); + } + } + } + + else if (b_topic.indexOf("/delta/resp") != -1) + { + buffEvent = CONTROL_JSON; + action = "CONTROL_JSON"; + + if (_payload.indexOf("20000") != -1) + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.indexOf("\":\"") + 8); + intern_EVENT.RESP = "SUCCESS"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + else + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); + intern_EVENT.RESP = "FAIL"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + + if (attr.ctrl_regis_json) + { + while (handleRegisJSON != NULL) + { + if (handleRegisJSON->Event == buffEvent) + { + break; + } + else + { + handleRegisJSON = (regisAPI *)handleRegisJSON->next; + } + } + if (handleRegisJSON != NULL) + { + handleRegisJSON->ctrl_Json_callback(_payload); + } + } + + if (attr.ctrl_jsonOBJ) + { + while (handleRegisJSON_CTRL_OBJ != NULL) + { + if (handleRegisJSON_CTRL_OBJ->Event == buffEvent) + { + break; + } + else + { + handleRegisJSON_CTRL_OBJ = (regisAPI *)handleRegisJSON_CTRL_OBJ->next; + } + } + if (handleRegisJSON_CTRL_OBJ != NULL) + { + // Serial.println(_payload); + String buffDocs = deControl(_payload); + // Serial.println(buffDocs); + JsonObject Docs = deJson(buffDocs); + handleRegisJSON_CTRL_OBJ->ctrl_obj_callback(Docs); + } + } + } + + if (b_topic.indexOf("/config/resp/pta/?config=") != -1) + { + int indexfound2 = String(b_topic).indexOf("="); + String keyOnTopic = b_topic.substring(indexfound2 + 1); + key = keyOnTopic; + buffEvent = CONFIG_PLAINTEXT; + action = "CONFIG_PLAINTEXT"; + + if ((_payload == "40300" || (_payload == "40400") && (_payload.length() == 5))) + { + code = _payload; + intern_EVENT.RESP = "FAIL"; + } + else + { + code = "20000"; + intern_EVENT.RESP = "SUCCESS"; + } + + if (attr.conf_regis_key) + { + while (handleRegisKEYConf != NULL) + { + if (handleRegisKEYConf->registerKey == key) + { + break; + } + else + { + handleRegisKEYConf = (regisAPI *)handleRegisKEYConf->next; + } + } + if (handleRegisKEYConf != NULL) + { + if (handleRegisKEYConf->registerKey == key) + { + handleRegisKEYConf->conf_key_callback(_payload); + } + } + } + + if (attr.conf_regis_pta) + { + while (handleRegisJSON != NULL) + { + if (handleRegisPTAConf->Event == buffEvent) + { + break; + } + else + { + handleRegisPTAConf = (regisAPI *)handleRegisPTAConf->next; + } + } + if (handleRegisPTAConf != NULL) + { + handleRegisPTAConf->conf_pta_callback(key, _payload); + } + } + } + else if (b_topic.indexOf("/config/resp") != -1) + { + buffEvent = CONFIG_JSON; + action = "CONFIG_JSON"; + + if (_payload.indexOf("20000") != -1) + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.indexOf("\":\"") + 8); + intern_EVENT.RESP = "SUCCESS"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + else + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); + intern_EVENT.RESP = "FAIL"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + + if (attr.conf_regis_json) + { + while (handleRegisJSONConf != NULL) + { + if (handleRegisJSONConf->Event == buffEvent) + { + break; + } + else + { + handleRegisJSONConf = (regisAPI *)handleRegisJSONConf->next; + } + } + if (handleRegisJSONConf != NULL) + { + handleRegisJSONConf->conf_json_callback(_payload); + } + } + + if (attr.conf_jsonOBJ) + { + while (handleRegisJSON_CONF_OBJ != NULL) + { + if (handleRegisJSON_CONF_OBJ->Event == buffEvent) + { + break; + } + else + { + handleRegisJSON_CONF_OBJ = (regisAPI *)handleRegisJSON_CONF_OBJ->next; + } + } + if (handleRegisJSON_CONF_OBJ != NULL) + { + // Serial.println(_payload); + String buffDocs = deConfig(_payload); + // Serial.println(buffDocs); + JsonObject Docs = deJson(buffDocs); + handleRegisJSON_CONF_OBJ->conf_obj_callback(Docs); + } + } + } + + if (b_topic.indexOf("dateTime") != -1) + { + buffEvent = UNIXTIME; + action = "UNIXTIME"; + } + if (b_topic.indexOf("/report/resp/pta/?") != -1) + { + buffEvent = RESP_REPORT_PLAINTEXT; + action = "RESP_REPORT_PLAINTEXT"; + + int valid_found_only_msgId = b_topic.indexOf("?id="); // only id + int valid_sensor = b_topic.indexOf("?sensor="); // focus only sensor + int valid_msgId = b_topic.indexOf("&id="); // start with key sensor and id + + if (valid_found_only_msgId != -1) // found only msg id {?id} + { + int indexfound = valid_found_only_msgId; + String msgIdOnTopic = b_topic.substring(indexfound + 4); + _MsgId = msgIdOnTopic.toInt(); + } + + if (valid_msgId != -1) // found MsgId + { + int indexfoundKey = valid_sensor; + int indexfoundId = valid_msgId; + String keyOnTopic = b_topic.substring(indexfoundKey + 8, indexfoundId); + String msgIdOnTopic = b_topic.substring(indexfoundId + 4); + // Serial.println("_payload: "+_payload); + // Serial.println("MsgIdontopic: "+msgIdOnTopic); + key = keyOnTopic; + _MsgId = msgIdOnTopic.toInt(); + } + else if (valid_msgId == -1 && valid_sensor != -1) // not found MsgId , found only key sensor + { + String keyOnTopic = b_topic.substring(valid_sensor + 8); + key = keyOnTopic; + _MsgId = -1; + } + + if (_payload.indexOf("20000") != -1) + { + code = _payload; + intern_EVENT.RESP = "SUCCESS"; + } + else + { + code = _payload; + intern_EVENT.RESP = "FAIL"; + } + } + else if (b_topic.indexOf("/report/resp") != -1) + { + buffEvent = RESP_REPORT_JSON; + action = "RESP_REPORT_JSON"; + + JsonObject OBJ_report_resp = deJson(_payload); + String _code = OBJ_report_resp["Code"]; + + if (_code != "null") + { + code = _code; + } + + if (_payload.indexOf("id") != -1) + { + String _msg_id = OBJ_report_resp["id"]; + if (_msg_id != "null") + { + _MsgId = _msg_id.toInt(); + } + } + else + { + _MsgId = -1; + } + + if (_payload.indexOf("20000") != -1) + { + // code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); + intern_EVENT.RESP = "SUCCESS"; + } + else + { + // code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() + 8); + intern_EVENT.RESP = "FAIL"; + } + } + + if (b_topic.indexOf("/heartbeat/resp/pta") != -1) + { + buffEvent = RESP_HEARTBEAT_PLAINTEXT; + action = "RESP_HEARTBEAT_PLAINTEXT"; + + if (_payload.indexOf("20000") != -1) + { + code = _payload; + intern_EVENT.RESP = "SUCCESS"; + } + else + { + code = _payload; + intern_EVENT.RESP = "FAIL"; + } + } + else if (b_topic.indexOf("/heartbeat/resp") != -1) + { + buffEvent = RESP_HEARTBEAT_JSON; + action = "RESP_HEARTBEAT_JSON"; + + if (_payload.indexOf("20000") != -1) + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); + intern_EVENT.RESP = "SUCCESS"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + else + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); + intern_EVENT.RESP = "FAIL"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + } + if (b_topic.indexOf("/report/timestamp/resp") != -1) + { + buffEvent = RESP_REPORT_TIMESTAMP; + action = "RESP_REPORT_TIMESTAMP"; + if (_payload.indexOf("20000") != -1) + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); + intern_EVENT.RESP = "SUCCESS"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + else + { + code = _payload.substring(_payload.indexOf("\":\"") + 3, _payload.length() - 2); + intern_EVENT.RESP = "FAIL"; + // Serial.println("test CODE ->"+ String(code) +" RESP :"+ String(intern_EVENT.RESP)); + } + } + if (b_topic.indexOf("/server/destination/response") != -1) + { + buffEvent = GET_ENDPOINT; + action = "GET_ENDPOINT"; + attr.ext_EndPoint = b_payload; + } + // Serial.println("#INSIDE "); + // Serial.println(action); + // Serial.println(_payload); + // Serial.println("#INSIDE "); + + intern_EVENT.CODE = code.toInt(); + intern_EVENT.Topic = b_topic; + intern_EVENT.Payload = _payload; + intern_EVENT.PayloadLength = length; + intern_EVENT.Action = action; + intern_EVENT.Key = key; + intern_EVENT.MsgId = _MsgId; + attr.matchMsgId_cb = intern_EVENT.MsgId; + checkRequestRetransmit(); + + if (ext_useAdvanceCallback) // routing to onMessage Callback when use setMessageListener(Callback) + { + cb_internal(intern_EVENT, b_payload); + } + + if (attr.resp_regis) + { + while (handleRESP != NULL) + { + if (handleRESP->Event == buffEvent) + { + break; + } + else + { + handleRESP = (regisAPI *)handleRESP->next; + } + } + // Serial.println("# IN RESP :"+ String(handleRESP->Event)); + // Serial.println("# IN RESP2 :"+ String(buffEvent)); + if (handleRESP != NULL) + { + if (handleRESP->Event == buffEvent) + { + handleRESP->resp_h_callback(intern_EVENT); + } + } + } + // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Action); + // Serial.println("#DEBUG INSIDE :"+intern_EVENT.Payload); +} + +MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core(Client &client) +{ + prev_time = 0; + now_time = millis(); + HB_prev_time = 0; + HB_now_time = millis(); + + attr.clientNetInterface = useExternalClient; + Client *newClient = &client; + attr.ClientNET = *&newClient; + attr.mqtt_client = new PubSubClient(*attr.ClientNET); + this->client = *&attr.mqtt_client; + // duplicate_subs_list = NULL; +} + +MAGELLAN_MQTT_device_core::MAGELLAN_MQTT_device_core() +{ + prev_time = 0; + now_time = millis(); + HB_prev_time = 0; + HB_now_time = millis(); + + attr.clientNetInterface = useGSMClient; + this->gsm_client = new GSMClient; + attr.ClientNET = *&gsm_client; + attr.mqtt_client = new PubSubClient(*attr.ClientNET); + this->client = *&attr.mqtt_client; + // duplicate_subs_list = NULL; +} + +String MAGELLAN_MQTT_device_core::getHostName() +{ + return this->host; +} + +void MAGELLAN_MQTT_device_core::setMQTTBufferSize(uint16_t sizeBuffer) +{ + // Serial.println(F("# SetBufferSize: ")); + // Serial.println(sizeBuffer); + this->_default_bufferSize = sizeBuffer; +} + +void MAGELLAN_MQTT_device_core::setAuthMagellan(String _thingIden, String _thingSecret, String _imei) +{ + Serial.println(F("#====== Setting Magellan Authentication =======")); + if (!(CheckString_isDigit(_thingIden) && CheckString_isDigit(_thingSecret))) + { + Serial.print(F("# ERROR Can't connect to Magellan")); + Serial.print(F("# Parameter from you setting invalid \n [thingIdentify]=> ")); + Serial.print(_thingIden); + Serial.print(F(" [thingSecret]=> ")); + Serial.println(_thingSecret); + Serial.println(F("# Invalid Parameter!! Please check [thingIdentify] and [thingSecret]")); + while (true) + { + Serial.print("."); + delay(300); + this->cnt_fail++; + if (cnt_fail >= 100) // timeout Restart board 30 sec + { + ESP.restart(); + } + } + } + this->thingIden = _thingIden; + this->thingSecret = _thingSecret; + this->imei = _imei; + // Serial.println(F("#Set Auth Success")); + // Serial.println(thingIden); + // Serial.println(thingSecret); + // Serial.println(imei); +} + +void getRadio() +{ + if (attr.clientNetInterface == useGSMClient) + { + Serial.println(F("#========= Radio Quality information ==========")); + Serial.println("Signal Strength: " + String(Network.getSignalStrength())); + Serial.println(F("#==============================================")); + } +} + +void MAGELLAN_MQTT_device_core::initialBoard() +{ + delay(1000); + setAuthMagellan(GSM.getICCID(), GSM.getIMSI(), GSM.getIMEI()); + Serial.println(F("#====== Initializing Board =======")); + Serial.println("ICCID: " + String(thingIden)); + Serial.println("IMSI: " + String(thingSecret)); + Serial.println("IMEI: " + String(imei)); + Serial.println(F("#=================================")); +} + +void MAGELLAN_MQTT_device_core::getBoardInfo() +{ + Serial.println(F("#====== Board information =========")); + Serial.println("ICCID: " + String(thingIden)); + Serial.println("IMSI: " + String(thingSecret)); + Serial.println("IMEI: " + String(imei)); + getRadio(); + Serial.println(F("#=================================")); +} + +String MAGELLAN_MQTT_device_core::getICCID() +{ + return this->thingIden; +} + +String MAGELLAN_MQTT_device_core::getIMEI() +{ + return this->imei; +} + +String MAGELLAN_MQTT_device_core::getIMSI() +{ + return this->thingSecret; +} + +String MAGELLAN_MQTT_device_core::readToken() +{ + return this->token; +} + +boolean MAGELLAN_MQTT_device_core::CheckString_isDigit(String valid_payload) +{ + for (byte i = 0; i < valid_payload.length(); i++) + { + if (!isDigit(valid_payload.charAt(i))) + return false; + } + return true; +} + +boolean MAGELLAN_MQTT_device_core::CheckString_isDouble(String valid_payload) +{ + char *input = (char *)valid_payload.c_str(); + char *end; + strtod(input, &end); + if (*input == '\0') + { + return false; + } + if (end == input || *end != '\0') + { + return false; + } + return true; +} + +// void MAGELLAN_MQTT_device_core::setCallback(void(callback(char*, byte*, unsigned int))) +// { +// this->client->setCallback(callback); +// } + +void MAGELLAN_MQTT_device_core::setCallback_msgHandle() +{ + this->client->setCallback(msgCallback_internalHandler); +} + +void MAGELLAN_MQTT_device_core::setMessageListener(void (*callback)(EVENTS, char *)) +{ + attr.useAdvanceCallback = true; + if (callback) + cb_internal = callback; +} + +void MAGELLAN_MQTT_device_core::reconnect() +{ + while (!isConnected()) + { + Serial.print(F("Device Disconected from Magellan...")); + checkConnection(); + if (flagToken) + { + Serial.print(F("# Remain Subscribes list\n")); + attr.triggerRemainSub = true; + + attr.triggerRemainOTA = true; + if (!attr.flagAutoOTA) + { + sub_InfoOTA(); + } + } + } +} + +boolean MAGELLAN_MQTT_device_core::acceptEndPoint(String payload) +{ + boolean acceptStatus = false; + if (payload.length() >= 10) + { + const char *buff_payload = payload.c_str(); + JsonObject getCetric = deJson(buff_payload); + + String buf1 = getCetric["ServerDestinationInfo"]; + String buf2 = getCetric["OperationStatus"]; + // Serial.println("buf1 :"+ buf1); + if (buf2.indexOf("20000") != -1) + { + JsonObject getCetric2 = deJson(buf1); + String buff_ip = getCetric2["ServerIP"]; + String buff_domain = getCetric2["ServerDomain"]; + String buff_port = getCetric2["ServerPort"]; + centric.endPoint_DOMAIN = buff_domain; + centric.endPoint_IP = buff_ip; + centric.endPoint_PORT = buff_port; + acceptStatus = true; + Serial.println(F("## NEW ZONE AVAILABLE #######")); + Serial.println("# Centric IP >>: " + centric.endPoint_IP); + Serial.println("# Centric Domain >>: " + centric.endPoint_DOMAIN); + Serial.println("# Centric Port >>: " + String(centric.endPoint_PORT)); + Serial.println(F("#############################")); + cnt_attempt = 0; + } + else + { + Serial.println(F("# Fail to Get Endpoint form centric")); + Serial.println(F("# Please check the thing device is activated")); + Serial.print(F("# response: ")); + Serial.println(payload); + } + } + return acceptStatus; +} + +void MAGELLAN_MQTT_device_core::acceptToken(String payload) +{ + if (payload.length() >= 36) + { + this->flagToken = true; + this->token = payload; + Serial.println("# Thingtoken: " + token); + } +} + +void MAGELLAN_MQTT_device_core::acceptToken(EVENTS event) +{ + String _payload = event.Payload; + if ((event.Topic == "api/v2/thing/" + String(thingIden) + "/" + String(thingSecret) + "/auth/resp/pta") && !flagToken) + { + if (_payload.length() >= 36) + { + this->flagToken = true; + this->token = _payload; + Serial.println("# Token >> :" + token); + } + } +} + +// String MAGELLAN_MQTT_device_core::byteToString(byte* payload, unsigned int length_payload) +// { +// char buffer_payload[length_payload+1] = {0}; +// memcpy(buffer_payload, (char*)payload, length_payload); +// return String(buffer_payload); +// } + +String MAGELLAN_MQTT_device_core::byteToString(byte *payload, unsigned int length_payload) +{ + return b2str(payload, length_payload); +} + +void MAGELLAN_MQTT_device_core::loop() +{ + this->client->loop(); + reconnect(); +} + +void MAGELLAN_MQTT_device_core::reconnectMagellan() +{ + while (!isConnected()) + { + srand(time(NULL)); + int randnum = rand() % 10000; // generate number concat in Client id + int randnum_2 = rand() % 10000; // generate number concat in Client id + String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); + Serial.println(F("Attempting MQTT connection ...")); + this->client->setServer(this->host.c_str(), this->port); + this->client->setCallback(msgCallback_internalHandler); + Serial.println("Connecting Magellan on: " + String(this->host) + ", Port: " + String(this->port)); + if (this->client->connect(client_idBuff.c_str(), this->thingIden.c_str(), this->thingSecret.c_str())) + { + Serial.println("Client id: " + client_idBuff + " is connected"); + recon_attempt = 0; + } + else + { + Serial.print(F("failed, reconnect =")); + Serial.print(this->client->state()); + Serial.println(F(" try again in 5 seconds")); + if (!flagToken) + { + Serial.println(F("# Please check the thing device is activated ")); + } + delay(5000); + recon_attempt++; + Serial.print(F("# attempt connect on :")); + Serial.println(String(recon_attempt) + " times"); + if (recon_attempt >= MAXrecon_attempt) + { + Serial.println(" attempt to connect more than " + String(MAXrecon_attempt) + " Restart Board"); + ESP.restart(); + } + } + } + thingRegister(); +} + +void MAGELLAN_MQTT_device_core::checkConnection() +{ + if (!isConnected()) + { + reconnectMagellan(); + } +} + +void MAGELLAN_MQTT_device_core::magellanCentric(const char *_host, int _port) +{ + if (!isConnected()) + { + while (!isConnected()) + { + srand(time(NULL)); + int randnum = rand() % 10000; // generate number concat in Client id + int randnum_2 = rand() % 10000; // generate number concat in Client id + String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); + Serial.println(F("#Attempting connection ...")); + this->client->setServer(_host, _port); + this->client->setCallback(msgCallback_internalHandler); + Serial.println("Connecting Magellan on: " + String(this->host) + ", Port: " + String(this->port)); + String thisIdenCentric = "Centric." + thingIden; + if (this->client->connect(client_idBuff.c_str(), thisIdenCentric.c_str(), this->thingSecret.c_str())) + { + Serial.println("Client id : " + client_idBuff + " is connected"); + recon_attempt = 0; + } + + else + { + Serial.print(F("failed, reconnect =")); + Serial.print(this->client->state()); + Serial.println(F(" try again in 5 seconds")); + Serial.print(F("Count Attemp Reconnect: ")); + recon_attempt++; + Serial.println(recon_attempt); + delay(5000); + if (recon_attempt >= MAXrecon_attempt) + { + Serial.println(" attempt to connect more than: " + String(MAXrecon_attempt) + " Restart Board"); + ESP.restart(); + } + } + } + getEndPoint(); + } +} + +void MAGELLAN_MQTT_device_core::getEndPoint() +{ + Serial.println(F("# REQUEST ENDPOINT")); + while (!flagRegisterEndPoint) + { + String topic = "api/v2/things/" + this->thingIden + "/" + this->thingSecret + "/server/destination/response"; + this->flagRegisterEndPoint = this->client->subscribe(topic.c_str()); + Serial.println("# Register destination server: " + String(flagRegisterEndPoint)); + } + while (!flagGetEndPoint) + { + this->client->loop(); + // Serial.println("Pub"); + this->requestEndpoint(); + if (attr.ext_EndPoint.length() >= 10) + { + // Serial.println(ext_EndPoint); + flagGetEndPoint = acceptEndPoint(attr.ext_EndPoint); + } + delay(5000); + } + if (flagGetEndPoint) + { + Serial.println(F("# Disconnect from Centric")); + this->client->disconnect(); + Serial.println(F("# Connect to new zone")); + srand(time(NULL)); + int randnum = rand() % 10000; // generate number concat in Client id + int randnum_2 = rand() % 10000; // generate number concat in Client id + String client_idBuff = client_id + "_" + String(randnum) + "_" + String(randnum_2); + this->beginCustom(client_idBuff, true, centric.endPoint_IP, (centric.endPoint_PORT).toInt(), this->_default_bufferSize); + } +} + +bool MAGELLAN_MQTT_device_core::isConnected() +{ + return this->client->connected(); +} + +void MAGELLAN_MQTT_device_core::beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize) +{ + Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); + if (attr.clientNetInterface == useGSMClient) + { + Serial.println("# AIS 4G Board"); + while (!GSM.begin()) + { + Serial.println(F("GSM setup fail")); + delay(2000); + } + if ((this->thingIden == NULL) && (this->thingSecret == NULL)) + { + initialBoard(); + // getRadio(); + } + } + else if (attr.clientNetInterface == useExternalClient) + { + Serial.println("# External Client"); + } + if (builtInSensor) + { + Serial.println(F("# Using Builtin SENSOR")); + attr.useBuiltInSensor = builtInSensor; + mySensor.begin(); + } + delay(5000); + getRadio(); + this->host = _host; + this->port = _port; + this->client_id = _client_id; + if (bufferSize > _default_OverBufferSize) + { + Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); + Serial.println(); + this->setBufferSize(_default_OverBufferSize); + attr.calculate_chunkSize = _default_bufferSize / 2; + } + else + { + this->setBufferSize(bufferSize); + attr.calculate_chunkSize = bufferSize / 2; + } + checkConnection(); +} + +void MAGELLAN_MQTT_device_core::beginCentric() +{ + Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); + if (attr.clientNetInterface == useGSMClient) + { + Serial.println(F("# AIS 4G Board")); + while (!GSM.begin()) + { + Serial.println(F("GSM setup fail")); + delay(2000); + } + if ((this->thingIden == NULL) && (this->thingSecret == NULL)) + { + initialBoard(); + // getRadio(); + } + } + else if (attr.clientNetInterface == useExternalClient) + { + Serial.println(F("# External Client")); + } + Serial.println(F("# Connect to Centric")); + delay(5000); + getRadio(); + this->host = hostCentric; + this->port = mgPort; + this->client_id = this->getICCID(); // auto_assigned Client ID with ThingIdent + setBufferSize(_default_bufferSize); + magellanCentric(); +} + +void MAGELLAN_MQTT_device_core::begin(boolean builtInSensor) +{ + Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); + if (attr.clientNetInterface == useGSMClient) + { + Serial.println(F("# AIS 4G Board")); + while (!GSM.begin()) + { + Serial.println(F("GSM setup fail")); + delay(2000); + } + if ((this->thingIden == NULL) && (this->thingSecret == NULL)) + { + initialBoard(); + // getRadio(); + } + } + else if (attr.clientNetInterface == useExternalClient) + { + Serial.println(F("# External Client")); + } + if (builtInSensor) + { + Serial.println(F("# Using Builtin SENSOR")); + attr.useBuiltInSensor = builtInSensor; + mySensor.begin(); + } + getRadio(); + delay(5000); + String _host = _host_production; + + this->host = _host; + this->port = mgPort; + this->client_id = getICCID(); // auto_assigned Client ID with ICCID + setBufferSize(_default_bufferSize); + checkConnection(); +} + +void MAGELLAN_MQTT_device_core::begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone, uint16_t bufferSize, boolean builtInSensor) +{ + setAuthMagellan(_thingIden, _thingSencret, _imei); + Serial.print(F("ThingIdentify: ")); + Serial.println(_thingIden); + Serial.print(F("ThingSecret: ")); + Serial.println(_thingSencret); + Serial.print(F("IMEI: ")); + Serial.println(_imei); + begin(_thingIden, builtInSensor, Zone, bufferSize); +} + +void MAGELLAN_MQTT_device_core::begin(String _client_id, boolean builtInSensor, unsigned int Zone, uint16_t bufferSize) +{ + Serial.println("=================== Begin MAGELLAN Library [AIS 4G Board] " + String(lib_version) + " ==================="); + if (attr.clientNetInterface == useGSMClient) + { + Serial.println(F("# AIS 4G Board")); + while (!GSM.begin()) + { + Serial.println(F("GSM setup fail")); + delay(2000); + } + if ((this->thingIden == NULL) && (this->thingSecret == NULL)) + { + initialBoard(); + // getRadio(); + } + } + + else if (attr.clientNetInterface == useExternalClient) + { + Serial.println(F("# External Client")); + } + + if (builtInSensor) + { + Serial.println(F("# Using Builtin SENSOR")); + attr.useBuiltInSensor = builtInSensor; + mySensor.begin(); + } + getRadio(); + delay(5000); + String _host = _host_production; + switch (Zone) + { + case Production: + _host = _host_production; + break; + default: + _host = _host_production; + Serial.println(F("# OUT OF LENGTH ZONE MOVE TO Production")); + break; + } + this->host = _host; + this->port = mgPort; + this->client_id = _client_id; + if (bufferSize > _default_OverBufferSize) + { + Serial.print(F("# Buffer size from you set over than 8192 set buffer to: ")); + Serial.println(); + this->setBufferSize(_default_OverBufferSize); + attr.calculate_chunkSize = _default_bufferSize / 2; + } + else + { + this->setBufferSize(bufferSize); + attr.calculate_chunkSize = bufferSize / 2; + } + checkConnection(); +} + +boolean MAGELLAN_MQTT_device_core::registerToken() +{ + String topic = "api/v2/thing/" + this->thingIden + "/" + this->thingSecret + "/auth/resp/pta"; + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println(F("# Register Token to magellan")); + Serial.println("# Register Token Status: " + _debug); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::report(String payload) +{ + + String topic = "api/v2/thing/" + token + "/report/persist"; + boolean Pub_status = client->publish(topic.c_str(), payload.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Report JSON: " + _debug); + Serial.println("# [Sensors]: " + payload); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::report(String key, String value) +{ + String topic = "api/v2/thing/" + token + "/report/persist/pta/?sensor=" + key; + boolean Pub_status = client->publish(topic.c_str(), value.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Report Plaintext: " + _debug); + Serial.println("# [key]: " + key); + Serial.println("# [value]: " + value); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reportSensor() +{ + String bufferPlayload = buildSensorJSON(*attr.docSensor); + boolean Pub_status = false; + if (bufferPlayload.indexOf("null") == -1) + { + Pub_status = report(bufferPlayload); + clearSensorBuffer(*attr.docSensor); + } + else + { + Serial.println(F("# Can't reportSensor Because Not set function \"void addSensor(key,value)\" before reportSensor")); + } + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::ACKControl(String key, String value) +{ + String topic = "api/v2/thing/" + token + "/report/persist/pta/?sensor=" + key; + boolean Pub_status = this->client->publish(topic.c_str(), value.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# ACKNOWNLEDGE Control Plaintext: " + _debug); + Serial.println("# [key]: " + key); + Serial.println("# [value]: " + value); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::ACKControl(String payload) +{ + String topic = "api/v2/thing/" + token + "/report/persist"; + boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# ACKNOWNLEDGE Control JSON: " + _debug); + Serial.println("# [Sensors]: " + payload); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type) +{ + boolean Pub_status = false; + String topic_ = "api/v2/thing/" + token + "/report/timestamp/persist"; + if (timestamp != NULL && JSONpayload != NULL) + { + String payload_ = "[{\"UNIXTS\":" + timestamp + ",\"Sensor\":" + JSONpayload + "}]"; + Pub_status = this->client->publish(topic_.c_str(), payload_.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println("# Report with timestamp: " + _debug); + Serial.println("# [Sensors]: " + payload_); + return Pub_status; + } + else + { + Serial.println(F("# Report with timestamp: Failure")); + Serial.println(F("# Error Empty timestamp or Sensor payload")); + } + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reportClientConfig(String payload) +{ + String topic = "api/v2/thing/" + token + "/config/persist"; + boolean Pub_status = this->client->publish(topic.c_str(), payload.c_str()); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Save ClientConfig: " + _debug); + Serial.println("# [ClientConfigs]: " + payload); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::requestEndpoint() +{ + boolean Pub_status = false; + if (!flagGetEndPoint) + { + if (cnt_attempt >= limit_attempt) + { + Serial.println("Device Attempt to request ENDPOINT more than " + String(limit_attempt) + " time. restart board"); + delay(1000); + ESP.restart(); + } + if (millis() - previouseMillis > 10000) + { + previouseMillis = millis(); + String topic = "api/v2/things/" + thingIden + "/" + thingSecret + "/server/destination/request"; + Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.print("# Request Endpoint: " + _debug); + if (cnt_attempt > 0) + { + Serial.print(" Attempt >> " + String(cnt_attempt - 1) + " time"); + } + Serial.println(); + cnt_attempt++; + } + } + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::requestToken() +{ + boolean Pub_status = false; + if (!flagToken) + { + if (cnt_attempt >= limit_attempt) + { + Serial.println("Device Attempt to request token more than " + String(limit_attempt) + " time. restart board"); + delay(1000); + ESP.restart(); + } + if (millis() - previouseMillis > 10000) + { + previouseMillis = millis(); + String topic = "api/v2/thing/" + thingIden + "/" + thingSecret + "/auth/req"; + Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + // Serial.println("topic :" + topic); + Serial.print("# Request Token: " + _debug); + if (cnt_attempt > 0) + { + Serial.print(" Attempt >> " + String(cnt_attempt - 1) + " time"); + } + Serial.println(); + cnt_attempt++; + } + } + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::setBufferSize(uint16_t size) +{ + Serial.println("# set BufferSize: " + String(size)); + return this->client->setBufferSize(size); +} + +boolean MAGELLAN_MQTT_device_core::heartbeat() +{ + String topic = "api/v2/thing/" + token + "/heartbeat"; + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Heartbeat Trigger: " + _debug); + return Pub_status; +} + +boolean firstHBdoing = true; +void MAGELLAN_MQTT_device_core::heartbeat(unsigned int triger_ms) +{ + HB_threshold_ms = triger_ms; + HB_now_time = millis(); + unsigned long different_ms = HB_now_time - HB_prev_time; + if (different_ms >= HB_threshold_ms || firstHBdoing) + { + firstHBdoing = false; + heartbeat(); + HB_prev_time = HB_now_time; + } +} + +void MAGELLAN_MQTT_device_core::setManualToken(String _token) +{ + Serial.println(F("# SET MANUAL TOKEN =====")); + Serial.println("#Token: " + _token); + if (_token.length() >= 36) + { + token = _token; + acceptToken(token); + } +} + +boolean MAGELLAN_MQTT_device_core::reqControlJSON() +{ + + String topic = "api/v2/thing/" + token + "/delta/req"; + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Request Control [JSON]: " + _debug); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reqControl(String key) +{ + String topic = "api/v2/thing/" + token + "/delta/req/?sensor=" + key; + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Request Control Plaintext by [Key]: \"" + key + "\": " + _debug); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reqConfigJSON() +{ + String topic = "api/v2/thing/" + token + "/config/req"; + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Request Config [JSON]: " + _debug); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::reqConfig(String key) +{ + String topic = "api/v2/thing/" + token + "/config/req/?config=" + key; // fact C c + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Request Config Plaintext [Key]: \"" + key + "\": " + _debug); + return Pub_status; +} + +void MAGELLAN_MQTT_device_core::getControl(String key, ctrl_handleCallback ctrl_callback) +{ + attr.ctrl_regis_key = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONTROL_PLAINTEXT; + newRegis->registerKey = key; + newRegis->ctrl_key_callback = ctrl_callback; + newRegis->next = NULL; + + if (_startRegis != NULL) + { + regisAPI *focusRegis = _startRegis; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegis = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getControl(ctrl_PTAhandleCallback ctrl_pta_callback) +{ + attr.ctrl_regis_pta = true; + + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONTROL_PLAINTEXT; + newRegis->ctrl_pta_callback = ctrl_pta_callback; + newRegis->next = NULL; + + if (_startRegisPTA != NULL) + { + regisAPI *focusRegis = _startRegisPTA; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegisPTA = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_Json_handleCallback ctrl_json_callback) +{ + attr.ctrl_regis_json = true; + + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONTROL_JSON; + newRegis->ctrl_Json_callback = ctrl_json_callback; + newRegis->next = NULL; + + if (_startRegisJSON != NULL) + { + regisAPI *focusRegis = _startRegisJSON; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegisJSON = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb) +{ + attr.ctrl_jsonOBJ = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONTROL_JSON; + newRegis->ctrl_obj_callback = jsonOBJ_cb; + newRegis->next = NULL; + + if (_startOBJ_CTRL != NULL) + { + regisAPI *focusRegis = _startOBJ_CTRL; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startOBJ_CTRL = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getConfig(String key, conf_handleCallback _conf_callback) +{ + attr.conf_regis_key = true; + + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONFIG_PLAINTEXT; + newRegis->registerKey = key; + newRegis->conf_key_callback = _conf_callback; + newRegis->next = NULL; + + if (_startRegisConf != NULL) + { + regisAPI *focusRegis = _startRegisConf; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegisConf = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getConfig(conf_PTAhandleCallback conf_pta_callback) +{ + attr.conf_regis_pta = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONFIG_PLAINTEXT; + newRegis->conf_pta_callback = conf_pta_callback; + newRegis->next = NULL; + + if (_startRegisPTAConf != NULL) + { + regisAPI *focusRegis = _startRegisPTAConf; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegisPTAConf = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getConfigJSON(conf_Json_handleCallback conf_json_callback) +{ + attr.conf_regis_json = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONFIG_JSON; + newRegis->conf_json_callback = conf_json_callback; + newRegis->next = NULL; + + if (_startRegisJSONConf != NULL) + { + regisAPI *focusRegis = _startRegisJSONConf; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRegisJSONConf = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb) +{ + attr.conf_jsonOBJ = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = CONFIG_JSON; + newRegis->conf_obj_callback = jsonOBJ_cb; + newRegis->next = NULL; + + if (_startOBJ_CONF != NULL) + { + regisAPI *focusRegis = _startOBJ_CONF; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startOBJ_CONF = newRegis; + } +} + +void MAGELLAN_MQTT_device_core::getRESP(unsigned int resp_event, resp_callback resp_cb) +{ + attr.resp_regis = true; + regisAPI *newRegis = new regisAPI; + newRegis->Event = resp_event; + newRegis->resp_h_callback = resp_cb; + newRegis->next = NULL; + + if (_startRESP != NULL) + { + regisAPI *focusRegis = _startRESP; + while (focusRegis->next != NULL) + { + focusRegis = (regisAPI *)focusRegis->next; + } + focusRegis->next = newRegis; + } + else + { + _startRESP = newRegis; + } +} + +boolean MAGELLAN_MQTT_device_core::registerResponseReport(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/report/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/report/resp"; + break; + default: + Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); + topic = "api/v2/thing/" + token + "/report/resp"; + break; + } + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterRESP Report: "+ _debug); + Serial.println("# Subscribe Response Report: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerResponseReportTimestamp() +{ + String topic = "api/v2/thing/" + token + "/report/timestamp/resp"; + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterRESP ReportTimestamp: "+ _debug); + Serial.println("# Subscribe Response ReportTimestamp: " + _debug); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerResponseHeartbeat(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/heartbeat/resp/pta"; + break; + case 1: + topic = "api/v2/thing/" + token + "/heartbeat/resp"; + break; + default: + Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); + topic = "api/v2/thing/" + token + "/heartbeat/resp"; + break; + } + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterRESP Heartbeat: "+ _debug); + Serial.println("# Subscribe Response Heartbeat: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerConfig(String key) +{ + String topic = "api/v2/thing/" + token + "/config/resp/pta/?config=" + key; // fact C c + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + // Serial.println("# Register Server Config [Key]: \""+key+"\" Register: "+ _debug); + Serial.println("# Subscribe ServerConfig [Key]: \"" + key + "\" Subscribe: " + _debug); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerConfig(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/config/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/config/resp"; + break; + default: + Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); + topic = "api/v2/thing/" + token + "/config/resp"; + break; + } + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + // Serial.println("# Register Server Config: "+ _debug); + Serial.println("# Subscribe ServerConfig: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::getTimestamp() +{ + String topic = "api/v2/server/dateTime/req"; + boolean Pub_status = this->client->publish(topic.c_str(), " "); + _debug = (Pub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Get ServerTime Request: " + _debug); + return Pub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerTimestamp(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/server/dateTime/resp/pta"; + break; + case 1: + topic = "api/v2/server/dateTime/resp"; + break; + default: + Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); + topic = "api/v2/server/dateTime/resp"; + break; + } + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + Serial.println(F("# Subscribe Timestamp magellan")); + // Serial.println(F("# RegisterTimestamp magellan")); + Serial.println("# Subscribe ServerTime: " + _debug); + // Serial.println("# RegisterTimestamp: "+ _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerControl(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/delta/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/delta/resp"; + break; + default: + Serial.println(F("out of length resp args format support [\"0\" or PLAINTEXT] is Plaint text(default) and [\"1\" or JSON]")); + topic = "api/v2/thing/" + token + "/delta/resp"; + break; + } + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterControl: "+ _debug); + Serial.println("# Subscribe Control: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} + +boolean MAGELLAN_MQTT_device_core::registerControl(String key) +{ + String topic = "api/v2/thing/" + token + "/delta/resp/pta/?sensor=" + key; // fact S s + boolean Sub_status = this->client->subscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(topic); + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterControl [Key]: \""+key+"\" Register: "+ _debug); + Serial.println("# Subscribe Control [Key]: \"" + key + "\" Subscribe: " + _debug); + return Sub_status; +} + +void MAGELLAN_MQTT_device_core::thingRegister() +{ + while (!flagRegisterToken) + { + this->flagRegisterToken = registerToken(); + } + while (!flagToken) + { + loop(); + requestToken(); + if (attr.ext_Token.length() >= 30) + { + token = attr.ext_Token; + acceptToken(token); + } + } +} + +void MAGELLAN_MQTT_device_core::registerList(func_callback_registerList cb_regisList) +{ + if (attr.triggerRemainSub) + { + if (attr.inProcessOTA) + { + Serial.println(F("# Subscribes List is terminated when Inprocess OTA")); + } + else + { + Serial.println(F("# Subscribes List")); + cb_regisList(); + if (!attr.flagAutoOTA) + { + sub_InfoOTA(); + } + } + attr.triggerRemainSub = false; + Serial.println(F("#============================")); + } +} + +boolean firstTimedoing = true; +void MAGELLAN_MQTT_device_core::interval_ms(unsigned long ms, func_callback_ms cb_ms) +{ + threshold_ms = ms; + now_time = millis(); + unsigned long different_ms = now_time - prev_time; + if (different_ms >= threshold_ms || firstTimedoing) + { + firstTimedoing = false; + prev_time = millis(); + cb_ms(); + } +} + +JsonObject MAGELLAN_MQTT_device_core::deserialJson(String jsonContent) +{ + JsonObject buffer; + if (jsonContent != NULL && jsonContent != "clear") + { + DeserializationError error = deserializeJson(docJson, jsonContent); + buffer = docJson.as(); + if (error) + Serial.println("# Error to DeserializeJson Control"); + } + return buffer; +} + +String MAGELLAN_MQTT_device_core::deserialControlJSON(String jsonContent) +{ + String content = "40300"; + JsonObject buffdoc = deserialJson(jsonContent); + String statusCode = buffdoc["Code"]; + String buffDelta; + if (statusCode == "20000") + { + if (jsonContent.indexOf("Delta") != -1) + { + buffDelta = buffdoc["Delta"].as(); + content = buffDelta; + } + else if (jsonContent.indexOf("Sensor") != -1) + { + buffDelta = buffdoc["Sensor"].as(); + content = buffDelta; + } + } + return content; +} + +void MAGELLAN_MQTT_device_core::updateSensor(String key, String value, JsonDocument &ref_docs) +{ + int len = value.length(); + char *c_value = new char[len + 1]; + std::copy(value.begin(), value.end(), c_value); + c_value[len] = '\0'; + ref_docs[key] = c_value; + delete[] c_value; +} + +void MAGELLAN_MQTT_device_core::updateSensor(String key, const char *value, JsonDocument &ref_docs) +{ + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::updateSensor(String key, int value, JsonDocument &ref_docs) +{ + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::updateSensor(String key, float value, JsonDocument &ref_docs) +{ + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::updateSensor(String key, boolean value, JsonDocument &ref_docs) +{ + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::addSensor(String key, String value, JsonDocument &ref_docs) +{ + int len = value.length(); + char *c_value = new char[len + 1]; + std::copy(value.begin(), value.end(), c_value); + c_value[len] = '\0'; + ref_docs[key] = c_value; + delete[] c_value; +} + +void MAGELLAN_MQTT_device_core::addSensor(String key, const char *value, JsonDocument &ref_docs) +{ + // Serial.println("[Key]: "+key+" [Value]: "+value); + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::addSensor(String key, int value, JsonDocument &ref_docs) +{ + // Serial.println("[Key]: "+key+" [Value]: "+String(value)); + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::addSensor(String key, float value, JsonDocument &ref_docs) +{ + // Serial.println("[Key]: "+key+" [Value]: "+String(value)); + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::addSensor(String key, boolean value, JsonDocument &ref_docs) +{ + // Serial.println("[Key]: "+key+" [Value]: "+String(value)); + ref_docs[key] = value; +} + +void MAGELLAN_MQTT_device_core::remove(String key, JsonDocument &ref_docs) +{ + Serial.println("Remove [Key]: " + key); + ref_docs.remove(key); +} + +boolean MAGELLAN_MQTT_device_core::findKey(String key, JsonDocument &ref_docs) +{ + return ref_docs.containsKey(key); +} + +String MAGELLAN_MQTT_device_core::buildSensorJSON(JsonDocument &ref_docs) +{ + String bufferJsonStr; + // Serial.println("# [Build JSON Key is]: "+ String(ref_docs.size()) +" key"); + size_t mmr_usage = ref_docs.memoryUsage(); + size_t max_size = ref_docs.memoryPool().capacity(); + size_t safety_size = max_size * (0.97); + // Serial.println("Safety size: "+String(safety_size)); + if (mmr_usage >= safety_size) + { + bufferJsonStr = "null"; + Serial.println("# [Overload memory toJSONString] *Maximum Safety Memory size to use is: " + String(safety_size)); + } + else + { + serializeJson(ref_docs, bufferJsonStr); + Serial.println("# [to JSON String Key is]: " + String(ref_docs.size()) + " key"); + } + + Serial.println("# MemoryUsage: " + String(mmr_usage) + "/" + String(safety_size) + " from(" + String(ref_docs.memoryPool().capacity()) + ")"); + return bufferJsonStr; +} + +void MAGELLAN_MQTT_device_core::adjustBufferSensor(size_t sizeJSONbuffer) +{ + attr.docSensor = new DynamicJsonDocument(sizeJSONbuffer); +} + +int MAGELLAN_MQTT_device_core::readBufferSensor(JsonDocument &ref_docs) +{ + return ref_docs.memoryPool().capacity(); +} + +void MAGELLAN_MQTT_device_core::clearSensorBuffer(JsonDocument &ref_docs) +{ + Serial.println(F("# [Clear JSON buffer]")); + ref_docs.clear(); + Serial.println(F("-------------------------------")); +} + +boolean MAGELLAN_MQTT_device_core::registerInfoOTA() +{ + return sub_InfoOTA(); +} + +boolean MAGELLAN_MQTT_device_core::unregisterInfoOTA() +{ + return unsub_InfoOTA(); +} + +boolean MAGELLAN_MQTT_device_core::requestFW_Info() +{ + return pub_Info(); +} + +boolean MAGELLAN_MQTT_device_core::registerDownloadOTA() +{ + return sub_DownloadOTA(); +} + +boolean MAGELLAN_MQTT_device_core::unregisterDownloadOTA() +{ + return unsub_DownloadOTA(); +} + +boolean MAGELLAN_MQTT_device_core::requestFW_Download(unsigned int fw_chunk, size_t chunk_size) +{ + return pub_Download(fw_chunk, chunk_size); +} + +boolean MAGELLAN_MQTT_device_core::updateProgressOTA(String OTA_state, String description) +{ + return pub_UpdateProgress(OTA_state, description); +} + +void MAGELLAN_MQTT_device_core::activeOTA(size_t chunk_size, boolean useChecksum) +{ + Serial.println(F("#============================")); + Serial.println(F("# Activated OTA")); + Update.begin(UPDATE_SIZE_UNKNOWN); + attr.using_Checksum = useChecksum; + String isC_sum = (attr.using_Checksum == true) ? "ENABLE" : "DISABLE"; + Serial.println(F(" ")); + Serial.print(isC_sum); + Serial.println(F(" Checksum FirmwareOTA")); + // Serial.println(*attr.chunk_size); + if (chunk_size > 4096) + { + Serial.print(F("# [Warning] Chunk Size Maximun is 4096 (use Default \"")); + Serial.print(attr.default_chunk_size); + Serial.println(F("\")")); + setChunkSize(attr.default_chunk_size); + } + else + { + setChunkSize(chunk_size); + } + configOTAFile.beginFileSystem(true); + if (!configOTAFile.checkFileOTA()) + { + configOTAFile.createConfigFileOTA(); + } + + if (!configOTAFile.checkLastedOTA()) + { + configOTAFile.createLastedOTA(); + if (configOTAFile.checkFileOTA()) + { + String fw_infoInFIleSys = configOTAFile.readLastedOTA(); + } + } + else + { + String fw_infoInFIleSys; + JsonObject fw_last = configOTAFile.readObjectLastedOTA(); + int bufferFW_size = fw_last["sizefirmware"]; + + fw_last.remove("namefirmware"); + fw_last.remove("sizefirmware"); + fw_last.remove("checksumAlgorithm"); + String bufferFW_v = fw_last["versionfirmware"]; + fw_last["firmwareVersion"] = bufferFW_v; + fw_last.remove("versionfirmware"); + serializeJson(fw_last, fw_infoInFIleSys); + if (fw_infoInFIleSys.indexOf("null") == -1) + { + this->reportClientConfig(fw_infoInFIleSys); + } + else if ((bufferFW_v.length() > 4 || bufferFW_v.indexOf("null") == -1) && (fw_infoInFIleSys.indexOf("null") != -1)) // handle if fw version !null but some key value found null is still pub client config + { + this->reportClientConfig(fw_infoInFIleSys); + } + else if ((bufferFW_v.indexOf("null") != -1) && (bufferFW_size > 0)) + { + this->reportClientConfig(fw_infoInFIleSys); + } + } +} +void MAGELLAN_MQTT_device_core::setChecksum(String md5Checksum) +{ + Serial.println("# Set Checksum md5: " + md5Checksum + " Status:" + (Update.setMD5(md5Checksum.c_str()) == true ? " Success" : " Fail")); +} + +void MAGELLAN_MQTT_device_core::setChunkSize(size_t chunkSize) +{ + attr.chunk_size = chunkSize; + Serial.println("# Set Chunk size: " + String(attr.chunk_size)); +} + +void checkTimeoutReq_fw_download() +{ + if (attr.checkTimeout_request_download_fw) + { + unsigned long differentTime = millis() - attr.prv_cb_timeout_millis; + if (differentTime > 60000 && !attemp_download_1) + { + Serial.println("#Attemp resume download 1 after checktimeout 1 minute"); + pub_Download(attr.fw_count_chunk, attr.chunk_size); + attemp_download_1 = true; + } + if (differentTime > 120000 && !attemp_download_2) + { + Serial.println("#Attemp resume download 2 after checktimeout 2 minute"); + pub_Download(attr.fw_count_chunk, attr.chunk_size); + attemp_download_2 = true; + } + if (differentTime > attr.timeout_req_download_fw) + { + // pub_UpdateProgress("FAILED","{\"errordescription\":\"Timeout from request firmware download (version. "+ MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion+")\"}"); + pub_UpdateProgress("FAILED", "{\"errordescription\":\"Downloading firmware " + MAGELLAN_MQTT_device_core::OTA_info.firmwareVersion + " is timeout on chunk (" + String(attr.current_chunk) + "/" + String(attr.totalChunk) + ")\"}"); + configOTAFile.saveSuccessOrFail("fail"); + + Serial.println("#device must restart timeout from request firmware dowload " + String(attr.timeout_req_download_fw / 60000) + " minute"); + delay(5000); + ESP.restart(); + } + // Serial.println("Counting Timeout: "+String(diferentTime/1000)); + } + else + { + attr.prv_cb_timeout_millis = millis(); + } +} + +unsigned long prv_mills_usingCheckOTA = 0; +void checkTimeoutCheckUpdate() +{ + if (attr.usingCheckUpdate) + { + unsigned long differentTime = millis() - prv_mills_usingCheckOTA; + if (differentTime > 15000) + { + attr.usingCheckUpdate = false; + } + } + else if (!attr.usingCheckUpdate) + { + prv_mills_usingCheckOTA = millis(); + } +} + +boolean remind_unsub_when_inProcessOTA = false; +unsigned long prv_mills_pubinfo = 0; +void MAGELLAN_MQTT_device_core::handleOTA(boolean OTA_after_getInfo) +{ + checkTimeoutReq_fw_download(); + checkTimeoutCheckUpdate(); + if (attr.triggerRemainOTA) + { + + Serial.println(F("# Active handleOTA")); + registerInfoOTA(); + if (attr.flagAutoOTA) + registerDownloadOTA(); + Serial.println(F("#============================")); + + if (attr.inProcessOTA) // if get fw in hook fw will auto count and request dowload fw + { + attr.flag_remain_ota = true; + attr.remain_ota_fw_info_match = false; + + if (!attr.remain_ota_fw_info_match) + { + if (millis() - prv_mills_pubinfo > 5000) + { + pub_Info(); + prv_mills_pubinfo = millis(); + } + } + else if (attr.remain_ota_fw_info_match) // remain get firmware + { + pub_Download(attr.fw_count_chunk, attr.chunk_size); + } + } + if (attr.startReqDownloadOTA && !attr.inProcessOTA) // if get part 0 fail but start ota still work when reconnect + { + pub_Download(attr.fw_count_chunk, attr.chunk_size); + } + attr.triggerRemainOTA = false; + } + if ((attr.fw_total_size > 0) && !(attr.remind_Event_GET_FW_infoOTA)) + { + // Serial.println(F("=======================")); + // Serial.println(F("# Firmware OTA Information Available #")); + // Serial.println(" ->Firmware Name: "+MAGELLAN_MQTT_device_core::OTA_info.fw_name); + // Serial.println(" ->Firmware total size: "+String(MAGELLAN_MQTT_device_core::OTA_info.fw_totalSize)); + // Serial.println(" ->Firmware version: "+MAGELLAN_MQTT_device_core::OTA_info.fw_version); + // Serial.println(" ->Firmware checksum Algorithm: "+MAGELLAN_MQTT_device_core::OTA_info.algorithm_check_sum); + // Serial.println(" ->Firmware checksum: "+MAGELLAN_MQTT_device_core::OTA_info.check_sum); + // Serial.println(F("=======================")); + if (attr.using_Checksum && !attr.isFirmwareUptodate) + { + if (MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "md5" || MAGELLAN_MQTT_device_core::OTA_info.checksumAlgorithm == "MD5") + setChecksum(MAGELLAN_MQTT_device_core::OTA_info.checksum); + else + { + Serial.println(F("#[Warning] Can't set checksum because algorithm checksum is not \"md5\"")); + Serial.println(F("#[Warning] But OTA Process still working without checksum ")); + attr.using_Checksum = false; + } + } + if (OTA_after_getInfo && !attr.isFirmwareUptodate) // auto request OTA after get fw information + { + pub_Download(0, attr.chunk_size); + } + attr.remind_Event_GET_FW_infoOTA = true; + } + if (attr.inProcessOTA && !remind_unsub_when_inProcessOTA) + { + Serial.println(F("=================================================")); + Serial.println(F("# Inprocess OTA terminate other incoming message")); + Serial.println(F("# Unsubscribe unuse function")); + if (attr.ctrl_regis_key || attr.ctrl_regis_pta) + { + unregisterControl(PLAINTEXT); + } + if (attr.ctrl_jsonOBJ || attr.ctrl_regis_json) + { + unregisterControl(JSON); + } + if (attr.conf_regis_key || attr.conf_regis_pta) + { + unregisterConfig(PLAINTEXT); + } + if (attr.conf_jsonOBJ || attr.conf_regis_json) + { + unregisterConfig(JSON); + } + if (attr.resp_regis) + { + unregisterResponseHeartbeat(PLAINTEXT); + unregisterResponseHeartbeat(JSON); + unregisterResponseReport(PLAINTEXT); + unregisterResponseReport(JSON); + unregisterResponseReportTimestamp(); + unregisterTimestamp(PLAINTEXT); + unregisterTimestamp(JSON); + } + remind_unsub_when_inProcessOTA = true; + Serial.println(F("=================================================")); + } +} +////////////////// Unsub /////////// +boolean MAGELLAN_MQTT_device_core::unregisterControl(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/delta/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/delta/resp"; + break; + default: + topic = "api/v2/thing/" + token + "/delta/resp"; + break; + } + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + // Serial.println("# RegisterControl: "+ _debug); + Serial.println("# Unsubscribe Control: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} // +boolean MAGELLAN_MQTT_device_core::unregisterControl(String key) +{ + String topic = "api/v2/thing/" + token + "/delta/resp/pta/?sensor=" + key; // fact S s + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(topic); + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Control [Key]: \"" + key + "\" Unsubscribe: " + _debug); + return Sub_status; +} // +boolean MAGELLAN_MQTT_device_core::unregisterConfig(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/config/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/config/resp"; + break; + default: + topic = "api/v2/thing/" + token + "/config/resp"; + break; + } + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe ServerConfig: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} // +boolean MAGELLAN_MQTT_device_core::unregisterConfig(String key) +{ + String topic = "api/v2/thing/" + token + "/config/resp/pta/?config=" + key; // fact C c + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe ServerConfig [Key]: \"" + key + "\" Unsubscribe: " + _debug); + return Sub_status; +} // +boolean MAGELLAN_MQTT_device_core::unregisterTimestamp(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/server/dateTime/resp/pta"; + break; + case 1: + topic = "api/v2/server/dateTime/resp"; + break; + default: + topic = "api/v2/server/dateTime/resp"; + break; + } + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe ServerTime: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} // +boolean MAGELLAN_MQTT_device_core::unregisterResponseReport(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/report/resp/pta/+"; + break; + case 1: + topic = "api/v2/thing/" + token + "/report/resp"; + break; + default: + topic = "api/v2/thing/" + token + "/report/resp"; + break; + } + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Response Report: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} +boolean MAGELLAN_MQTT_device_core::unregisterResponseReportTimestamp() +{ + String topic = "api/v2/thing/" + token + "/report/timestamp/resp"; + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Response ReportTimestamp: " + _debug); + return Sub_status; +} +boolean MAGELLAN_MQTT_device_core::unregisterResponseHeartbeat(int format) +{ + String topic; + switch (format) + { + case 0: + topic = "api/v2/thing/" + token + "/heartbeat/resp/pta"; + break; + case 1: + topic = "api/v2/thing/" + token + "/heartbeat/resp"; + break; + default: + topic = "api/v2/thing/" + token + "/heartbeat/resp"; + break; + } + boolean Sub_status = this->client->unsubscribe(topic.c_str()); + _debug = (Sub_status == true) ? "Success" : "Failure"; + String respType = (format == 0) ? "Plaintext" : "JSON"; + Serial.println(F("-------------------------------")); + Serial.println("# Unsubscribe Response Heartbeat: " + _debug); + Serial.println("# Response type: " + respType); + return Sub_status; +} +////////////////// Unsub ////////// diff --git a/src/utils/MAGELLAN_MQTT_device_core.h b/src/utils/MAGELLAN_MQTT_device_core.h new file mode 100644 index 0000000..37c611d --- /dev/null +++ b/src/utils/MAGELLAN_MQTT_device_core.h @@ -0,0 +1,313 @@ +/* +Copyright (c) 2020, Advanced Wireless Network +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +support SIMCOM SIM7600E(AIS 4G Board) + +Author:(POC Device Magellan team) +Create Date: 25 April 2022. +Modified: 22 may 2023. +Released for private usage. +*/ +#ifndef MAGELLAN_MQTT_DEVICE_CORE_h +#define MAGELLAN_MQTT_DEVICE_CORE_h + +#include +#include "../PubSubClient.h" +#include "../ArduinoJson-v6.18.3.h" +#include +#include +#include +#include +#include +#include "Attribute_MQTT_core.h" +#include "BuiltinSensor.h" + +//Response Payload format some function can be set. +#define lib_version lib_ver +#define major_version _major_ver +#define feature_version _feature_ver +#define enhance_version _enhance_ver + +#define PLAINTEXT 0 //Plaintext +#define JSON 1 //Json + +#define ERROR 0 +#define TOKEN 1 +#define CONTROL_JSON 2 +#define CONTROL_PLAINTEXT 3 +#define CONFIG_JSON 4 +#define CONFIG_PLAINTEXT 5 +#define UNIXTIME 6 +#define UTCTIME 7 +#define RESP_REPORT_JSON 8 +#define RESP_REPORT_PLAINTEXT 9 +#define RESP_REPORT_TIMESTAMP 10 +#define RESP_HEARTBEAT_JSON 11 +#define RESP_HEARTBEAT_PLAINTEXT 12 +#define GET_ENDPOINT 13 + +#define mgPort 1883 +#define hostCentric "centric-magellan.ais.co.th" +//for define mode Timestamp +#define SET_UNIXTS 0 +#define SET_UTC 1 + +#define Production 1 +#define Staging 2 +#define IoT 3 + +#define _host_production "magellan.ais.co.th" + +#define defaultBuffer 1024 +#define defaultOTABuffer 8192 +#define _default_OverBufferSize 8192 + +#define UNKNOWN -1 +#define OUT_OF_DATE 0 +#define UP_TO_DATE 1 +typedef struct { + String Topic; + String Key; + String Action; + String Payload; + String RESP; + unsigned int CODE; + unsigned int PayloadLength; + //update 1.2.0 msgId + int MsgId = -1; +}EVENTS; +typedef struct { + String endPoint_IP; + String endPoint_DOMAIN; + String endPoint_PORT; +}Centric; + +typedef struct { + boolean isReadyOTA = false; + int firmwareIsUpToDate = -1; + boolean inProcessOTA = false; + unsigned int firmwareTotalSize = 0; + String firmwareName = "UNKNOWN"; + String firmwareVersion = "UNKNOWN"; + String checksum = "UNKNOWN"; + String checksumAlgorithm = "UNKNOWN"; +}OTA_INFO; + +typedef std::function ctrl_handleCallback; +typedef std::function ctrl_Json_handleCallback; +typedef std::function ctrl_JsonOBJ_handleCallback; +typedef std::function conf_handleCallback; +typedef std::function conf_Json_handleCallback; +typedef std::function conf_JsonOBJ_handleCallback; + +typedef std::function ctrl_PTAhandleCallback; +typedef std::function conf_PTAhandleCallback; +typedef std::function resp_callback; + +typedef std::function func_callback_registerList; + + + +//Client Internet interface connection +#define useGSMClient 0 +#define useExternalClient 1 + +typedef std::function func_callback_ms; + +class MAGELLAN_MQTT_device_core +{ +public: + MAGELLAN_MQTT_device_core(Client& client); // for customize client internet interface + MAGELLAN_MQTT_device_core(); // for GSM client internet interface + boolean flagToken = false; + String client_id; + // String unixtTime; + void setAuthMagellan(String _thingIden, String _thingSecret, String _imei = "none"); // add on + void begin(boolean builtInSensor = false); + void begin(String _thingIden, String _thingSencret, String _imei, unsigned int Zone = Production, uint16_t bufferSize = 1024, boolean builtInSensor = true); + void beginCentric(); + void beginCustom(String _client_id, boolean builtInSensor, String _host, int _port, uint16_t bufferSize); // + void begin(String _client_id, boolean buildInSensor = true, unsigned int Zone = Production, uint16_t bufferSize = 1024); // + String getHostName(); // + void getBoardInfo(); // + String getIMEI(); + String getIMSI(); + String getICCID(); + String readToken(); + + void magellanCentric(const char* _host = hostCentric, int _port = mgPort); //add on + boolean reportSensor(); + boolean report(String payload); // + boolean report(String key, String value); // + boolean registerResponseReport(int format = JSON); + boolean registerResponseReportTimestamp(); + boolean registerResponseHeartbeat(int format = JSON); + boolean reportTimestamp(String timestamp, String JSONpayload, unsigned int timestamp_type = SET_UNIXTS); // Json Payload + boolean heartbeat(); // + void heartbeat(unsigned int triger_ms); // + boolean registerConfig(int format = JSON); // PTA and JSON + boolean registerConfig(String key);// + boolean registerControl(int format = JSON); // + boolean registerControl(String key); // + boolean registerTimestamp(int format = JSON); // + boolean reqControl(String key); + boolean reqControlJSON(); + + ////// unsub //////////////// + boolean unregisterControl(int format = JSON); // + boolean unregisterControl(String key); // + boolean unregisterConfig(int format = JSON); // PTA and JSON + boolean unregisterConfig(String key); // + boolean unregisterTimestamp(int format = JSON); // + boolean unregisterResponseReport(int format = JSON); + boolean unregisterResponseReportTimestamp(); + boolean unregisterResponseHeartbeat(int format = JSON); + ////// unsub //////////////// + + void getControl(String key, ctrl_handleCallback ctrl_callback); + void getControl(ctrl_PTAhandleCallback ctrl_pta_callback); + void getControlJSON(ctrl_Json_handleCallback ctrl_json_callback); + void getControlJSON(ctrl_JsonOBJ_handleCallback jsonOBJ_cb); + + void getConfig(String key, conf_handleCallback _conf_callback); + void getConfig(conf_PTAhandleCallback conf_pta_callback); + void getConfigJSON(conf_Json_handleCallback conf_json_callback); + void getConfigJSON(conf_JsonOBJ_handleCallback jsonOBJ_cb); + void getRESP(unsigned int resp_event ,resp_callback resp_cb); + + boolean getTimestamp(); // + boolean reqConfigJSON(); // + boolean reqConfig(String key); // + boolean reportClientConfig(String payload); // + boolean isConnected(); + void loop(); // + void setMessageListener(void(*callback)(EVENTS, char*)); + + void setManualToken(String _token); + void acceptToken(EVENTS event); + + boolean ACKControl(String key, String value); + boolean ACKControl(String payload); + + void interval_ms(unsigned long ms, func_callback_ms cb_ms); + void registerList(func_callback_registerList cb_regisList); + + // interface MAGELLANJSON + StaticJsonDocument<256> docJson; + + // StaticJsonDocument<1024> docBuild; + // StaticJsonDocument<512> docClientConf; + + String deserialControlJSON(String jsonContent); + JsonObject deserialJson(String jsonContent); + void addSensor(String key, String value, JsonDocument &ref_docs); + void addSensor(String key, const char* value, JsonDocument &ref_docs); + void addSensor(String key, int value, JsonDocument &ref_docs); + void addSensor(String key, float value, JsonDocument &ref_docs); + void addSensor(String key, boolean value, JsonDocument &ref_docs); + void updateSensor(String key, String value, JsonDocument &ref_docs); + void updateSensor(String key, const char* value, JsonDocument &ref_docs); + void updateSensor(String key, int value, JsonDocument &ref_docs); + void updateSensor(String key, float value, JsonDocument &ref_docs); + void updateSensor(String key, boolean value, JsonDocument &ref_docs); + String buildSensorJSON(JsonDocument &ref_docs); + void remove(String key, JsonDocument &ref_docs); + boolean findKey(String key, JsonDocument &ref_docs); + void adjustBufferSensor(size_t sizeJSONbuffer); + int readBufferSensor(JsonDocument &ref_docs); + void clearSensorBuffer(JsonDocument &ref_docs); + + void setMQTTBufferSize(uint16_t size); + boolean CheckString_isDigit(String valid_payload); // + boolean CheckString_isDouble(String valid_payload); // + + //OTA Feature// + void activeOTA(size_t part_size, boolean useChecksum = true); + void handleOTA(boolean OTA_after_getInfo = true); + boolean registerInfoOTA(); + boolean registerDownloadOTA(); + boolean unregisterInfoOTA(); + boolean unregisterDownloadOTA(); + boolean updateProgressOTA(String OTA_state, String description); + boolean requestFW_Info(); + boolean requestFW_Download(unsigned int fw_part, size_t part_size); + void setChecksum(String md5Checksum); + void setChunkSize(size_t Chunksize); + static OTA_INFO OTA_info; + static func_callback_registerList duplicate_subs_list; //ver.1.2.0 + /////////////// + +private: + int _default_bufferSize = 1024; + // BuiltinSensor mySensor; + void reconnect(); //add on + void checkConnection(); // + void getEndPoint(); //get end point from centric + boolean acceptEndPoint(String payload); //get end point from centric + void thingRegister(); // + void acceptToken(String payload); // + boolean setBufferSize(uint16_t size); // default 256 (uplink 128 + downlink 128) + String byteToString(byte* payload, unsigned int length_payload); // convert byte* to string + void setCallback_msgHandle(); + void initialBoard(); // + unsigned long previouseMillis = 0; // + boolean flagRegisterEndPoint= false; // + boolean flagGetEndPoint = false; // + boolean flagRegisterToken = false; // + boolean flagReportRetry = false; + boolean flagAuthMagellan = false; + + boolean registerToken(); // + boolean requestToken(); // + boolean requestEndpoint(); // + void reconnectMagellan(); // + int limit_attempt = 11; // 11 -> for atempt 10 request token + int cnt_attempt = 0; // + int recon_attempt = 0; + int MAXrecon_attempt = 10; + unsigned long prev_time; + unsigned long now_time; + unsigned long threshold_ms; + + unsigned long HB_prev_time; + unsigned long HB_now_time; + unsigned long HB_threshold_ms; + + unsigned long cnt_fail = 0; + + String host; + String thingIden; + String thingSecret; + String imei; + String token; + String _debug; + int port; + +protected: + PubSubClient *client = NULL; + GSMClient *gsm_client = NULL; +}; + +#endif + + diff --git a/src/utils/StorageMemory.cpp b/src/utils/StorageMemory.cpp new file mode 100644 index 0000000..0b344c5 --- /dev/null +++ b/src/utils/StorageMemory.cpp @@ -0,0 +1,154 @@ +#include +#include "StorageMemory.h" + +StorageMemory::StorageMemory() +{ + Storaged = new GSMStorage; +} + +boolean StorageMemory::writeFile(String path, String content) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + bool result = Storaged->fileWrite(path, *&content); + Serial.println("# Write file in \""+path+"\" is: "+((result)?"Success":"Fail")); + return result; +} + +String StorageMemory::readFile(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + String res = Storaged->fileRead(path); + return res; +} + +String StorageMemory::readLargeFIle(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + return Storaged->readBigFile(path); +} + +boolean StorageMemory::deleteFile(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + bool result = Storaged->remove(path); + Serial.println("# Delete file in \""+path+"\" is: "+((result)?"Success":"Fail")); + return result; +} + +boolean StorageMemory::createDirectory(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + bool result = Storaged->mkdir(path); + Serial.println("# Create Directory in \""+path+"\" is: "+((result)?"Success":"Fail")); + return result; +} + +boolean StorageMemory::deleteDirectory(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + bool result = Storaged->rmdir(path); + Serial.println("# Remove Directory in \""+path+"\" is: "+((result)?"Success":"Fail")); + return result; +} + +boolean StorageMemory::isFileExist(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + bool result = Storaged->isFileExist(path); + Serial.println("# file \""+path+"\" is file exist: "+((result)?"Found":"Not Found")); + return result; +} + +ListFileString StorageMemory::getListOfFiles(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(path); + return Storaged->getListOfFiles(path); +} + +ListFileString StorageMemory::getListOfDirectories(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(path); + return Storaged->getListOfDirectories(path); +} + +size_t StorageMemory::getFileSize(String path) +{ + // GSMStorage *Storaged = new GSMStorage; + setCurrentPATH(getRootPath(path)); + return Storaged->getFileSize(path); +} + +String StorageMemory::getCurrentRootPATH() +{ + String result; + String valid_path = currentPath.substring(0,1); //valid first charecter + valid_path.toUpperCase(); + if(valid_path == "D") + { + if(currentPath.startsWith("D:/") && currentPath == "D:/") + { + result = currentPath; + } + else if(currentPath.startsWith("D:/") && currentPath.length() > 3) + { + result = currentPath + "/"; + } + } + else if(valid_path == "C") + { + if(currentPath == "C:/") + { + result = currentPath; + } + else if(currentPath.startsWith("C:/") && currentPath.length() > 3) + { + result = currentPath + "/"; + } + } + else{ // if use etc path like E: F: + result = currentPath; + } + return result; +} + +boolean StorageMemory::setCurrentPATH(String path){ + if (!_SIM_Base.sendCommandFindOK("AT+FSCD=" + path)) + { + Serial.println("# something wrong"); + Serial.println("# can't not set current path: "+path); + return false; + } + + currentPath = path; + + // Serial.println("# move to path on: "+currentPath); + return true; +} + +String StorageMemory::getRootPath(String path) +{ + String basePath = "D:/"; + int pathLength = path.length()+1; + const int index = path.lastIndexOf("/"); + if(index == 2) + { + basePath = path.substring(0, index + 1); + } + else if(index > 2) + { + basePath = path.substring(0, index); + } + // Serial.println(basePath); + // Serial.println("basePath is: "+basePath); + // Serial.println("index /: "+String(index)); + return basePath; +} diff --git a/src/utils/StorageMemory.h b/src/utils/StorageMemory.h new file mode 100644 index 0000000..22b2ad3 --- /dev/null +++ b/src/utils/StorageMemory.h @@ -0,0 +1,33 @@ +#ifndef STORAGEMEMORY_H +#define STORAGEMEMORY_H +#include +#include +#include "SIMBase.h" +#include +#include +#include "utility.h" +class StorageMemory +{ +private: + GSMStorage *Storaged; + String currentPath; + String getRootPath(String path); // +public: + StorageMemory(); + + boolean writeFile(String path, String content);// + String readFile(String path); // + String readLargeFIle(String path); + boolean deleteFile(String path); // + boolean createDirectory(String path); + boolean deleteDirectory(String path); // + boolean isFileExist(String path); // + ListFileString getListOfFiles(String path) ; // + ListFileString getListOfDirectories(String path) ; // + size_t getFileSize(String path); // + + boolean setCurrentPATH(String path); // + String getCurrentRootPATH(); // +}; +extern StorageMemory ext_mem; +#endif \ No newline at end of file diff --git a/src/utils/manageConfigOTAFile.cpp b/src/utils/manageConfigOTAFile.cpp new file mode 100644 index 0000000..e0e1220 --- /dev/null +++ b/src/utils/manageConfigOTAFile.cpp @@ -0,0 +1,326 @@ +//lasted update 15/11/2022 - check lasted too if state configfile fail, before decide to ota must compare lasted with incoming fw info too +#include "manageConfigOTAFile.h" + +void manageConfigOTAFile::beginFileSystem(boolean formatIfFail) +{ + fileSys.begin(formatIfFail); +} + +boolean manageConfigOTAFile::checkFileOTA() +{ + return fileSys.isFileExist(configOTAFilePath); +} + +boolean manageConfigOTAFile::checkLastedOTA() +{ + return fileSys.isFileExist(lastedOTAPath); +} + + +boolean manageConfigOTAFile::createConfigFileOTA() +{ + String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\",\"status\":\"null\"}"; + return fileSys.writeFile(configOTAFilePath, init_config.c_str()); +} + +boolean manageConfigOTAFile::createLastedOTA() +{ + String init_config = "{\"namefirmware\":\"null\",\"sizefirmware\":\"0\",\"versionfirmware\":\"null\",\"checksumAlgorithm\":\"null\",\"checksum\":\"null\"}"; + return fileSys.writeFile(lastedOTAPath, init_config.c_str()); +} + +String manageConfigOTAFile::readConfigFileOTA() +{ + return fileSys.readFile(configOTAFilePath); +} + +String manageConfigOTAFile::readLastedOTA() +{ + return fileSys.readFile(lastedOTAPath); +} + +JsonObject manageConfigOTAFile::readObjectConfigFileOTA() +{ + String buffReadConfigOTA = readConfigFileOTA(); + JsonObject buffer; + OTAdoc.clear(); + if(buffReadConfigOTA != NULL) + { + DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); + buffer = OTAdoc.as(); + if(error) + Serial.println("# Error to DeserializeJson readConfigFileOTA"); + } + return buffer; +} +JsonObject manageConfigOTAFile::readObjectLastedOTA() +{ + String buffReadConfigOTA = readLastedOTA(); + JsonObject buffer; + OTAdoc.clear(); + if(buffReadConfigOTA != NULL) + { + DeserializationError error = deserializeJson(OTAdoc, buffReadConfigOTA); + buffer = OTAdoc.as(); + if(error) + Serial.println("# Error to DeserializeJson readLastedOTA"); + } + return buffer; +} + +String manageConfigOTAFile::readSpacificFromConfFile(String readKey) +{ + String result = readObjectConfigFileOTA()[readKey.c_str()]; + return result; +} + +boolean manageConfigOTAFile::saveProfileOTA(JsonObject dataOTA, String stateOTA) +{ + OTAdoc.clear(); + if(stateOTA != NULL && dataOTA.size() > 0) + { + OTAdoc = dataOTA; + OTAdoc.remove("Code"); + OTAdoc["status"] = stateOTA.c_str(); + + String contentToWrite; + serializeJson(OTAdoc, contentToWrite); + + bool saveFile = fileSys.writeFile(configOTAFilePath, contentToWrite.c_str()); + if(saveFile) + { + // Serial.println("# New Information OTA: "+contentToWrite); + Serial.println(F("# Save firmware information success!")); + } + return saveFile; + } + else + { + return false; + } +} + +boolean manageConfigOTAFile::saveLastedOTA(String lastedDataOTA) +{ + +// #ifdef ESP32 +// String buffReadLastedOTA = lastedDataOTA.c_str(); +// #elif defined ESP8266 +// String buffReadLastedOTA = lastedDataOTA; +// #endif + bool saveFile = false; + JsonObject buffer; + OTAdoc.clear(); + if(lastedDataOTA.c_str() != NULL) + { + DeserializationError error = deserializeJson(OTAdoc, lastedDataOTA.c_str()); + buffer = OTAdoc.as(); + if(error) + { + Serial.println("# Error to DeserializeJson saveLastedOTA"); + return false; + } + else + { + buffer.remove("status"); + String contentLasted; + serializeJson(buffer, contentLasted); + + saveFile = fileSys.writeFile(lastedOTAPath, contentLasted.c_str()); + if(saveFile) + { + // Serial.println("# New Information OTA: "+contentToWrite); + // Serial.println("# saveLastedOTA: "+contentLasted); + Serial.println(F("# Save lastedOTA success!")); + } + return saveFile; + } + } + return saveFile; +} + +boolean manageConfigOTAFile::saveSuccessOrFail(String stateOTA) +{ + JsonObject bufferProfile = readObjectConfigFileOTA(); + + StaticJsonDocument<512> docsBuffer = bufferProfile; + bufferProfile.remove("Code"); + docsBuffer["status"] = stateOTA.c_str(); + String ProfileUpdate; + serializeJson(docsBuffer, ProfileUpdate); + return fileSys.writeFile(configOTAFilePath, ProfileUpdate.c_str()); +} + +boolean manageConfigOTAFile::compareFirmwareOTA(JsonObject dataOTA) +{ + JsonObject bufferProfile = readObjectConfigFileOTA(); + String status = readSpacificFromConfFile("status"); + + String readFW_name = bufferProfile["namefirmware"]; + String incomingFW_name = dataOTA["namefirmware"]; + + size_t readFW_size = bufferProfile["sizefirmware"]; + size_t incomingFW_size = dataOTA["sizefirmware"]; + + String readFW_checksum = bufferProfile["checksum"]; + String incomingFW_checksum = dataOTA["checksum"]; + + String readFW_version = bufferProfile["versionfirmware"]; + String incomingFW_version = dataOTA["versionfirmware"]; + + String readFW_csAlg = bufferProfile["checksumAlgorithm"]; + String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; + + String readFW_cs = bufferProfile["checksum"]; + String incomingFW_cs = dataOTA["checksum"]; + + // Lasted check + JsonObject buffLasted = readObjectLastedOTA(); + + String LastedFW_name = buffLasted["namefirmware"]; + size_t LastedFW_Size = buffLasted["sizefirmware"]; + String LastedFW_checksum = buffLasted["checksum"]; + // Lasted check + if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") + { + Serial.println(F("")); + Serial.println(F("# Device is unknow version in file system")); + Serial.println(F("# Save firmware information")); + Serial.println("# ======== Information OTA ========"); + // Serial.println("# firmware name: "+ incomingFW_name); + // Serial.println("# firmware size: "+ String(incomingFW_size)); + Serial.println("# firmware version: "+ incomingFW_version); + // Serial.println("# firmware checksumAlgorithm: "+ incomingFW_csAlg); + Serial.println("# firmware checksum: "+ incomingFW_checksum); + Serial.println(F("")); + saveProfileOTA(*&dataOTA, "initialize"); + return false; //false mean firmware not match + } + if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && + readFW_checksum == incomingFW_checksum) + { + if(status == "done") + { + Serial.println(F("")); + Serial.println(F("# ======== Firmware is up to date ========")); + // Serial.println("# firmware name: "+ incomingFW_name); + // Serial.println("# firmware size: "+ String(incomingFW_size)); + Serial.println("# Firmware device version: "+ incomingFW_version); + Serial.println(F("# =========================================")); + Serial.println(F("")); + return true; + } + else if(status == "fail" && !(LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) + { + Serial.println(F("")); + Serial.println(F("#[OTA Failed] Try to OTA firmware again")); + Serial.println(F("# ======== Information OTA ========")); + // Serial.println("# firmware name: "+ incomingFW_name); + // Serial.println("# firmware size: "+ String(incomingFW_size)); + Serial.println("# firmware version: "+ incomingFW_version); + Serial.println(F("")); + saveProfileOTA(*&dataOTA, "initialize"); + return false; //false mean firmware not match + } + else{ + Serial.println(F("")); + Serial.println(F("# Keep going to OTA firmware again")); + Serial.println(F("# ======== Information OTA ========")); + // Serial.println("# firmware name: "+ incomingFW_name); + // Serial.println("# firmware size: "+ String(incomingFW_size)); + Serial.println("# firmware version: "+ incomingFW_version); + Serial.println(F("")); + return false; //false mean firmware not match + } + } + else{ // fw not match incoming != file => new version + if(status == "done") + { + Serial.println(F("")); + Serial.println(F("# Device have new version")); + Serial.println(F("# ======== Information OTA change ========")); + // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); + // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); + Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); + Serial.println(F("")); + saveProfileOTA(*&dataOTA, "initialize"); + return false; //false mean firmware not match + } + else if(status != "done" && (LastedFW_name == incomingFW_name && LastedFW_Size == incomingFW_size && LastedFW_checksum == incomingFW_checksum)) + { + Serial.println(F("")); + Serial.println(F("# ======== Firmware is up to date ========")); + // Serial.println("# firmware name: "+ incomingFW_name); + // Serial.println("# firmware size: "+ String(incomingFW_size)); + Serial.println("# Firmware device version: "+ incomingFW_version); + Serial.println(F("# =========================================")); + Serial.println(F("")); + return true; + } + else{ + Serial.println(F("")); + Serial.println("# Previous version OTA does not success status is: \""+ status +"\"# but have new version"); + Serial.println(F("# ======== Information OTA change ========")); + // Serial.println("# firmware name: "+ readFW_name +" ==> "+incomingFW_name); + // Serial.println("# firmware size: "+ String(readFW_size) +" ==> "+ String(incomingFW_size)); + Serial.println("# firmware version: "+ readFW_version + " ==> "+ incomingFW_version); + Serial.println(F("")); + saveProfileOTA(*&dataOTA, "initialize"); + return false; //false mean firmware not match + } + } +} + +boolean manageConfigOTAFile::compareFirmwareIsUpToDate(JsonObject dataOTA) +{ + JsonObject buffLastedOTA = readObjectLastedOTA(); + + String readFW_name = buffLastedOTA["namefirmware"]; + String incomingFW_name = dataOTA["namefirmware"]; + + size_t readFW_size = buffLastedOTA["sizefirmware"]; + size_t incomingFW_size = dataOTA["sizefirmware"]; + + String readFW_checksum = buffLastedOTA["checksum"]; + String incomingFW_checksum = dataOTA["checksum"]; + + String readFW_version = buffLastedOTA["versionfirmware"]; + String incomingFW_version = dataOTA["versionfirmware"]; + + String readFW_csAlg = buffLastedOTA["checksumAlgorithm"]; + String incomingFW_csAlg = dataOTA["checksumAlgorithm"]; + + String readFW_cs = buffLastedOTA["checksum"]; + String incomingFW_cs = dataOTA["checksum"]; + + if(readFW_name == "null" || readFW_size <= 0 || readFW_checksum == "null") + { + Serial.println(F("")); + Serial.println(F("# ======== Firmware is out of date ========")); + Serial.println(F("# ======== Device unknown version ========")); + Serial.println("# New version is available: "+ incomingFW_version); + Serial.println(F("# ========================================")); + Serial.println(F("")); + return false; + } + if(readFW_name == incomingFW_name && readFW_size == incomingFW_size && + readFW_checksum == incomingFW_checksum) + { + Serial.println(F("")); + Serial.println(F("# ======== Firmware is up to date ========")); + Serial.println("# Firmware device version: "+ readFW_version); + Serial.println(F("# =========================================")); + Serial.println(F("")); + return true; + } + else{ + Serial.println(F("")); + Serial.println(F("# ======== Firmware is out of date ========")); + Serial.println(F("# ======== NEW firmware available ========")); + Serial.println("# New version is available: "+ incomingFW_version); + Serial.println("# Firmware device version: "+ readFW_version); + Serial.println(F("# ========================================")); + Serial.println(F("")); + return false; + } +} \ No newline at end of file diff --git a/src/utils/manageConfigOTAFile.h b/src/utils/manageConfigOTAFile.h new file mode 100644 index 0000000..c7b9946 --- /dev/null +++ b/src/utils/manageConfigOTAFile.h @@ -0,0 +1,35 @@ +#ifndef MANAGECONFIGOTAFILE_H +#define MANAGECONFIGOTAFILE_H +#include +#include "SPIFFS.h" +#include "FS.h" +#include +#include "FileSystem.h" +#include "../ArduinoJson-v6.18.3.h" +// typedef std::vector ListFileString; + +class manageConfigOTAFile +{ +private: + const char* configOTAFilePath = "/configOTAFile.json"; + const char* lastedOTAPath = "/lastedOTAFile.json"; + StaticJsonDocument<512> OTAdoc; +public: + void beginFileSystem(boolean formatIfFail = true); + boolean checkFileOTA(); + boolean checkLastedOTA(); + boolean createConfigFileOTA(); + boolean createLastedOTA(); + String readConfigFileOTA(); + String readLastedOTA(); + JsonObject readObjectConfigFileOTA(); + JsonObject readObjectLastedOTA(); + String readSpacificFromConfFile(String readKey); + boolean saveProfileOTA(JsonObject dataOTA, String stateOTA); + boolean saveLastedOTA(String lastedDataOTA); + boolean saveSuccessOrFail(String stateOTA); + boolean compareFirmwareOTA(JsonObject dataOTA); //using for incoming without check update + boolean compareFirmwareIsUpToDate(JsonObject dataOTA); //using when incoming by check update +}; +extern manageConfigOTAFile configOTAFile; +#endif \ No newline at end of file diff --git a/src/utils/utility.cpp b/src/utils/utility.cpp new file mode 100644 index 0000000..49f81b2 --- /dev/null +++ b/src/utils/utility.cpp @@ -0,0 +1,78 @@ +#include +#include +#include "./utility.h" + + tm utility::convertUnix(unsigned long unix, int timeZone) + { + time_t timestamp = unix + (timeZone * 60 * 60); + tm *local_time = gmtime(×tamp); + return *local_time; + } + + String utility::toDateTimeString(unsigned long unixtTime, int timeZone) + { + tm buff_tm = utls.convertUnix(unixtTime, timeZone); + char dateSTR[] = "00/00/0000 00:00:00"; + if(buff_tm.tm_year < 1900) + { + sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year + 1900, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); + } + else + { + sprintf(dateSTR, "%02i/%02i/%04i %02i:%02i:%02i", buff_tm.tm_mday, buff_tm.tm_mon +1, buff_tm.tm_year, buff_tm.tm_hour, buff_tm.tm_min, buff_tm.tm_sec); + } + return String(dateSTR); + } + + String utility::toUniversalTime(unsigned long unixtTime, int timeZone) + { + tm buff_tm = convertUnix(unixtTime, timeZone); + char _utc[] = "0000-00-00T00:00:00"; + char _lc[] = "00:00"; + char _lc_h[] = "00"; + String result = "0000-00-00T00:00:00+00:00"; + sprintf(_utc, "%04i-%02i-%02iT%02i:%02i:%02i", buff_tm.tm_year + 1900, buff_tm.tm_mon +1, buff_tm.tm_mday, + buff_tm.tm_hour,buff_tm.tm_min, buff_tm.tm_sec); + if(timeZone >= 0) + { + sprintf(_lc_h, "%02i", timeZone); + sprintf(_lc, "%03s:%02s", "+"+String(_lc_h), "00"); + } + else{ + sprintf(_lc_h, "%03i", timeZone); + sprintf(_lc, "%03s:%02s", String(_lc_h), "00"); + } + result = String(_utc) + String(_lc); + return result; + } + + unsigned long utility::toUnix(tm time_) + { + unsigned long _unix = (long)0000000000; + tm t; + t.tm_mday = time_.tm_mday; + t.tm_mon = time_.tm_mon; + if(time_.tm_year < 1900) + { + t.tm_year = time_.tm_year; + } + else + { + t.tm_year = time_.tm_year -1900; + } + t.tm_hour = time_.tm_hour; + t.tm_min = time_.tm_min; + t.tm_sec = time_.tm_sec; + t.tm_isdst = -1; + _unix = mktime(&t); + return _unix; + } + + boolean utility::StringIsDigit(String validate_str) + { + for(byte i = 0; i < validate_str.length(); i++) + { + if(!isDigit(validate_str.charAt(i))) return false; + } + return true; + } \ No newline at end of file diff --git a/src/utils/utility.h b/src/utils/utility.h new file mode 100644 index 0000000..186559d --- /dev/null +++ b/src/utils/utility.h @@ -0,0 +1,17 @@ + +#ifndef UTILITY_H +#define UTILITY_H +#include + class utility + { + private: + + public: + String toDateTimeString(unsigned long unixtTime, int timeZone); + String toUniversalTime(unsigned long unixtTime, int timeZone); + unsigned long toUnix(tm time_); + tm convertUnix(unsigned long unix, int timeZone); + boolean StringIsDigit(String validate_str); + }; + extern utility utls; +#endif \ No newline at end of file