/**
 * @brief Settings.c
 * @author muratdemirtastr@gmail.com
 */
 #include "Application/Application.h"
 #include "Application/JSON/parson.h"
 #include "BSP_ESP32/RealTimeClock/rtc_pcf8563.h"
 #include "BSP_ESP32/Tone/bsp_tone.h"
 #include "BSP_ESP32/UART/bsp_uart.h"
 #include "Settings.h"
 #include "driver/gpio.h"
 #include "esp_err.h"
 #include "esp_system.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/projdefs.h"
 #include "freertos/task.h"
 #include "BSP_ESP32/InternalFlash/esp32_internal_flash.h"
 #include "BSP_ESP32/Bluetooth/bsp_bluetooth.h"
 #include "BSP_ESP32/TCPServer/tcpserver.h"
 #include "BSP_ESP32/OTA/esp_ota_http.h"
 #include "BSP_ESP32/LittleFS/bsp_littlefs.h"
 #include "BSP_ESP32/AES/bsp_aes.h"
 #include "esp_log.h"
 #include "mbedtls/base64.h"
 #include "BSP_ESP32/RNG/rng.h"
 #include "BSP_ESP32/RFID/bsp_mfrc522.h"
 #include <stdint.h>
 #include <time.h>
 /**
  * Check and get device commands
  * @param command_buffer command buffer
  * @param request_from command to where?
  */
 void Device_Execute_Cloud_Settings(uint8_t command_buffer[], int request_from){
      /*json ana dizini icin kullanýlan pointer*/
     JSON_Value *root_value;
     /*json object icin kullanýlan pointer*/
     JSON_Object *commit;
     /* alýnan veriyi json olarak parse etmeye çalýþ*/
     root_value = json_parse_string((char*)command_buffer);
     /* alýnan verinin kok json deðerlerini al*/
     commit = json_value_get_object(root_value);
     /* clear response buffers*/
     ESP_LOGE("Cloud", "Recv %s", command_buffer);
     /* check commands*/
     if(strstr((char*)command_buffer, "setdatetime")){
         Device_Settings_Set_Time(commit, request_from);
     }else if(strstr((char*)command_buffer, "refreshpublickey")){
         Device_Settings_Refresh_PublicKey(commit, request_from);
     }else if(strstr((char*)command_buffer, "readlog")){
         Application_Send_Log_2Server(request_from);
     }else if(strstr((char*)command_buffer, "addcards")){
         Device_Settings_RFID_AddCards(commit, request_from);
     }else if(strstr((char*)command_buffer, "deletecards")){
         Device_Settings_RFID_DeleteCards(commit, request_from);
     }else if(strstr((char*)command_buffer, "readaccess")){
         Device_Settings_RFID_RS485ReadRequest(request_from);
     }else if(strstr((char*)command_buffer, "updatecards")){
         Device_Settings_RFID_UpdateCards(request_from);
     }else if(strstr((char*)command_buffer, "formatcards")){
         Device_Settings_RFID_FormatCards(request_from);
     }else if(strstr((char*)command_buffer, "getcards")){
         Device_Settings_RFID_GetCards(request_from);
     }else if(strstr((char*)command_buffer, "restart")){
         Device_Settings_Set_Reset(request_from);
     }else if(strstr((char*)command_buffer, "setsoftwareupdate")){
         Device_Settings_Set_Update(commit, request_from);
     }else if(strstr((char*)command_buffer, "getdeviceinfo")){
         Device_Settings_Get_Device_Config(request_from);
     }else if(strstr((char*)command_buffer, "setrelay1")){
         Device_Settings_Set_RelayConfig1(commit, request_from);
     }else if(strstr((char*)command_buffer, "setrelay2")){
         Device_Settings_Set_RelayConfig2(commit, request_from);
     }else if(strstr((char*)command_buffer, "setinput1")){
         Device_Settings_Set_InputConfig1(commit, request_from);
     }else if(strstr((char*)command_buffer, "setinput2")){
         Device_Settings_Set_InputConfig2(commit, request_from);
     }else if(strstr((char*)command_buffer, "clearinputs")){
         Device_Settings_ClearInputAlarms(commit, request_from);
     }else if(strstr((char*)command_buffer, "setstaticwifi")){
         Device_Settings_Set_WifiStaticIP(commit, request_from);
     }else if(strstr((char*)command_buffer, "setstaticeth")){
         Device_Settings_Set_ETHStaticIP(commit, request_from);	
     }else if(strstr((char*)command_buffer, "formatfs")){
         Device_Settings_Format_FS(commit, request_from);
     }else if(strstr((char*)command_buffer, "setwifissid")){
         Device_Settings_Set_WifiConfig(commit, request_from);
     }else if(strstr((char*)command_buffer, "rollbackapp")){
         Device_Settings_RollbackOldAPP(commit, request_from);
     }else if(strstr((char*)command_buffer, "setvalidapp")){
         Device_Settings_SetValidAPP(commit, request_from);
     }else if(strstr((char*)command_buffer, "setterminalmode")){
         Device_Settings_setTerminalMode(commit, request_from);
     }else if(strstr((char*)command_buffer, "setbacklight")){
         Device_Settings_setBacklight(commit, request_from);
     }else if(strstr((char*)command_buffer, "setremotetarget")){
         Device_Settings_setRemoteIp(commit, request_from);
     }else if(strstr((char*)command_buffer, "setrs485baud")){
         Device_Settings_setRS485Baud(commit, request_from);
     }else if(strstr((char*)command_buffer, "setcryptomode")){
         Device_Settings_setCryptoMode(commit, request_from);
     }else if(strstr((char*)command_buffer, "setmastercarduuid")){
         Device_Settings_setMasterCard(commit, request_from);
     }else if(strstr((char*)command_buffer, "grantaccess")){
         Device_Settings_GrantAccess(commit, request_from);
     }else if(strstr((char*)command_buffer, "clearlog")){
         Device_Settings_ClearLogs(commit, request_from);
     }else if(strstr((char*)command_buffer, "setaccessrate")){
         Device_Settings_setAccessRate(commit, request_from);
     }else if(strstr((char*)command_buffer, "setfactorysettings")){
         Device_Settings_setFactorySettings(commit, request_from);
     }else if(strstr((char*)command_buffer, "dobackup")){
         Device_Settings_DoBackup(commit, request_from);
     }
     else{
         Device_Settings_Send_ResponseRaw(request_from, "commandnotfound");
     }
     /*memory leak'in önlenmesi için kök veriyi boþalt*/
     json_value_free(root_value);
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_WifiStaticIP(JSON_Object *commit, int target_device){
     /* get static config */
     JSON_Object *config_root = json_object_get_object(commit, "setstaticwifi");
     /* checyk null */
     if(config_root == NULL){
         /* send response code */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get ip and address */
     const char* ip = json_object_get_string(config_root, "ip");
     const char* netmask =json_object_get_string(config_root, "netmask");
     const char* gw  = json_object_get_string(config_root, "gateway");
     const char* dns  = json_object_get_string(config_root, "dns");
     bool active = json_object_get_boolean(config_root,  "active");
     /* check active */
     if((active != 1) && (active != 0)){
         goto PARAM_ERROR;
     }
     /* check only active */
     if((ip == NULL) || (netmask == NULL) ||(gw == NULL) || (dns == NULL)){
         /* check active flag */
         if(active == 0 || active == 1){
             /* check active */
             if(active == 1){
                 device_settings.wifiStaticCFG.active = 222;
             }else{
                 device_settings.wifiStaticCFG.active = 111;
             }
         }else{
             goto PARAM_ERROR;
         }	
     }else{
         /* clear existing wifi config */
         memset(&device_settings.wifiStaticCFG, 0, sizeof(ts_static_ip_cfg));
         /* set new wifi static config */
         memcpy(device_settings.wifiStaticCFG.ip_addr, ip, strlen(ip));
         memcpy(device_settings.wifiStaticCFG.netmask, netmask, strlen(netmask));
         memcpy(device_settings.wifiStaticCFG.gw_addr, gw, strlen(gw));
         memcpy(device_settings.wifiStaticCFG.dns, dns, strlen(dns));
         /* check active status */
         if(active == 1){
             device_settings.wifiStaticCFG.active = 222;
         }else{
             device_settings.wifiStaticCFG.active = 111;
         }
         /* print message */
         ESP_LOGE("WiFi", "Received static ip: %s, netmask: %s, gw: %s, dns: %s", 
                                             device_settings.wifiStaticCFG.ip_addr,
                                             device_settings.wifiStaticCFG.netmask,
                                             device_settings.wifiStaticCFG.gw_addr,
                                             device_settings.wifiStaticCFG.dns);
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_ETHStaticIP(JSON_Object *commit, int target_device){
      /* get static config */
     JSON_Object *config_root = json_object_get_object(commit, "setstaticeth");
     /* checyk null */
     if(config_root == NULL){
         /* send response code */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get ip and address */
     const char* ip = json_object_get_string(config_root, "ip");
     const char* netmask =json_object_get_string(config_root, "netmask");
     const char* gw  = json_object_get_string(config_root, "gateway");
     const char* dns  = json_object_get_string(config_root, "dns");
     bool active = json_object_get_boolean(config_root,  "active");
     /* check active */
     if((active != 1) && (active != 0)){
         goto PARAM_ERROR;
     }
     /* check only active */
     if((ip == NULL) || (netmask == NULL) ||(gw == NULL) || (dns == NULL)){
         /* check active flag */
         if(active == 0 || active == 1){
             /* check active */
             if(active == 1){
                 device_settings.ethStaticCFG.active = 222;
             }else{
                 device_settings.ethStaticCFG.active = 111;
             }
         }else{
             goto PARAM_ERROR;
         }	
     }else{
         /* clear existing wifi config */
         memset(&device_settings.ethStaticCFG, 0, sizeof(ts_static_ip_cfg));
         /* set new wifi static config */
         memcpy(device_settings.ethStaticCFG.ip_addr, ip, strlen(ip));
         memcpy(device_settings.ethStaticCFG.netmask, netmask, strlen(netmask));
         memcpy(device_settings.ethStaticCFG.gw_addr, gw, strlen(gw));
         memcpy(device_settings.ethStaticCFG.dns, dns, strlen(dns));
         /* check active status */
         if(active == 1){
             device_settings.ethStaticCFG.active = 222;
         }else{
             device_settings.ethStaticCFG.active = 111;
         }
         /* print message */
         ESP_LOGE("ETH", "Received static ip: %s, netmask: %s, gw: %s, dns: %s", 
                                             device_settings.ethStaticCFG.ip_addr,
                                             device_settings.ethStaticCFG.netmask,
                                             device_settings.ethStaticCFG.gw_addr,
                                             device_settings.ethStaticCFG.dns);
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * @brief Sends a read request to the specified RFID device over RS485.
  *
  * This function initiates a read operation by sending a command over the RS485
  * communication bus to the RFID reader identified by the given target device.
  * It is typically used to request the current state or card list from a remote RFID module.
  *
  * @param target_device The index or address of the RFID device on the RS485 bus.
  *
  * @return void
  *
  * @note The function assumes the RS485 communication layer is already initialized
  *       and the target device address is valid.
  *
  * @warning Ensure RS485 bus is not busy before calling this function to avoid collisions.
  */
 void Device_Settings_RFID_RS485ReadRequest(int target_device){
     /* check rs475 flag */
     if(target_device == SOURCE_RS485){
          start_data.rs485AccessReceive = 222;
     }
 }
 /**
  * @brief Adds new RFID cards to the specified device using data from a JSON object.
  *
  * This function parses the provided JSON object to extract RFID card information
  * (such as UID or access level) and adds the specified cards to the internal database
  * or memory of the target RFID device.
  *
  * @param commit         Pointer to the JSON object containing the card data to add.
  *                       The expected structure may include fields like "cards", which
  *                       holds an array of card UIDs or objects.
  * @param target_device  The index or identifier of the RFID reader device to update.
  *
  * @return void
  *
  * @note The JSON format must match the expected schema. For example:
  *       {
  *           "cards": [
  *               { "uid": "A1B2C3D4", "access": 1 },
  *               { "uid": "11223344", "access": 0 }
  *           ]
  *       }
  *
  * @warning Invalid or incomplete JSON data may result in cards not being added.
  */ 
 void Device_Settings_RFID_AddCards(JSON_Object *commit, int target_device){
     /* variables */
     bool freeSlotFound = false;
     /* clear heartbeat timeout*/
     BSP_RFID_ClearHeartbeatTimeout();
     /* get array */
     JSON_Array *cards_array = json_object_get_array(commit, "addcards");
     /* check null */
     if (cards_array == NULL) {
          /* send response */
         Device_Settings_Send_Response(target_device, "jsonfailed ");
         return;
     }
     /* get count */
     size_t count = json_array_get_count(cards_array);
      /* iterate over count */
     for (size_t i = 0; i < count; i++) {
         /* get card uuid */
         const char *card = json_array_get_string(cards_array, i);
         /* check uuid */
         if (card != NULL) {
             /* get card value*/
             uint32_t card_value = strtoul(card, NULL, 0);
             bool cardExist = false;
             /* iterate over RFID*/
             for(uint16_t it = 0; it < BSP_RFID_TOTAL_RECORDS; it++){
                 /* check card exits */
                 if(card_value == rfidCredentials[it].id_credentials){
                     /* param control */
                     if(rfidCredentials[it].setFlag != 222){
                         rfidCredentials[it].setFlag = 222;
                     }
                     /* break*/
                     cardExist = true;
                     break;
                 }
             }
             /* check card exist */
             if(cardExist){
                 continue;
             }else{
                 /* iterate over RFID*/
                 for(uint16_t it = 0; it < BSP_RFID_TOTAL_RECORDS; it++){
                     /* check set flag */
                     if(rfidCredentials[it].setFlag != 222){
                         /* set new card uuit*/
                         rfidCredentials[it].setFlag = 222;
                         rfidCredentials[it].id_credentials = card_value;
                         freeSlotFound = true;
                         break;
                     }
                 }
                 /* check free slot */
                 if(!freeSlotFound){	
                     /* send and exit */
                     Device_Settings_Send_Response(target_device, "nomorespace");
                     return;
                 }
             }
         }
     }
      /* send response */
     Device_Settings_Send_Response(target_device, "saveok");
 }
 /**
  * @brief Retrieves the currently detected RFID cards for the specified device.
  *
  * This function fetches or returns the list of RFID cards detected or stored 
  * by the RFID reader associated with the given target device. It may involve 
  * accessing internal buffers, memory, or communicating with the RFID hardware.
  *
  * @param target_device The index or identifier of the RFID reader device to query.
  *
  * @return void
  *
  * @note The retrieved data may be stored in a global variable or accessed via 
  *       another API, depending on the implementation.
  */
 void Device_Settings_RFID_GetCards(int target_device) {
     /* batch index */
     uint8_t batch_index = 0;
     /* check ble and set flag and exit */
     if(target_device == SOURCE_BLE){
         BSP_Bluetooth_ReadCardReceived();
         return;
     }
     /* send response */
     Device_Settings_Send_Response(target_device, "readstarted");
     /* clear heartbeat timeout */
     BSP_RFID_ClearHeartbeatTimeout();
     /* create objects */
     JSON_Value *root_value = json_value_init_object();
     JSON_Object *root_object = json_value_get_object(root_value);
     JSON_Value *array_value = json_value_init_array();
     JSON_Array *cards_array = json_value_get_array(array_value);
     /* iterate over cards */
     for (uint16_t it = 0; it < BSP_RFID_TOTAL_RECORDS; it++) {
         /* check active */
         if (rfidCredentials[it].setFlag == 222) {
             /* build card uui*/
             char hex_str[20]; 
             snprintf(hex_str, sizeof(hex_str), "0x%08lX", 
                             (unsigned long)rfidCredentials[it].id_credentials);
             /* append json */
             json_array_append_string(cards_array, hex_str);
             /* increment batch */
             batch_index++;
             /* check batch index */
             if(batch_index >= 50) {
                 /* put array */
                 json_object_set_value(root_object, "getcards", array_value);
                 /* serialize it */
                 char *serialized = json_serialize_to_string(root_value);
                 /* check null ptr */
                 if (serialized != NULL) {
                     Device_Settings_Send_Response(target_device, serialized);
                     json_free_serialized_string(serialized);
                 }
                 /* free json */
                 json_value_free(root_value);
                   /* recreate jsons */
                 root_value = json_value_init_object();
                 root_object = json_value_get_object(root_value);
                 array_value = json_value_init_array();
                 cards_array = json_value_get_array(array_value);
                 /* clear batch index */
                 batch_index = 0;
             }
         }
     }
        /* check remaining */
     if (batch_index > 0) {
         /* create array */
         json_object_set_value(root_object, "getcards", array_value);
         /* check serialized */
         char *serialized = json_serialize_to_string(root_value);
         /* check null ptr */
         if (serialized != NULL) {
             Device_Settings_Send_Response(target_device, serialized);
             json_free_serialized_string(serialized);
         }
         /* free json*/
         json_value_free(root_value);
     } else {
         /* free json*/
         json_value_free(root_value);
     }
     /* send response*/
     Device_Settings_Send_Response(target_device, "readfinished");
 }
 /**
  * @brief Deletes one or more RFID cards based on the given JSON request.
  *
  * This function processes a JSON object (typically from a configuration or command interface)
  * to delete specific RFID cards associated with the specified target RFID device.
  *
  * @param commit         Pointer to the JSON object containing the card(s) to delete.
  *                       The object is expected to include relevant card identifiers.
  * @param target_device  The index or identifier of the RFID device from which the cards should be deleted.
  *
  * @return void
  *
  * @note The structure and required fields in the JSON object must match the expected format,
  *       such as containing a card UID or an array of UIDs under a specific key.
  *
  * @warning Invalid or malformed JSON input may result in no action or unexpected behavior.
  */
 void Device_Settings_RFID_DeleteCards(JSON_Object *commit, int target_device){
     /* clear heartbeat */
     BSP_RFID_ClearHeartbeatTimeout();
     /* get json array */
     JSON_Array *cards_array = json_object_get_array(commit, "deletecards");
     /* check array */
     if (cards_array == NULL) {
         /* */
         Device_Settings_Send_Response(target_device, "jsonfailed");
         false;
     }
     /* get array count */
     size_t count = json_array_get_count(cards_array);
     /* iterate over count */
     for (size_t i = 0; i < count; i++) {
         /* get card uuid */
         const char *card = json_array_get_string(cards_array, i);
         /* check null ptr */
         if (card != NULL) {	
             /* convert card */
             uint32_t card_value = strtoul(card, NULL, 0);
             for(uint16_t it = 0; it < BSP_RFID_TOTAL_RECORDS; it++){
                 /* check credential equality */
                 if(card_value == rfidCredentials[it].id_credentials){
                     /* clear it */
                     rfidCredentials[it].id_credentials = UINT32_MAX;
                     rfidCredentials[it].setFlag = 111;
                 }
             }
         }
     }
     /* sent ok*/
     Device_Settings_Send_Response(target_device, "saveok");
 }
 /**
  * @brief Erases all RFID card records stored for the specified device.
  *
  * This function clears or formats the internal memory or storage area where
  * RFID card data is held for the specified RFID reader device. It is typically
  * used to reset the card database or remove all authorized cards.
  *
  * @param target_device The index or identifier of the RFID reader device to format.
  *
  * @return void
  *
  * @note Use with caution. This operation will permanently delete all stored card data.
  */
 void Device_Settings_RFID_FormatCards(int target_device){
     /* clear heartbeat timeout */
     BSP_RFID_ClearHeartbeatTimeout();
 
     /* remove credentials*/
     if(BSP_RFID_RemoveCredentials()){
         BSP_RFID_RemoveCredentialsBackup();
         Device_Settings_Send_Response(target_device, "formatok");
         memset(&rfidCredentials, 0xFF, sizeof(ts_rc522_cred_t) * BSP_RFID_TOTAL_RECORDS);
     }else{
         Device_Settings_Send_Response(target_device, "formatfailed");
     }
 }
 /**
  * @brief Updates the list of detected RFID cards for the specified device.
  *
  * This function communicates with the RFID reader associated with the given
  * target device and updates the internal list of RFID cards currently detected.
  * It may also trigger application-level events or callbacks if the card list
  * has changed (e.g., cards added or removed).
  *
  * @param target_device The index or identifier of the RFID reader device to update.
  *
  * @return void
  */
 void Device_Settings_RFID_UpdateCards(int target_device){
     /* clear heartbeat timeout */
     BSP_RFID_ClearHeartbeatTimeout();
     /* dump RFID */
     if(BSP_RFID_Dump()){
         Device_Settings_Send_Response(target_device, "saveok");
     }else{
         Device_Settings_Send_Response(target_device, "savefailed");
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_GrantAccess(JSON_Object *commit, int target_device){
     /* create notify queue and clear */
     ts_notify_task_queue_t data;
     memset(&data, 0, sizeof(ts_notify_task_queue_t));
     /* get uuid */
     const char* uuid = json_object_get_string(commit, "grantaccess");
     /* check uuid len and null ptr */
     if(uuid == NULL || (strlen(uuid) > sizeof(data.accessUUID))){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* check requested source */
     switch (target_device) {
         case SOURCE_RS485:
             data.accessType = ACCESS_RS485;
             break;
         case SOURCE_TCP_SERVER:
             data.accessType = ACCESS_TCPSERVER;
             break;
         case SOURCE_TCP_CLIENT:
             data.accessType = ACCESS_TCPCLIENT;
             break;
         case SOURCE_BLE:
             data.accessType = ACCESS_BLE;
             break;
         default:
             Device_Settings_Send_ResponseCodeParameters(target_device, false);
             return false;
     }
     /* fill notify data*/
     memcpy(data.accessUUID, uuid, strlen(uuid));
     data.isgranted = 222;
     data.terminalMode = 111;
     data.timeStamp = rtc_handler.timeStamp;
     /* notify */
     App_Notify(&data);
     /* send value */
     Device_Settings_Send_ResponseCodeParameters(target_device, true);
     return true;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_ClearLogs(JSON_Object *commit, int target_device){
     /* take semaphore */
     if(xSemaphoreTake(fileSystemSemaphoreHandle, pdMS_TO_TICKS(5000)) != pdTRUE){
         /* send message */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         /* return */
         return false;
     }
     /* remove log file */
     if(BSP_LittleFS_RemoveFile("log_file.txt")){
         /* send message */
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         /* release semaphore */
         xSemaphoreGive(fileSystemSemaphoreHandle);
         /* return */
         return true;
     }else{
         /* send message */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         /* release semaphore */
         xSemaphoreGive(fileSystemSemaphoreHandle);
         /* return */
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_RelayConfig1(JSON_Object *commit, int target_device){
     /* get json object */
     JSON_Object *config_root = json_object_get_object(commit, "setrelay1");
     /* check null */
     if(config_root == NULL){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get mode */
     uint32_t mode = json_object_get_number(config_root, "mode");
      /* check timeout */
     uint32_t timeout  = json_object_get_number(config_root, "timeout");
     /* check param */
     if(mode >= ACCESS_MODE_MAX){
         goto PARAM_ERROR;
     }
     /* check param */
     if(timeout < 500 || timeout > 10000){
         goto PARAM_ERROR;
     }
     /* set values */
     device_settings.accessDevs[0].access_mode = mode;
     device_settings.accessDevs[0].triggerTimeout = timeout;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_RelayConfig2(JSON_Object *commit, int target_device){
     /* get json object */
     JSON_Object *config_root = json_object_get_object(commit, "setrelay2");
     /* check null */
     if(config_root == NULL){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get mode */
     uint32_t mode = json_object_get_number(config_root, "mode");
      /* check timeout */
     uint32_t timeout  = json_object_get_number(config_root, "timeout");
     /* check param */
     if(mode >= ACCESS_MODE_MAX){
         goto PARAM_ERROR;
     }
     /* check param */
     if(timeout < 500 || timeout > 10000){
         goto PARAM_ERROR;
     }
     /* set values */
     device_settings.accessDevs[1].access_mode = mode;
     device_settings.accessDevs[1].triggerTimeout = timeout;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_InputConfig1(JSON_Object *commit, int target_device){
     /* get json */
     JSON_Object *config_root = json_object_get_object(commit, "setinput1");
     /* check null*/
     if(config_root == NULL){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get mode, polarity and counter */
     uint32_t mode = json_object_get_number(config_root, "mode");
     uint32_t polarity =json_object_get_number(config_root, "polarity");
     uint32_t counter  = json_object_get_number(config_root, "detectcounter");
     /* limit control */
     if(mode > ACCESS_INPUT_MODE_MAX){
         goto PARAM_ERROR;
     }
     /* limit control */
     if(polarity >= ACCESS_INPUT_POL_MAX){
         goto PARAM_ERROR;
     }
     /* limit control */
     if(counter < 100 || counter > 2000){
         goto PARAM_ERROR;
     }
     /* set new values */
     device_settings.accessInputDev[0].accessInputMode = mode;
     device_settings.accessInputDev[0].accessInputPolarity = polarity;
     device_settings.accessInputDev[0].accessInputCounter = counter;
 
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_InputConfig2(JSON_Object *commit, int target_device){
     /* get json */
     JSON_Object *config_root = json_object_get_object(commit, "setinput2");
     /* check null*/
     if(config_root == NULL){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* get mode, polarity and counter */
     uint32_t mode = json_object_get_number(config_root, "mode");
     uint32_t polarity =json_object_get_number(config_root, "polarity");
     uint32_t counter  = json_object_get_number(config_root, "detectcounter");
     /* limit control */
     if(mode > ACCESS_INPUT_MODE_MAX){
         goto PARAM_ERROR;
     }
     /* limit control */
     if(polarity >= ACCESS_INPUT_POL_MAX){
         goto PARAM_ERROR;
     }
     /* limit control */
     if(counter < 100 || counter > 2000){
         goto PARAM_ERROR;
     }
     /* set new values */
     device_settings.accessInputDev[1].accessInputMode = mode;
     device_settings.accessInputDev[1].accessInputPolarity = polarity;
     device_settings.accessInputDev[1].accessInputCounter = counter;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 PARAM_ERROR:
      Device_Settings_Send_ResponseCodeParameters(target_device, false);
      return false;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_WifiConfig(JSON_Object *commit, int target_device){
     /* get new ssid */
     const char *ssid = json_object_get_string(commit, "setwifissid");
     /* get new password*/
     const char *passwd = json_object_get_string(commit, "setwifipassword");
     /* check nullable */
     if(ssid == NULL || passwd == NULL){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }else{
         /* if save is succesfully send response*/
         if(BSP_Device_Settings_SaveWiFi(true, (char*)ssid,
                         strlen(ssid), (char*)passwd, strlen(passwd))){
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }else{
             Device_Settings_Send_ResponseCodeParameters(target_device, false);
             return false;
         }
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_ClearInputAlarms(JSON_Object *commit, int target_device){
      /* clear flags */
     if((device_settings.alarmInput1State == 0) && (device_settings.alarmInput2State == 0)){
         device_settings.alarmInput1StateTime = 0;
         device_settings.alarmInput2StateTime = 0;
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }
     device_settings.alarmInput1State = 0;
     device_settings.alarmInput2State = 0;
     device_settings.alarmInput1StateTime = 0;
     device_settings.alarmInput2StateTime = 0;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setTerminalMode(JSON_Object *commit, int target_device){
      /* clear flags */
     uint8_t value = json_object_get_boolean(commit, "setterminalmode");
     /* check activated */
     if(value == true){
         /* check and set */
         if(device_settings.terminalMode != 222){
             device_settings.terminalMode = 222;
         }else{
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }
     }else{
         /* check and set */
         if(device_settings.terminalMode != 111){
             device_settings.terminalMode = 111;
         }else{
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setAccessRate(JSON_Object *commit, int target_device){
      /* clear flags */
     uint8_t value = json_object_get_number(commit, "setaccessrate");
 
     if(value > 10){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 
     if(value == device_settings.accessRateLimit){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }
 
     device_settings.accessRateLimit = value;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setFactorySettings(JSON_Object *commit, int target_device){
      /* clear flags */
      memset(&device_settings, 0xFF, sizeof(ts_device_settings_t));
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
 
         vTaskDelay(pdMS_TO_TICKS(1000));
 
         esp_restart();
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_DoBackup(JSON_Object *commit, int target_device){
      device_settings.backupUsed = 111;
     device_settings.backupUseTimestamp = 0;
     /* if save is succesfully send response*/
     if(BSP_RFID_Dump_Backup()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setMasterCard(JSON_Object *commit, int target_device){
      /* clear flags */
     uint32_t value = json_object_get_number(commit, "setmastercarduuid");
     /* check master card max uuid*/
     if(value == UINT32_MAX){
         /* check already set */
         if(device_settings.masterCardSet == 111){
             /* send response */
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }
         device_settings.masterCardUid = 0xFFFFFFFF;
         device_settings.masterCardSet = 111;
     }else{
         /* set new variables*/
         device_settings.masterCardSet = 222;
         device_settings.masterCardUid = value;
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setCryptoMode(JSON_Object *commit, int target_device){
      /* clear flags */
     uint8_t value = json_object_get_boolean(commit, "setcryptomode");
     /* check activated */
     if(value == true){
         /* check and set */
         if(device_settings.cryptoStatus != 222){
             device_settings.cryptoStatus = 222;
         }else{
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }
     }else{
         /* check and set */
         if(device_settings.cryptoStatus != 111){
             device_settings.cryptoStatus = 111;
         }else{
             Device_Settings_Send_ResponseCodeParameters(target_device, true);
             return true;
         }
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setBacklight(JSON_Object *commit, int target_device){
      /* clear flags */
     uint16_t value = json_object_get_number(commit, "setbacklight");
     /* check value */
     if(value > 255){
         /* return false */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* check same value */
     if(device_settings.ledBrightness == value){
         /* return true */
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }
     /* set new backlight value */
     device_settings.ledBrightness = value;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setRS485Baud(JSON_Object *commit, int target_device){
      /* clear flags */
     uint32_t newBaud = json_object_get_number(commit, "setrs485baud");
      /* check supported baudrate*/
     if(!BSP_UART_RS485_CheckSupportedSpeed(newBaud)){
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
     /* check already exists */
     if(device_settings.rs485Baudrate == newBaud){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }
     /* set new baud */
     device_settings.rs485Baudrate = newBaud;
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_setRemoteIp(JSON_Object *commit, int target_device){
      /* clear flags */
     const char* newURL = json_object_get_string(commit, "setremotetarget");
     /* check parameters */
     if((newURL == NULL || (strlen(newURL)) >= sizeof(device_settings.remoteIpAddr))){
         /* return true */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return true;
     }
     /* clear remote ip addr */
     memset(device_settings.remoteIpAddr, 0 , sizeof(device_settings.remoteIpAddr));
     /* set new remote ip addr */
     memcpy(device_settings.remoteIpAddr, newURL, strlen(newURL));
     /* check empty*/
     if (newURL[0] == '\0') {
         /* set remote ip */
         device_settings.remoteIpSet = 111;
     } else {
            /* set remote ip */
         device_settings.remoteIpSet = 222;
     }
     /* if save is succesfully send response*/
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_SetValidAPP(JSON_Object *commit, int target_device){
     /* set flags */
     start_data.otaWriteStarted = 111;
     start_data.otaWriteTimeout = 0;
     /* set valid app*/
     BSP_OTA_Mark_Valid_App(true);
     /* send response code parameter */
     Device_Settings_Send_ResponseCodeParameters(target_device, true);
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_RollbackOldAPP(JSON_Object *commit, int target_device){
     /* set rollback */
     if(BSP_OTA_RollbackOldApp()){
         /* send response code parameter */
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
     }else{
         /* send response code parameter */
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_Get_Device_Config(int target_device){
     /* collect device data */
     Application_Collect_Device_Data((char*)deviceResponseBuffer);
     /* send device response buffers */
     Device_Settings_Send_DeviceConfig(target_device);
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_Set_Reset(int target_device){
     /* try to format device data */
     Device_Settings_Send_ResponseCodeParameters(target_device, true);
     /* wait 100 ms*/
     vTaskDelay(pdMS_TO_TICKS(1000));
     /* restart esp32*/
     esp_restart();
     return;
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 bool Device_Settings_Set_Time(JSON_Object *commit, int target_device){
     /* get device rtc time struct and update it*/
     if(Device_Set_RTC_Date_Time(commit)){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
         return true;
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
         return false;
     }
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_Set_Update(JSON_Object *commit, int target_device){
     /* set flag */
     device_settings.bootloadRequested = 222;
     /* try to save flash */
     if(BSP_Device_Settings_Save()){
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
     }
     /* wait 3 second */
     vTaskDelay(pdMS_TO_TICKS(3000U));
     /* restart system */
     esp_restart();
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_Format_FS(JSON_Object *commit, int target_device){
     /* try to format partition */
     if(BSP_LittleFS_Format()){
         /* set response */
         Device_Settings_Send_ResponseCodeParameters(target_device, true);
     }else{
         Device_Settings_Send_ResponseCodeParameters(target_device, false);
     }
 }
 /**
  * That function will set air conditioner working mode
  * @param commit device received buffer
  * @param target_device Which channel will use for status response
  */
 void Device_Settings_Get_PublicKey(int target_device){
     uint8_t iwkey[16];
     char publicKey[64];
     size_t arrlen = sizeof(iwkey);
     char * p = publicKey;
     /* get crypto status */
     uint8_t cryptoStatus = device_settings.cryptoStatus;
     /* check crypto status */
     if((cryptoStatus != 222) && (cryptoStatus != 111)){
         cryptoStatus = 222;
     }
     /* check crypto status */
     if(cryptoStatus != 222){
         /* send response */
         Device_Settings_Send_ResponseRaw(target_device, "crypto disabled");
         return;
     }
     /* clear public key*/
     memset(publicKey, 0, sizeof(publicKey));
     /* get current iv vector */
     BSP_RNG_GetIV(iwkey, 16);
     /* build hex string */
     for (size_t i = 0; i < arrlen; i++) {
         p += sprintf(p, "%.2x", iwkey[i]);
     }
     /* send response */
     Device_Settings_Send_ResponseRaw(target_device, publicKey);
 }
 /**
  * Set target parameter value
  * @param commit json commit
  * @param target_device target device
  */
 void Device_Settings_Refresh_PublicKey(JSON_Object *commit, int target_device){
     /* refresh key variable */
     BSP_RNG_RefreshKey();
     /* send response*/
     Device_Settings_Get_PublicKey(target_device);
 }
 /**
  * Application log sender function
  * @param file_name file name 
  * @param remote online or offline mode  
  */
 bool Application_Send_Log_2Server(int request_from){
     /* calculation parameters */
     int32_t send_count = 0;
     int32_t remaining = 0;
     int32_t offset = 0;
     FILE * pFile;
     /* check ble operation */
     if(request_from == SOURCE_BLE){
         /* set flag and return */
         BSP_Bluetooth_ReadLogReceived();
         return true;
     }
     /* if file system not mounted */
     if(start_data.file_system_mounted != 222){
         /* send response message and return */
         Device_Settings_Send_Response(request_from, "FSNOTMOUNTED");
         return false;
     }
     /* get semaphore */
     if(xSemaphoreTake(fileSystemSemaphoreHandle, 2000) == pdTRUE){
         /* get file size */
         int32_t file_size = BSP_LittleFS_Read_File_Size("log_file.txt");
         /* get remaining size */
         remaining = file_size;
         /* open file in read mode */
         pFile = fopen("/littlefs/log_file.txt", "r");
         /* check file */
         if(pFile == NULL){
             /* send response */
             Device_Settings_Send_Response(request_from, "FILENOTFOUND");
             /* release semaphore */
             xSemaphoreGive(fileSystemSemaphoreHandle);
             return false;
         }
         /* if there is any log string */
         if(file_size > 1){
                 /* send response message and return */
                 Device_Settings_Send_Response(request_from, "UPLOADSTARTED");
                  /* read all of file */
                 while(!feof(pFile)){
                     /* clear buffers */
                     memset(deviceResponseBuffer, 0, sizeof(deviceResponseBuffer));
                     /* read file */
                     size_t bytesRead = fread(deviceResponseBuffer, 1, sizeof(deviceResponseBuffer), pFile);
                     /* on read */
                     if (bytesRead > 0){
                         /* send data to server */
                         Device_Settings_Send_Response(request_from, (char*)deviceResponseBuffer);
                         /* if there any error */
                         if(send_count < 0){
                             /* send response message and return */
                             Device_Settings_Send_Response(request_from, "LOGSENDFAIL");
                             /* close file and release semaphore */
                             fclose(pFile);
                             xSemaphoreGive(fileSystemSemaphoreHandle);
                             return false;
                         }
                         /* increment offset */
                         offset += bytesRead;
                         /* if end of the file */
                         if(offset >= remaining){
                             Device_Settings_Send_Response(request_from, "UPLOADFINISHED");
                             /* close file and release semaphore */	
                             fclose(pFile);
                             xSemaphoreGive(fileSystemSemaphoreHandle);
                             return true;
                         } 
                     }else{
                         Device_Settings_Send_Response(request_from, "LOGREADFAIL");
                         /* close file and release semaphore */	
                         fclose(pFile);
                         xSemaphoreGive(fileSystemSemaphoreHandle);
                         return false;
                     }
                 }
             }
         }else{
             Device_Settings_Send_Response(request_from, "SEMAPHOREERROR");
         }
     /* relase semaphore */
     xSemaphoreGive(fileSystemSemaphoreHandle);
     return false;
 }
  /**
  * Function for set RTC date
  * @param commit rtc date time string
  * @return operation status
  */
 bool Device_Set_RTC_Date_Time(JSON_Object *commit){
     /* new date time struct */
     ts_date_time_t newDateTime;
     /* datetime nesnesini al */
     JSON_Object *datetime = json_object_get_object(commit, "setdatetime");
     /* check null ptr */
     if (datetime == NULL) {
         ESP_LOGE("CLOUD", "Missing 'datetime' object in JSON");
         return false;
     }
     /* get fields */
     newDateTime.day    = (int)json_object_get_number(datetime, "day");
     newDateTime.month  = (int)json_object_get_number(datetime, "month");
     newDateTime.year   = (int)json_object_get_number(datetime, "year");
     newDateTime.wday   = (int)json_object_get_number(datetime, "wday");
     newDateTime.hour   = (int)json_object_get_number(datetime, "hour");
     newDateTime.minute = (int)json_object_get_number(datetime, "minute");
     newDateTime.second = (int)json_object_get_number(datetime, "second");
     /* set new date time */
     if (BSP_PCF8563_setDateTime(newDateTime)) {
         /* print message and return */
         ESP_LOGE("CLOUD", "New Date time is set successfully");
         return true;
     } else {
         /* print message and return */
         ESP_LOGE("CLOUD", "Cannot set new date time");
         return false;
     }
 }