From 00b7d2b29ac6a3b8a62e270aedaecd448174ea24 Mon Sep 17 00:00:00 2001 From: Manticore Date: Fri, 21 Feb 2025 15:00:04 +0530 Subject: [PATCH] Added Wifi credntials store to NVM --- main/adc_ifx.c | 374 ++-- main/adc_ifx.h | 36 +- main/comms.c | 4250 ++++++++++++++++++++++---------------------- main/comms.h | 566 +++--- main/main.c | 96 +- main/nvm.c | 2234 +++++++++++------------ main/nvm.h | 148 +- main/ota.c | 848 ++++----- main/ota.h | 64 +- main/wifi_Client.h | 100 +- main/wifi_Init.h | 128 +- main/wifi_OTA.c | 566 +++--- main/wifi_OTA.h | 44 +- 13 files changed, 4727 insertions(+), 4727 deletions(-) diff --git a/main/adc_ifx.c b/main/adc_ifx.c index 40f41aa..c087381 100644 --- a/main/adc_ifx.c +++ b/main/adc_ifx.c @@ -1,187 +1,187 @@ -/* - * adc_ifc.c - * - * Created on: Jan 17, 2023 - * Author: Partha - */ -#include -#include -#include -#include -#include "esp_log.h" -//#include "driver/adc.h" -#include "esp_adc/adc_oneshot.h" -#include "esp_adc/adc_cali.h" -#include "esp_adc/adc_cali_scheme.h" -//#include "esp_adc_cal.h" -#include "data_processing.h" -#include "hmi.h" -#include "ulp_main.h" - -static const char* TAG = "ADC_IF"; - -#define LOG_LOCAL_LEVEL ESP_LOG_INFO - -//static esp_adc_cal_characteristics_t adc1_chars; -RTC_DATA_ATTR uint32_t light_data3; -RTC_DATA_ATTR uint32_t prev_light_data3; - -adc_oneshot_unit_handle_t adc1_handle; -adc_cali_handle_t adc1_cali_handle = NULL; -static int adc_raw[2]; -static int voltage[2]; - -static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle) -{ - adc_cali_handle_t handle = NULL; - esp_err_t ret = ESP_FAIL; - bool calibrated = false; - -#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED - if (!calibrated) { - ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting"); - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = unit, - .atten = atten, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle); - if (ret == ESP_OK) { - calibrated = true; - } - } -#endif - -#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED - if (!calibrated) { - ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting"); - adc_cali_line_fitting_config_t cali_config = { - .unit_id = unit, - .atten = atten, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle); - if (ret == ESP_OK) { - calibrated = true; - } - } -#endif - - *out_handle = handle; - if (ret == ESP_OK) { - ESP_LOGI(TAG, "Calibration Success"); - } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) { - ESP_LOGW(TAG, "eFuse not burnt, skip software calibration"); - } else { - ESP_LOGE(TAG, "Invalid arg or no memory"); - } - - return calibrated; -} - -void adc_ifx_init(void) -{ - /*esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars); - - //Check type of calibration value used to characterize ADC - if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) - { - printf("ADC: eFuse Vref"); - } - else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) - { - printf("ADC: Two Point"); - } - else - { - printf("ADC: Default"); - } - adc1_ulp_enable(); - ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));*/ - - //-------------ADC1 Init---------------// - adc_oneshot_unit_init_cfg_t init_config1 = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); - - //-------------ADC1 Config---------------// - adc_oneshot_chan_cfg_t config = { - .bitwidth = ADC_BITWIDTH_13, - .atten = ADC_ATTEN_DB_11, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_0, &config)); - //ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_1, &config)); - - //-------------ADC1 Calibration Init---------------// - if(false == adc_calibration_init(ADC_UNIT_1, ADC_ATTEN_DB_11, &adc1_cali_handle)) - { - ESP_LOGI(TAG, "ADC Calibration NOT Supported"); - } -} - -static void adc_cal_deinit(adc_cali_handle_t handle) -{ -#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED - ESP_LOGI(TAG, "deregister %s calibration scheme", "Curve Fitting"); - ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle)); - -#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED - ESP_LOGI(TAG, "deregister %s calibration scheme", "Line Fitting"); - ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle)); -#endif -} - -void adx_ifx_deinit(void) -{ - //adc_cal_deinit(adc1_cali_handle); - adc_oneshot_del_unit(adc1_handle); -} - -uint32_t adc_if_get_batt_mV(void) -{ - //uint32_t val = 4*esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_0), &adc1_chars); - ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, &adc_raw[0])); - ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[0], &voltage[0])); - return 4*voltage[0]; -} - -#if 0 -uint32_t adc_if_get_light_mV(void) -{ - uint32_t test_val = 0; - //uint32_t val = esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_1), &adc1_chars); - ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_1, &adc_raw[1])); - ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[1], &voltage[1])); - - uint32_t val = voltage[1]; - - ESP_LOGI(TAG, "Light mV: %ld", val); - test_val = (val*255)/2504; - //if(data_get_light_sensor_gp() && data_get_light_sensor_gn()) - { - /*if the new light_sensor value is greater than GB_threshold or lower than GN_threshold*/ - //if((data_get_light_sensor_gn() > test_val) || (data_get_light_sensor_gp() < test_val)) - { - /* set the prev_light_data to the previous reading */ - //ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, ulp_raw_light_data, (int *)&prev_light_data)); - //prev_light_data = ulp_light_data; - //ulp_prev_light_data=ulp_light_data;//light_data; - //prev_light_data = (255*prev_light_data)/2504; - //ulp_light_data = (255*val)/2504; - //ESP_LOGI(TAG,"LIGHT_GN = %ld\nLIGHT_GP = %ld",data_get_light_sensor_gn(),data_get_light_sensor_gp()); - ESP_LOGI(TAG,"Updating Prev_light_data"); - prev_light_data3 = light_data3; - light_data3 = test_val; - //ulp_light_data = val; - } - } - return val; -} - -uint32_t adc_if_get_prev_light_mV(void) -{ - return prev_light_data3; -} -#endif +/* + * adc_ifc.c + * + * Created on: Jan 17, 2023 + * Author: Partha + */ +#include +#include +#include +#include +#include "esp_log.h" +//#include "driver/adc.h" +#include "esp_adc/adc_oneshot.h" +#include "esp_adc/adc_cali.h" +#include "esp_adc/adc_cali_scheme.h" +//#include "esp_adc_cal.h" +#include "data_processing.h" +#include "hmi.h" +#include "ulp_main.h" + +static const char* TAG = "ADC_IF"; + +#define LOG_LOCAL_LEVEL ESP_LOG_INFO + +//static esp_adc_cal_characteristics_t adc1_chars; +RTC_DATA_ATTR uint32_t light_data3; +RTC_DATA_ATTR uint32_t prev_light_data3; + +adc_oneshot_unit_handle_t adc1_handle; +adc_cali_handle_t adc1_cali_handle = NULL; +static int adc_raw[2]; +static int voltage[2]; + +static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle) +{ + adc_cali_handle_t handle = NULL; + esp_err_t ret = ESP_FAIL; + bool calibrated = false; + +#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED + if (!calibrated) { + ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting"); + adc_cali_curve_fitting_config_t cali_config = { + .unit_id = unit, + .atten = atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle); + if (ret == ESP_OK) { + calibrated = true; + } + } +#endif + +#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED + if (!calibrated) { + ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting"); + adc_cali_line_fitting_config_t cali_config = { + .unit_id = unit, + .atten = atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle); + if (ret == ESP_OK) { + calibrated = true; + } + } +#endif + + *out_handle = handle; + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Calibration Success"); + } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) { + ESP_LOGW(TAG, "eFuse not burnt, skip software calibration"); + } else { + ESP_LOGE(TAG, "Invalid arg or no memory"); + } + + return calibrated; +} + +void adc_ifx_init(void) +{ + /*esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars); + + //Check type of calibration value used to characterize ADC + if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) + { + printf("ADC: eFuse Vref"); + } + else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) + { + printf("ADC: Two Point"); + } + else + { + printf("ADC: Default"); + } + adc1_ulp_enable(); + ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));*/ + + //-------------ADC1 Init---------------// + adc_oneshot_unit_init_cfg_t init_config1 = { + .unit_id = ADC_UNIT_1, + .ulp_mode = ADC_ULP_MODE_DISABLE + }; + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); + + //-------------ADC1 Config---------------// + adc_oneshot_chan_cfg_t config = { + .bitwidth = ADC_BITWIDTH_13, + .atten = ADC_ATTEN_DB_11, + }; + ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_0, &config)); + //ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_1, &config)); + + //-------------ADC1 Calibration Init---------------// + if(false == adc_calibration_init(ADC_UNIT_1, ADC_ATTEN_DB_11, &adc1_cali_handle)) + { + ESP_LOGI(TAG, "ADC Calibration NOT Supported"); + } +} + +static void adc_cal_deinit(adc_cali_handle_t handle) +{ +#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED + ESP_LOGI(TAG, "deregister %s calibration scheme", "Curve Fitting"); + ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle)); + +#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED + ESP_LOGI(TAG, "deregister %s calibration scheme", "Line Fitting"); + ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle)); +#endif +} + +void adx_ifx_deinit(void) +{ + //adc_cal_deinit(adc1_cali_handle); + adc_oneshot_del_unit(adc1_handle); +} + +uint32_t adc_if_get_batt_mV(void) +{ + //uint32_t val = 4*esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_0), &adc1_chars); + ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, &adc_raw[0])); + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[0], &voltage[0])); + return 4*voltage[0]; +} + +#if 0 +uint32_t adc_if_get_light_mV(void) +{ + uint32_t test_val = 0; + //uint32_t val = esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_1), &adc1_chars); + ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_1, &adc_raw[1])); + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[1], &voltage[1])); + + uint32_t val = voltage[1]; + + ESP_LOGI(TAG, "Light mV: %ld", val); + test_val = (val*255)/2504; + //if(data_get_light_sensor_gp() && data_get_light_sensor_gn()) + { + /*if the new light_sensor value is greater than GB_threshold or lower than GN_threshold*/ + //if((data_get_light_sensor_gn() > test_val) || (data_get_light_sensor_gp() < test_val)) + { + /* set the prev_light_data to the previous reading */ + //ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, ulp_raw_light_data, (int *)&prev_light_data)); + //prev_light_data = ulp_light_data; + //ulp_prev_light_data=ulp_light_data;//light_data; + //prev_light_data = (255*prev_light_data)/2504; + //ulp_light_data = (255*val)/2504; + //ESP_LOGI(TAG,"LIGHT_GN = %ld\nLIGHT_GP = %ld",data_get_light_sensor_gn(),data_get_light_sensor_gp()); + ESP_LOGI(TAG,"Updating Prev_light_data"); + prev_light_data3 = light_data3; + light_data3 = test_val; + //ulp_light_data = val; + } + } + return val; +} + +uint32_t adc_if_get_prev_light_mV(void) +{ + return prev_light_data3; +} +#endif diff --git a/main/adc_ifx.h b/main/adc_ifx.h index 80ff1d1..60ea305 100644 --- a/main/adc_ifx.h +++ b/main/adc_ifx.h @@ -1,18 +1,18 @@ -/* - * adc_ifx.h - * - * Created on: Jan 17, 2023 - * Author: Partha - */ - -#ifndef MAIN_ADC_IFX_H_ -#define MAIN_ADC_IFX_H_ - -void adc_ifx_init(void); -void adx_ifx_deinit(void); -uint32_t adc_if_get_batt_mV(void); -uint32_t adc_if_get_light_mV(void); -uint32_t adc_if_get_prev_light_mV(void); - - -#endif /* MAIN_ADC_IFX_H_ */ +/* + * adc_ifx.h + * + * Created on: Jan 17, 2023 + * Author: Partha + */ + +#ifndef MAIN_ADC_IFX_H_ +#define MAIN_ADC_IFX_H_ + +void adc_ifx_init(void); +void adx_ifx_deinit(void); +uint32_t adc_if_get_batt_mV(void); +uint32_t adc_if_get_light_mV(void); +uint32_t adc_if_get_prev_light_mV(void); + + +#endif /* MAIN_ADC_IFX_H_ */ diff --git a/main/comms.c b/main/comms.c index 578a2c5..0c7e57b 100644 --- a/main/comms.c +++ b/main/comms.c @@ -1,2125 +1,2125 @@ -/* - * comms.c - * - * Created on: Jan 16, 2023 - * Author: Sword - */ - - - -#include "rtc.h" -#include "nvm.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include -#include "esp_timer.h" -#include -#include -#include -#include "modem.h" -#include "wifi_Client.h" -#include "main.h" -#include "comms.h" -#include "port.h" -#include "data_processing.h" -#include "ota.h" -#include "hmi.h" - -#define LOG_LOCAL_LEVEL ESP_LOG_INFO -#include "esp_log.h" - -// Development support: force the operation of the following configuration functions -#ifdef SET_CFG_BITS -// set 1 to force the appropriate functions -#define FORCE_MCU_CONFIG_DOWNLOAD 1 -#define FORCE_MCU_PROG_DOWNLOAD 1 -#define FORCE_MODEM_PROG_DOWNLOAD 1 -#else -#define FORCE_MCU_CONFIG_DOWNLOAD 0 -#define FORCE_MCU_PROG_DOWNLOAD 0 -#define FORCE_MODEM_PROG_DOWNLOAD 0 -#endif - -/* Set 1 to use "unwired/[IMEI]", e.g. "unwired/862061049756488" -* Set 0 to use "unwiredct" -*/ -#define COMMS_PUBLISH_WITH_IMEI 0 -#define JWT_LEN 1024 - - - -//#define MCU_SP4_URL "https://parthasarathimishra.com/hae/tempstick/%s/mcu_config_download/" - - -/* Name of file to create in modem file system for the downloaded image. -* This is arbitrary, but we name the upper and lower version differently -* to avoid possible mixing up at the firmware level (the server can -* still mix them up if a lower app was put at the /higher URL) -*/ -#if ST_OTA_HIGHER_APPLICATION -/* A running "higher" app must download and install a "lower" app and vice versa. */ -#define MCU_FW_UPDATE_FILE "lrsm0005_fw_ota_image_lower.bin" -#else -#define MCU_FW_UPDATE_FILE "lrsm0005_fw_ota_image_higher.bin" -#endif - -//#define MCU_FW_BIN_FILE_URL1_HIGHER "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/lrsm0005_fw_ota_image_higher.bin" -//#define MCU_FW_BIN_FILE_URL1_LOWER "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/lrsm0005_fw_ota_image_lower.bin" -#define MCU_PROG_VER_URL SERVER_URL_BASE "mcu_pgm_download/version" -//#define MODEM_FW_BIN_FILE_URL1 SERVER_URL_BASE "modem_pgm_download" -#define MODEM_PROG_VER_URL SERVER_URL_BASE "modem_pgm_download/version" -#define WHITELIST_URL SERVER_URL_BASE "whitelist" -//#define MCU_FW_BIN_FILE_URL1 "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/" MCU_FW_UPDATE_FILE -//#define MCU_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/mcu_pgm_download/OTA.bin" - - -//#define MODEM_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/modem_pgm_download/MOTA.bin"/*upgrade*/ -//#define MODEM_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/modem_pgm_download/Update_BG77LAR02A04_01.009.01.009-R02A04_01.006.01.006.bin"/*downgrade*/ - - - -#define MQTT_PUB_TOPIC_LEN 48 - -#define MCU_CONFIG_FLAG_WHITELIST_UPDATE 0x1 -#define MCU_CONFIG_FLAG_MCU_UPDATE 0x2 -#define MCU_CONFIG_FLAG_MODEM_UPDATE 0x4 - -#define HTTP_RETRY_COUNT_MAX 5 -#define HTTP_POST_RETRY_MAX 2 -#define HTTP_RETRY_WAIT 20000 - -static const char *TAG = "COMMS"; - -extern uint32_t g_ConfigUpdate; -extern uint32_t g_McuUpdate; -extern uint32_t g_ModemUpdate; -extern uint32_t g_version; - -typedef enum -{ - COMMS_EVENT_START, - COMMS_EVENT_TIMER, - COMMS_EVENT_STOP, - COMMS_EVENT_CONNECT, -} comms_event_t; - -/* State of the comms process */ -typedef enum -{ - COMMS_STATE_INIT, - COMMS_STATE_WAIT_MODEM, - COMMS_STATE_WAIT_NET_CONNECT, - COMMS_STATE_WIFI_CONNECT, - COMMS_STATE_WIFI_POST_REQ, - COMMS_STATE_WIFI_GET_REQ, - COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS, - COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS, - COMMS_STATE_WAIT_HTTP_POST_REQ, - COMMS_STATE_WAIT_HTTP_POST_RES, - COMMS_STATE_WAIT_HTTP_SEND_SP5, - COMMS_STATE_WAIT_HTTP_GET_SP5, - COMMS_STATE_WAIT_HTTP_SEND_SP6, - COMMS_STATE_WAIT_HTTP_GET_SP6, - COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE, /* Get modem update version */ - COMMS_STATE_WAIT_MODEM_UPDATE, /* Wait for modem to do its thing */ - COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE, /* Get version */ - COMMS_STATE_WAIT_HTTP_GET_MCU_FILE, /* Download file */ - COMMS_STATE_WAIT_MCU_UPDATE, /* Install update */ - COMMS_STATE_GOING_IDLE, - COMMS_STATE_IDLE, - COMMS_STATE_WAIT, - COMMS_STATE_WAIT_MODEM_OFF, - -} comms_state_t; - - -typedef int (*comms_switch_cb)(comms_state_t init_state, const char* url,const char* msg, comms_state_t success_state); - -typedef struct -{ - comms_state_t state; - - /* Timer */ - bool poll_timer; - - /* User start callback */ - comms_op_cb_t start_cb; - bool is_starting; - - /* User connect callback */ - comms_op_cb_t connect_cb; - - char mqtt_pub_topic[MQTT_PUB_TOPIC_LEN]; - /* Printing an SP2 message: - * Header: 3 + 1 + [IMEI-15] +1 + 10 + 1+ 10 + 1 = 42 - * [32],[4],[4],[3] = 46 * 20 = 920 - * Footer: 3 - * 42 + 920 + 3 = 965 - * Add buffer overflow protection in writing routines. - */ - char mqtt_buf[1024]; /* Also general buffer */ - //char jwt[JWT_LEN]; - uint8_t overflow_check; - int mqtt_pub_counter; - - /* flagged actions to take */ - bool get_whitelist; - bool get_mcu_update; - bool get_modem_update; - - /* Status of the last communication cycle - * OK or ERROR - */ - int last_cycle_status; - - /* Status of last pending operation */ - bool last_op_success; - bool wf1_msg; - - int httpRetryCnt; - comms_state_t http_init_state; -} comms_t; - -/* Unique timer ID for this process for use with timer module */ -//#define COMMS_TIMER_ID 1 -esp_timer_handle_t comms_timer; -/* Local process state */ - -static comms_t comms; - - -//nvs_handle_t my_handle; -extern uint8_t onBoarded; -extern uint8_t comms_mode; -comms_medium_t comms_medium; - -static bool comms_do_wifi_backup; -static bool comms_do_cell_backup; -static bool comms_posting_failed; - -uint8_t checkin_cycle_counter; -uint8_t number_of_check_in_to_do; - -char jsonMessage[2560]; -char http_post_header[250]; - -#if (FAKE_NETWORK == 1) -char server_resp[] = "{\"request\":\"settings\",\"id\":10608508,\"minTemp\":-1.11,\"maxTemp\":26.67,\"minHum\":10,\"maxHum\":80,\"voltageQuit\":2.3,\"alertInterval\":900,\"sendInterval\":60,\"sendDetails\":1,\"postURLNumber\":2,\"postURLMax\":3,\"tmpThA_GP\":71.11,\"tmpThA_GN\":70,\"tmpThB_GP\":71.11,\"tmpThB_GN\":70,\"tmpThC_GP\":71.11,\"tmpThC_GN\":70,\"tmpThD_GP\":-44.44,\"tmpThD_GN\":-45.56,\"tmpThE_GP\":-44.44,\"tmpThE_GN\":-45.56,\"tmpThF_GP\":-44.44,\"tmpThF_GN\":-45.56,\"T_TKN\":5,\"humThA_GP\":103,\"humThA_GN\":101,\"humThB_GP\":103,\"humThB_GN\":101,\"humThC_GP\":103,\"humThC_GN\":101,\"humThD_GP\":-1,\"humThD_GN\":-3,\"humThE_GP\":-1,\"humThE_GN\":-3,\"humThF_GP\":-1,\"humThF_GN\":-3,\"H_TKN\":5,\"TC_M\":1,\"TC_TYPE\":\"K\",\"tcThA_GP\":71.11,\"tcThA_GN\":70,\"tcThB_GP\":71.11,\"tcThB_GN\":70,\"tcThC_GP\":71.11,\"tcThC_GN\":70,\"tcThD_GP\":-168.33,\"tcThD_GN\":-169.44,\"tcThE_GP\":-168.33,\"tcThE_GN\":-169.44,\"tcThF_GP\":-168.33,\"tcThF_GN\":-169.44,\"TC_TKN\":5,\"LT_M\":3,\"LT_LVLGP\":200,\"LT_LVLGN\":50,\"LT_LOCK\":900,\"LT_TKN\":5,\"AC_M\":1,\"AC_LVL\":15000,\"AC_INT\":60,\"AC_LOCK\":60,\"AC_TKN\":5,\"PWR_M\":3,\"PWR_DBNC\":60,\"PWR_TKN\":5,\"PUSH_TKN\":5,\"TKN_RLD\":300}"; -#endif -/* ------------------------------------------------------------------------- */ - -static const char* state_str(comms_state_t s) -{ - switch (s) { - case COMMS_STATE_INIT:return "INIT"; - case COMMS_STATE_WAIT_MODEM:return "WAIT_MODEM"; - case COMMS_STATE_WAIT_NET_CONNECT:return "WAIT_NET_CONNECT"; - case COMMS_STATE_WIFI_CONNECT:return "WIFI_CONNECT"; - case COMMS_STATE_WIFI_POST_REQ:return "WIFI_POST_REQ"; - case COMMS_STATE_WIFI_GET_REQ:return "WIFI_GET_REQ"; - case COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS:return "WAIT_HTTP_SEND_CONFIG_FLAGS"; - case COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS:return "WAIT_HTTP_GET_CONFIG_FLAGS"; - case COMMS_STATE_WAIT_HTTP_POST_REQ:return "WAIT_HTTP_POST_REQ"; - case COMMS_STATE_WAIT_HTTP_POST_RES:return "WAIT_HTTP_POST_RES"; - case COMMS_STATE_WAIT_HTTP_SEND_SP5:return "WAIT_HTTP_SEND_SP5"; - case COMMS_STATE_WAIT_HTTP_GET_SP5:return "HTTP_GET_SP5"; - case COMMS_STATE_WAIT_HTTP_SEND_SP6:return "HTTP_SEND_SP6"; - case COMMS_STATE_WAIT_HTTP_GET_SP6:return "HTTP_GET_SP6"; - case COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE:return "WAIT_HTTP_GET_MODEM_UPDATE"; - case COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE:return "WAIT_HTTP_GET_MCU_UPDATE"; - case COMMS_STATE_WAIT_HTTP_GET_MCU_FILE:return "WAIT_HTTP_GET_MCU_FILE"; - case COMMS_STATE_WAIT_MODEM_UPDATE:return "WAIT_MODEM_UPDATE"; - case COMMS_STATE_WAIT_MCU_UPDATE:return "WAIT_MCU_UPDATE"; - case COMMS_STATE_GOING_IDLE: return "COMMS_STATE_GOING_IDLE"; - case COMMS_STATE_IDLE:return "IDLE"; - case COMMS_STATE_WAIT:return "STATE_WAIT"; - case COMMS_STATE_WAIT_MODEM_OFF:return "WAIT_MODEM_OFF"; - default: - return ""; - } -} - -static esp_err_t build_http_headerBodyMsg(uint32_t len) -{ - /* jsonMessage address is the same address as msg*/ - uint32_t header_len = 0; - int index = 0; - - /* Setup the HTTP header*/ - sprintf(http_post_header, HTTP_POST_HEADER,(unsigned int)len); - - /* Calculate http-header length*/ - header_len = strlen(http_post_header); - - /* Shift jsonMessage right by length of http-header*/ - if( (len+header_len)>= 2560) - { - ESP_LOGI(TAG,"Shifting exceeded the maximum size of jsonMessage buffer"); - return ESP_FAIL; - } - - /* Shift the message in jsonMessage buffer to right by length of http-header*/ - for(index = len-1; index >= 0; index--) - { - jsonMessage[index+header_len] = jsonMessage[index]; - - /* Copy http-header at the beginning of jsonMessage*/ - if(index < header_len) - jsonMessage[index] = http_post_header[index]; - } - return ESP_OK; -} - -static void transition(comms_state_t state_to) -{ - ESP_LOGD(TAG,"%s->%s\n", state_str(comms.state), state_str(state_to)); - comms.state = state_to; -} - - -/* These handlers handle completion events for commands issued by the BG96 modem driver. -* If success, the comms process continues by way of a "timer" event. -* If fail, the comms process stops what it was doing and goes back to "idle" state. -* The comms process is started once at startup and does not stop thereafter. -*/ -static void modem_start_cb(int status) -{ - comms.poll_timer = true; - if (MODEM_STATUS_OK == status) - { - /* started */ - transition(COMMS_STATE_WAIT_MODEM); - } - else - { - /* Nope - back to init */ - ESP_LOGW(TAG,"BG96 startup failed.\r\n"); - - if(comms_mode == COMMS_OVER_CELL) - { - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - if(!onBoarded) //Unable to connect to LTE network - { - hmi_set_leds_state(RED_LED_FLASHING); - } //Unable to connect to LTE network - } - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - transition(COMMS_STATE_GOING_IDLE); - } -} -//bool net_connected = false; -static void net_connect_cb(int status) -{ - //net_connected = true; - comms.poll_timer = true; - if (MODEM_STATUS_OK == status) - { - /* connected */ - ESP_LOGI(TAG,"Network connection Successful.\r\n"); - } - else - { - /* Nope - back to init */ - ESP_LOGW(TAG,"Network connection failed.\r\n"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - if(comms_mode == COMMS_OVER_CELL) - { - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - if(!onBoarded) //Unable to connect to LTE network - { - hmi_set_leds_state(RED_LED_FLASHING); - } //Unable to connect to LTE network - } - transition(COMMS_STATE_GOING_IDLE); - } -} - -static void http_op_cb(int status) -{ - if (MODEM_STATUS_OK == status) - { - /*Connected. Set the poll_timer to be true*/ - comms.poll_timer = true; - } - else - { - /*If not connected then check the number of http retries if it's greater than zero*/ - if(comms.httpRetryCnt) - { - /*decrement the number of retries by 1*/ - comms.httpRetryCnt--; - - /*start a timer for 20sec*/ - esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); - - /*Logging waiting message*/ - ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); - - /*transition to COMMS_STATE_WAIT state*/ - transition(COMMS_STATE_WAIT); - } - else - { - /*Reinitialize the counter of http retries with 3*/ - comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /* Nope - back to idle */ - ESP_LOGW(TAG,"HTTP operation failed.\r\n"); - - //SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message - //int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */ - int retval = MODEM_STATUS_ERROR; - if(MODEM_STATUS_OK==retval) - { - ESP_LOGI(TAG,"MQTT Publish SP1 message success"); - } - else - { - ESP_LOGI(TAG,"MQTT Publish SP1 message failed"); - } - - /*transition to COMMS_STATE_GOING_IDLE state*/ - transition(COMMS_STATE_GOING_IDLE); - } - } -} - - - -static void http_post_op_cb(int status) -{ - if (MODEM_STATUS_OK == status) - { - comms.poll_timer = true; - - /* Update the number of already done check-ins */ - checkin_cycle_counter++; - - /* Clear history array (So that its current readings don't affect the readings of the next sector) - * Just clear the array (don't clear anything from NVS) */ - data_clear_history(); - - /* Check if this was the last check-in to do (in other words, check if there are no more previous readings to send to server) */ - if(checkin_cycle_counter == number_of_check_in_to_do) - { - /* Reset the last post sector in the NVS partition to 0*/ - nvm_set_last_posted_history_sector(0); - - /* successfully posted. */ - ESP_LOGI(TAG,"HTTP post message SUCCESS.\r\n"); - - /* Clear History sectors - * Clear from NVS Partition */ - nvm_clear_history_sector(NVM_HISTORY_ALL_SECTORS); - - /* Reset the posting_failed to be false */ - comms_posting_failed = false; - comms_do_wifi_backup = false; - - /*Set the last operation to be completed successfully*/ - comms.last_op_success = true; - - comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; - } - else - { - /* Coming here means that there were some previous readings that are stored in NVS and need to posted in multiple check-in cycles - * and we already posted the readings in history_sector x ----> so we need to update the last_posted_sector flag */ - - /* Update the last post sector in the NVS partition */ - uint8_t x = nvm_get_last_posted_history_sector()+1; - nvm_set_last_posted_history_sector(x); - - /* Wait some time before doing the next check-in of the remaining previous readings */ - vTaskDelay(2000/portTICK_PERIOD_MS); - - /* Do a transition to "COMMS_STATE_WAIT_HTTP_POST_REQ" state */ - transition(COMMS_STATE_WAIT_HTTP_POST_REQ); - } - } - else - { - if(comms.httpRetryCnt) - { - /*decrement the number of retries by 1*/ - comms.httpRetryCnt--; - - /*start a timer for 20sec*/ - esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); - - /*Logging waiting message*/ - ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /*transition to COMMS_STATE_WAIT state*/ - transition(COMMS_STATE_WAIT); - } - else - { - /*Reinitialize the counter of http_post retries with 3*/ - comms.httpRetryCnt = HTTP_POST_RETRY_MAX; - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /* Nope - back to idle */ - /* failed. */ - ESP_LOGW(TAG,"HTTP post message FAILED.\r\n"); - comms.last_op_success = false; - - /* Give Red-led indication*/ - if(comms_mode == COMMS_OVER_CELL) - { - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - if(!onBoarded) //Unable to connect to LTE network - { - hmi_set_leds_state(RED_LED_FLASHING); - } //Unable to connect to LTE network - } - - /* alternating between three servers - * - * transition to COMMS_STATE_GOING_IDLE state if the connection to the servers failed*/ - - switch(data_get_postToServer()){ - - case TEMPSTICK_SERVER1: - if( 1 == data_get_postUrlMax()) - { - ESP_LOGI(TAG,"Just one server available"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do wifi backup for the check-in process */ - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - transition(COMMS_STATE_GOING_IDLE); - } - else - { - data_set_postToServer(TEMPSTICK_SERVER2); - ESP_LOGI(TAG,"Transition to the next server --> %d",TEMPSTICK_SERVER2); - transition(COMMS_STATE_WAIT_HTTP_POST_REQ); - } - break; - case TEMPSTICK_SERVER2: - if( 2 == data_get_postUrlMax()) - { - ESP_LOGI(TAG,"Just two servers available"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do wifi backup for the check-in process */ - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - transition(COMMS_STATE_GOING_IDLE); - } - else - { - data_set_postToServer(TEMPSTICK_SERVER3); - ESP_LOGI(TAG,"Transition to the next server --> %d",TEMPSTICK_SERVER3); - transition(COMMS_STATE_WAIT_HTTP_POST_REQ); - } - break; - case TEMPSTICK_SERVER3: - data_set_postToServer(TEMPSTICK_SERVER1); - ESP_LOGI(TAG,"Transition to default server --> %d then going to IDLE",TEMPSTICK_SERVER1); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do wifi backup for the check-in process */ - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - transition(COMMS_STATE_GOING_IDLE); - break; - default: - - data_set_postToServer(TEMPSTICK_SERVER1); - ESP_LOGI(TAG,"connection to servers Failed"); - ESP_LOGI(TAG,"Transition to default server --> %d then going to IDLE",TEMPSTICK_SERVER1); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do wifi backup for the check-in process */ - if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) - { - comms_do_wifi_backup = true; - } - - transition(COMMS_STATE_GOING_IDLE); - break; - - - - } - } - } -} - -static void fotadl_op_cb(int status) -{ - comms.poll_timer = true; - if (MODEM_STATUS_OK == status) - { - /* completed. */ - ESP_LOGI(TAG,"Modem upgrade SUCCESS.\r\n"); - } - else - { - if(comms.httpRetryCnt) - { - /*decrement the number of retries by 1*/ - comms.httpRetryCnt--; - - /*start a timer for 20sec*/ - esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); - - /*Logging waiting message*/ - ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /*transition to COMMS_STATE_WAIT state*/ - transition(COMMS_STATE_WAIT); - } - else - { - /*Reinitialize the counter of http retries with 3*/ - comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /* Nope - back to idle */ - /* failed. */ - /* failed. */ - /* failed. */ - ESP_LOGW(TAG,"Modem upgrade FAILED.\r\n"); - /* Give Red-led indication*/ - if(comms_mode == COMMS_OVER_CELL) - { - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - if(!onBoarded) //Unable to connect to LTE network - { - hmi_set_leds_state(RED_LED_FLASHING); - } //Unable to connect to LTE network - } - transition(COMMS_STATE_GOING_IDLE); - } - /* Let state handle it */ -} -} - - -static int start_http_get_request(comms_state_t init_state,const char* url, const char* log_msg, comms_state_t success_state) -{ - /* Reset the operation status flag */ - comms.last_op_success = false; - /* Initialize the comms.http_init_state to init_state */ - comms.http_init_state = init_state; - /* Now make the GET request. */ - /* Setup URL */ - memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), url, modem_get_imei()); - - /* Download the GET data to modem */ - int retval = modem_http_get_to_buf(http_op_cb, comms.mqtt_buf); - - if (retval == MODEM_STATUS_OK) - { - ESP_LOGI(TAG,"GET %s\r\n", log_msg); - transition(success_state); - } - else - { - ESP_LOGE(TAG,"GET %s failed.\r\n", log_msg); - comms.poll_timer = true; - - /* Give Red-led indication*/ - if(comms_mode == COMMS_OVER_CELL) - { - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - if(!onBoarded) //Unable to connect to LTE network - { - hmi_set_leds_state(RED_LED_FLASHING); - } //Unable to connect to LTE network - } - - transition(COMMS_STATE_GOING_IDLE); - } - return retval; -} - - -static int start_http_post_request(comms_state_t init_state,const char* url, const char* message, comms_state_t success_state) -{ - esp_err_t ret; - - /* Reset the operation status flag */ - comms.last_op_success = false; - /* Initialize the comms.http_init_state to init_state */ - comms.http_init_state = init_state; - - - /* Setup URL */ - memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), url, modem_get_imei()); - - //sprintf(http_post_header,HTTP_POST_HEADER,(uint32_t)strlen(message)); - /*concatenate http-header with http-body*/ - //strcat(http_post_header,message); - - /* Build the headerBody of the http-post message*/ - ret = build_http_headerBodyMsg((uint32_t)strlen(jsonMessage)); - //ret = ESP_OK; - - if(ESP_OK == ret) - { - /* Send HTTP POST data to modem to upload it to server*/ - int retval = modem_http_post_message(http_post_op_cb, comms.mqtt_buf, message); - - if (retval == MODEM_STATUS_OK) - { - ESP_LOGI(TAG,"HTTP-POST Started\r\n"); - transition(success_state); - } - else - { - ESP_LOGE(TAG,"HTTP-POST failed to proceed\r\n"); - } - return retval; - } - else - { - ESP_LOGI(TAG,"Failed to build header-body of http-post message"); - return MODEM_STATUS_ERROR; - } -} - - -static void fwdl_op_cb(int status) -{ - if (MODEM_STATUS_OK == status) - { - /* Firmware file was downloaded to the modem. */ - ESP_LOGI(TAG,"MCU FW download SUCCESS.\r\n"); - - comms.last_op_success = true; - /* Continue in the current state */ - comms.poll_timer = true; - } - else - { - if(comms.httpRetryCnt) - { - /*decrement the number of retries by 1*/ - comms.httpRetryCnt--; - - /*start a timer for 20sec*/ - esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); - - /*Logging waiting message*/ - ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); - - /*transition to COMMS_STATE_WAIT state*/ - transition(COMMS_STATE_WAIT); - } - else - { - /*Reinitialize the counter of http retries with 3*/ - comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; - - /*Set the poll_timer to be true*/ - comms.poll_timer = true; - - /* Nope - back to idle */ - /* Firmware file not downloaded. */ - ESP_LOGW(TAG,"MCU FW download operation failed.\r\n"); - //SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message - // int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */ - int retval = MODEM_STATUS_ERROR; - if(MODEM_STATUS_OK==retval) - { - ESP_LOGI(TAG,"MQTT Publish SP1 message success"); - } - else - { - ESP_LOGI(TAG,"MQTT Publish SP1 message failed"); - } - - comms.last_op_success = false; - - /*transition to COMMS_STATE_GOING_IDLE state*/ - transition(COMMS_STATE_GOING_IDLE); - } - } -} - -static void fwupd_op_cb(int status) -{ - comms.poll_timer = true; - if (MODEM_STATUS_OK == status) - { - /* Firmware file was installed into device. */ - ESP_LOGI(TAG,"MCU FW update SUCCESS.\r\n"); - - comms.last_op_success = true; - } - else - { - /* Firmware file not installed. */ - ESP_LOGW(TAG,"MCU FW installation failed.\r\n"); - transition(COMMS_STATE_GOING_IDLE); - comms.poll_timer = true; - comms.last_op_success = false; - } -} - -/* ------------------------------------------------------------------------- */ -/* OTA firmware update. - * These callbacks handle the file transfer from the modem and interface with - * the OTA_btl firmware update system. - * - * The main interface is the OTA_Offline_Init and OTA_Offline_Data functions. - * These are added to interface with the stock OTA_btl update engine. - * - * To initialize, we use OTA_Offline_Init(file_size) API. - * This will either accept or reject the firmware image based on - * available space. - * - * To feed update data, call OTA_Offline_Data with a chunk of data. - * - * Be mindful of the return values and feed them back to the updater engine. - * - */ - -static int ota_file_open_cb(uint32_t fileSize) -{ - int retval = MODEM_STATUS_OK; - - esp_err_t res = ota_init(fileSize); - if (ESP_OK == res) { - ESP_LOGI(TAG,"OTA file opened\r\n"); - } - else { - ESP_LOGI(TAG,"OTA file open error: %d\r\n", res); - /* This will abort the entire update process. */ - retval = MODEM_STATUS_ERROR; - } - - return retval; -} - -static int ota_file_data_cb(const char* buf, int buf_len) -{ - int retval = MODEM_STATUS_OK; - - /* Data callback: we can receive a buffer up to MODEM_FREAD_SIZE bytes */ - esp_err_t res = ota_get_data_to_buffer(buf, buf_len); - - if (ESP_OK == res) { - ESP_LOGI(TAG,"%d bytes OTA data processed\r\n", buf_len); - } - else { - ESP_LOGI(TAG,"%d bytes OTA data error: %d\r\n", buf_len, res); - /* This will abort the entire update process. */ - retval = MODEM_STATUS_ERROR; - } - - return retval; -} - -static int sum_digits(int digit) -{ - int sum = 0; - while (digit > 0) - { - sum = sum + digit % 10; - digit = digit / 10; - } - return sum; -} -/** -This function is used to check if IMEI has correct length (15) -to check if IMEI has numerical values (0-9) -to check if the parsed IMEI is same as hardware IMEI -to check if IMEI is valid by help of luhn algorithm -https://www.geeksforgeeks.org/luhn-algorithm/ -*/ -static bool imei_check_valid(char *message_imei) -{ - //find the length of message imei - int len = strlen(message_imei); - int sum = 0; - ESP_LOGI(TAG,"IMEI : %s",message_imei); - - //check length of imei field - if (len != 15){ - //invalid IMEI - ESP_LOGW(TAG,"Invalid IMEI length"); - return false; - } - if(!strcmp(message_imei,modem_get_imei())){ - - for(int i = len-1 ; i >= 0; i--) - { - //check if message imei fields contain numbers (0-9) - if((message_imei[i] > 47) && (message_imei[i] < 58)){ - int digit = (message_imei[i] - 48); - // Doubling every alternate beginning at [13] digit - //ignore last number [14] and first number [0] as well - if (i % 2 != 0) - digit = 2 * digit; - // Finding sum of the digits - // if digit*2 is a two digit number add the two digits - sum += sum_digits(digit); - - } - else{ - ESP_LOGW(TAG,"Invalid IMEI (not numerical values)"); - return false; - } - } - } - else{ - ESP_LOGI(TAG,"Message IMEI doesn't match board IMEI"); - return false; - } - - return (sum % 10 == 0); -} - -void check_for_update(){ - - if(g_ConfigUpdate==true){ - - // get the data from server - //transition(); - comms.poll_timer=true; /* just for a test*/ - transition(COMMS_STATE_GOING_IDLE); /* just for a test*/ - } - else if(g_McuUpdate==true){ - - // that mean we should check for program update - //transition(); - comms.poll_timer=true; /* just for a test*/ - transition(COMMS_STATE_WAIT_HTTP_SEND_SP5); /* just for a test*/ - } - else if(g_ModemUpdate==true){ - // that mean we need to update the modem software. - comms.poll_timer=true; - transition(COMMS_STATE_WAIT_HTTP_SEND_SP6); - } - else - { - comms.poll_timer=true; - transition(COMMS_STATE_GOING_IDLE); - - } -} - -/* function for parsing SP5 message */ -// format example -/*SP5 IMEI epoch T FW_V EP */ -/* | | | | | */ -/* | | | | | */ -/*SP5 866349048889004 1676395843 FW_2002 EP */ -static void Comms_Parse_SP5(char *buf, int len) -{ - char messageheader[4] = {0}; /*ex: SPx*/ - char messageIMEI[15] = {0}; - // char messageIMEI[] = "866349048890473";/*//hard coded IMEI*/ - char epochTime[30] = {0}; - char firmware_version[10] = {0}; - char *strret = NULL; - uint32_t new_fw_version = 0; - char epcheck[2] = {0}; - int ret_sp5 = COMMS_STATUS_ERROR; - - /**********************************************************************************************************/ - /*SP5*/ - strret = strtok(buf, " "); - strcpy(messageheader, strret); - ESP_LOGI(TAG,"%s message is received",messageheader); - - /**********************************************************************************************************/ - /*IMEI*/ - strret = strtok (NULL," "); - strcpy(messageIMEI, strret); - ret_sp5 = imei_check_valid(messageIMEI); - if(ret_sp5 != false){ - //ok IMEI - ESP_LOGI(TAG,"Fetched IMEI matches board"); - } - else{ - ESP_LOGW(TAG,"INVALID IMEI"); - comms.poll_timer = true; - transition(COMMS_STATE_GOING_IDLE); - return; - //return ret_sp5; - } - - /**********************************************************************************************************/ - /*epoch time*/ - strret = strtok (NULL," "); - strcpy(epochTime, strret); - ESP_LOGI(TAG,"epoch Time : %s",epochTime); - - /**********************************************************************************************************/ - /*new FW version*/ - strret = strtok(NULL, "FW_"); - strcpy(firmware_version,strret); - new_fw_version = (uint32_t)atoi(firmware_version); - ESP_LOGI(TAG,"Firmware version from SP5: %ld",new_fw_version); //logging/printing FR_version message for tracing - ESP_LOGI(TAG,"Board Firmware version: %ld",g_version); - - /**********************************************************************************************************/ - /*EP*/ - /* strret = strtok (NULL," "); - strcpy(epcheck, strret); - if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){ - ESP_LOGI(TAG,"(%s) %s message is terminated", epcheck,messageheader); - } - else{ - ESP_LOGI(TAG,"(%s) %s message is not terminated!!", epcheck,messageheader); - }*/ - - /**********************************************************************************************************/ - /*check if the new version is greater than current version*/ - if(!(new_fw_version > g_version)) - { - ESP_LOGI(TAG,"MCU F/W UP TO DATE"); - /*if its not check if modem update needed*/ - /*read ModemFlag*/ - if(g_ModemUpdate == true) - { - ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP6"); - comms.poll_timer = true; - transition(COMMS_STATE_WAIT_HTTP_SEND_SP6); - } - else { - /* */ - comms.poll_timer = true; - transition(COMMS_STATE_GOING_IDLE); - } - } - else - { - /*Logging/printing this message*/ - ESP_LOGI(TAG,"F/W Update NEEDED"); - ESP_LOGI(TAG,"GET MCU UPDATE"); - comms.poll_timer = true; - transition(COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE); - /*reading OTA files*/ - } -} - - - -/* function for parsing SP6 message */ -// format example -/*SP6 IMEI epoch T FW_V EP */ -/* | | | | | */ -/* | | | | | */ -/*SP6 866349048889004 1676395909 BG77LAR02A04_01.009.01.009 EP */ -static void Comms_Parse_SP6(char *buf, int len) -{ - char messageheader[4] = {'0'}; /*ex: SPx*/ - char messageIMEI[15] = {'0'}; -// char messageIMEI[] = "866349048890473";/*//hard coded IMEI*/ - char epochTime[30] = {'0'}; - char modem_sp6_fwv[50] = {'0'}; - int ret_sp6 = COMMS_STATUS_ERROR; - char* strret = NULL; - char epcheck[2] = {0}; - - /**********************************************************************************************************/ - /*SP6*/ - strret = strtok(buf, " "); - strcpy(messageheader, strret); - ESP_LOGI(TAG,"%s message is received",messageheader); - - /**********************************************************************************************************/ - /*IMEI*/ - strret = strtok (NULL," "); - strcpy(messageIMEI, strret); - ret_sp6 = imei_check_valid(messageIMEI); - if(ret_sp6 != false){ - //ok IMEI - ESP_LOGI(TAG,"Fetched IMEI matches board"); - } - else{ - ESP_LOGW(TAG,"INVALID IMEI!!"); - comms.poll_timer = true; - transition(COMMS_STATE_GOING_IDLE); - return; - } - - /**********************************************************************************************************/ - /*epoch Time*/ - strret = strtok (NULL," "); - strcpy(epochTime, strret); - ESP_LOGI(TAG,"epoch Time : %s",epochTime); - - /**********************************************************************************************************/ - /*modem version from SP6 */ - strret = strtok (NULL," "); - strcpy(modem_sp6_fwv, strret); - ESP_LOGI(TAG,"Board modem firmware version: %s",modem_get_fw_ver()); - ESP_LOGI(TAG,"Modem firmware version from SP6: %s",modem_sp6_fwv); - - /**********************************************************************************************************/ - /*EP*/ - strret = strtok (NULL," "); - strcpy(epcheck, strret); - if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){ - ESP_LOGI(TAG,"(%s) %s message is terminated",epcheck,messageheader); - } - else{ - ESP_LOGI(TAG,"(%s) %s message is not terminated!!",epcheck,messageheader); - - } - - /**********************************************************************************************************/ - /*Case: - - str1 SP6 fw: BG77LAR02A04_01.009.01.009 - str2 fw: BG77LAR02A04_01.008.01.008 - - 9 is the first non-matching character in str1 greater - than that of str2. return > 0(update needed) - - - str1 SP6 fw: BG77LAR02A04_01.008.01.008 - str2 fw: BG77LAR02A04_01.009.01.009 - - '9' is the first non-matching character in str1 lower - than that of str2. return < 0 - - */ - if(strcmp(modem_sp6_fwv,modem_get_fw_ver()) <= 0) - { - - /*If the existing version is the same go to idle*/ - comms.poll_timer = true; - ESP_LOGI(TAG,"No update need GOING TO IDLE FROM SP6"); - transition(COMMS_STATE_GOING_IDLE); - - } - else - { - /*Logging/printing this message*/ - ESP_LOGI(TAG,"F/W Modem Update NEEDED"); - ESP_LOGI(TAG,"GET MODEM UPDATE"); - comms.poll_timer = true; - transition(COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE); - } -} - - -esp_err_t comms_http_request(comms_switch_cb cb,comms_state_t init_state, const char* msg, comms_state_t success_state,const char* url1,const char* url2,const char* url3){ - esp_err_t retval = ESP_FAIL; - int32_t val=data_get_postToServer(); - switch(val){ - - case TEMPSTICK_SERVER1: - - /* make the get/post request to server 1. */ - //ESP_LOGI(TAG,"get/post request to server 1........... "); - retval = cb(init_state, url1,msg, success_state); - - break; - case TEMPSTICK_SERVER2: - - /* make the get/post request to server 2. */ - //ESP_LOGI(TAG,"get/post request to server 2........... "); - retval = cb(init_state, url2, msg, success_state); - break; - - case TEMPSTICK_SERVER3: - - /* make the get/post request to server 3. */ - //ESP_LOGI(TAG,"get/post request to server 3........... "); - retval = cb(init_state, url3,msg, success_state); - break; - - default: - data_set_postToServer(TEMPSTICK_SERVER1); - ESP_LOGI(TAG,"connection to server %ld failed ",data_get_postToServer()); - ESP_LOGI(TAG,"connect to the default server "); - comms.poll_timer=true; - transition(init_state); - break; -} - - return retval; -} - -/* ------------------------------------------------------------------------- */ - -/*Handler for COMMS timer*/ -static void timer_handler(void* context) -{ - comms.poll_timer = true; -} - -static int state_machine(comms_event_t evt) -{ - int retval = COMMS_STATUS_OK; - switch (comms.state) - { - case COMMS_STATE_INIT: - if (evt == COMMS_EVENT_START) - { - /* Set the number of check-in cycles to do and reset the checkin_cycle_counter */ - number_of_check_in_to_do = nvm_get_last_written_history_sector() - nvm_get_last_posted_history_sector(); - checkin_cycle_counter = 0; - - ESP_LOGI(TAG,"---------> Number of check-in cycles to do is %d",number_of_check_in_to_do); - - /* Reset the backup flag */ - comms_do_wifi_backup = false; - comms_do_cell_backup = false; - - /* Status is ERROR until cleared by successful completion. */ - comms.last_cycle_status = COMMS_STATUS_ERROR; - - /*This must be changed to true inside modem_start_cb to transfer to the next state*/ - comms.poll_timer = false; - - if (modem_is_started()) - { - modem_start_cb(MODEM_STATUS_OK); - } - else - { - /* start the bg96 process */ - retval = modem_start(modem_start_cb); - if (retval == MODEM_STATUS_OK) - { - comms.is_starting = true; - ESP_LOGI(TAG,"Process starting.\n"); - transition(COMMS_STATE_WAIT_MODEM); - } - } - } - break; - case COMMS_STATE_WAIT_MODEM: - - /* Wait for BG96 startup event */ - if (evt == COMMS_EVENT_TIMER) - { -#if (FAKE_NETWORK == 1) - data_parse_http_response(server_resp); - comms.poll_timer = true; - comms.last_cycle_status = COMMS_STATUS_OK; - transition(COMMS_STATE_GOING_IDLE); -#else - - /* Start the LED-event of connecting to network */ - if(!comms_do_cell_backup) - { - hmi_set_leds_state(BLUE_LED_FLASHING); //connecting to LTE network - } - - /* Check if need to do check-in over WIFI */ - if((COMMS_OVER_CELL != comms_mode) && (COMMS_OVER_CELL_WIFI_BACKUP != comms_mode) && (!comms_do_cell_backup)) - { - comms.poll_timer = true; - - transition(COMMS_STATE_WIFI_CONNECT); - break; - } - - if(comms_do_cell_backup) - comms_do_cell_backup = false; - - /* modem is started. connect to network */ - retval = modem_network_connect(net_connect_cb); - if (retval == MODEM_STATUS_OK) - { - /* Set the communication_medium flag to be CELL */ - comms_medium = COMMS_MEDIUM_CELL; - - ESP_LOGI(TAG,"LTE Connecting to Cellular network\r\n"); - transition(COMMS_STATE_WAIT_NET_CONNECT); - } -#endif - } - - break; - - case COMMS_STATE_WAIT_NET_CONNECT: - - /* Wait for BG96 network connect event */ - if (evt == COMMS_EVENT_TIMER) - { - ESP_LOGI(TAG,"Network connected\r\n"); - - comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; - - /* Network connected */ - comms.poll_timer = true; - comms.last_cycle_status = COMMS_STATUS_OK; - comms.httpRetryCnt = HTTP_POST_RETRY_MAX; //Setting the number of http_post retries - transition(COMMS_STATE_WAIT_HTTP_POST_REQ); - } - break; - - case COMMS_STATE_WIFI_CONNECT: - if(evt == COMMS_EVENT_TIMER) - { - /* Set the communication_medium flag to be WIFI */ - comms_medium = COMMS_MEDIUM_WIFI; - - /* Initialize the wifi */ - retval = wifi_first_init(); - - /* If the initialization retval is OK then continue to connect to the registered WIFI access-point */ - if(retval == WIFI_OK) - { - /* Connect to the registered WIFI access-point */ - retval = Connect_wifi_sta(WIFI_CLIENT_MODE); - - /* if the connection retval is OK then jump to the "WIFI_POST_REQ" state */ - if(retval == WIFI_OK) - { - /* Do a transition to "WIFI_POST_REQ" */ - transition(COMMS_STATE_WIFI_POST_REQ); - } - else - { - /* Print this Log */ - ESP_LOGI(TAG,"Failed to connect to the WIFI access-point"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do cellular backup for the check-in process */ - if(COMMS_OVER_WIFI_CELL_BACKUP) - { - comms_do_cell_backup = true; - } - - /* Do a transition to "GOING_IDLE" state */ - transition(COMMS_STATE_GOING_IDLE); - } - } - else - { - /* Print this Log */ - ESP_LOGI(TAG,"Failed to initialize the WIFI"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do cellular backup for the check-in process */ - if(COMMS_OVER_WIFI_CELL_BACKUP) - { - comms_do_cell_backup = true; - } - - /* Do a transition to "GOING_IDLE" state */ - transition(COMMS_STATE_GOING_IDLE); - } - - /* Set poll_timer to true to allow executing whatever next state */ - comms.poll_timer = true; - } - - break; - - case COMMS_STATE_WIFI_POST_REQ: - if(evt == COMMS_EVENT_TIMER) - { - /* Get the address of the receiving buffer */ - char *buf = modem_get_rxbuf(); - - /* Do WIFI post-request for the CHECK_IN message - * (Creating the check-in string is done internally inside this function) - * (Also, Switching between the 3-servers are done inside this function) */ - retval = http_client_do_post_request(jsonMessage,buf); - - /* check whether POST-Req was successful and managed to receive/parse server-response or not*/ - if(retval == WIFI_OK) - { - /* Update the number of already done check-ins */ - checkin_cycle_counter++; - - /* Clear history array (So that its current readings don't affect the readings of the next sector) - * Just clear the array (don't clear anything from NVS) */ - data_clear_history(); - - /* Check if this was the last check-in to do (in other words, check if there are no more previous readings to send to server) */ - if(checkin_cycle_counter == number_of_check_in_to_do) - { - /* Close the connection of http-post */ - http_client_post_stop(); - - /* Reset the last post sector in the NVS partition to 0*/ - nvm_set_last_posted_history_sector(0); - - /* Clear History sectors - * Clear from NVS Partition */ - nvm_clear_history_sector(NVM_HISTORY_ALL_SECTORS); - - - /* Print the POST server response */ - ESP_LOGI(TAG,"HTTP-POST response is :\n%s\n",buf); - - /* Parse the server-response */ - data_parse_http_response((const char*)buf); - - /* Reset the posting_failed to be false */ - comms_posting_failed = false; - - /* Don't do cellular backup */ - comms_do_cell_backup = false; - - /* Do a transition to "WIFI_GET_REQ" state */ - transition(COMMS_STATE_WIFI_GET_REQ); - } - else - { - /* Coming here means that there were some previous readings that are stored in NVS and need to posted in multiple check-in cycles - * and we already posted the readings in history_sector x ----> so we need to update the last_posted_sector flag */ - - /* Update the last post sector in the NVS partition */ - uint8_t x = nvm_get_last_posted_history_sector()+1; - nvm_set_last_posted_history_sector(x); - - /* Wait some time before doing the next check-in of the remaining previous readings */ - vTaskDelay(2000/portTICK_PERIOD_MS); - } - } - else - { - /* Close the connection of http-post */ - http_client_post_stop(); - - /* Print this Log */ - ESP_LOGI(TAG,"Failed to do WIFI POST-Request"); - - /* Set the posting_failed to be true */ - comms_posting_failed = true; - - /* Do cellular backup for the check-in process */ - if(COMMS_OVER_WIFI_CELL_BACKUP) - { - comms_do_cell_backup = true; - } - - /* Do a transition to "GOING_IDLE" state */ - transition(COMMS_STATE_GOING_IDLE); - } - - /* Set poll_timer to true to allow executing whatever next state */ - comms.poll_timer = true; - } - - break; - - case COMMS_STATE_WIFI_GET_REQ: - if(evt == COMMS_EVENT_TIMER) - { - /* Get the address of the receiving buffer */ - char *buf = modem_get_rxbuf(); - - /* Do WIFI get-request for the SP messages - * Parsing SP5 message and checking the firmware version is done internally inside this function - * (Also, Starting WIFI-OTA session is done internally inside this function) - * (Also, Switching between the 3-servers are done inside this function) - * (Also, Parsing the server-response -if get request succeeded- is done internally inside this function */ - retval = http_client_do_get_request(GET_CONFIGURATIONS,(char*)modem_get_imei(),buf); - - /* check whether GET-Req was successful and managed to receive/parse server-response or not*/ - if(retval != WIFI_OK) - { - /* Print this Log */ - ESP_LOGI(TAG,"Failed to do GET-Request"); - } - - /* Set poll_timer to true to allow executing whatever next state */ - comms.poll_timer = true; - - /* Do a transition to "GOING_IDLE" state */ - transition(COMMS_STATE_GOING_IDLE); - } - - break; - - case COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS: - - /* Wait for BG96 HTTP setup event */ - if (evt == COMMS_EVENT_TIMER) - { - - retval= comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS,"configuration flags",COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS,MCU_GET_CONFIG_FLAGS_URL1,MCU_GET_CONFIG_FLAGS_URL2,MCU_GET_CONFIG_FLAGS_URL3); - - } - break; - - case COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS: - - /* Wait for BG96 HTTP GET config event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Get the buffer and process the configuration. */ - int len = 0; - char* buf = 0; - retval = modem_http_get_buf(&buf, &len); - if (retval == MODEM_STATUS_OK) - { - ESP_LOGI(TAG,"CONFIG BUF :\n%s\n",buf); - - /// Parsing config ........ - retval = data_parsing_config(buf,len); - if(!retval){ - //if parsing success check update flags g_ConfigUpdate, g_McuUpdate, g_ModemUpdate. - ESP_LOGI(TAG,"config Parsing success"); - check_for_update(); - } - else - { - ESP_LOGI(TAG,"config Parsing Failed"); - } - } - else{ - ESP_LOGI(TAG,"Modem get buff Failed (GET_CONFIG_FLAGS state)"); - comms.poll_timer= true; - transition(COMMS_STATE_GOING_IDLE); - } - } - - break; - - case COMMS_STATE_WAIT_HTTP_POST_REQ: - if(evt == COMMS_EVENT_TIMER) - { -//suceesUrl = 1 - data_create_checkin_string(jsonMessage, sizeof(jsonMessage)); - - retval=comms_http_request(start_http_post_request,COMMS_STATE_WAIT_HTTP_POST_REQ,jsonMessage,COMMS_STATE_WAIT_HTTP_POST_RES,MCU_POST_URL1,MCU_POST_URL2,MCU_POST_URL3); - - } - - break; - - case COMMS_STATE_WAIT_HTTP_POST_RES: - - /* Wait for BG96 HTTP GET config event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Get the buffer and process the configuration. */ - int len = 0; - char* buf = 0; - retval = modem_http_get_buf(&buf, &len); - if (retval == MODEM_STATUS_OK) - { - - ESP_LOGI(TAG,"HTTP-POST response is :\n%s\n",buf); - data_parse_http_response((const char *)buf); - - - //comms_update_onboarding_status(); - if(NVM_ONBOARDING_NOT_SET_VAL != nvm_read_onboarding_flag(CELL_ONBOARDING_KEY)) - { - nvm_write_onboarding_flag(CELL_ONBOARDING_KEY,NVM_ONBOARDING_SET_VAL); - } - - comms.poll_timer= true; - transition(COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS); - } - else{ - comms.poll_timer= true; - transition(COMMS_STATE_GOING_IDLE); - } - } - - break; - - case COMMS_STATE_WAIT_HTTP_SEND_SP5: - - /* Wait for comms timer event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Now make the GET request. */ - retval = comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_SP5,"McuUpdate",COMMS_STATE_WAIT_HTTP_GET_SP5,MCU_FW_VERSION_URL1,MCU_FW_VERSION_URL2,MCU_FW_VERSION_URL3); - - } - break; - - case COMMS_STATE_WAIT_HTTP_GET_SP5: - - /* Wait for BG96 HTTP GET config event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Get the buffer and process the configuration. */ - int len = 0; - char* buf = 0; - retval = modem_http_get_buf(&buf, &len); - if (retval == MODEM_STATUS_OK) - { - - ESP_LOGI(TAG,"SP5 BUF: %s",buf); - - //SP5 parsing... - Comms_Parse_SP5(buf, len); - } - else - { - ESP_LOGI(TAG,"SP5 Parsing Failed"); - comms.poll_timer = true; - transition(COMMS_STATE_GOING_IDLE); - } - } - break; - - - case COMMS_STATE_WAIT_HTTP_SEND_SP6: - - /* Wait for comms timer event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Now make the GET request. */ - retval = comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_SP6,"ModemUpdate",COMMS_STATE_WAIT_HTTP_GET_SP6,MODEM_FW_VERSION_URL1,MODEM_FW_VERSION_URL2,MODEM_FW_VERSION_URL3); - - } - break; - - case COMMS_STATE_WAIT_HTTP_GET_SP6: - - /* Wait for BG96 HTTP GET config event */ - if (evt == COMMS_EVENT_TIMER) - { - /* Get the buffer and process the configuration. */ - int len = 0; - char* buf = 0; - retval = modem_http_get_buf(&buf, &len); - if (retval == MODEM_STATUS_OK) - { - - ESP_LOGI(TAG,"SP6 BUF: %s",buf); - - //SP6 parsing... - Comms_Parse_SP6(buf, len); - } - else - { - ESP_LOGI(TAG,"SP6 Parsing Failed"); - comms.poll_timer = true; - transition(COMMS_STATE_GOING_IDLE); - } - } - break; - - case COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE: - - /* Wait for BG96 HTTP GET modem update event */ - if (evt == COMMS_EVENT_TIMER) - { - comms.get_modem_update = false; - /* Get the buffer and process the configuration. */ - int len = 0; - char* buf = 0; - retval = modem_http_get_buf(&buf, &len); - if (retval == MODEM_STATUS_OK) - { - // if (COMMS_STATUS_OK == check_modem_update(buf, len)) - { - /* Different firmware on server. Use it. */ - /* Setup URL */ - memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); - - - switch(data_get_postToServer()){ - - case TEMPSTICK_SERVER1: - - /* make the POST request to server 1. */ - ESP_LOGI(TAG,"Get Modem bin file from server 1"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL1, modem_get_imei()); - - break; - case TEMPSTICK_SERVER2: - - /* make the POST request to server 2. */ - ESP_LOGI(TAG,"Get Modem bin file from server 2"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL2, modem_get_imei()); - break; - - case TEMPSTICK_SERVER3: - - /* make the POST request to server 3. */ - ESP_LOGI(TAG,"Get Modem bin file from server 3"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL3, modem_get_imei()); - break; - - } - - - /* Download the GET data to modem */ - int retval = modem_update_modem(fotadl_op_cb, comms.mqtt_buf); - if (retval == MODEM_STATUS_OK) - { - hmi_set_leds_state(BLUE_LED_FLASHING_OTA); - ESP_LOGI(TAG,"FOTADL started\r\n"); - transition(COMMS_STATE_WAIT_MODEM_UPDATE); - break; - } - else - { - ESP_LOGE(TAG,"FOTADL failed to start\r\n"); - /* Continue with session */ - } - } - } - } - break; - - case COMMS_STATE_WAIT_MODEM_UPDATE: - - /* Wait for modem update callback. */ - if (evt == COMMS_EVENT_TIMER) - { - /* In either case, stop the comm process. We want to connect again to do the uplink, - * and we can do that by returning "UPDATED" status, allowing main - * to schedule another connection attempt right away - if desired. - */ - comms.last_cycle_status = COMMS_STATUS_UPDATED; - comms.poll_timer = true; /* request state machine to be polled again right away in new state */ - hmi_stop_ota_event(); - transition(COMMS_STATE_GOING_IDLE); - } - break; - - case COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE: - - /* Set http_init_state to COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE */ - comms.http_init_state = COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE; - - /* Wait for BG96 HTTP GET MCU update event */ - //if (evt == COMMS_EVENT_TIMER) - { - comms.get_mcu_update = false; - /* Get the buffer and process the MCU fw version message. */ - //int len = 0; - //char* buf = 0; - //retval = modem_http_get_buf(&buf, &len); - //if (retval == MODEM_STATUS_OK) - { - //if (COMMS_STATUS_OK == check_mcu_update(buf, len)) - { - /* Different firmware on server. Use it. */ - /* Setup URL: - * Need to download either upper or lower version of the application, - * depending on what we're running now. (i.e. if we are the lower app, need - * to get the upper app) - */ - memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); - -#if ST_OTA_HIGHER_APPLICATION -//// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_LOWER, modem_get_imei()); -#elif ST_OTA_LOWER_APPLICATION -// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_HIGHER, modem_get_imei()); -#else -//// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_LOWER, modem_get_imei()); -#endif - /*Creating file path and store it in comms.mqtt_buf*/ -// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1, modem_get_imei()); - - switch(data_get_postToServer()){ - - case TEMPSTICK_SERVER1: - - /* make the get request to server 1. */ - ESP_LOGI(TAG,"Get MCU bin file from server 1"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1, modem_get_imei()); - break; - - case TEMPSTICK_SERVER2: - - /* make the get request to server 2. */ - ESP_LOGI(TAG,"Get MCU bin file from server 2"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL2, modem_get_imei()); - break; - - case TEMPSTICK_SERVER3: - - /* make the get request to server 3. */ - ESP_LOGI(TAG,"Get MCU bin file from server 3"); - snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL3, modem_get_imei()); - break; - - } - - - - /* Download the file data to modem file system */ - int retval = modem_http_get_to_file(fwdl_op_cb, comms.mqtt_buf, MCU_OTA_FILE_LOCAL); - - if (retval == MODEM_STATUS_OK) - { - ESP_LOGI(TAG,"MCU FW download started\r\n"); - ///hmi_set_offload_mode(false); - transition(COMMS_STATE_WAIT_HTTP_GET_MCU_FILE); - //hmi_set_update_mode(true); - break; - } - else - { - ESP_LOGE(TAG,"MCU FW download failed to start\r\n"); - /* Continue with session */ - } - } - } - } - - break; - - case COMMS_STATE_WAIT_HTTP_GET_MCU_FILE: - - /* Wait for download complete callback. */ - if (evt == COMMS_EVENT_TIMER) - { - if (comms.last_op_success) - { - /* Download is ready. Now we can start the read from file operation on the bg96 driver - * and use the callbacks to drive the update. The bg96 process is driving the update. - */ - retval = modem_read_from_file( - fwupd_op_cb, /* called when completed or failed at any point */ - MCU_OTA_FILE_LOCAL, - ota_file_open_cb, /* Can fail and continue the comms state machine */ - ota_file_data_cb); /* Callback for the file data in chunks */ - - if (retval == MODEM_STATUS_OK) - { - hmi_set_leds_state(BLUE_LED_FLASHING_OTA); - ESP_LOGI(TAG,"MCU FW update started\r\n"); - transition(COMMS_STATE_WAIT_MCU_UPDATE); - break; - } - else - { - ESP_LOGE(TAG,"MCU FW update failed to start\r\n"); - /* Continue with session */ - //hmi_set_update_mode(false); - } - } - } - break; - - case COMMS_STATE_WAIT_MCU_UPDATE: - - /* Wait while updating. */ - if (evt == COMMS_EVENT_TIMER) - { - if (comms.last_op_success) - { - /* If it completes, it will ping this and here and we finish it up. - * OTA_terminate_connection sets the flag that is handled in OTA_Tick() - * and main to do a reset to start the new application after comm completes. - */ - ESP_LOGD(TAG,"Ending OTA session, ready for reset\r\n"); - - ota_finish_processing(); - - /* Clear this, in case we have just turned on and have updated - - * no need to trigger the startup callback in main. - */ - comms.is_starting = false; - } - } - break; - - case COMMS_STATE_GOING_IDLE: - - /* Check if we can use WIFI as backup technique for check-in */ - if((COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) && (comms_do_wifi_backup)) - { - /* Print this log */ - ESP_LOGI(TAG,"Doing WIFI-BACKUP for CHECK-IN process."); - - /* Transfer the control state to "WIFI_CONNECT" */ - transition(COMMS_STATE_WIFI_CONNECT); - - /* Set the comms.poll_timer to be true */ - comms.poll_timer = true; - - /* Reset the wifi-backup flag */ - comms_do_wifi_backup = false; - - /* Break from the state-machine */ - break; - } - else if((COMMS_OVER_WIFI_CELL_BACKUP == comms_mode) && (comms_do_cell_backup)) - { - /* Print this log */ - ESP_LOGI(TAG,"Doing CELL-BACKUP for CHECK-IN process."); - - /* Transfer the control state to "WAIT_MODEM" */ - transition(COMMS_STATE_WAIT_MODEM); - - /* Set the comms.poll_timer to be true */ - comms.poll_timer = true; - - /* Reset the cell-backup flag */ - //comms_do_cell_backup = false; - - /* Break from the state-machine */ - break; - } - - ESP_LOGI(TAG,"Process going idle.\n"); - - /* Reset the backup flag */ - comms_do_wifi_backup = false; - comms_do_cell_backup = false; - -#if (FAKE_NETWORK == 1) - comms_update_onboarding_status(); -#endif - - /* Stop BLUE_LED_FLASHING if it's still running*/ - hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event - - - /* Check if MCU failed to post the check-in message to the tempstick-server */ - if(comms_posting_failed) - { - /* Print this log */ - ESP_LOGI(TAG," -----> Posting the check-in message failed.\n Storing sensor data to NVS to be published in the next successful CHECK-IN process "); - - /**/ - // put your code here to store sensor data to NVS - data_save_history(); - - /* Reset the comms_posting_failed flag */ - comms_posting_failed = false; - } - - /*===========================================*/ - /* Make sure that wifi is turned-off*/ - if(wifi_isStarted()) - { - retval = wifi_stop(); - } - - /* Make sure that modem is turned-off*/ - if(modem_is_started()) - { - retval = modem_stop(); - } - /*===========================================*/ - transition(COMMS_STATE_WAIT_MODEM_OFF); - comms.poll_timer = true; - - break; - - case COMMS_STATE_IDLE: - if (evt == COMMS_EVENT_CONNECT) - { - /* Set the number of check-in cycles to do and reset the checkin_cycle_counter */ - number_of_check_in_to_do = nvm_get_last_written_history_sector() - nvm_get_last_posted_history_sector(); - checkin_cycle_counter = 0; - - ESP_LOGI(TAG, "Inside comms IDLE state \r\n"); - - /* Status is ERROR until cleared by successful completion. */ - comms.last_cycle_status = COMMS_STATUS_ERROR; - - if (modem_is_ready()) - { - modem_start_cb(MODEM_STATUS_OK); - } - else if(!modem_is_started()) - { - /* start the bg77 process */ - retval = modem_start(modem_start_cb); - - if (retval == MODEM_STATUS_OK) - { - ESP_LOGI(TAG,"Waiting for Modem.\n"); - transition(COMMS_STATE_WAIT_MODEM); - } - } - else - { - ESP_LOGI(TAG, "Modem is busy. Comm cycle aborted.\r\n"); - } - } - break; - - case COMMS_STATE_WAIT: - check_in_attempts_count(comms.httpRetryCnt,HTTP_RETRY_COUNT_MAX); - esp_timer_stop(comms_timer); - comms.poll_timer = true; - transition(comms.http_init_state); - ESP_LOGI(TAG,"Number of remaining HTTP retry is : %d\n", comms.httpRetryCnt); - break; - - case COMMS_STATE_WAIT_MODEM_OFF: - if(!modem_is_started()) - { - /* transition to INIT state only if not started. */ - transition(COMMS_STATE_IDLE); - - /* Invoke callback if supplied.*/ - if(comms.connect_cb) - { - comms.connect_cb(comms.last_cycle_status); - comms.connect_cb = 0; - } - } - else - { - //ESP_LOGW(TAG,"Modem is busy.\r\n"); - comms.poll_timer = true; - } - break; - - default: - break; - } - - return retval; -} - -/* ------------------------------------------------------------------------- */ - - - /* Initialize. */ -int comms_init(void) -{ - int retval = COMMS_STATUS_OK; - - memset(&comms, 0, sizeof(comms)); - comms.overflow_check = 0xFF; - - /*Initializing the COMMS_TIMER */ - const esp_timer_create_args_t comms_timer_args = { - .callback = &timer_handler, - /* argument specified here will be passed to timer callback function */ - .arg = (void*) comms_timer, - .name = "comms-timer" - }; - esp_timer_create(&comms_timer_args, &comms_timer); - - comms.poll_timer = false; - - ESP_LOGI(TAG,"Process initialized.\n"); - - return retval; -} - -/* Start the process */ -int comms_start(comms_op_cb_t start_cb, comms_op_cb_t connect_cb) -{ - comms.start_cb = start_cb; - comms.connect_cb = connect_cb; - int retval = state_machine(COMMS_EVENT_START); - return retval; -} - -/* Stop the process */ -int comms_stop(void) -{ - int retval = state_machine(COMMS_EVENT_STOP); - return retval; -} - -/* Poll the process */ -int comms_poll(void) -{ - int retval = COMMS_STATUS_OK; - if (comms.poll_timer) - { - comms.poll_timer = false; - retval = state_machine(COMMS_EVENT_TIMER); - } - else if (0 /* */) - { - } - - return retval; -} - -int comms_connect(comms_op_cb_t cb) -{ - comms.connect_cb = cb; - int retval = state_machine(COMMS_EVENT_CONNECT); - return retval; -} - -/* Check if the process needs to be polled */ -bool comms_needs_poll(void) -{ - return - comms.poll_timer; -} - - -/* Check if the process is started */ -bool comms_is_started(void) -{ - return comms.state != COMMS_STATE_INIT; -} - -bool comms_is_idle(void) -{ - return comms.state == COMMS_STATE_IDLE; -} - -int comms_get_status(void) -{ - return comms.last_cycle_status; -} - -/* ------ Process Callbacks ------------------------- */ - -__attribute__((weak)) void comms_ready_cb(void) { } - - - - +/* + * comms.c + * + * Created on: Jan 16, 2023 + * Author: Sword + */ + + + +#include "rtc.h" +#include "nvm.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include "esp_timer.h" +#include +#include +#include +#include "modem.h" +#include "wifi_Client.h" +#include "main.h" +#include "comms.h" +#include "port.h" +#include "data_processing.h" +#include "ota.h" +#include "hmi.h" + +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "esp_log.h" + +// Development support: force the operation of the following configuration functions +#ifdef SET_CFG_BITS +// set 1 to force the appropriate functions +#define FORCE_MCU_CONFIG_DOWNLOAD 1 +#define FORCE_MCU_PROG_DOWNLOAD 1 +#define FORCE_MODEM_PROG_DOWNLOAD 1 +#else +#define FORCE_MCU_CONFIG_DOWNLOAD 0 +#define FORCE_MCU_PROG_DOWNLOAD 0 +#define FORCE_MODEM_PROG_DOWNLOAD 0 +#endif + +/* Set 1 to use "unwired/[IMEI]", e.g. "unwired/862061049756488" +* Set 0 to use "unwiredct" +*/ +#define COMMS_PUBLISH_WITH_IMEI 0 +#define JWT_LEN 1024 + + + +//#define MCU_SP4_URL "https://parthasarathimishra.com/hae/tempstick/%s/mcu_config_download/" + + +/* Name of file to create in modem file system for the downloaded image. +* This is arbitrary, but we name the upper and lower version differently +* to avoid possible mixing up at the firmware level (the server can +* still mix them up if a lower app was put at the /higher URL) +*/ +#if ST_OTA_HIGHER_APPLICATION +/* A running "higher" app must download and install a "lower" app and vice versa. */ +#define MCU_FW_UPDATE_FILE "lrsm0005_fw_ota_image_lower.bin" +#else +#define MCU_FW_UPDATE_FILE "lrsm0005_fw_ota_image_higher.bin" +#endif + +//#define MCU_FW_BIN_FILE_URL1_HIGHER "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/lrsm0005_fw_ota_image_higher.bin" +//#define MCU_FW_BIN_FILE_URL1_LOWER "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/lrsm0005_fw_ota_image_lower.bin" +#define MCU_PROG_VER_URL SERVER_URL_BASE "mcu_pgm_download/version" +//#define MODEM_FW_BIN_FILE_URL1 SERVER_URL_BASE "modem_pgm_download" +#define MODEM_PROG_VER_URL SERVER_URL_BASE "modem_pgm_download/version" +#define WHITELIST_URL SERVER_URL_BASE "whitelist" +//#define MCU_FW_BIN_FILE_URL1 "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/" MCU_FW_UPDATE_FILE +//#define MCU_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/mcu_pgm_download/OTA.bin" + + +//#define MODEM_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/modem_pgm_download/MOTA.bin"/*upgrade*/ +//#define MODEM_FW_BIN_FILE_URL1 "https://www.parthasarathimishra.com/hae/tempstick/%s/modem_pgm_download/Update_BG77LAR02A04_01.009.01.009-R02A04_01.006.01.006.bin"/*downgrade*/ + + + +#define MQTT_PUB_TOPIC_LEN 48 + +#define MCU_CONFIG_FLAG_WHITELIST_UPDATE 0x1 +#define MCU_CONFIG_FLAG_MCU_UPDATE 0x2 +#define MCU_CONFIG_FLAG_MODEM_UPDATE 0x4 + +#define HTTP_RETRY_COUNT_MAX 5 +#define HTTP_POST_RETRY_MAX 2 +#define HTTP_RETRY_WAIT 20000 + +static const char *TAG = "COMMS"; + +extern uint32_t g_ConfigUpdate; +extern uint32_t g_McuUpdate; +extern uint32_t g_ModemUpdate; +extern uint32_t g_version; + +typedef enum +{ + COMMS_EVENT_START, + COMMS_EVENT_TIMER, + COMMS_EVENT_STOP, + COMMS_EVENT_CONNECT, +} comms_event_t; + +/* State of the comms process */ +typedef enum +{ + COMMS_STATE_INIT, + COMMS_STATE_WAIT_MODEM, + COMMS_STATE_WAIT_NET_CONNECT, + COMMS_STATE_WIFI_CONNECT, + COMMS_STATE_WIFI_POST_REQ, + COMMS_STATE_WIFI_GET_REQ, + COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS, + COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS, + COMMS_STATE_WAIT_HTTP_POST_REQ, + COMMS_STATE_WAIT_HTTP_POST_RES, + COMMS_STATE_WAIT_HTTP_SEND_SP5, + COMMS_STATE_WAIT_HTTP_GET_SP5, + COMMS_STATE_WAIT_HTTP_SEND_SP6, + COMMS_STATE_WAIT_HTTP_GET_SP6, + COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE, /* Get modem update version */ + COMMS_STATE_WAIT_MODEM_UPDATE, /* Wait for modem to do its thing */ + COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE, /* Get version */ + COMMS_STATE_WAIT_HTTP_GET_MCU_FILE, /* Download file */ + COMMS_STATE_WAIT_MCU_UPDATE, /* Install update */ + COMMS_STATE_GOING_IDLE, + COMMS_STATE_IDLE, + COMMS_STATE_WAIT, + COMMS_STATE_WAIT_MODEM_OFF, + +} comms_state_t; + + +typedef int (*comms_switch_cb)(comms_state_t init_state, const char* url,const char* msg, comms_state_t success_state); + +typedef struct +{ + comms_state_t state; + + /* Timer */ + bool poll_timer; + + /* User start callback */ + comms_op_cb_t start_cb; + bool is_starting; + + /* User connect callback */ + comms_op_cb_t connect_cb; + + char mqtt_pub_topic[MQTT_PUB_TOPIC_LEN]; + /* Printing an SP2 message: + * Header: 3 + 1 + [IMEI-15] +1 + 10 + 1+ 10 + 1 = 42 + * [32],[4],[4],[3] = 46 * 20 = 920 + * Footer: 3 + * 42 + 920 + 3 = 965 + * Add buffer overflow protection in writing routines. + */ + char mqtt_buf[1024]; /* Also general buffer */ + //char jwt[JWT_LEN]; + uint8_t overflow_check; + int mqtt_pub_counter; + + /* flagged actions to take */ + bool get_whitelist; + bool get_mcu_update; + bool get_modem_update; + + /* Status of the last communication cycle + * OK or ERROR + */ + int last_cycle_status; + + /* Status of last pending operation */ + bool last_op_success; + bool wf1_msg; + + int httpRetryCnt; + comms_state_t http_init_state; +} comms_t; + +/* Unique timer ID for this process for use with timer module */ +//#define COMMS_TIMER_ID 1 +esp_timer_handle_t comms_timer; +/* Local process state */ + +static comms_t comms; + + +//nvs_handle_t my_handle; +extern uint8_t onBoarded; +extern uint8_t comms_mode; +comms_medium_t comms_medium; + +static bool comms_do_wifi_backup; +static bool comms_do_cell_backup; +static bool comms_posting_failed; + +uint8_t checkin_cycle_counter; +uint8_t number_of_check_in_to_do; + +char jsonMessage[2560]; +char http_post_header[250]; + +#if (FAKE_NETWORK == 1) +char server_resp[] = "{\"request\":\"settings\",\"id\":10608508,\"minTemp\":-1.11,\"maxTemp\":26.67,\"minHum\":10,\"maxHum\":80,\"voltageQuit\":2.3,\"alertInterval\":900,\"sendInterval\":60,\"sendDetails\":1,\"postURLNumber\":2,\"postURLMax\":3,\"tmpThA_GP\":71.11,\"tmpThA_GN\":70,\"tmpThB_GP\":71.11,\"tmpThB_GN\":70,\"tmpThC_GP\":71.11,\"tmpThC_GN\":70,\"tmpThD_GP\":-44.44,\"tmpThD_GN\":-45.56,\"tmpThE_GP\":-44.44,\"tmpThE_GN\":-45.56,\"tmpThF_GP\":-44.44,\"tmpThF_GN\":-45.56,\"T_TKN\":5,\"humThA_GP\":103,\"humThA_GN\":101,\"humThB_GP\":103,\"humThB_GN\":101,\"humThC_GP\":103,\"humThC_GN\":101,\"humThD_GP\":-1,\"humThD_GN\":-3,\"humThE_GP\":-1,\"humThE_GN\":-3,\"humThF_GP\":-1,\"humThF_GN\":-3,\"H_TKN\":5,\"TC_M\":1,\"TC_TYPE\":\"K\",\"tcThA_GP\":71.11,\"tcThA_GN\":70,\"tcThB_GP\":71.11,\"tcThB_GN\":70,\"tcThC_GP\":71.11,\"tcThC_GN\":70,\"tcThD_GP\":-168.33,\"tcThD_GN\":-169.44,\"tcThE_GP\":-168.33,\"tcThE_GN\":-169.44,\"tcThF_GP\":-168.33,\"tcThF_GN\":-169.44,\"TC_TKN\":5,\"LT_M\":3,\"LT_LVLGP\":200,\"LT_LVLGN\":50,\"LT_LOCK\":900,\"LT_TKN\":5,\"AC_M\":1,\"AC_LVL\":15000,\"AC_INT\":60,\"AC_LOCK\":60,\"AC_TKN\":5,\"PWR_M\":3,\"PWR_DBNC\":60,\"PWR_TKN\":5,\"PUSH_TKN\":5,\"TKN_RLD\":300}"; +#endif +/* ------------------------------------------------------------------------- */ + +static const char* state_str(comms_state_t s) +{ + switch (s) { + case COMMS_STATE_INIT:return "INIT"; + case COMMS_STATE_WAIT_MODEM:return "WAIT_MODEM"; + case COMMS_STATE_WAIT_NET_CONNECT:return "WAIT_NET_CONNECT"; + case COMMS_STATE_WIFI_CONNECT:return "WIFI_CONNECT"; + case COMMS_STATE_WIFI_POST_REQ:return "WIFI_POST_REQ"; + case COMMS_STATE_WIFI_GET_REQ:return "WIFI_GET_REQ"; + case COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS:return "WAIT_HTTP_SEND_CONFIG_FLAGS"; + case COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS:return "WAIT_HTTP_GET_CONFIG_FLAGS"; + case COMMS_STATE_WAIT_HTTP_POST_REQ:return "WAIT_HTTP_POST_REQ"; + case COMMS_STATE_WAIT_HTTP_POST_RES:return "WAIT_HTTP_POST_RES"; + case COMMS_STATE_WAIT_HTTP_SEND_SP5:return "WAIT_HTTP_SEND_SP5"; + case COMMS_STATE_WAIT_HTTP_GET_SP5:return "HTTP_GET_SP5"; + case COMMS_STATE_WAIT_HTTP_SEND_SP6:return "HTTP_SEND_SP6"; + case COMMS_STATE_WAIT_HTTP_GET_SP6:return "HTTP_GET_SP6"; + case COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE:return "WAIT_HTTP_GET_MODEM_UPDATE"; + case COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE:return "WAIT_HTTP_GET_MCU_UPDATE"; + case COMMS_STATE_WAIT_HTTP_GET_MCU_FILE:return "WAIT_HTTP_GET_MCU_FILE"; + case COMMS_STATE_WAIT_MODEM_UPDATE:return "WAIT_MODEM_UPDATE"; + case COMMS_STATE_WAIT_MCU_UPDATE:return "WAIT_MCU_UPDATE"; + case COMMS_STATE_GOING_IDLE: return "COMMS_STATE_GOING_IDLE"; + case COMMS_STATE_IDLE:return "IDLE"; + case COMMS_STATE_WAIT:return "STATE_WAIT"; + case COMMS_STATE_WAIT_MODEM_OFF:return "WAIT_MODEM_OFF"; + default: + return ""; + } +} + +static esp_err_t build_http_headerBodyMsg(uint32_t len) +{ + /* jsonMessage address is the same address as msg*/ + uint32_t header_len = 0; + int index = 0; + + /* Setup the HTTP header*/ + sprintf(http_post_header, HTTP_POST_HEADER,(unsigned int)len); + + /* Calculate http-header length*/ + header_len = strlen(http_post_header); + + /* Shift jsonMessage right by length of http-header*/ + if( (len+header_len)>= 2560) + { + ESP_LOGI(TAG,"Shifting exceeded the maximum size of jsonMessage buffer"); + return ESP_FAIL; + } + + /* Shift the message in jsonMessage buffer to right by length of http-header*/ + for(index = len-1; index >= 0; index--) + { + jsonMessage[index+header_len] = jsonMessage[index]; + + /* Copy http-header at the beginning of jsonMessage*/ + if(index < header_len) + jsonMessage[index] = http_post_header[index]; + } + return ESP_OK; +} + +static void transition(comms_state_t state_to) +{ + ESP_LOGD(TAG,"%s->%s\n", state_str(comms.state), state_str(state_to)); + comms.state = state_to; +} + + +/* These handlers handle completion events for commands issued by the BG96 modem driver. +* If success, the comms process continues by way of a "timer" event. +* If fail, the comms process stops what it was doing and goes back to "idle" state. +* The comms process is started once at startup and does not stop thereafter. +*/ +static void modem_start_cb(int status) +{ + comms.poll_timer = true; + if (MODEM_STATUS_OK == status) + { + /* started */ + transition(COMMS_STATE_WAIT_MODEM); + } + else + { + /* Nope - back to init */ + ESP_LOGW(TAG,"BG96 startup failed.\r\n"); + + if(comms_mode == COMMS_OVER_CELL) + { + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + if(!onBoarded) //Unable to connect to LTE network + { + hmi_set_leds_state(RED_LED_FLASHING); + } //Unable to connect to LTE network + } + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + transition(COMMS_STATE_GOING_IDLE); + } +} +//bool net_connected = false; +static void net_connect_cb(int status) +{ + //net_connected = true; + comms.poll_timer = true; + if (MODEM_STATUS_OK == status) + { + /* connected */ + ESP_LOGI(TAG,"Network connection Successful.\r\n"); + } + else + { + /* Nope - back to init */ + ESP_LOGW(TAG,"Network connection failed.\r\n"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + if(comms_mode == COMMS_OVER_CELL) + { + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + if(!onBoarded) //Unable to connect to LTE network + { + hmi_set_leds_state(RED_LED_FLASHING); + } //Unable to connect to LTE network + } + transition(COMMS_STATE_GOING_IDLE); + } +} + +static void http_op_cb(int status) +{ + if (MODEM_STATUS_OK == status) + { + /*Connected. Set the poll_timer to be true*/ + comms.poll_timer = true; + } + else + { + /*If not connected then check the number of http retries if it's greater than zero*/ + if(comms.httpRetryCnt) + { + /*decrement the number of retries by 1*/ + comms.httpRetryCnt--; + + /*start a timer for 20sec*/ + esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); + + /*Logging waiting message*/ + ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); + + /*transition to COMMS_STATE_WAIT state*/ + transition(COMMS_STATE_WAIT); + } + else + { + /*Reinitialize the counter of http retries with 3*/ + comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /* Nope - back to idle */ + ESP_LOGW(TAG,"HTTP operation failed.\r\n"); + + //SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message + //int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */ + int retval = MODEM_STATUS_ERROR; + if(MODEM_STATUS_OK==retval) + { + ESP_LOGI(TAG,"MQTT Publish SP1 message success"); + } + else + { + ESP_LOGI(TAG,"MQTT Publish SP1 message failed"); + } + + /*transition to COMMS_STATE_GOING_IDLE state*/ + transition(COMMS_STATE_GOING_IDLE); + } + } +} + + + +static void http_post_op_cb(int status) +{ + if (MODEM_STATUS_OK == status) + { + comms.poll_timer = true; + + /* Update the number of already done check-ins */ + checkin_cycle_counter++; + + /* Clear history array (So that its current readings don't affect the readings of the next sector) + * Just clear the array (don't clear anything from NVS) */ + data_clear_history(); + + /* Check if this was the last check-in to do (in other words, check if there are no more previous readings to send to server) */ + if(checkin_cycle_counter == number_of_check_in_to_do) + { + /* Reset the last post sector in the NVS partition to 0*/ + nvm_set_last_posted_history_sector(0); + + /* successfully posted. */ + ESP_LOGI(TAG,"HTTP post message SUCCESS.\r\n"); + + /* Clear History sectors + * Clear from NVS Partition */ + nvm_clear_history_sector(NVM_HISTORY_ALL_SECTORS); + + /* Reset the posting_failed to be false */ + comms_posting_failed = false; + comms_do_wifi_backup = false; + + /*Set the last operation to be completed successfully*/ + comms.last_op_success = true; + + comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; + } + else + { + /* Coming here means that there were some previous readings that are stored in NVS and need to posted in multiple check-in cycles + * and we already posted the readings in history_sector x ----> so we need to update the last_posted_sector flag */ + + /* Update the last post sector in the NVS partition */ + uint8_t x = nvm_get_last_posted_history_sector()+1; + nvm_set_last_posted_history_sector(x); + + /* Wait some time before doing the next check-in of the remaining previous readings */ + vTaskDelay(2000/portTICK_PERIOD_MS); + + /* Do a transition to "COMMS_STATE_WAIT_HTTP_POST_REQ" state */ + transition(COMMS_STATE_WAIT_HTTP_POST_REQ); + } + } + else + { + if(comms.httpRetryCnt) + { + /*decrement the number of retries by 1*/ + comms.httpRetryCnt--; + + /*start a timer for 20sec*/ + esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); + + /*Logging waiting message*/ + ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /*transition to COMMS_STATE_WAIT state*/ + transition(COMMS_STATE_WAIT); + } + else + { + /*Reinitialize the counter of http_post retries with 3*/ + comms.httpRetryCnt = HTTP_POST_RETRY_MAX; + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /* Nope - back to idle */ + /* failed. */ + ESP_LOGW(TAG,"HTTP post message FAILED.\r\n"); + comms.last_op_success = false; + + /* Give Red-led indication*/ + if(comms_mode == COMMS_OVER_CELL) + { + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + if(!onBoarded) //Unable to connect to LTE network + { + hmi_set_leds_state(RED_LED_FLASHING); + } //Unable to connect to LTE network + } + + /* alternating between three servers + * + * transition to COMMS_STATE_GOING_IDLE state if the connection to the servers failed*/ + + switch(data_get_postToServer()){ + + case TEMPSTICK_SERVER1: + if( 1 == data_get_postUrlMax()) + { + ESP_LOGI(TAG,"Just one server available"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do wifi backup for the check-in process */ + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + transition(COMMS_STATE_GOING_IDLE); + } + else + { + data_set_postToServer(TEMPSTICK_SERVER2); + ESP_LOGI(TAG,"Transition to the next server --> %d",TEMPSTICK_SERVER2); + transition(COMMS_STATE_WAIT_HTTP_POST_REQ); + } + break; + case TEMPSTICK_SERVER2: + if( 2 == data_get_postUrlMax()) + { + ESP_LOGI(TAG,"Just two servers available"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do wifi backup for the check-in process */ + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + transition(COMMS_STATE_GOING_IDLE); + } + else + { + data_set_postToServer(TEMPSTICK_SERVER3); + ESP_LOGI(TAG,"Transition to the next server --> %d",TEMPSTICK_SERVER3); + transition(COMMS_STATE_WAIT_HTTP_POST_REQ); + } + break; + case TEMPSTICK_SERVER3: + data_set_postToServer(TEMPSTICK_SERVER1); + ESP_LOGI(TAG,"Transition to default server --> %d then going to IDLE",TEMPSTICK_SERVER1); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do wifi backup for the check-in process */ + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + transition(COMMS_STATE_GOING_IDLE); + break; + default: + + data_set_postToServer(TEMPSTICK_SERVER1); + ESP_LOGI(TAG,"connection to servers Failed"); + ESP_LOGI(TAG,"Transition to default server --> %d then going to IDLE",TEMPSTICK_SERVER1); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do wifi backup for the check-in process */ + if(COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) + { + comms_do_wifi_backup = true; + } + + transition(COMMS_STATE_GOING_IDLE); + break; + + + + } + } + } +} + +static void fotadl_op_cb(int status) +{ + comms.poll_timer = true; + if (MODEM_STATUS_OK == status) + { + /* completed. */ + ESP_LOGI(TAG,"Modem upgrade SUCCESS.\r\n"); + } + else + { + if(comms.httpRetryCnt) + { + /*decrement the number of retries by 1*/ + comms.httpRetryCnt--; + + /*start a timer for 20sec*/ + esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); + + /*Logging waiting message*/ + ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /*transition to COMMS_STATE_WAIT state*/ + transition(COMMS_STATE_WAIT); + } + else + { + /*Reinitialize the counter of http retries with 3*/ + comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /* Nope - back to idle */ + /* failed. */ + /* failed. */ + /* failed. */ + ESP_LOGW(TAG,"Modem upgrade FAILED.\r\n"); + /* Give Red-led indication*/ + if(comms_mode == COMMS_OVER_CELL) + { + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + if(!onBoarded) //Unable to connect to LTE network + { + hmi_set_leds_state(RED_LED_FLASHING); + } //Unable to connect to LTE network + } + transition(COMMS_STATE_GOING_IDLE); + } + /* Let state handle it */ +} +} + + +static int start_http_get_request(comms_state_t init_state,const char* url, const char* log_msg, comms_state_t success_state) +{ + /* Reset the operation status flag */ + comms.last_op_success = false; + /* Initialize the comms.http_init_state to init_state */ + comms.http_init_state = init_state; + /* Now make the GET request. */ + /* Setup URL */ + memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), url, modem_get_imei()); + + /* Download the GET data to modem */ + int retval = modem_http_get_to_buf(http_op_cb, comms.mqtt_buf); + + if (retval == MODEM_STATUS_OK) + { + ESP_LOGI(TAG,"GET %s\r\n", log_msg); + transition(success_state); + } + else + { + ESP_LOGE(TAG,"GET %s failed.\r\n", log_msg); + comms.poll_timer = true; + + /* Give Red-led indication*/ + if(comms_mode == COMMS_OVER_CELL) + { + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + if(!onBoarded) //Unable to connect to LTE network + { + hmi_set_leds_state(RED_LED_FLASHING); + } //Unable to connect to LTE network + } + + transition(COMMS_STATE_GOING_IDLE); + } + return retval; +} + + +static int start_http_post_request(comms_state_t init_state,const char* url, const char* message, comms_state_t success_state) +{ + esp_err_t ret; + + /* Reset the operation status flag */ + comms.last_op_success = false; + /* Initialize the comms.http_init_state to init_state */ + comms.http_init_state = init_state; + + + /* Setup URL */ + memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), url, modem_get_imei()); + + //sprintf(http_post_header,HTTP_POST_HEADER,(uint32_t)strlen(message)); + /*concatenate http-header with http-body*/ + //strcat(http_post_header,message); + + /* Build the headerBody of the http-post message*/ + ret = build_http_headerBodyMsg((uint32_t)strlen(jsonMessage)); + //ret = ESP_OK; + + if(ESP_OK == ret) + { + /* Send HTTP POST data to modem to upload it to server*/ + int retval = modem_http_post_message(http_post_op_cb, comms.mqtt_buf, message); + + if (retval == MODEM_STATUS_OK) + { + ESP_LOGI(TAG,"HTTP-POST Started\r\n"); + transition(success_state); + } + else + { + ESP_LOGE(TAG,"HTTP-POST failed to proceed\r\n"); + } + return retval; + } + else + { + ESP_LOGI(TAG,"Failed to build header-body of http-post message"); + return MODEM_STATUS_ERROR; + } +} + + +static void fwdl_op_cb(int status) +{ + if (MODEM_STATUS_OK == status) + { + /* Firmware file was downloaded to the modem. */ + ESP_LOGI(TAG,"MCU FW download SUCCESS.\r\n"); + + comms.last_op_success = true; + /* Continue in the current state */ + comms.poll_timer = true; + } + else + { + if(comms.httpRetryCnt) + { + /*decrement the number of retries by 1*/ + comms.httpRetryCnt--; + + /*start a timer for 20sec*/ + esp_timer_start_once(comms_timer, 1000*HTTP_RETRY_WAIT); + + /*Logging waiting message*/ + ESP_LOGI(TAG,"Waiting for another HTTP Retry.\r\n"); + + /*transition to COMMS_STATE_WAIT state*/ + transition(COMMS_STATE_WAIT); + } + else + { + /*Reinitialize the counter of http retries with 3*/ + comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; + + /*Set the poll_timer to be true*/ + comms.poll_timer = true; + + /* Nope - back to idle */ + /* Firmware file not downloaded. */ + ESP_LOGW(TAG,"MCU FW download operation failed.\r\n"); + //SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message + // int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */ + int retval = MODEM_STATUS_ERROR; + if(MODEM_STATUS_OK==retval) + { + ESP_LOGI(TAG,"MQTT Publish SP1 message success"); + } + else + { + ESP_LOGI(TAG,"MQTT Publish SP1 message failed"); + } + + comms.last_op_success = false; + + /*transition to COMMS_STATE_GOING_IDLE state*/ + transition(COMMS_STATE_GOING_IDLE); + } + } +} + +static void fwupd_op_cb(int status) +{ + comms.poll_timer = true; + if (MODEM_STATUS_OK == status) + { + /* Firmware file was installed into device. */ + ESP_LOGI(TAG,"MCU FW update SUCCESS.\r\n"); + + comms.last_op_success = true; + } + else + { + /* Firmware file not installed. */ + ESP_LOGW(TAG,"MCU FW installation failed.\r\n"); + transition(COMMS_STATE_GOING_IDLE); + comms.poll_timer = true; + comms.last_op_success = false; + } +} + +/* ------------------------------------------------------------------------- */ +/* OTA firmware update. + * These callbacks handle the file transfer from the modem and interface with + * the OTA_btl firmware update system. + * + * The main interface is the OTA_Offline_Init and OTA_Offline_Data functions. + * These are added to interface with the stock OTA_btl update engine. + * + * To initialize, we use OTA_Offline_Init(file_size) API. + * This will either accept or reject the firmware image based on + * available space. + * + * To feed update data, call OTA_Offline_Data with a chunk of data. + * + * Be mindful of the return values and feed them back to the updater engine. + * + */ + +static int ota_file_open_cb(uint32_t fileSize) +{ + int retval = MODEM_STATUS_OK; + + esp_err_t res = ota_init(fileSize); + if (ESP_OK == res) { + ESP_LOGI(TAG,"OTA file opened\r\n"); + } + else { + ESP_LOGI(TAG,"OTA file open error: %d\r\n", res); + /* This will abort the entire update process. */ + retval = MODEM_STATUS_ERROR; + } + + return retval; +} + +static int ota_file_data_cb(const char* buf, int buf_len) +{ + int retval = MODEM_STATUS_OK; + + /* Data callback: we can receive a buffer up to MODEM_FREAD_SIZE bytes */ + esp_err_t res = ota_get_data_to_buffer(buf, buf_len); + + if (ESP_OK == res) { + ESP_LOGI(TAG,"%d bytes OTA data processed\r\n", buf_len); + } + else { + ESP_LOGI(TAG,"%d bytes OTA data error: %d\r\n", buf_len, res); + /* This will abort the entire update process. */ + retval = MODEM_STATUS_ERROR; + } + + return retval; +} + +static int sum_digits(int digit) +{ + int sum = 0; + while (digit > 0) + { + sum = sum + digit % 10; + digit = digit / 10; + } + return sum; +} +/** +This function is used to check if IMEI has correct length (15) +to check if IMEI has numerical values (0-9) +to check if the parsed IMEI is same as hardware IMEI +to check if IMEI is valid by help of luhn algorithm +https://www.geeksforgeeks.org/luhn-algorithm/ +*/ +static bool imei_check_valid(char *message_imei) +{ + //find the length of message imei + int len = strlen(message_imei); + int sum = 0; + ESP_LOGI(TAG,"IMEI : %s",message_imei); + + //check length of imei field + if (len != 15){ + //invalid IMEI + ESP_LOGW(TAG,"Invalid IMEI length"); + return false; + } + if(!strcmp(message_imei,modem_get_imei())){ + + for(int i = len-1 ; i >= 0; i--) + { + //check if message imei fields contain numbers (0-9) + if((message_imei[i] > 47) && (message_imei[i] < 58)){ + int digit = (message_imei[i] - 48); + // Doubling every alternate beginning at [13] digit + //ignore last number [14] and first number [0] as well + if (i % 2 != 0) + digit = 2 * digit; + // Finding sum of the digits + // if digit*2 is a two digit number add the two digits + sum += sum_digits(digit); + + } + else{ + ESP_LOGW(TAG,"Invalid IMEI (not numerical values)"); + return false; + } + } + } + else{ + ESP_LOGI(TAG,"Message IMEI doesn't match board IMEI"); + return false; + } + + return (sum % 10 == 0); +} + +void check_for_update(){ + + if(g_ConfigUpdate==true){ + + // get the data from server + //transition(); + comms.poll_timer=true; /* just for a test*/ + transition(COMMS_STATE_GOING_IDLE); /* just for a test*/ + } + else if(g_McuUpdate==true){ + + // that mean we should check for program update + //transition(); + comms.poll_timer=true; /* just for a test*/ + transition(COMMS_STATE_WAIT_HTTP_SEND_SP5); /* just for a test*/ + } + else if(g_ModemUpdate==true){ + // that mean we need to update the modem software. + comms.poll_timer=true; + transition(COMMS_STATE_WAIT_HTTP_SEND_SP6); + } + else + { + comms.poll_timer=true; + transition(COMMS_STATE_GOING_IDLE); + + } +} + +/* function for parsing SP5 message */ +// format example +/*SP5 IMEI epoch T FW_V EP */ +/* | | | | | */ +/* | | | | | */ +/*SP5 866349048889004 1676395843 FW_2002 EP */ +static void Comms_Parse_SP5(char *buf, int len) +{ + char messageheader[4] = {0}; /*ex: SPx*/ + char messageIMEI[15] = {0}; + // char messageIMEI[] = "866349048890473";/*//hard coded IMEI*/ + char epochTime[30] = {0}; + char firmware_version[10] = {0}; + char *strret = NULL; + uint32_t new_fw_version = 0; + char epcheck[2] = {0}; + int ret_sp5 = COMMS_STATUS_ERROR; + + /**********************************************************************************************************/ + /*SP5*/ + strret = strtok(buf, " "); + strcpy(messageheader, strret); + ESP_LOGI(TAG,"%s message is received",messageheader); + + /**********************************************************************************************************/ + /*IMEI*/ + strret = strtok (NULL," "); + strcpy(messageIMEI, strret); + ret_sp5 = imei_check_valid(messageIMEI); + if(ret_sp5 != false){ + //ok IMEI + ESP_LOGI(TAG,"Fetched IMEI matches board"); + } + else{ + ESP_LOGW(TAG,"INVALID IMEI"); + comms.poll_timer = true; + transition(COMMS_STATE_GOING_IDLE); + return; + //return ret_sp5; + } + + /**********************************************************************************************************/ + /*epoch time*/ + strret = strtok (NULL," "); + strcpy(epochTime, strret); + ESP_LOGI(TAG,"epoch Time : %s",epochTime); + + /**********************************************************************************************************/ + /*new FW version*/ + strret = strtok(NULL, "FW_"); + strcpy(firmware_version,strret); + new_fw_version = (uint32_t)atoi(firmware_version); + ESP_LOGI(TAG,"Firmware version from SP5: %ld",new_fw_version); //logging/printing FR_version message for tracing + ESP_LOGI(TAG,"Board Firmware version: %ld",g_version); + + /**********************************************************************************************************/ + /*EP*/ + /* strret = strtok (NULL," "); + strcpy(epcheck, strret); + if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){ + ESP_LOGI(TAG,"(%s) %s message is terminated", epcheck,messageheader); + } + else{ + ESP_LOGI(TAG,"(%s) %s message is not terminated!!", epcheck,messageheader); + }*/ + + /**********************************************************************************************************/ + /*check if the new version is greater than current version*/ + if(!(new_fw_version > g_version)) + { + ESP_LOGI(TAG,"MCU F/W UP TO DATE"); + /*if its not check if modem update needed*/ + /*read ModemFlag*/ + if(g_ModemUpdate == true) + { + ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP6"); + comms.poll_timer = true; + transition(COMMS_STATE_WAIT_HTTP_SEND_SP6); + } + else { + /* */ + comms.poll_timer = true; + transition(COMMS_STATE_GOING_IDLE); + } + } + else + { + /*Logging/printing this message*/ + ESP_LOGI(TAG,"F/W Update NEEDED"); + ESP_LOGI(TAG,"GET MCU UPDATE"); + comms.poll_timer = true; + transition(COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE); + /*reading OTA files*/ + } +} + + + +/* function for parsing SP6 message */ +// format example +/*SP6 IMEI epoch T FW_V EP */ +/* | | | | | */ +/* | | | | | */ +/*SP6 866349048889004 1676395909 BG77LAR02A04_01.009.01.009 EP */ +static void Comms_Parse_SP6(char *buf, int len) +{ + char messageheader[4] = {'0'}; /*ex: SPx*/ + char messageIMEI[15] = {'0'}; +// char messageIMEI[] = "866349048890473";/*//hard coded IMEI*/ + char epochTime[30] = {'0'}; + char modem_sp6_fwv[50] = {'0'}; + int ret_sp6 = COMMS_STATUS_ERROR; + char* strret = NULL; + char epcheck[2] = {0}; + + /**********************************************************************************************************/ + /*SP6*/ + strret = strtok(buf, " "); + strcpy(messageheader, strret); + ESP_LOGI(TAG,"%s message is received",messageheader); + + /**********************************************************************************************************/ + /*IMEI*/ + strret = strtok (NULL," "); + strcpy(messageIMEI, strret); + ret_sp6 = imei_check_valid(messageIMEI); + if(ret_sp6 != false){ + //ok IMEI + ESP_LOGI(TAG,"Fetched IMEI matches board"); + } + else{ + ESP_LOGW(TAG,"INVALID IMEI!!"); + comms.poll_timer = true; + transition(COMMS_STATE_GOING_IDLE); + return; + } + + /**********************************************************************************************************/ + /*epoch Time*/ + strret = strtok (NULL," "); + strcpy(epochTime, strret); + ESP_LOGI(TAG,"epoch Time : %s",epochTime); + + /**********************************************************************************************************/ + /*modem version from SP6 */ + strret = strtok (NULL," "); + strcpy(modem_sp6_fwv, strret); + ESP_LOGI(TAG,"Board modem firmware version: %s",modem_get_fw_ver()); + ESP_LOGI(TAG,"Modem firmware version from SP6: %s",modem_sp6_fwv); + + /**********************************************************************************************************/ + /*EP*/ + strret = strtok (NULL," "); + strcpy(epcheck, strret); + if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){ + ESP_LOGI(TAG,"(%s) %s message is terminated",epcheck,messageheader); + } + else{ + ESP_LOGI(TAG,"(%s) %s message is not terminated!!",epcheck,messageheader); + + } + + /**********************************************************************************************************/ + /*Case: + + str1 SP6 fw: BG77LAR02A04_01.009.01.009 + str2 fw: BG77LAR02A04_01.008.01.008 + + 9 is the first non-matching character in str1 greater + than that of str2. return > 0(update needed) + + + str1 SP6 fw: BG77LAR02A04_01.008.01.008 + str2 fw: BG77LAR02A04_01.009.01.009 + + '9' is the first non-matching character in str1 lower + than that of str2. return < 0 + + */ + if(strcmp(modem_sp6_fwv,modem_get_fw_ver()) <= 0) + { + + /*If the existing version is the same go to idle*/ + comms.poll_timer = true; + ESP_LOGI(TAG,"No update need GOING TO IDLE FROM SP6"); + transition(COMMS_STATE_GOING_IDLE); + + } + else + { + /*Logging/printing this message*/ + ESP_LOGI(TAG,"F/W Modem Update NEEDED"); + ESP_LOGI(TAG,"GET MODEM UPDATE"); + comms.poll_timer = true; + transition(COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE); + } +} + + +esp_err_t comms_http_request(comms_switch_cb cb,comms_state_t init_state, const char* msg, comms_state_t success_state,const char* url1,const char* url2,const char* url3){ + esp_err_t retval = ESP_FAIL; + int32_t val=data_get_postToServer(); + switch(val){ + + case TEMPSTICK_SERVER1: + + /* make the get/post request to server 1. */ + //ESP_LOGI(TAG,"get/post request to server 1........... "); + retval = cb(init_state, url1,msg, success_state); + + break; + case TEMPSTICK_SERVER2: + + /* make the get/post request to server 2. */ + //ESP_LOGI(TAG,"get/post request to server 2........... "); + retval = cb(init_state, url2, msg, success_state); + break; + + case TEMPSTICK_SERVER3: + + /* make the get/post request to server 3. */ + //ESP_LOGI(TAG,"get/post request to server 3........... "); + retval = cb(init_state, url3,msg, success_state); + break; + + default: + data_set_postToServer(TEMPSTICK_SERVER1); + ESP_LOGI(TAG,"connection to server %ld failed ",data_get_postToServer()); + ESP_LOGI(TAG,"connect to the default server "); + comms.poll_timer=true; + transition(init_state); + break; +} + + return retval; +} + +/* ------------------------------------------------------------------------- */ + +/*Handler for COMMS timer*/ +static void timer_handler(void* context) +{ + comms.poll_timer = true; +} + +static int state_machine(comms_event_t evt) +{ + int retval = COMMS_STATUS_OK; + switch (comms.state) + { + case COMMS_STATE_INIT: + if (evt == COMMS_EVENT_START) + { + /* Set the number of check-in cycles to do and reset the checkin_cycle_counter */ + number_of_check_in_to_do = nvm_get_last_written_history_sector() - nvm_get_last_posted_history_sector(); + checkin_cycle_counter = 0; + + ESP_LOGI(TAG,"---------> Number of check-in cycles to do is %d",number_of_check_in_to_do); + + /* Reset the backup flag */ + comms_do_wifi_backup = false; + comms_do_cell_backup = false; + + /* Status is ERROR until cleared by successful completion. */ + comms.last_cycle_status = COMMS_STATUS_ERROR; + + /*This must be changed to true inside modem_start_cb to transfer to the next state*/ + comms.poll_timer = false; + + if (modem_is_started()) + { + modem_start_cb(MODEM_STATUS_OK); + } + else + { + /* start the bg96 process */ + retval = modem_start(modem_start_cb); + if (retval == MODEM_STATUS_OK) + { + comms.is_starting = true; + ESP_LOGI(TAG,"Process starting.\n"); + transition(COMMS_STATE_WAIT_MODEM); + } + } + } + break; + case COMMS_STATE_WAIT_MODEM: + + /* Wait for BG96 startup event */ + if (evt == COMMS_EVENT_TIMER) + { +#if (FAKE_NETWORK == 1) + data_parse_http_response(server_resp); + comms.poll_timer = true; + comms.last_cycle_status = COMMS_STATUS_OK; + transition(COMMS_STATE_GOING_IDLE); +#else + + /* Start the LED-event of connecting to network */ + if(!comms_do_cell_backup) + { + hmi_set_leds_state(BLUE_LED_FLASHING); //connecting to LTE network + } + + /* Check if need to do check-in over WIFI */ + if((COMMS_OVER_CELL != comms_mode) && (COMMS_OVER_CELL_WIFI_BACKUP != comms_mode) && (!comms_do_cell_backup)) + { + comms.poll_timer = true; + + transition(COMMS_STATE_WIFI_CONNECT); + break; + } + + if(comms_do_cell_backup) + comms_do_cell_backup = false; + + /* modem is started. connect to network */ + retval = modem_network_connect(net_connect_cb); + if (retval == MODEM_STATUS_OK) + { + /* Set the communication_medium flag to be CELL */ + comms_medium = COMMS_MEDIUM_CELL; + + ESP_LOGI(TAG,"LTE Connecting to Cellular network\r\n"); + transition(COMMS_STATE_WAIT_NET_CONNECT); + } +#endif + } + + break; + + case COMMS_STATE_WAIT_NET_CONNECT: + + /* Wait for BG96 network connect event */ + if (evt == COMMS_EVENT_TIMER) + { + ESP_LOGI(TAG,"Network connected\r\n"); + + comms.httpRetryCnt = HTTP_RETRY_COUNT_MAX; + + /* Network connected */ + comms.poll_timer = true; + comms.last_cycle_status = COMMS_STATUS_OK; + comms.httpRetryCnt = HTTP_POST_RETRY_MAX; //Setting the number of http_post retries + transition(COMMS_STATE_WAIT_HTTP_POST_REQ); + } + break; + + case COMMS_STATE_WIFI_CONNECT: + if(evt == COMMS_EVENT_TIMER) + { + /* Set the communication_medium flag to be WIFI */ + comms_medium = COMMS_MEDIUM_WIFI; + + /* Initialize the wifi */ + retval = wifi_first_init(); + + /* If the initialization retval is OK then continue to connect to the registered WIFI access-point */ + if(retval == WIFI_OK) + { + /* Connect to the registered WIFI access-point */ + retval = Connect_wifi_sta(WIFI_CLIENT_MODE); + + /* if the connection retval is OK then jump to the "WIFI_POST_REQ" state */ + if(retval == WIFI_OK) + { + /* Do a transition to "WIFI_POST_REQ" */ + transition(COMMS_STATE_WIFI_POST_REQ); + } + else + { + /* Print this Log */ + ESP_LOGI(TAG,"Failed to connect to the WIFI access-point"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do cellular backup for the check-in process */ + if(COMMS_OVER_WIFI_CELL_BACKUP) + { + comms_do_cell_backup = true; + } + + /* Do a transition to "GOING_IDLE" state */ + transition(COMMS_STATE_GOING_IDLE); + } + } + else + { + /* Print this Log */ + ESP_LOGI(TAG,"Failed to initialize the WIFI"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do cellular backup for the check-in process */ + if(COMMS_OVER_WIFI_CELL_BACKUP) + { + comms_do_cell_backup = true; + } + + /* Do a transition to "GOING_IDLE" state */ + transition(COMMS_STATE_GOING_IDLE); + } + + /* Set poll_timer to true to allow executing whatever next state */ + comms.poll_timer = true; + } + + break; + + case COMMS_STATE_WIFI_POST_REQ: + if(evt == COMMS_EVENT_TIMER) + { + /* Get the address of the receiving buffer */ + char *buf = modem_get_rxbuf(); + + /* Do WIFI post-request for the CHECK_IN message + * (Creating the check-in string is done internally inside this function) + * (Also, Switching between the 3-servers are done inside this function) */ + retval = http_client_do_post_request(jsonMessage,buf); + + /* check whether POST-Req was successful and managed to receive/parse server-response or not*/ + if(retval == WIFI_OK) + { + /* Update the number of already done check-ins */ + checkin_cycle_counter++; + + /* Clear history array (So that its current readings don't affect the readings of the next sector) + * Just clear the array (don't clear anything from NVS) */ + data_clear_history(); + + /* Check if this was the last check-in to do (in other words, check if there are no more previous readings to send to server) */ + if(checkin_cycle_counter == number_of_check_in_to_do) + { + /* Close the connection of http-post */ + http_client_post_stop(); + + /* Reset the last post sector in the NVS partition to 0*/ + nvm_set_last_posted_history_sector(0); + + /* Clear History sectors + * Clear from NVS Partition */ + nvm_clear_history_sector(NVM_HISTORY_ALL_SECTORS); + + + /* Print the POST server response */ + ESP_LOGI(TAG,"HTTP-POST response is :\n%s\n",buf); + + /* Parse the server-response */ + data_parse_http_response((const char*)buf); + + /* Reset the posting_failed to be false */ + comms_posting_failed = false; + + /* Don't do cellular backup */ + comms_do_cell_backup = false; + + /* Do a transition to "WIFI_GET_REQ" state */ + transition(COMMS_STATE_WIFI_GET_REQ); + } + else + { + /* Coming here means that there were some previous readings that are stored in NVS and need to posted in multiple check-in cycles + * and we already posted the readings in history_sector x ----> so we need to update the last_posted_sector flag */ + + /* Update the last post sector in the NVS partition */ + uint8_t x = nvm_get_last_posted_history_sector()+1; + nvm_set_last_posted_history_sector(x); + + /* Wait some time before doing the next check-in of the remaining previous readings */ + vTaskDelay(2000/portTICK_PERIOD_MS); + } + } + else + { + /* Close the connection of http-post */ + http_client_post_stop(); + + /* Print this Log */ + ESP_LOGI(TAG,"Failed to do WIFI POST-Request"); + + /* Set the posting_failed to be true */ + comms_posting_failed = true; + + /* Do cellular backup for the check-in process */ + if(COMMS_OVER_WIFI_CELL_BACKUP) + { + comms_do_cell_backup = true; + } + + /* Do a transition to "GOING_IDLE" state */ + transition(COMMS_STATE_GOING_IDLE); + } + + /* Set poll_timer to true to allow executing whatever next state */ + comms.poll_timer = true; + } + + break; + + case COMMS_STATE_WIFI_GET_REQ: + if(evt == COMMS_EVENT_TIMER) + { + /* Get the address of the receiving buffer */ + char *buf = modem_get_rxbuf(); + + /* Do WIFI get-request for the SP messages + * Parsing SP5 message and checking the firmware version is done internally inside this function + * (Also, Starting WIFI-OTA session is done internally inside this function) + * (Also, Switching between the 3-servers are done inside this function) + * (Also, Parsing the server-response -if get request succeeded- is done internally inside this function */ + retval = http_client_do_get_request(GET_CONFIGURATIONS,(char*)modem_get_imei(),buf); + + /* check whether GET-Req was successful and managed to receive/parse server-response or not*/ + if(retval != WIFI_OK) + { + /* Print this Log */ + ESP_LOGI(TAG,"Failed to do GET-Request"); + } + + /* Set poll_timer to true to allow executing whatever next state */ + comms.poll_timer = true; + + /* Do a transition to "GOING_IDLE" state */ + transition(COMMS_STATE_GOING_IDLE); + } + + break; + + case COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS: + + /* Wait for BG96 HTTP setup event */ + if (evt == COMMS_EVENT_TIMER) + { + + retval= comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS,"configuration flags",COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS,MCU_GET_CONFIG_FLAGS_URL1,MCU_GET_CONFIG_FLAGS_URL2,MCU_GET_CONFIG_FLAGS_URL3); + + } + break; + + case COMMS_STATE_WAIT_HTTP_GET_CONFIG_FLAGS: + + /* Wait for BG96 HTTP GET config event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Get the buffer and process the configuration. */ + int len = 0; + char* buf = 0; + retval = modem_http_get_buf(&buf, &len); + if (retval == MODEM_STATUS_OK) + { + ESP_LOGI(TAG,"CONFIG BUF :\n%s\n",buf); + + /// Parsing config ........ + retval = data_parsing_config(buf,len); + if(!retval){ + //if parsing success check update flags g_ConfigUpdate, g_McuUpdate, g_ModemUpdate. + ESP_LOGI(TAG,"config Parsing success"); + check_for_update(); + } + else + { + ESP_LOGI(TAG,"config Parsing Failed"); + } + } + else{ + ESP_LOGI(TAG,"Modem get buff Failed (GET_CONFIG_FLAGS state)"); + comms.poll_timer= true; + transition(COMMS_STATE_GOING_IDLE); + } + } + + break; + + case COMMS_STATE_WAIT_HTTP_POST_REQ: + if(evt == COMMS_EVENT_TIMER) + { +//suceesUrl = 1 + data_create_checkin_string(jsonMessage, sizeof(jsonMessage)); + + retval=comms_http_request(start_http_post_request,COMMS_STATE_WAIT_HTTP_POST_REQ,jsonMessage,COMMS_STATE_WAIT_HTTP_POST_RES,MCU_POST_URL1,MCU_POST_URL2,MCU_POST_URL3); + + } + + break; + + case COMMS_STATE_WAIT_HTTP_POST_RES: + + /* Wait for BG96 HTTP GET config event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Get the buffer and process the configuration. */ + int len = 0; + char* buf = 0; + retval = modem_http_get_buf(&buf, &len); + if (retval == MODEM_STATUS_OK) + { + + ESP_LOGI(TAG,"HTTP-POST response is :\n%s\n",buf); + data_parse_http_response((const char *)buf); + + + //comms_update_onboarding_status(); + if(NVM_ONBOARDING_NOT_SET_VAL != nvm_read_onboarding_flag(CELL_ONBOARDING_KEY)) + { + nvm_write_onboarding_flag(CELL_ONBOARDING_KEY,NVM_ONBOARDING_SET_VAL); + } + + comms.poll_timer= true; + transition(COMMS_STATE_WAIT_HTTP_SEND_CONFIG_FLAGS); + } + else{ + comms.poll_timer= true; + transition(COMMS_STATE_GOING_IDLE); + } + } + + break; + + case COMMS_STATE_WAIT_HTTP_SEND_SP5: + + /* Wait for comms timer event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Now make the GET request. */ + retval = comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_SP5,"McuUpdate",COMMS_STATE_WAIT_HTTP_GET_SP5,MCU_FW_VERSION_URL1,MCU_FW_VERSION_URL2,MCU_FW_VERSION_URL3); + + } + break; + + case COMMS_STATE_WAIT_HTTP_GET_SP5: + + /* Wait for BG96 HTTP GET config event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Get the buffer and process the configuration. */ + int len = 0; + char* buf = 0; + retval = modem_http_get_buf(&buf, &len); + if (retval == MODEM_STATUS_OK) + { + + ESP_LOGI(TAG,"SP5 BUF: %s",buf); + + //SP5 parsing... + Comms_Parse_SP5(buf, len); + } + else + { + ESP_LOGI(TAG,"SP5 Parsing Failed"); + comms.poll_timer = true; + transition(COMMS_STATE_GOING_IDLE); + } + } + break; + + + case COMMS_STATE_WAIT_HTTP_SEND_SP6: + + /* Wait for comms timer event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Now make the GET request. */ + retval = comms_http_request(start_http_get_request,COMMS_STATE_WAIT_HTTP_SEND_SP6,"ModemUpdate",COMMS_STATE_WAIT_HTTP_GET_SP6,MODEM_FW_VERSION_URL1,MODEM_FW_VERSION_URL2,MODEM_FW_VERSION_URL3); + + } + break; + + case COMMS_STATE_WAIT_HTTP_GET_SP6: + + /* Wait for BG96 HTTP GET config event */ + if (evt == COMMS_EVENT_TIMER) + { + /* Get the buffer and process the configuration. */ + int len = 0; + char* buf = 0; + retval = modem_http_get_buf(&buf, &len); + if (retval == MODEM_STATUS_OK) + { + + ESP_LOGI(TAG,"SP6 BUF: %s",buf); + + //SP6 parsing... + Comms_Parse_SP6(buf, len); + } + else + { + ESP_LOGI(TAG,"SP6 Parsing Failed"); + comms.poll_timer = true; + transition(COMMS_STATE_GOING_IDLE); + } + } + break; + + case COMMS_STATE_WAIT_HTTP_GET_MODEM_UPDATE: + + /* Wait for BG96 HTTP GET modem update event */ + if (evt == COMMS_EVENT_TIMER) + { + comms.get_modem_update = false; + /* Get the buffer and process the configuration. */ + int len = 0; + char* buf = 0; + retval = modem_http_get_buf(&buf, &len); + if (retval == MODEM_STATUS_OK) + { + // if (COMMS_STATUS_OK == check_modem_update(buf, len)) + { + /* Different firmware on server. Use it. */ + /* Setup URL */ + memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); + + + switch(data_get_postToServer()){ + + case TEMPSTICK_SERVER1: + + /* make the POST request to server 1. */ + ESP_LOGI(TAG,"Get Modem bin file from server 1"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL1, modem_get_imei()); + + break; + case TEMPSTICK_SERVER2: + + /* make the POST request to server 2. */ + ESP_LOGI(TAG,"Get Modem bin file from server 2"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL2, modem_get_imei()); + break; + + case TEMPSTICK_SERVER3: + + /* make the POST request to server 3. */ + ESP_LOGI(TAG,"Get Modem bin file from server 3"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MODEM_FW_BIN_FILE_URL3, modem_get_imei()); + break; + + } + + + /* Download the GET data to modem */ + int retval = modem_update_modem(fotadl_op_cb, comms.mqtt_buf); + if (retval == MODEM_STATUS_OK) + { + hmi_set_leds_state(BLUE_LED_FLASHING_OTA); + ESP_LOGI(TAG,"FOTADL started\r\n"); + transition(COMMS_STATE_WAIT_MODEM_UPDATE); + break; + } + else + { + ESP_LOGE(TAG,"FOTADL failed to start\r\n"); + /* Continue with session */ + } + } + } + } + break; + + case COMMS_STATE_WAIT_MODEM_UPDATE: + + /* Wait for modem update callback. */ + if (evt == COMMS_EVENT_TIMER) + { + /* In either case, stop the comm process. We want to connect again to do the uplink, + * and we can do that by returning "UPDATED" status, allowing main + * to schedule another connection attempt right away - if desired. + */ + comms.last_cycle_status = COMMS_STATUS_UPDATED; + comms.poll_timer = true; /* request state machine to be polled again right away in new state */ + hmi_stop_ota_event(); + transition(COMMS_STATE_GOING_IDLE); + } + break; + + case COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE: + + /* Set http_init_state to COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE */ + comms.http_init_state = COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE; + + /* Wait for BG96 HTTP GET MCU update event */ + //if (evt == COMMS_EVENT_TIMER) + { + comms.get_mcu_update = false; + /* Get the buffer and process the MCU fw version message. */ + //int len = 0; + //char* buf = 0; + //retval = modem_http_get_buf(&buf, &len); + //if (retval == MODEM_STATUS_OK) + { + //if (COMMS_STATUS_OK == check_mcu_update(buf, len)) + { + /* Different firmware on server. Use it. */ + /* Setup URL: + * Need to download either upper or lower version of the application, + * depending on what we're running now. (i.e. if we are the lower app, need + * to get the upper app) + */ + memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf)); + +#if ST_OTA_HIGHER_APPLICATION +//// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_LOWER, modem_get_imei()); +#elif ST_OTA_LOWER_APPLICATION +// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_HIGHER, modem_get_imei()); +#else +//// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1_LOWER, modem_get_imei()); +#endif + /*Creating file path and store it in comms.mqtt_buf*/ +// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1, modem_get_imei()); + + switch(data_get_postToServer()){ + + case TEMPSTICK_SERVER1: + + /* make the get request to server 1. */ + ESP_LOGI(TAG,"Get MCU bin file from server 1"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL1, modem_get_imei()); + break; + + case TEMPSTICK_SERVER2: + + /* make the get request to server 2. */ + ESP_LOGI(TAG,"Get MCU bin file from server 2"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL2, modem_get_imei()); + break; + + case TEMPSTICK_SERVER3: + + /* make the get request to server 3. */ + ESP_LOGI(TAG,"Get MCU bin file from server 3"); + snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_FW_BIN_FILE_URL3, modem_get_imei()); + break; + + } + + + + /* Download the file data to modem file system */ + int retval = modem_http_get_to_file(fwdl_op_cb, comms.mqtt_buf, MCU_OTA_FILE_LOCAL); + + if (retval == MODEM_STATUS_OK) + { + ESP_LOGI(TAG,"MCU FW download started\r\n"); + ///hmi_set_offload_mode(false); + transition(COMMS_STATE_WAIT_HTTP_GET_MCU_FILE); + //hmi_set_update_mode(true); + break; + } + else + { + ESP_LOGE(TAG,"MCU FW download failed to start\r\n"); + /* Continue with session */ + } + } + } + } + + break; + + case COMMS_STATE_WAIT_HTTP_GET_MCU_FILE: + + /* Wait for download complete callback. */ + if (evt == COMMS_EVENT_TIMER) + { + if (comms.last_op_success) + { + /* Download is ready. Now we can start the read from file operation on the bg96 driver + * and use the callbacks to drive the update. The bg96 process is driving the update. + */ + retval = modem_read_from_file( + fwupd_op_cb, /* called when completed or failed at any point */ + MCU_OTA_FILE_LOCAL, + ota_file_open_cb, /* Can fail and continue the comms state machine */ + ota_file_data_cb); /* Callback for the file data in chunks */ + + if (retval == MODEM_STATUS_OK) + { + hmi_set_leds_state(BLUE_LED_FLASHING_OTA); + ESP_LOGI(TAG,"MCU FW update started\r\n"); + transition(COMMS_STATE_WAIT_MCU_UPDATE); + break; + } + else + { + ESP_LOGE(TAG,"MCU FW update failed to start\r\n"); + /* Continue with session */ + //hmi_set_update_mode(false); + } + } + } + break; + + case COMMS_STATE_WAIT_MCU_UPDATE: + + /* Wait while updating. */ + if (evt == COMMS_EVENT_TIMER) + { + if (comms.last_op_success) + { + /* If it completes, it will ping this and here and we finish it up. + * OTA_terminate_connection sets the flag that is handled in OTA_Tick() + * and main to do a reset to start the new application after comm completes. + */ + ESP_LOGD(TAG,"Ending OTA session, ready for reset\r\n"); + + ota_finish_processing(); + + /* Clear this, in case we have just turned on and have updated - + * no need to trigger the startup callback in main. + */ + comms.is_starting = false; + } + } + break; + + case COMMS_STATE_GOING_IDLE: + + /* Check if we can use WIFI as backup technique for check-in */ + if((COMMS_OVER_CELL_WIFI_BACKUP == comms_mode) && (comms_do_wifi_backup)) + { + /* Print this log */ + ESP_LOGI(TAG,"Doing WIFI-BACKUP for CHECK-IN process."); + + /* Transfer the control state to "WIFI_CONNECT" */ + transition(COMMS_STATE_WIFI_CONNECT); + + /* Set the comms.poll_timer to be true */ + comms.poll_timer = true; + + /* Reset the wifi-backup flag */ + comms_do_wifi_backup = false; + + /* Break from the state-machine */ + break; + } + else if((COMMS_OVER_WIFI_CELL_BACKUP == comms_mode) && (comms_do_cell_backup)) + { + /* Print this log */ + ESP_LOGI(TAG,"Doing CELL-BACKUP for CHECK-IN process."); + + /* Transfer the control state to "WAIT_MODEM" */ + transition(COMMS_STATE_WAIT_MODEM); + + /* Set the comms.poll_timer to be true */ + comms.poll_timer = true; + + /* Reset the cell-backup flag */ + //comms_do_cell_backup = false; + + /* Break from the state-machine */ + break; + } + + ESP_LOGI(TAG,"Process going idle.\n"); + + /* Reset the backup flag */ + comms_do_wifi_backup = false; + comms_do_cell_backup = false; + +#if (FAKE_NETWORK == 1) + comms_update_onboarding_status(); +#endif + + /* Stop BLUE_LED_FLASHING if it's still running*/ + hmi_stop_continued_led_state(BLUE_LED_FLASHING); //stop BLUE_LED_FLASHING event + + + /* Check if MCU failed to post the check-in message to the tempstick-server */ + if(comms_posting_failed) + { + /* Print this log */ + ESP_LOGI(TAG," -----> Posting the check-in message failed.\n Storing sensor data to NVS to be published in the next successful CHECK-IN process "); + + /**/ + // put your code here to store sensor data to NVS + data_save_history(); + + /* Reset the comms_posting_failed flag */ + comms_posting_failed = false; + } + + /*===========================================*/ + /* Make sure that wifi is turned-off*/ + if(wifi_isStarted()) + { + retval = wifi_stop(); + } + + /* Make sure that modem is turned-off*/ + if(modem_is_started()) + { + retval = modem_stop(); + } + /*===========================================*/ + transition(COMMS_STATE_WAIT_MODEM_OFF); + comms.poll_timer = true; + + break; + + case COMMS_STATE_IDLE: + if (evt == COMMS_EVENT_CONNECT) + { + /* Set the number of check-in cycles to do and reset the checkin_cycle_counter */ + number_of_check_in_to_do = nvm_get_last_written_history_sector() - nvm_get_last_posted_history_sector(); + checkin_cycle_counter = 0; + + ESP_LOGI(TAG, "Inside comms IDLE state \r\n"); + + /* Status is ERROR until cleared by successful completion. */ + comms.last_cycle_status = COMMS_STATUS_ERROR; + + if (modem_is_ready()) + { + modem_start_cb(MODEM_STATUS_OK); + } + else if(!modem_is_started()) + { + /* start the bg77 process */ + retval = modem_start(modem_start_cb); + + if (retval == MODEM_STATUS_OK) + { + ESP_LOGI(TAG,"Waiting for Modem.\n"); + transition(COMMS_STATE_WAIT_MODEM); + } + } + else + { + ESP_LOGI(TAG, "Modem is busy. Comm cycle aborted.\r\n"); + } + } + break; + + case COMMS_STATE_WAIT: + check_in_attempts_count(comms.httpRetryCnt,HTTP_RETRY_COUNT_MAX); + esp_timer_stop(comms_timer); + comms.poll_timer = true; + transition(comms.http_init_state); + ESP_LOGI(TAG,"Number of remaining HTTP retry is : %d\n", comms.httpRetryCnt); + break; + + case COMMS_STATE_WAIT_MODEM_OFF: + if(!modem_is_started()) + { + /* transition to INIT state only if not started. */ + transition(COMMS_STATE_IDLE); + + /* Invoke callback if supplied.*/ + if(comms.connect_cb) + { + comms.connect_cb(comms.last_cycle_status); + comms.connect_cb = 0; + } + } + else + { + //ESP_LOGW(TAG,"Modem is busy.\r\n"); + comms.poll_timer = true; + } + break; + + default: + break; + } + + return retval; +} + +/* ------------------------------------------------------------------------- */ + + + /* Initialize. */ +int comms_init(void) +{ + int retval = COMMS_STATUS_OK; + + memset(&comms, 0, sizeof(comms)); + comms.overflow_check = 0xFF; + + /*Initializing the COMMS_TIMER */ + const esp_timer_create_args_t comms_timer_args = { + .callback = &timer_handler, + /* argument specified here will be passed to timer callback function */ + .arg = (void*) comms_timer, + .name = "comms-timer" + }; + esp_timer_create(&comms_timer_args, &comms_timer); + + comms.poll_timer = false; + + ESP_LOGI(TAG,"Process initialized.\n"); + + return retval; +} + +/* Start the process */ +int comms_start(comms_op_cb_t start_cb, comms_op_cb_t connect_cb) +{ + comms.start_cb = start_cb; + comms.connect_cb = connect_cb; + int retval = state_machine(COMMS_EVENT_START); + return retval; +} + +/* Stop the process */ +int comms_stop(void) +{ + int retval = state_machine(COMMS_EVENT_STOP); + return retval; +} + +/* Poll the process */ +int comms_poll(void) +{ + int retval = COMMS_STATUS_OK; + if (comms.poll_timer) + { + comms.poll_timer = false; + retval = state_machine(COMMS_EVENT_TIMER); + } + else if (0 /* */) + { + } + + return retval; +} + +int comms_connect(comms_op_cb_t cb) +{ + comms.connect_cb = cb; + int retval = state_machine(COMMS_EVENT_CONNECT); + return retval; +} + +/* Check if the process needs to be polled */ +bool comms_needs_poll(void) +{ + return + comms.poll_timer; +} + + +/* Check if the process is started */ +bool comms_is_started(void) +{ + return comms.state != COMMS_STATE_INIT; +} + +bool comms_is_idle(void) +{ + return comms.state == COMMS_STATE_IDLE; +} + +int comms_get_status(void) +{ + return comms.last_cycle_status; +} + +/* ------ Process Callbacks ------------------------- */ + +__attribute__((weak)) void comms_ready_cb(void) { } + + + + diff --git a/main/comms.h b/main/comms.h index 9ab89b1..728cd51 100644 --- a/main/comms.h +++ b/main/comms.h @@ -1,283 +1,283 @@ -/* - * comms.h - * - * Created on: Jan 16, 2023 - * Author: Sword - */ - -#ifndef MAIN_COMMS_H_ -#define MAIN_COMMS_H_ - - -#include -#include -#include "sdkconfig.h" -#include "main.h" -/* comms.h - * - * Copyright 2020 HAE Innovations - * - * Celluar Communications process manager. - * - * Handles communication to/from server over cell modem, - * collecting and sending events from queue, processing configuration - * and firmware updates from server, etc. - * - * Author: E. Ross - */ - -#define COMMS_STATUS_UPDATED 1 -#define COMMS_STATUS_OK 0 -#define COMMS_STATUS_ERROR -1 - - -#define MCU_BASE_URL1 "https://testdevice.tempstickapi.com" -#define MCU_BASE_URL2 "https://testdevice.tempstickapi.com" -#define MCU_BASE_URL3 "https://testdevice.tempstickapi.com" -#define MCU_BASE_URL4 "http://testdevice.tempstickapi.com" - - -#define MCU_ONBOARDING_URL "https://device-status.idealsciences%u.com" -#define POSTING_ONBOARDING "POST /sensor-account.php HTTP/1.0" -#define ON_BOARDING_SERVER_DOMAIN_NAME "device-status.idealsciences.com" -#define USER_AGENT_ONBOARDING "SensorDHT/1.0" -#define AUTHERIZATION_VALUE_ONBOARDING "Basic ZGV2OmRldjEyMw==" -#define CONTENT_TYPE_VALUE_ONBOARDING "application/x-www-form-urlencoded" -#define ONBOARDING_SERVER_POSTURL_MAX 3 -#define ONBOARDING_SERVER_POSTURL_MIN 1 - - -#define PARTHA_SERVER_BASE_URL "https://www.parthasarathimishra.com" -#define TESTING_SERVER_BASE_URL "http://3.90.70.38:8080" - - -typedef enum -{ - COMMS_OVER_CELL_WIFI_BACKUP = 1, - COMMS_OVER_WIFI_CELL_BACKUP, - COMMS_OVER_CELL, - COMMS_OVER_WIFI, - COMMS_MODE_5 //wifi as default for all readings /cellular for alerts /wifi back up for alerts -}comms_type_t; - -typedef enum -{ - COMMS_MEDIUM_CELL, - COMMS_MEDIUM_WIFI, -}comms_medium_t; - -#if (TEMPSTICK_SERVER == 1) - - -/*HTTP POST header component for tempstick server*/ -#define END_POINT_POSTING1 "POST / HTTP/1.1\r\n" -#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" -#define AUTHERIZATION_VALUE "Bearer 19730e88-886d-4c94-89d6-3066b79b7630" -#define END_POINT_HOST "Host: testdevice.tempstickapi.com\r\n" -#define HOST_VALUE "testdevice.tempstickapi.com" -#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" -#define USER_AGENT_VALUE "\"SensorDHT\\/1.0\"" -#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" -#define CONTENT_TYPE_VALUE "application/json" -#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" - -#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN - - -// URL to post on servers 1, 2, and 3 -#define MCU_POST_URL1 MCU_BASE_URL1 -#define MCU_POST_URL2 MCU_BASE_URL2 -#define MCU_POST_URL3 MCU_BASE_URL3 - -//URL to get configuration flags from servers 1, 2, and 3 -#define MCU_GET_CONFIG_FLAGS_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 -#define MCU_GET_CONFIG_FLAGS_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 -#define MCU_GET_CONFIG_FLAGS_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 - -/* this endpoint not implemented yet in the code (customer pending) */ -// if the config_update flag is set -// URL to get settings from servers 1, 2, and 3 -#define MCU_GET_SETTINGS_URL1 TESTING_SERVER_BASE_URL//settings/server1 -#define MCU_GET_SETTINGS_URL2 TESTING_SERVER_BASE_URL//settings/server2 -#define MCU_GET_SETTINGS_URL3 TESTING_SERVER_BASE_URL//settings/server3 - -//URL to get MCU FW version from servers 1, 2, and 3 -#define MCU_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ -#define MCU_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 -#define MCU_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 - -//URL to get MCU FW bin file from servers 1, 2, and 3 -#define MCU_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 -#define MCU_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 -#define MCU_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 - -//URL to get MODEM FW version from servers 1, 2, and 3 -#define MODEM_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 -#define MODEM_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 -#define MODEM_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 - -//URL to get MODEM FW bin file from servers 1, 2, and 3 -#define MODEM_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 -#define MODEM_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 -#define MODEM_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 - - -#else - -#if (TESTING_SERVER==1) - -/*HTTP POST header component for Partha server*/ -#define END_POINT_POSTING1 "POST /hae/tempstick/send HTTP/1.1\r\n" -#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" -#define AUTHERIZATION_VALUE "Bearer 19730e88-886d-4c94-89d6-3066b79b7630" -#define END_POINT_HOST "Host: 3.90.70.38:8080\r\n" -#define HOST_VALUE "3.90.70.38:8080" -#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" -#define USER_AGENT_VALUE "\"SensorDHT\\/1.0\"" -#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" -#define CONTENT_TYPE_VALUE "application/json" -#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" -/*HTTP POST header */ -#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN - - -// URL to post on servers 1, 2, and 3 -#define MCU_POST_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/send" -#define MCU_POST_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/send" -#define MCU_POST_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/send" - -//URL to get configuration flags from servers 1, 2, and 3 -#define MCU_GET_CONFIG_FLAGS_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 -#define MCU_GET_CONFIG_FLAGS_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 -#define MCU_GET_CONFIG_FLAGS_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 - -/* this endpoint not implemented yet in the code (customer pending) */ -// if the config_update flag is set -// URL to get settings from servers 1, 2, and 3 -#define MCU_GET_SETTINGS_URL1 TESTING_SERVER_BASE_URL//settings/server1 -#define MCU_GET_SETTINGS_URL2 TESTING_SERVER_BASE_URL//settings/server2 -#define MCU_GET_SETTINGS_URL3 TESTING_SERVER_BASE_URL//settings/server3 - -//URL to get MCU FW version from servers 1, 2, and 3 -#define MCU_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ -#define MCU_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 -#define MCU_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 - -//URL to get MCU FW bin file from servers 1, 2, and 3 -#define MCU_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 -#define MCU_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 -#define MCU_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 - -//URL to get MODEM FW version from servers 1, 2, and 3 -#define MODEM_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 -#define MODEM_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 -#define MODEM_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 - -//URL to get MODEM FW bin file from servers 1, 2, and 3 -#define MODEM_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 -#define MODEM_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 -#define MODEM_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 - - -#else -/*HTTP POST header component for Partha server*/ -#define END_POINT_POSTING1 "POST /hae/tempstick/send.php HTTP/1.1\r\n" -#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" -#define END_POINT_HOST "Host: www.parthasarathimishra.com\r\n" -#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" -#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" -#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" -/*HTTP POST header */ -#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN - - -// URL to post on servers 1, 2, and 3 -#define MCU_POST_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" -#define MCU_POST_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" -#define MCU_POST_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" - -//URL to get configuration flags from servers 1, 2, and 3 -#define MCU_GET_CONFIG_FLAGS_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 -#define MCU_GET_CONFIG_FLAGS_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 -#define MCU_GET_CONFIG_FLAGS_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 - -/* this endpoint not implemented yet in the code (customer pending) */ -// if the config_update flag is set -// URL to get settings from servers 1, 2, and 3 -#define MCU_GET_SETTINGS_URL1 MCU_BASE_URL1//settings/server1 -#define MCU_GET_SETTINGS_URL2 MCU_BASE_URL2//settings/server2 -#define MCU_GET_SETTINGS_URL3 MCU_BASE_URL3//settings/server3 - -//URL to get MCU FW version from servers 1, 2, and 3 -#define MCU_FW_VERSION_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ -#define MCU_FW_VERSION_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 -#define MCU_FW_VERSION_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 - -//URL to get MCU FW bin file from servers 1, 2, and 3 -#define MCU_FW_BIN_FILE_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 -#define MCU_FW_BIN_FILE_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 -#define MCU_FW_BIN_FILE_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 - -//URL to get MODEM FW version from servers 1, 2, and 3 -#define MODEM_FW_VERSION_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 -#define MODEM_FW_VERSION_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 -#define MODEM_FW_VERSION_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 - -//URL to get MODEM FW bin file from servers 1, 2, and 3 -#define MODEM_FW_BIN_FILE_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 -#define MODEM_FW_BIN_FILE_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 -#define MODEM_FW_BIN_FILE_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 -#endif -#endif - - - - - - -/* TEMPSTICK servers URL's */ -typedef enum { - TEMPSTICK_SERVER1=1, - TEMPSTICK_SERVER2, - TEMPSTICK_SERVER3 -}serverUrl_t; - - /* Operation complete indication callback */ -typedef void (*comms_op_cb_t)(int status); - -/* Initialize process. */ -int comms_init(void); - -/* Start process. - * The server is contacted for configuration. - * When this processes completes, the callback is notified. - */ -int comms_start(comms_op_cb_t start_cb, comms_op_cb_t connect_cb); - -/* Stop process. */ -int comms_stop(void); - -/* Poll process. */ -int comms_poll(void); - -/* Check if the process needs to be polled. */ -bool comms_needs_poll(void); - -/* Connect to server once process has completed startup and is idle -* Optional callback is invoked when process completes. -*/ -int comms_connect(comms_op_cb_t cb); - -/* Check if the process is idle and not doing any communications. */ -bool comms_is_idle(void); - -/* Check if the process is started */ -bool comms_is_started(void); - -/* Get the status of the last communication attempt. - * OK - everything completed. - * ERROR - something failed. - */ -int comms_get_status(void); - -#endif /* MAIN_COMMS_H_ */ +/* + * comms.h + * + * Created on: Jan 16, 2023 + * Author: Sword + */ + +#ifndef MAIN_COMMS_H_ +#define MAIN_COMMS_H_ + + +#include +#include +#include "sdkconfig.h" +#include "main.h" +/* comms.h + * + * Copyright 2020 HAE Innovations + * + * Celluar Communications process manager. + * + * Handles communication to/from server over cell modem, + * collecting and sending events from queue, processing configuration + * and firmware updates from server, etc. + * + * Author: E. Ross + */ + +#define COMMS_STATUS_UPDATED 1 +#define COMMS_STATUS_OK 0 +#define COMMS_STATUS_ERROR -1 + + +#define MCU_BASE_URL1 "https://testdevice.tempstickapi.com" +#define MCU_BASE_URL2 "https://testdevice.tempstickapi.com" +#define MCU_BASE_URL3 "https://testdevice.tempstickapi.com" +#define MCU_BASE_URL4 "http://testdevice.tempstickapi.com" + + +#define MCU_ONBOARDING_URL "https://device-status.idealsciences%u.com" +#define POSTING_ONBOARDING "POST /sensor-account.php HTTP/1.0" +#define ON_BOARDING_SERVER_DOMAIN_NAME "device-status.idealsciences.com" +#define USER_AGENT_ONBOARDING "SensorDHT/1.0" +#define AUTHERIZATION_VALUE_ONBOARDING "Basic ZGV2OmRldjEyMw==" +#define CONTENT_TYPE_VALUE_ONBOARDING "application/x-www-form-urlencoded" +#define ONBOARDING_SERVER_POSTURL_MAX 3 +#define ONBOARDING_SERVER_POSTURL_MIN 1 + + +#define PARTHA_SERVER_BASE_URL "https://www.parthasarathimishra.com" +#define TESTING_SERVER_BASE_URL "http://3.90.70.38:8080" + + +typedef enum +{ + COMMS_OVER_CELL_WIFI_BACKUP = 1, + COMMS_OVER_WIFI_CELL_BACKUP, + COMMS_OVER_CELL, + COMMS_OVER_WIFI, + COMMS_MODE_5 //wifi as default for all readings /cellular for alerts /wifi back up for alerts +}comms_type_t; + +typedef enum +{ + COMMS_MEDIUM_CELL, + COMMS_MEDIUM_WIFI, +}comms_medium_t; + +#if (TEMPSTICK_SERVER == 1) + + +/*HTTP POST header component for tempstick server*/ +#define END_POINT_POSTING1 "POST / HTTP/1.1\r\n" +#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" +#define AUTHERIZATION_VALUE "Bearer 19730e88-886d-4c94-89d6-3066b79b7630" +#define END_POINT_HOST "Host: testdevice.tempstickapi.com\r\n" +#define HOST_VALUE "testdevice.tempstickapi.com" +#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" +#define USER_AGENT_VALUE "\"SensorDHT\\/1.0\"" +#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" +#define CONTENT_TYPE_VALUE "application/json" +#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" + +#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN + + +// URL to post on servers 1, 2, and 3 +#define MCU_POST_URL1 MCU_BASE_URL1 +#define MCU_POST_URL2 MCU_BASE_URL2 +#define MCU_POST_URL3 MCU_BASE_URL3 + +//URL to get configuration flags from servers 1, 2, and 3 +#define MCU_GET_CONFIG_FLAGS_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 +#define MCU_GET_CONFIG_FLAGS_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 +#define MCU_GET_CONFIG_FLAGS_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 + +/* this endpoint not implemented yet in the code (customer pending) */ +// if the config_update flag is set +// URL to get settings from servers 1, 2, and 3 +#define MCU_GET_SETTINGS_URL1 TESTING_SERVER_BASE_URL//settings/server1 +#define MCU_GET_SETTINGS_URL2 TESTING_SERVER_BASE_URL//settings/server2 +#define MCU_GET_SETTINGS_URL3 TESTING_SERVER_BASE_URL//settings/server3 + +//URL to get MCU FW version from servers 1, 2, and 3 +#define MCU_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ +#define MCU_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 +#define MCU_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 + +//URL to get MCU FW bin file from servers 1, 2, and 3 +#define MCU_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 +#define MCU_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 +#define MCU_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 + +//URL to get MODEM FW version from servers 1, 2, and 3 +#define MODEM_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 +#define MODEM_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 +#define MODEM_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 + +//URL to get MODEM FW bin file from servers 1, 2, and 3 +#define MODEM_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 +#define MODEM_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 +#define MODEM_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 + + +#else + +#if (TESTING_SERVER==1) + +/*HTTP POST header component for Partha server*/ +#define END_POINT_POSTING1 "POST /hae/tempstick/send HTTP/1.1\r\n" +#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" +#define AUTHERIZATION_VALUE "Bearer 19730e88-886d-4c94-89d6-3066b79b7630" +#define END_POINT_HOST "Host: 3.90.70.38:8080\r\n" +#define HOST_VALUE "3.90.70.38:8080" +#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" +#define USER_AGENT_VALUE "\"SensorDHT\\/1.0\"" +#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" +#define CONTENT_TYPE_VALUE "application/json" +#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" +/*HTTP POST header */ +#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN + + +// URL to post on servers 1, 2, and 3 +#define MCU_POST_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/send" +#define MCU_POST_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/send" +#define MCU_POST_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/send" + +//URL to get configuration flags from servers 1, 2, and 3 +#define MCU_GET_CONFIG_FLAGS_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 +#define MCU_GET_CONFIG_FLAGS_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 +#define MCU_GET_CONFIG_FLAGS_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 + +/* this endpoint not implemented yet in the code (customer pending) */ +// if the config_update flag is set +// URL to get settings from servers 1, 2, and 3 +#define MCU_GET_SETTINGS_URL1 TESTING_SERVER_BASE_URL//settings/server1 +#define MCU_GET_SETTINGS_URL2 TESTING_SERVER_BASE_URL//settings/server2 +#define MCU_GET_SETTINGS_URL3 TESTING_SERVER_BASE_URL//settings/server3 + +//URL to get MCU FW version from servers 1, 2, and 3 +#define MCU_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ +#define MCU_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 +#define MCU_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 + +//URL to get MCU FW bin file from servers 1, 2, and 3 +#define MCU_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 +#define MCU_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 +#define MCU_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 + +//URL to get MODEM FW version from servers 1, 2, and 3 +#define MODEM_FW_VERSION_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 +#define MODEM_FW_VERSION_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 +#define MODEM_FW_VERSION_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 + +//URL to get MODEM FW bin file from servers 1, 2, and 3 +#define MODEM_FW_BIN_FILE_URL1 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 +#define MODEM_FW_BIN_FILE_URL2 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 +#define MODEM_FW_BIN_FILE_URL3 TESTING_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 + + +#else +/*HTTP POST header component for Partha server*/ +#define END_POINT_POSTING1 "POST /hae/tempstick/send.php HTTP/1.1\r\n" +#define END_POINT_AUTHERIZATION "Authorization: Bearer 19730e88-886d-4c94-89d6-3066b79b7630\r\n" +#define END_POINT_HOST "Host: www.parthasarathimishra.com\r\n" +#define END_POINT_USER_AGENT "User-Agent: \"SensorDHT\\/1.0\"\r\n" +#define END_POINT_CONTENT_TYPE "Content-Type: application/json\r\n" +#define END_POINT_CONTENT_LEN "Content-Length: %u\r\n\r\n" +/*HTTP POST header */ +#define HTTP_POST_HEADER END_POINT_POSTING1 END_POINT_AUTHERIZATION END_POINT_HOST END_POINT_USER_AGENT END_POINT_CONTENT_TYPE END_POINT_CONTENT_LEN + + +// URL to post on servers 1, 2, and 3 +#define MCU_POST_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" +#define MCU_POST_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" +#define MCU_POST_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/send.php" + +//URL to get configuration flags from servers 1, 2, and 3 +#define MCU_GET_CONFIG_FLAGS_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL1//config/flag/server1 +#define MCU_GET_CONFIG_FLAGS_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL2//config/flag/server2 +#define MCU_GET_CONFIG_FLAGS_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/config/"//MCU_BASE_URL3//config/flag/server3 + +/* this endpoint not implemented yet in the code (customer pending) */ +// if the config_update flag is set +// URL to get settings from servers 1, 2, and 3 +#define MCU_GET_SETTINGS_URL1 MCU_BASE_URL1//settings/server1 +#define MCU_GET_SETTINGS_URL2 MCU_BASE_URL2//settings/server2 +#define MCU_GET_SETTINGS_URL3 MCU_BASE_URL3//settings/server3 + +//URL to get MCU FW version from servers 1, 2, and 3 +#define MCU_FW_VERSION_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"/*MCU_BASE_URL1//mcu/fw/version/server1*/ +#define MCU_FW_VERSION_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL2//mcu/fw/version/server2 +#define MCU_FW_VERSION_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/version/"//MCU_BASE_URL3//mcu/fw/version/server3 + +//URL to get MCU FW bin file from servers 1, 2, and 3 +#define MCU_FW_BIN_FILE_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL1//mcu/fw/bin/file/server1 +#define MCU_FW_BIN_FILE_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL2//mcu/fw/bin/file/server2 +#define MCU_FW_BIN_FILE_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/mcu_pgm_download/OTA.bin"//MCU_BASE_URL3//mcu/fw/bin/file/server3 + +//URL to get MODEM FW version from servers 1, 2, and 3 +#define MODEM_FW_VERSION_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL1//modem/fw/version/server1 +#define MODEM_FW_VERSION_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL2//modem/fw/version/server2 +#define MODEM_FW_VERSION_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/version/"//MCU_BASE_URL3//modem/fw/version/server3 + +//URL to get MODEM FW bin file from servers 1, 2, and 3 +#define MODEM_FW_BIN_FILE_URL1 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL1//modem/fw/bin/file/server1 +#define MODEM_FW_BIN_FILE_URL2 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL2//modem/fw/bin/file/server2 +#define MODEM_FW_BIN_FILE_URL3 PARTHA_SERVER_BASE_URL"/hae/tempstick/%s/modem_pgm_download/MOTA.bin"//MCU_BASE_URL3//modem/fw/bin/file/server3 +#endif +#endif + + + + + + +/* TEMPSTICK servers URL's */ +typedef enum { + TEMPSTICK_SERVER1=1, + TEMPSTICK_SERVER2, + TEMPSTICK_SERVER3 +}serverUrl_t; + + /* Operation complete indication callback */ +typedef void (*comms_op_cb_t)(int status); + +/* Initialize process. */ +int comms_init(void); + +/* Start process. + * The server is contacted for configuration. + * When this processes completes, the callback is notified. + */ +int comms_start(comms_op_cb_t start_cb, comms_op_cb_t connect_cb); + +/* Stop process. */ +int comms_stop(void); + +/* Poll process. */ +int comms_poll(void); + +/* Check if the process needs to be polled. */ +bool comms_needs_poll(void); + +/* Connect to server once process has completed startup and is idle +* Optional callback is invoked when process completes. +*/ +int comms_connect(comms_op_cb_t cb); + +/* Check if the process is idle and not doing any communications. */ +bool comms_is_idle(void); + +/* Check if the process is started */ +bool comms_is_started(void); + +/* Get the status of the last communication attempt. + * OK - everything completed. + * ERROR - something failed. + */ +int comms_get_status(void); + +#endif /* MAIN_COMMS_H_ */ diff --git a/main/main.c b/main/main.c index 1dcb935..aae49c6 100644 --- a/main/main.c +++ b/main/main.c @@ -1,48 +1,48 @@ - -#include -#include -#include -#include "esp_log.h" -#include "nvm.h" -#include "port.h" -#include "uart_ifx.h" -#include "wifi_webServer.h" -#include "comms.h" -#include "main.h" - -static const char* TAG = "MAIN"; -uint8_t comms_mode = DEFAULT_COMMS_MODE; -void app_main(void) -{ - - ESP_LOGI(TAG,"*** Starting app_main ***"); - - /* Initialize the dedicated NVS partition */ - nvm_init(); - port_init(); - uart_ifx_init(); - - /* Create the UART tasks for both UART0 and UART1 */ - uart_create_rx_tasks(); - - /* read the comms-mode from the NVS (if any) */ - comms_mode = nvm_read_comms_mode(); - - if((COMMS_OVER_CELL != comms_mode)) - { - /* Start On-Boarding process */ - webserver_start(); - - /* Wait till the onboarding process is completed */ - while(!webserver_get_status()) - { - //ESP_LOGI(TAG," -------------> PASSWORD is: %s",wifi_get_pswd()); - vTaskDelay(750/portTICK_PERIOD_MS); - } - } - - ESP_LOGI(TAG," -------------> Wifi Connected ... :)"); - while(1); - - vTaskDelete(NULL); -} + +#include +#include +#include +#include "esp_log.h" +#include "nvm.h" +#include "port.h" +#include "uart_ifx.h" +#include "wifi_webServer.h" +#include "comms.h" +#include "main.h" + +static const char* TAG = "MAIN"; +uint8_t comms_mode = DEFAULT_COMMS_MODE; +void app_main(void) +{ + + ESP_LOGI(TAG,"*** Starting app_main ***"); + + /* Initialize the dedicated NVS partition */ + nvm_init(); + port_init(); + uart_ifx_init(); + + /* Create the UART tasks for both UART0 and UART1 */ + uart_create_rx_tasks(); + + /* read the comms-mode from the NVS (if any) */ + comms_mode = nvm_read_comms_mode(); + + if((COMMS_OVER_CELL != comms_mode)) + { + /* Start On-Boarding process */ + webserver_start(); + + /* Wait till the onboarding process is completed */ + while(!webserver_get_status()) + { + //ESP_LOGI(TAG," -------------> PASSWORD is: %s",wifi_get_pswd()); + vTaskDelay(750/portTICK_PERIOD_MS); + } + } + + ESP_LOGI(TAG," -------------> Wifi Connected ... :)"); + + while(1); + vTaskDelete(NULL); +} diff --git a/main/nvm.c b/main/nvm.c index 2ff9b5d..99c373c 100644 --- a/main/nvm.c +++ b/main/nvm.c @@ -1,1117 +1,1117 @@ -/* - * nvm.c - * - * Created on: Aug 14, 2023 - * Author: Sword - */ - -#include -#include "nvs_flash.h" -#include "nvs.h" -#include "esp_system.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include -#include "hmi.h" -#include "nvm.h" -#include "main.h" - -static const char* TAG = "NVM"; - -#define LOG_LOCAL_LEVEL ESP_LOG_INFO -#include "esp_log.h" - - -nvs_handle_t my_handle; - -RTC_DATA_ATTR static uint8_t last_posted_sector; - -extern uint8_t onBoarded; - - -/**/ -void nvm_init(void) -{ - /* Initialize the dedicated NVS partition */ - esp_err_t ret = nvs_flash_init(); - - /* Check if NVS partition doesn't contain any empty pages or contains data in new format and cannot be recognized by this version of code */ - if((ret == ESP_ERR_NVS_NO_FREE_PAGES) || (ret == ESP_ERR_NVS_NEW_VERSION_FOUND)) - { - /* If so ----> then erase the NVS partition reinitialize it one more time*/ - ESP_ERROR_CHECK(nvs_flash_erase()); - - /* reinitialize NVS partition one more time */ - ret = nvs_flash_init(); - } - - //Check that there is no problem with initializing NVS partition - ESP_ERROR_CHECK(ret); -} - -/**/ -void nvm_clear(void) -{ - /* erase the NVS partition */ - ESP_ERROR_CHECK(nvs_flash_erase()); -} - - - -/**/ -uint8_t nvm_read_onboarding_flag(onboarding_type_t flag_key) -{ - uint8_t onBoarding; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - //ESP_LOGI(TAG,"Done\nReading on-boarding value from NVS ... "); - - if(WIFI_ONBOARDING_KEY == flag_key) - { - err = nvs_get_u8(my_handle, NVM_WIFI_ONBOARDING_KEY, &onBoarding); - } - else - { - err = nvs_get_u8(my_handle, NVM_CELL_ONBOARDING_KEY, &onBoarding); - } - - switch (err) - { - case ESP_OK: - - ESP_LOGI(TAG,"On-Boarding = %d\n",onBoarding); - - // Close the opened NVS - nvs_close(my_handle); - - return onBoarding; - - break; - - case ESP_ERR_NVS_NOT_FOUND: - ESP_LOGI(TAG,"The on-boarding value is not initialized yet!\n"); - break; - - default: - ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); - } - } - - // Close the opened NVS - nvs_close(my_handle); - - return 0; - -} - -/**/ -void nvm_write_onboarding_flag(onboarding_type_t flag_key, uint8_t flag_value) -{ - esp_err_t err; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - //ESP_LOGI(TAG,"Done\nUpdating on-boarding value in NVS ... "); - - if(WIFI_ONBOARDING_KEY == flag_key) - { - err = nvs_set_u8(my_handle, NVM_WIFI_ONBOARDING_KEY, flag_value); - } - else - { - err = nvs_set_u8(my_handle, NVM_CELL_ONBOARDING_KEY, flag_value); - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Failed"); - } - else - { - //ESP_LOGI(TAG,"Done"); - } - - // Commit written value. - // After setting any values, nvs_commit() must be called to ensure changes are written - // to flash storage. Implementations may write to storage at other times, - // but this is not guaranteed. - hmi_stop_red_flashing(); - - //ESP_LOGI(TAG,"Committing updates in NVS ... "); - - err = nvs_commit(my_handle); - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Failed Updating on-boarding value in NVS"); - } - else - { - ESP_LOGI(TAG,"Done Updating on-boarding value in NVS"); - } - } - - // Close the opened NVS - nvs_close(my_handle); -} - - - -/**/ -uint8_t nvm_read_comms_mode(void) -{ - uint8_t commsMode; - esp_err_t err; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - //ESP_LOGI(TAG,"Done\nReading Communication-Mode value from NVS ... "); - - err = nvs_get_u8(my_handle, NVM_COMMS_MODE_KEY, &commsMode); - - switch (err) - { - case ESP_OK: - - ESP_LOGI(TAG,"Communication Mode = %d\n",commsMode); - - // Close the opened NVS - nvs_close(my_handle); - - return commsMode; - - break; - - case ESP_ERR_NVS_NOT_FOUND: - ESP_LOGI(TAG,"The Communication-Mode value is not initialized yet!\n"); - break; - - default: - ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); - } - } - - // Close the opened NVS - nvs_close(my_handle); - - return DEFAULT_COMMS_MODE; - -} - -/**/ -void nvm_write_comms_mode(uint8_t commsMode) -{ - esp_err_t err; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - //ESP_LOGI(TAG,"Done\nUpdating Communication-Mode value in NVS ... "); - - err = nvs_set_u8(my_handle, NVM_COMMS_MODE_KEY, commsMode); - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Failed"); - } - else - { - //ESP_LOGI(TAG,"Done"); - } - - //ESP_LOGI(TAG,"Committing updates in NVS ... "); - - err = nvs_commit(my_handle); - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Failed Updating Communication-Mode value in NVS"); - } - else - { - ESP_LOGI(TAG,"Done Updating Communication-Mode value in NVS"); - } - } - - // Close the opened NVS - nvs_close(my_handle); -} - - - -/**/ -esp_err_t nvm_read_wifi_credentials(char* ssid, char* pswd) -{ - esp_err_t err; - size_t ssid_len; - size_t pswd_len; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - /* Make sure that NVS storage has been opened successfully */ - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - /* Get the length of the WIFI-SSID */ - nvs_get_str(my_handle, NVM_WIFI_SSID_KEY, NULL, (size_t*)&ssid_len); - - /* Get the length of the WIFI-PSWD */ - nvs_get_str(my_handle, NVM_WIFI_PSWD_KEY, NULL, (size_t*)&pswd_len); - - //ESP_LOGI(TAG,"NVM-SSID len = %d, and NVM-PWD len = %d",ssid_len,pswd_len); - - //char* sid = malloc(ssid_len); - //char* pwd = malloc(pswd_len); - - /* Retrieve the WIFI-SSID */ - if(ESP_OK == err) - err = nvs_get_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, ssid, (size_t*)&ssid_len); - - /* Retrieve the WIFI-PSWD */ - if(ESP_OK == err) - err = nvs_get_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, pswd, (size_t*)&pswd_len); - - /* Check the result of the NVS reading */ - switch (err) - { - case ESP_OK: - - //strcpy(ssid,sid); - //strcpy(pswd,pwd); - ESP_LOGI(TAG,"WIFI_SSID is: %s and WIFI_PSWD is: %s",ssid,pswd); - break; - - case ESP_ERR_NVS_NOT_FOUND: - ESP_LOGI(TAG,"The WIFI_Credentials not initialized yet!\n"); - break; - - default: - ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); - } - - //free(sid); - //free(pwd); - } - - // Close the opened NVS - nvs_close(my_handle); - - return err; -} - -/**/ -void nvm_write_wifi_credentials(char* ssid, uint8_t ssid_len, char* pswd, uint8_t pswd_len) -{ - esp_err_t err; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); - } - } - - /* Make sure that NVS storage has been opened successfully */ - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - //ESP_LOGI(TAG,"Done\nUpdating WIFI-Credentials in NVS ... "); - - /* Store the WIFI-SSID string in NVS */ - err = nvs_set_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, (const char*)ssid); - - /* If WIFI-SSID stored successfully in NVS then ---> Store the WIFI-PSWD string in NVS */ - if(ESP_OK == err) - err = nvs_set_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, (const char*)pswd); - - /* Inform the user with one of these logs to indicate failing or succeeding to store wifi-credentials */ - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Failed"); - } - else - { - //ESP_LOGI(TAG,"Done"); - } - - // Commit written value. - // After setting any values, nvs_commit() must be called to ensure changes are written - // to flash storage. Implementations may write to storage at other times, - // but this is not guaranteed. - - //ESP_LOGI(TAG,"Committing updates in NVS ... "); - - err = nvs_commit(my_handle); - - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Failed Updating WIFI-Credentials in NVS"); - } - else - { - ESP_LOGI(TAG,"Done Updating WIFI-Credentials in NVS"); - } - } - - // Close the opened NVS - nvs_close(my_handle); -} - - -#if 0 -/**/ -void nvm_read_wifi_backup_credentials(char* ssid, char* pswd, char* key1, char* key2) -{ - esp_err_t err; - size_t ssid_len; - size_t pswd_len; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - /* Make sure that NVS storage has been opened successfully */ - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - /* Get the length of the WIFI-SSID */ - nvs_get_str(my_handle, key1, NULL, (size_t*)&ssid_len); - - /* Get the length of the WIFI-PSWD */ - nvs_get_str(my_handle, key2, NULL, (size_t*)&pswd_len); - - ESP_LOGI(TAG,"NVM-SSID len = %d, and NVM-PWD len = %d",ssid_len,pswd_len); - - //char* sid = malloc(ssid_len); - //char* pwd = malloc(pswd_len); - - /* Retrieve the WIFI-SSID */ - if(ESP_OK == err) - err = nvs_get_str(my_handle, (const char*)key1, ssid, (size_t*)&ssid_len); - - /* Retrieve the WIFI-PSWD */ - if(ESP_OK == err) - err = nvs_get_str(my_handle, (const char*)key2, pswd, (size_t*)&pswd_len); - - /* Check the result of the NVS reading */ - switch (err) - { - case ESP_OK: - - //strcpy(ssid,sid); - //strcpy(pswd,pwd); - ESP_LOGI(TAG,"WIFI_SSID is: %s and WIFI_PSWD is: %s",ssid,pswd); - break; - - case ESP_ERR_NVS_NOT_FOUND: - ESP_LOGI(TAG,"The WIFI_Credentials not initialized yet!\n"); - break; - - default: - ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); - } - - //free(sid); - //free(pwd); - } - - // Close the opened NVS - nvs_close(my_handle); -} - -/**/ -void nvm_write_wifi_backup_credentials(char* ssid1, char* pswd1, char* ssid2, char* pswd2) -{ - esp_err_t err; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); - } - } - - /* Make sure that NVS storage has been opened successfully */ - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - ESP_LOGI(TAG,"Done\nUpdating WIFI-Credentials in NVS ... "); - - /* Store the WIFI-SSID string in NVS */ - err = nvs_set_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, (const char*)ssid); - - /* If WIFI-SSID stored successfully in NVS then ---> Store the WIFI-PSWD string in NVS */ - if(ESP_OK == err) - err = nvs_set_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, (const char*)pswd); - - /* Inform the user with one of these logs to indicate failing or succeeding to store wifi-credentials */ - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Failed"); - } - else - { - ESP_LOGI(TAG,"Done"); - } - - // Commit written value. - // After setting any values, nvs_commit() must be called to ensure changes are written - // to flash storage. Implementations may write to storage at other times, - // but this is not guaranteed. - - ESP_LOGI(TAG,"Committing updates in NVS ... "); - - err = nvs_commit(my_handle); - - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Failed"); - } - else - { - ESP_LOGI(TAG,"Done"); - } - } - - // Close the opened NVS - nvs_close(my_handle); -} -#endif - - -/**/ -void nvm_write_history_data(historyLog_t* history_data) -{ - esp_err_t err; - size_t required_size = 0; // value will default to 0, if not set yet in NVS - - char key_str[18]; - uint8_t sector_counter = 1; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); - } - } - - /* Make sure that NVS storage has been opened successfully */ - if (err != ESP_OK) - { - ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - do - { - /* Setup the NVS sector to write to */ - sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); - - /* get the size of the history space */ - err = nvs_get_blob(my_handle, key_str, NULL, &required_size); - - /* Check if we can store data at that sector or not*/ - if(required_size >= (NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))) - { - /* Reset the required_size again to 0 */ - required_size = 0; - - /* if not then check the next sector */ - sector_counter++; - } - else - { - /* if yes then increase the size of data to be stored by one element */ - required_size += sizeof(historyLog_t); - break; - } - }while(sector_counter <= NVM_NUMBER_OF_SECTORS); - - /* Make sure that there are some free sectors to store data in */ - if(sector_counter <= NVM_NUMBER_OF_SECTORS) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, key_str, history_data, required_size); - - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) - ESP_LOGI(TAG," ---> History space not there"); - - if (required_size == 0) - { - ESP_LOGI(TAG," ---> Nothing saved yet"); - } - else - { - // Commit - err = nvs_commit(my_handle); - if (err == ESP_OK) - ESP_LOGI(TAG," ---> the new history data has been committed successfully to nvm-sector %d\nand its size now is %d (max allowed size is %d)",sector_counter,required_size,(NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))); - } - } - else - { - ESP_LOGE(TAG," ----> All the NVM sectors are full. can't store additional data"); - } - } - - // Close - nvs_close(my_handle); -} - -/**/ -size_t nvm_read_history_data(historyLog_t* history_data, uint8_t sector_number) -{ - esp_err_t err; - size_t required_size = 0; // value will default to 0, if not set yet in NVS - - char key_str[18]; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - /* Setup the NVS sector to write to */ - sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_number); - - // obtain required memory space to store blob being read from NVS - err = nvs_get_blob(my_handle, key_str, NULL, &required_size); - - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) - ESP_LOGI(TAG," ---> History not found yet"); - - //ESP_LOGI(TAG,"History data are:"); - - if (required_size == 0) - { - ESP_LOGI(TAG," ---> Nothing saved yet!\n"); - } - else - { - err = nvs_get_blob(my_handle, key_str, history_data, &required_size); - if (err != ESP_OK) - { - ESP_LOGI(TAG," ---> ERROR in retrieving history data for NVM sector %d",sector_number); - } - } - } - - // Close - nvs_close(my_handle); - - return required_size; -} - -/**/ -void nvm_clear_history_sector(uint8_t sector_num) -{ - esp_err_t wifi_err; - uint8_t wifi_onboarding; - uint8_t cell_onboarding; - uint8_t comms_mode; - char ssid[32] = {0}; - char pswd[64] = {0}; - - ESP_LOGI(TAG,"Clearing NVM History Sectors After successful POST process"); - - /* If there are some written data in the first sector ---> then this means that you should clear it. otherwise no (just to save read-write cycles for nvs) */ - if(nvm_read_history_data(NULL,1)) - { - /* 1- Firstly retrieve stored data in NVS */ - wifi_onboarding = nvm_read_onboarding_flag(WIFI_ONBOARDING_KEY); - cell_onboarding = nvm_read_onboarding_flag(CELL_ONBOARDING_KEY); - comms_mode = nvm_read_comms_mode(); - wifi_err = nvm_read_wifi_credentials(ssid,pswd); - - /* Reload the WDT */ - vTaskDelay(10/portTICK_PERIOD_MS); - - /* 2- Clear NVS partition */ - nvm_clear(); - - /* Reload the WDT */ - vTaskDelay(10/portTICK_PERIOD_MS); - - /* 3- Store the retrieved data again in NVS */ - nvm_write_onboarding_flag(WIFI_ONBOARDING_KEY,wifi_onboarding); - nvm_write_onboarding_flag(CELL_ONBOARDING_KEY,cell_onboarding); - nvm_write_comms_mode(comms_mode); - if(wifi_err == ESP_OK) - nvm_write_wifi_credentials(ssid,32,pswd,64); - } - - -#if 0 - esp_err_t err; - char key_str[18]; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - for(int sector_counter=1; sector_counter<=NVM_NUMBER_OF_SECTORS; sector_counter++) - { - /* Setup the NVS sector to clear */ - sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); - - /* Check which sector number need to be cleared */ - if((sector_num == sector_counter) || ((sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, key_str, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector %d",sector_counter); - break; - } - else - { - /* Check if the sector_num isn't equal to the NVM_HISTORY_ALL_SECTORS then break the loop after first successful clear process */ - if(sector_num != NVM_HISTORY_ALL_SECTORS) - { - break; - } - } - } - } -#endif -#if 0 - if((sector_num == NVM_HISTORY_SECTOR_1) || ((sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR1, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 1"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_2) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR2, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 2"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_3) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR3, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 3"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_4) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR4, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 4"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_5) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR5, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 5"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_6) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR6, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 6"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_7) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR7, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 7"); - } - } - - if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_8) || (sector_num == NVM_HISTORY_ALL_SECTORS))) - { - /* set the new values for the history data */ - err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR8, NULL, 0); - if(err != ESP_OK) - { - ESP_LOGI(TAG,"Failed to clear sector 8"); - } - } -#endif -// err = nvs_commit(my_handle); -// } - - // Close -// nvs_close(my_handle); -} - -/**/ -uint8_t nvm_get_last_written_history_sector(void) -{ - esp_err_t err; - size_t required_size = 0; // value will default to 0, if not set yet in NVS - - char key_str[18]; - uint8_t sector_counter = 1; - - /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ - //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); - err = nvs_open("storage", NVS_READWRITE, &my_handle); - - /* Make sure that NVS is initialized */ - if(ESP_ERR_NVS_NOT_INITIALIZED == err) - { - /* initialized it if not */ - err = nvs_flash_init(); - - /* Check if the response is OK then OPEN it */ - if(err == ESP_OK) - { - /* Retry to open the NVS */ - err = nvs_open("storage", NVS_READWRITE, &my_handle); - } - else - { - /* Print this LOG if failed to initialize it */ - ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); - } - } - - if (err != ESP_OK) - { - ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } - else - { - do - { - /* Setup the key of NVS sector to read the size of it's written data */ - sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); - - /* get the size of the history space */ - err = nvs_get_blob(my_handle, key_str, NULL, &required_size); - - /* Check if that sector is not full */ - if(required_size >= (NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))) - { - /* Reset the required_size again to 0 */ - required_size = 0; - - /* if full then check the next sector */ - sector_counter++; - } - else - { - /* if not full then return the sector_number */ - break; - } - }while(sector_counter <= NVM_NUMBER_OF_SECTORS); - - if(sector_counter > NVM_NUMBER_OF_SECTORS) - { - /* Setup the key of NVS sector to read it's written data */ - sector_counter--; - } - } - - // Close - nvs_close(my_handle); - - return sector_counter; -} - - - -/**/ -void nvm_set_last_posted_history_sector(uint8_t sector_num) -{ - if(sector_num <= NVM_NUMBER_OF_SECTORS) - last_posted_sector = sector_num; - else - last_posted_sector = 0; -} - -/**/ -uint8_t nvm_get_last_posted_history_sector(void) -{ - return last_posted_sector; -} - - - - +/* + * nvm.c + * + * Created on: Aug 14, 2023 + * Author: Sword + */ + +#include +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include "hmi.h" +#include "nvm.h" +#include "main.h" + +static const char* TAG = "NVM"; + +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "esp_log.h" + + +nvs_handle_t my_handle; + +RTC_DATA_ATTR static uint8_t last_posted_sector; + +extern uint8_t onBoarded; + + +/**/ +void nvm_init(void) +{ + /* Initialize the dedicated NVS partition */ + esp_err_t ret = nvs_flash_init(); + + /* Check if NVS partition doesn't contain any empty pages or contains data in new format and cannot be recognized by this version of code */ + if((ret == ESP_ERR_NVS_NO_FREE_PAGES) || (ret == ESP_ERR_NVS_NEW_VERSION_FOUND)) + { + /* If so ----> then erase the NVS partition reinitialize it one more time*/ + ESP_ERROR_CHECK(nvs_flash_erase()); + + /* reinitialize NVS partition one more time */ + ret = nvs_flash_init(); + } + + //Check that there is no problem with initializing NVS partition + ESP_ERROR_CHECK(ret); +} + +/**/ +void nvm_clear(void) +{ + /* erase the NVS partition */ + ESP_ERROR_CHECK(nvs_flash_erase()); +} + + + +/**/ +uint8_t nvm_read_onboarding_flag(onboarding_type_t flag_key) +{ + uint8_t onBoarding; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + //ESP_LOGI(TAG,"Done\nReading on-boarding value from NVS ... "); + + if(WIFI_ONBOARDING_KEY == flag_key) + { + err = nvs_get_u8(my_handle, NVM_WIFI_ONBOARDING_KEY, &onBoarding); + } + else + { + err = nvs_get_u8(my_handle, NVM_CELL_ONBOARDING_KEY, &onBoarding); + } + + switch (err) + { + case ESP_OK: + + ESP_LOGI(TAG,"On-Boarding = %d\n",onBoarding); + + // Close the opened NVS + nvs_close(my_handle); + + return onBoarding; + + break; + + case ESP_ERR_NVS_NOT_FOUND: + ESP_LOGI(TAG,"The on-boarding value is not initialized yet!\n"); + break; + + default: + ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); + } + } + + // Close the opened NVS + nvs_close(my_handle); + + return 0; + +} + +/**/ +void nvm_write_onboarding_flag(onboarding_type_t flag_key, uint8_t flag_value) +{ + esp_err_t err; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + //ESP_LOGI(TAG,"Done\nUpdating on-boarding value in NVS ... "); + + if(WIFI_ONBOARDING_KEY == flag_key) + { + err = nvs_set_u8(my_handle, NVM_WIFI_ONBOARDING_KEY, flag_value); + } + else + { + err = nvs_set_u8(my_handle, NVM_CELL_ONBOARDING_KEY, flag_value); + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Failed"); + } + else + { + //ESP_LOGI(TAG,"Done"); + } + + // Commit written value. + // After setting any values, nvs_commit() must be called to ensure changes are written + // to flash storage. Implementations may write to storage at other times, + // but this is not guaranteed. + hmi_stop_red_flashing(); + + //ESP_LOGI(TAG,"Committing updates in NVS ... "); + + err = nvs_commit(my_handle); + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Failed Updating on-boarding value in NVS"); + } + else + { + ESP_LOGI(TAG,"Done Updating on-boarding value in NVS"); + } + } + + // Close the opened NVS + nvs_close(my_handle); +} + + + +/**/ +uint8_t nvm_read_comms_mode(void) +{ + uint8_t commsMode; + esp_err_t err; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + //ESP_LOGI(TAG,"Done\nReading Communication-Mode value from NVS ... "); + + err = nvs_get_u8(my_handle, NVM_COMMS_MODE_KEY, &commsMode); + + switch (err) + { + case ESP_OK: + + ESP_LOGI(TAG,"Communication Mode = %d\n",commsMode); + + // Close the opened NVS + nvs_close(my_handle); + + return commsMode; + + break; + + case ESP_ERR_NVS_NOT_FOUND: + ESP_LOGI(TAG,"The Communication-Mode value is not initialized yet!\n"); + break; + + default: + ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); + } + } + + // Close the opened NVS + nvs_close(my_handle); + + return DEFAULT_COMMS_MODE; + +} + +/**/ +void nvm_write_comms_mode(uint8_t commsMode) +{ + esp_err_t err; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + //ESP_LOGI(TAG,"Done\nUpdating Communication-Mode value in NVS ... "); + + err = nvs_set_u8(my_handle, NVM_COMMS_MODE_KEY, commsMode); + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Failed"); + } + else + { + //ESP_LOGI(TAG,"Done"); + } + + //ESP_LOGI(TAG,"Committing updates in NVS ... "); + + err = nvs_commit(my_handle); + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Failed Updating Communication-Mode value in NVS"); + } + else + { + ESP_LOGI(TAG,"Done Updating Communication-Mode value in NVS"); + } + } + + // Close the opened NVS + nvs_close(my_handle); +} + + + +/**/ +esp_err_t nvm_read_wifi_credentials(char* ssid, char* pswd) +{ + esp_err_t err; + size_t ssid_len; + size_t pswd_len; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + /* Make sure that NVS storage has been opened successfully */ + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + /* Get the length of the WIFI-SSID */ + nvs_get_str(my_handle, NVM_WIFI_SSID_KEY, NULL, (size_t*)&ssid_len); + + /* Get the length of the WIFI-PSWD */ + nvs_get_str(my_handle, NVM_WIFI_PSWD_KEY, NULL, (size_t*)&pswd_len); + + //ESP_LOGI(TAG,"NVM-SSID len = %d, and NVM-PWD len = %d",ssid_len,pswd_len); + + //char* sid = malloc(ssid_len); + //char* pwd = malloc(pswd_len); + + /* Retrieve the WIFI-SSID */ + if(ESP_OK == err) + err = nvs_get_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, ssid, (size_t*)&ssid_len); + + /* Retrieve the WIFI-PSWD */ + if(ESP_OK == err) + err = nvs_get_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, pswd, (size_t*)&pswd_len); + + /* Check the result of the NVS reading */ + switch (err) + { + case ESP_OK: + + //strcpy(ssid,sid); + //strcpy(pswd,pwd); + ESP_LOGI(TAG,"WIFI_SSID is: %s and WIFI_PSWD is: %s",ssid,pswd); + break; + + case ESP_ERR_NVS_NOT_FOUND: + ESP_LOGI(TAG,"The WIFI_Credentials not initialized yet!\n"); + break; + + default: + ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); + } + + //free(sid); + //free(pwd); + } + + // Close the opened NVS + nvs_close(my_handle); + + return err; +} + +/**/ +void nvm_write_wifi_credentials(char* ssid, uint8_t ssid_len, char* pswd, uint8_t pswd_len) +{ + esp_err_t err; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); + } + } + + /* Make sure that NVS storage has been opened successfully */ + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + //ESP_LOGI(TAG,"Done\nUpdating WIFI-Credentials in NVS ... "); + + /* Store the WIFI-SSID string in NVS */ + err = nvs_set_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, (const char*)ssid); + + /* If WIFI-SSID stored successfully in NVS then ---> Store the WIFI-PSWD string in NVS */ + if(ESP_OK == err) + err = nvs_set_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, (const char*)pswd); + + /* Inform the user with one of these logs to indicate failing or succeeding to store wifi-credentials */ + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Failed"); + } + else + { + //ESP_LOGI(TAG,"Done"); + } + + // Commit written value. + // After setting any values, nvs_commit() must be called to ensure changes are written + // to flash storage. Implementations may write to storage at other times, + // but this is not guaranteed. + + //ESP_LOGI(TAG,"Committing updates in NVS ... "); + + err = nvs_commit(my_handle); + + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Failed Updating WIFI-Credentials in NVS"); + } + else + { + ESP_LOGI(TAG,"Done Updating WIFI-Credentials in NVS"); + } + } + + // Close the opened NVS + nvs_close(my_handle); +} + + +#if 0 +/**/ +void nvm_read_wifi_backup_credentials(char* ssid, char* pswd, char* key1, char* key2) +{ + esp_err_t err; + size_t ssid_len; + size_t pswd_len; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + /* Make sure that NVS storage has been opened successfully */ + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + /* Get the length of the WIFI-SSID */ + nvs_get_str(my_handle, key1, NULL, (size_t*)&ssid_len); + + /* Get the length of the WIFI-PSWD */ + nvs_get_str(my_handle, key2, NULL, (size_t*)&pswd_len); + + ESP_LOGI(TAG,"NVM-SSID len = %d, and NVM-PWD len = %d",ssid_len,pswd_len); + + //char* sid = malloc(ssid_len); + //char* pwd = malloc(pswd_len); + + /* Retrieve the WIFI-SSID */ + if(ESP_OK == err) + err = nvs_get_str(my_handle, (const char*)key1, ssid, (size_t*)&ssid_len); + + /* Retrieve the WIFI-PSWD */ + if(ESP_OK == err) + err = nvs_get_str(my_handle, (const char*)key2, pswd, (size_t*)&pswd_len); + + /* Check the result of the NVS reading */ + switch (err) + { + case ESP_OK: + + //strcpy(ssid,sid); + //strcpy(pswd,pwd); + ESP_LOGI(TAG,"WIFI_SSID is: %s and WIFI_PSWD is: %s",ssid,pswd); + break; + + case ESP_ERR_NVS_NOT_FOUND: + ESP_LOGI(TAG,"The WIFI_Credentials not initialized yet!\n"); + break; + + default: + ESP_LOGI(TAG,"Error (%s) reading!\n", esp_err_to_name(err)); + } + + //free(sid); + //free(pwd); + } + + // Close the opened NVS + nvs_close(my_handle); +} + +/**/ +void nvm_write_wifi_backup_credentials(char* ssid1, char* pswd1, char* ssid2, char* pswd2) +{ + esp_err_t err; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); + } + } + + /* Make sure that NVS storage has been opened successfully */ + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + ESP_LOGI(TAG,"Done\nUpdating WIFI-Credentials in NVS ... "); + + /* Store the WIFI-SSID string in NVS */ + err = nvs_set_str(my_handle, (const char*)NVM_WIFI_SSID_KEY, (const char*)ssid); + + /* If WIFI-SSID stored successfully in NVS then ---> Store the WIFI-PSWD string in NVS */ + if(ESP_OK == err) + err = nvs_set_str(my_handle, (const char*)NVM_WIFI_PSWD_KEY, (const char*)pswd); + + /* Inform the user with one of these logs to indicate failing or succeeding to store wifi-credentials */ + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Failed"); + } + else + { + ESP_LOGI(TAG,"Done"); + } + + // Commit written value. + // After setting any values, nvs_commit() must be called to ensure changes are written + // to flash storage. Implementations may write to storage at other times, + // but this is not guaranteed. + + ESP_LOGI(TAG,"Committing updates in NVS ... "); + + err = nvs_commit(my_handle); + + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Failed"); + } + else + { + ESP_LOGI(TAG,"Done"); + } + } + + // Close the opened NVS + nvs_close(my_handle); +} +#endif + + +/**/ +void nvm_write_history_data(historyLog_t* history_data) +{ + esp_err_t err; + size_t required_size = 0; // value will default to 0, if not set yet in NVS + + char key_str[18]; + uint8_t sector_counter = 1; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGE(TAG,"Failed to reinitialized The NVS partition"); + } + } + + /* Make sure that NVS storage has been opened successfully */ + if (err != ESP_OK) + { + ESP_LOGE(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + do + { + /* Setup the NVS sector to write to */ + sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); + + /* get the size of the history space */ + err = nvs_get_blob(my_handle, key_str, NULL, &required_size); + + /* Check if we can store data at that sector or not*/ + if(required_size >= (NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))) + { + /* Reset the required_size again to 0 */ + required_size = 0; + + /* if not then check the next sector */ + sector_counter++; + } + else + { + /* if yes then increase the size of data to be stored by one element */ + required_size += sizeof(historyLog_t); + break; + } + }while(sector_counter <= NVM_NUMBER_OF_SECTORS); + + /* Make sure that there are some free sectors to store data in */ + if(sector_counter <= NVM_NUMBER_OF_SECTORS) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, key_str, history_data, required_size); + + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) + ESP_LOGI(TAG," ---> History space not there"); + + if (required_size == 0) + { + ESP_LOGI(TAG," ---> Nothing saved yet"); + } + else + { + // Commit + err = nvs_commit(my_handle); + if (err == ESP_OK) + ESP_LOGI(TAG," ---> the new history data has been committed successfully to nvm-sector %d\nand its size now is %d (max allowed size is %d)",sector_counter,required_size,(NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))); + } + } + else + { + ESP_LOGE(TAG," ----> All the NVM sectors are full. can't store additional data"); + } + } + + // Close + nvs_close(my_handle); +} + +/**/ +size_t nvm_read_history_data(historyLog_t* history_data, uint8_t sector_number) +{ + esp_err_t err; + size_t required_size = 0; // value will default to 0, if not set yet in NVS + + char key_str[18]; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + /* Setup the NVS sector to write to */ + sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_number); + + // obtain required memory space to store blob being read from NVS + err = nvs_get_blob(my_handle, key_str, NULL, &required_size); + + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) + ESP_LOGI(TAG," ---> History not found yet"); + + //ESP_LOGI(TAG,"History data are:"); + + if (required_size == 0) + { + ESP_LOGI(TAG," ---> Nothing saved yet!\n"); + } + else + { + err = nvs_get_blob(my_handle, key_str, history_data, &required_size); + if (err != ESP_OK) + { + ESP_LOGI(TAG," ---> ERROR in retrieving history data for NVM sector %d",sector_number); + } + } + } + + // Close + nvs_close(my_handle); + + return required_size; +} + +/**/ +void nvm_clear_history_sector(uint8_t sector_num) +{ + esp_err_t wifi_err; + uint8_t wifi_onboarding; + uint8_t cell_onboarding; + uint8_t comms_mode; + char ssid[32] = {0}; + char pswd[64] = {0}; + + ESP_LOGI(TAG,"Clearing NVM History Sectors After successful POST process"); + + /* If there are some written data in the first sector ---> then this means that you should clear it. otherwise no (just to save read-write cycles for nvs) */ + if(nvm_read_history_data(NULL,1)) + { + /* 1- Firstly retrieve stored data in NVS */ + wifi_onboarding = nvm_read_onboarding_flag(WIFI_ONBOARDING_KEY); + cell_onboarding = nvm_read_onboarding_flag(CELL_ONBOARDING_KEY); + comms_mode = nvm_read_comms_mode(); + wifi_err = nvm_read_wifi_credentials(ssid,pswd); + + /* Reload the WDT */ + vTaskDelay(10/portTICK_PERIOD_MS); + + /* 2- Clear NVS partition */ + nvm_clear(); + + /* Reload the WDT */ + vTaskDelay(10/portTICK_PERIOD_MS); + + /* 3- Store the retrieved data again in NVS */ + nvm_write_onboarding_flag(WIFI_ONBOARDING_KEY,wifi_onboarding); + nvm_write_onboarding_flag(CELL_ONBOARDING_KEY,cell_onboarding); + nvm_write_comms_mode(comms_mode); + if(wifi_err == ESP_OK) + nvm_write_wifi_credentials(ssid,32,pswd,64); + } + + +#if 0 + esp_err_t err; + char key_str[18]; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + for(int sector_counter=1; sector_counter<=NVM_NUMBER_OF_SECTORS; sector_counter++) + { + /* Setup the NVS sector to clear */ + sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); + + /* Check which sector number need to be cleared */ + if((sector_num == sector_counter) || ((sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, key_str, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector %d",sector_counter); + break; + } + else + { + /* Check if the sector_num isn't equal to the NVM_HISTORY_ALL_SECTORS then break the loop after first successful clear process */ + if(sector_num != NVM_HISTORY_ALL_SECTORS) + { + break; + } + } + } + } +#endif +#if 0 + if((sector_num == NVM_HISTORY_SECTOR_1) || ((sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR1, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 1"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_2) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR2, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 2"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_3) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR3, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 3"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_4) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR4, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 4"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_5) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR5, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 5"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_6) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR6, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 6"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_7) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR7, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 7"); + } + } + + if((err == ESP_OK) && ((sector_num == NVM_HISTORY_SECTOR_8) || (sector_num == NVM_HISTORY_ALL_SECTORS))) + { + /* set the new values for the history data */ + err = nvs_set_blob(my_handle, NVM_HISTORY_SECTOR8, NULL, 0); + if(err != ESP_OK) + { + ESP_LOGI(TAG,"Failed to clear sector 8"); + } + } +#endif +// err = nvs_commit(my_handle); +// } + + // Close +// nvs_close(my_handle); +} + +/**/ +uint8_t nvm_get_last_written_history_sector(void) +{ + esp_err_t err; + size_t required_size = 0; // value will default to 0, if not set yet in NVS + + char key_str[18]; + uint8_t sector_counter = 1; + + /*Storing the on-boarding value in the NVS so that to indicate that each time power on/off the value would be the same*/ + //ESP_LOGI(TAG,"Opening Non-Volatile Storage (NVS) handle... "); + err = nvs_open("storage", NVS_READWRITE, &my_handle); + + /* Make sure that NVS is initialized */ + if(ESP_ERR_NVS_NOT_INITIALIZED == err) + { + /* initialized it if not */ + err = nvs_flash_init(); + + /* Check if the response is OK then OPEN it */ + if(err == ESP_OK) + { + /* Retry to open the NVS */ + err = nvs_open("storage", NVS_READWRITE, &my_handle); + } + else + { + /* Print this LOG if failed to initialize it */ + ESP_LOGI(TAG,"Failed to reinitialized The NVS partition"); + } + } + + if (err != ESP_OK) + { + ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } + else + { + do + { + /* Setup the key of NVS sector to read the size of it's written data */ + sprintf(key_str,NVM_HISTORY_DATA_KEY,sector_counter); + + /* get the size of the history space */ + err = nvs_get_blob(my_handle, key_str, NULL, &required_size); + + /* Check if that sector is not full */ + if(required_size >= (NVM_MAX_NUMBER_OF_IN_ONE_SECTOR*sizeof(historyLog_t))) + { + /* Reset the required_size again to 0 */ + required_size = 0; + + /* if full then check the next sector */ + sector_counter++; + } + else + { + /* if not full then return the sector_number */ + break; + } + }while(sector_counter <= NVM_NUMBER_OF_SECTORS); + + if(sector_counter > NVM_NUMBER_OF_SECTORS) + { + /* Setup the key of NVS sector to read it's written data */ + sector_counter--; + } + } + + // Close + nvs_close(my_handle); + + return sector_counter; +} + + + +/**/ +void nvm_set_last_posted_history_sector(uint8_t sector_num) +{ + if(sector_num <= NVM_NUMBER_OF_SECTORS) + last_posted_sector = sector_num; + else + last_posted_sector = 0; +} + +/**/ +uint8_t nvm_get_last_posted_history_sector(void) +{ + return last_posted_sector; +} + + + + diff --git a/main/nvm.h b/main/nvm.h index cbf0e83..b1498b5 100644 --- a/main/nvm.h +++ b/main/nvm.h @@ -1,74 +1,74 @@ -/* - * nvm.h - * - * Created on: Aug 14, 2023 - * Author: Sword - */ - -#ifndef MAIN_NVM_H_ -#define MAIN_NVM_H_ - -#include "data_processing.h" - -#define NVM_CELL_ONBOARDING_KEY "on_boarding" -#define NVM_WIFI_ONBOARDING_KEY "wifi_onboarding" -#define NVM_WIFI_SSID_KEY "wifi_ssid" -#define NVM_WIFI_SSID_LENGTH_KEY "wifi_ssid_len" -#define NVM_WIFI_PSWD_KEY "wifi_pswd" -#define NVM_WIFI_PSWD_LENGTH_KEY "wifi_pswd_len" -#define NVM_COMMS_MODE_KEY "commsMode" -#define NVM_HISTORY_DATA_KEY "history_data%u" - -#define NVM_HISTORY_SECTOR1 "history_data1" -#define NVM_HISTORY_SECTOR2 "history_data2" -#define NVM_HISTORY_SECTOR3 "history_data3" -#define NVM_HISTORY_SECTOR4 "history_data4" -#define NVM_HISTORY_SECTOR5 "history_data5" -#define NVM_HISTORY_SECTOR6 "history_data6" -#define NVM_HISTORY_SECTOR7 "history_data7" -#define NVM_HISTORY_SECTOR8 "history_data8" - -#define NVM_ONBOARDING_SET_VAL 1 -#define NVM_ONBOARDING_NOT_SET_VAL 0 -#define NVM_ONBOARDING_NOT_STORED_VAL 2 - -#define NVM_MAX_NUMBER_OF_ALL_READINGS 750 //max number of sensor_readings in all NVM sector -#define NVM_MAX_NUMBER_OF_IN_ONE_SECTOR 20 //max number of readings in one NVM/NVS sector -#define NVM_NUMBER_OF_SECTORS ((NVM_MAX_NUMBER_OF_ALL_READINGS) / NVM_MAX_NUMBER_OF_IN_ONE_SECTOR) // ----> number_of_sectors = max_num_readings / number of readings in one NVM sector -#define NVM_ONE_SECOTR_SIZE (37 * (NVM_NUMBER_OF_SECTORS)) - -#define NVM_HISTORY_ALL_SECTORS (NVM_NUMBER_OF_SECTORS+1) - -typedef enum -{ - WIFI_ONBOARDING_KEY, - CELL_ONBOARDING_KEY -}onboarding_type_t; - - -void nvm_init(void); -void nvm_clear(void); - - -uint8_t nvm_read_onboarding_flag(onboarding_type_t flag_key); -void nvm_write_onboarding_flag(onboarding_type_t flag_key, uint8_t flag_value); - - -uint8_t nvm_read_comms_mode(void); -void nvm_write_comms_mode(uint8_t commsMode); - - -esp_err_t nvm_read_wifi_credentials(char* ssid, char* pswd); -void nvm_write_wifi_credentials(char* ssid, uint8_t ssid_len, char* pswd, uint8_t pswd_len); - - -void nvm_write_history_data(historyLog_t* history_data); -size_t nvm_read_history_data(historyLog_t* history_data, uint8_t sector_number); -void nvm_clear_history_sector(uint8_t sector_num); -uint8_t nvm_get_last_written_history_sector(void); - - -void nvm_set_last_posted_history_sector(uint8_t sector_num); -uint8_t nvm_get_last_posted_history_sector(void); - -#endif /* MAIN_NVM_H_ */ +/* + * nvm.h + * + * Created on: Aug 14, 2023 + * Author: Sword + */ + +#ifndef MAIN_NVM_H_ +#define MAIN_NVM_H_ + +#include "data_processing.h" + +#define NVM_CELL_ONBOARDING_KEY "on_boarding" +#define NVM_WIFI_ONBOARDING_KEY "wifi_onboarding" +#define NVM_WIFI_SSID_KEY "wifi_ssid" +#define NVM_WIFI_SSID_LENGTH_KEY "wifi_ssid_len" +#define NVM_WIFI_PSWD_KEY "wifi_pswd" +#define NVM_WIFI_PSWD_LENGTH_KEY "wifi_pswd_len" +#define NVM_COMMS_MODE_KEY "commsMode" +#define NVM_HISTORY_DATA_KEY "history_data%u" + +#define NVM_HISTORY_SECTOR1 "history_data1" +#define NVM_HISTORY_SECTOR2 "history_data2" +#define NVM_HISTORY_SECTOR3 "history_data3" +#define NVM_HISTORY_SECTOR4 "history_data4" +#define NVM_HISTORY_SECTOR5 "history_data5" +#define NVM_HISTORY_SECTOR6 "history_data6" +#define NVM_HISTORY_SECTOR7 "history_data7" +#define NVM_HISTORY_SECTOR8 "history_data8" + +#define NVM_ONBOARDING_SET_VAL 1 +#define NVM_ONBOARDING_NOT_SET_VAL 0 +#define NVM_ONBOARDING_NOT_STORED_VAL 2 + +#define NVM_MAX_NUMBER_OF_ALL_READINGS 750 //max number of sensor_readings in all NVM sector +#define NVM_MAX_NUMBER_OF_IN_ONE_SECTOR 20 //max number of readings in one NVM/NVS sector +#define NVM_NUMBER_OF_SECTORS ((NVM_MAX_NUMBER_OF_ALL_READINGS) / NVM_MAX_NUMBER_OF_IN_ONE_SECTOR) // ----> number_of_sectors = max_num_readings / number of readings in one NVM sector +#define NVM_ONE_SECOTR_SIZE (37 * (NVM_NUMBER_OF_SECTORS)) + +#define NVM_HISTORY_ALL_SECTORS (NVM_NUMBER_OF_SECTORS+1) + +typedef enum +{ + WIFI_ONBOARDING_KEY, + CELL_ONBOARDING_KEY +}onboarding_type_t; + + +void nvm_init(void); +void nvm_clear(void); + + +uint8_t nvm_read_onboarding_flag(onboarding_type_t flag_key); +void nvm_write_onboarding_flag(onboarding_type_t flag_key, uint8_t flag_value); + + +uint8_t nvm_read_comms_mode(void); +void nvm_write_comms_mode(uint8_t commsMode); + + +esp_err_t nvm_read_wifi_credentials(char* ssid, char* pswd); +void nvm_write_wifi_credentials(char* ssid, uint8_t ssid_len, char* pswd, uint8_t pswd_len); + + +void nvm_write_history_data(historyLog_t* history_data); +size_t nvm_read_history_data(historyLog_t* history_data, uint8_t sector_number); +void nvm_clear_history_sector(uint8_t sector_num); +uint8_t nvm_get_last_written_history_sector(void); + + +void nvm_set_last_posted_history_sector(uint8_t sector_num); +uint8_t nvm_get_last_posted_history_sector(void); + +#endif /* MAIN_NVM_H_ */ diff --git a/main/ota.c b/main/ota.c index d5b891a..e45f7c3 100644 --- a/main/ota.c +++ b/main/ota.c @@ -1,424 +1,424 @@ -/* - * ota.c - * - * Created on: Feb 13, 2023 - * Author: Sword - */ - - -/* OTA example - This example code is in the Public Domain (or CC0 licensed, at your option.) - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. - */ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#include "esp_event.h" -#include "esp_ota_ops.h" -#include "esp_app_format.h" -#include "esp_log.h" -#include "esp_flash_partitions.h" -#include "esp_partition.h" -#include "nvs.h" -#include "nvs_flash.h" -#include "driver/gpio.h" -#include "ota.h" - - -#define BUFFSIZE 2048 -#define HASH_LEN 32 /* SHA-256 digest length */ -#define LOG_LOCAL_LEVEL ESP_LOG_INFO - -static const char *TAG = "OTA"; - -/*an ota data write buffer ready to write to the flash*/ -static char *ota_write_data; -static ota_bytes_status_t ota_bytes = OTA_BYTES_WRITTEN_WAIT; -static uint32_t ota_file_size = OTA_WITH_SEQUENTIAL_WRITES; - -esp_ota_handle_t update_handle; -const esp_partition_t *update_partition = NULL; -const esp_partition_t *configured = NULL; -const esp_partition_t *running = NULL; - -static uint8_t ota_needed = OTA_NOT_NEEDED; -static int data_read = -1; -int binary_file_length; -bool image_header_was_checked; - -#define OTA_URL_SIZE 256 - - -/******************************************************/ -/********** Static Functions for OTA-Process **********/ -/******************************************************/ -static void print_sha256 (const uint8_t *image_hash, const char *label) -{ - char hash_print[HASH_LEN * 2 + 1]; - hash_print[HASH_LEN * 2] = 0; - for (int i = 0; i < HASH_LEN; ++i) { - sprintf(&hash_print[i * 2], "%02x", image_hash[i]); - } - ESP_LOGI(TAG, "%s: %s", label, hash_print); -} - -static void ota_start_session(void) -{ - /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ - update_handle = 0; - update_partition = NULL; - - /* Get partition info of currently configured boot app (the partition for current app)*/ - configured = esp_ota_get_boot_partition(); - /* Get partition info of currently running app (the partition for current app)*/ - running = esp_ota_get_running_partition(); - - - ESP_LOGI(TAG, "Starting OTA session"); - - /* The result of esp_ota_get_boot_partition() is usually the same as esp_ota_get_running_partition(). - * The two results are not equal if the configured boot partition does not contain a valid app (meaning that - * the running partition will be an app that the bootloader chose via fallback) */ - if (configured != running) { - ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", - (unsigned int)configured->address, (unsigned int)running->address); - ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); - } - ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", - running->type, running->subtype, (unsigned int)running->address); - - /* The following line returns the next OTA app partition which should be written with a new firmware*/ - /* So, update_partition is the partition where the new image will be written*/ - update_partition = esp_ota_get_next_update_partition(NULL); - - assert(update_partition != NULL); - ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", - update_partition->subtype, (unsigned int)update_partition->address); - - /*deal with all receive packet*/ - image_header_was_checked = false; - -} - -static void ota_process_incoming_image(void) -{ - esp_err_t err; - - if ((data_read < 0) && (OTA_NEEDED == ota_needed)) { - ESP_LOGE(TAG, "Error: No OTA data have been received yet"); - } - else if ((data_read > 0) && (OTA_NEEDED == ota_needed)) { - if (image_header_was_checked == false) { - esp_app_desc_t new_app_info; - if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { - // check current version with downloading - /* 1- Check the firmware version of the new fetched-app*/ - memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); - ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); - - /* 2- Check the firmware version of the current running app*/ - esp_app_desc_t running_app_info; - if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); - } - - /* 3- Check the firmware version of the last disabled/aborted/invalid app (which is an app that )*/ - const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition(); - esp_app_desc_t invalid_app_info; - if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { - /*---> Stop OTA updating*/ - ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); - } - - // check current version with last invalid partition - /* 4- Compare the new fetched-image with the last invalid-image*/ - if (last_invalid_app != NULL) { - if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { - /*---> Stop OTA updating*/ - ESP_LOGW(TAG, "New version is the same as invalid version."); - ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version); - ESP_LOGW(TAG, "The firmware has been rolled back to the previous version."); - - /* EXIT OTA task*/ - ota_bytes = OTA_BYTES_WRITTEN_FAILED; - return; - } - } - - /* 5- Compare the new-fetched-image with the current running-image*/ - if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { - /*---> Stop OTA updating*/ - ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update."); - - /* EXIT OTA task*/ - ota_bytes = OTA_BYTES_WRITTEN_FAILED; - return; - } - - /* 7- Start an OTA-update writing to the specified partition. - The specified partition is erased to the specified image size. - If image size is not yet known, pass OTA_SIZE_UNKNOWN which will cause the entire partition to be erased.*/ - err = esp_ota_begin(update_partition, ota_file_size, &update_handle); - if (err != ESP_OK) { - /*---> Stop OTA updating*/ - ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); - esp_ota_abort(update_handle); - ESP_LOGI(TAG, "Aborting the update-data partition"); - - /* EXIT OTA task*/ - ota_bytes = OTA_BYTES_WRITTEN_FAILED; - return; - } - - /* 6- Set the image_header_checked flag to be true*/ - image_header_was_checked = true; - - ESP_LOGI(TAG, "esp_ota_begin succeeded"); - } else { - /*---> Stop OTA updating*/ - ESP_LOGE(TAG, "received package is not fit len"); - esp_ota_abort(update_handle); - ESP_LOGI(TAG, "Aborting the update-data partition"); - - /* EXIT OTA task*/ - ota_bytes = OTA_BYTES_WRITTEN_FAILED; - return; - } - } - /* 8- Write OTA update data to partition. - * This function can be called multiple times as data is received during the OTA operation. - * Data is written sequentially to the partition */ - err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); - if (err != ESP_OK) { - /*---> Stop OTA updating*/ - esp_ota_abort(update_handle); - ESP_LOGI(TAG, "Aborting the update-data partition"); - - /* EXIT OTA task*/ - ota_bytes = OTA_BYTES_WRITTEN_FAILED; - return; - } - /* 9- Set the binary file length*/ - binary_file_length += data_read; - /* Reset data_read variable to 0*/ - data_read = 0; - ESP_LOGD(TAG, "Written bytes length %d", binary_file_length); - ota_bytes = OTA_BYTES_WRITTEN_SUCCESS; - } - else if ((data_read == 0) && (OTA_FINISHED == ota_needed)) { - ESP_LOGI(TAG, "OTA session finished"); - ota_bytes = OTA_BYTES_WRITTEN_SUCCESS; - return; - } -} - -static void ota_end_session(void) -{ - esp_err_t err; - if(OTA_BYTES_WRITTEN_SUCCESS == ota_bytes) - { - ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length); - /* 10- Checks if entire data in the response has been read without any error */ - if ( OTA_FINISHED != ota_needed ) { - ESP_LOGI(TAG, "OTA session stopped for errors but didn't get finished"); - esp_ota_abort(update_handle); - ESP_LOGI(TAG, "Aborting the update-data partition"); - /* EXIT OTA task*/ - return ; - } - - /* 11- Finish OTA update and validate newly written app image*/ - err = esp_ota_end(update_handle); - if (err != ESP_OK) { - /*---> Stop OTA updating*/ - if (err == ESP_ERR_OTA_VALIDATE_FAILED) { - ESP_LOGI(TAG, "Image validation failed, image is corrupted"); - } else { - ESP_LOGI(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); - } - /* EXIT OTA task*/ - return ; - } - - /* 12- Set the new validated-written image to be the boot partition (Configure OTA data for a new boot partition) - * On the next restart, ESP will boot from that new partition*/ - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - /*Stop OTA update*/ - ESP_LOGI(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); - - /* EXIT OTA task*/ - return ; - } - /* 13- Restart the device (ESP32)*/ - ESP_LOGI(TAG, "Prepare to restart system!"); - esp_restart(); - return ; - } - else if(OTA_BYTES_WRITTEN_FAILED == ota_bytes) - { - ESP_LOGI(TAG,"No Changing in boot_partition"); - } -} - -static bool diagnostic(void) -{ - /* gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << CONFIG_EXAMPLE_GPIO_DIAGNOSTIC); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - ESP_LOGI(TAG, "Diagnostics (5 sec)..."); - vTaskDelay(5000 / portTICK_PERIOD_MS); - - bool diagnostic_is_ok = gpio_get_level(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC); - - gpio_reset_pin(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);*/ - return true; -} - - -void ota_set_needed(void) -{ - ota_needed = OTA_NEEDED; -} - -void ota_set_not_needed(void) -{ - ota_needed = OTA_NOT_NEEDED; -} - -void ota_set_finished(void) -{ - ota_needed = OTA_FINISHED; -} - -/******************************************************/ -/* Functions that gonna be used in comms state machine*/ -/******************************************************/ -esp_err_t ota_init(uint32_t fileSize) -{ - /*This function should be invoked in the ota_file_open_cb() in comms.c (instead of the OTA_Offline_Init())*/ - uint8_t sha_256[HASH_LEN] = { 0 }; - esp_partition_t partition; - - // get sha256 digest for the partition table - partition.address = ESP_PARTITION_TABLE_OFFSET; - partition.size = ESP_PARTITION_TABLE_MAX_LEN; - partition.type = ESP_PARTITION_TYPE_DATA; - esp_partition_get_sha256(&partition, sha_256); - print_sha256(sha_256, "SHA-256 for the partition table: "); - - // get sha256 digest for bootloader - partition.address = ESP_BOOTLOADER_OFFSET; - partition.size = ESP_PARTITION_TABLE_OFFSET; - partition.type = ESP_PARTITION_TYPE_APP; - esp_partition_get_sha256(&partition, sha_256); - print_sha256(sha_256, "SHA-256 for bootloader: "); - - // get sha256 digest for running partition - esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256); - print_sha256(sha_256, "SHA-256 for current firmware: "); - - const esp_partition_t *running = esp_ota_get_running_partition(); - esp_ota_img_states_t ota_state; - if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { - if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { - // run diagnostic function ... - bool diagnostic_is_ok = diagnostic(); - if (diagnostic_is_ok) { - ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ..."); - esp_ota_mark_app_valid_cancel_rollback(); - } else { - ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ..."); - esp_ota_mark_app_invalid_rollback_and_reboot(); - - } - } - } - - /*set the ota file size */ - if(0 == fileSize) - fileSize = OTA_WITH_SEQUENTIAL_WRITES; - else - ota_file_size = fileSize; - - /* Initialize OTA session*/ - ota_start_session(); - - /* */ - return ESP_OK; -} - -esp_err_t ota_get_data_to_buffer(const char* buf, int buf_len) -{ - /* This function should be called in comms.c inside the callback function ota_file_data_cb() */ - /* This function should copy the bytes that we get from qfread command via uart*/ - /* handle of qfread cmd stores the incoming bytes from modem via uart in buf */ - /* After that we gonna use ota-buffer in ota_process_incoming_image() function to start ota-session*/ - - esp_err_t retval = ESP_FAIL; - int index = 0; - - /*Check if the number of bytes to be processed is greater than ota-buffer size*/ - /*if(BUFFSIZE < buf_len) - { - ESP_LOGI(TAG, "Number of bytes to be processed is greater than the size of OTA buffer"); - return retval; - }*/ - - /* Set the status of ota-bytes to be processed ---> OTA_BYTES_WRITTEN_WAIT*/ - ota_bytes = OTA_BYTES_WRITTEN_WAIT; - - /* Reset the number of bytes that have been read to 0 (because the initial value is -1)*/ - data_read = 0; - - /*Copy the incoming bytes (from uart) to ota-buffer */ - //for(index = 0; index < buf_len; index++) - { - ota_write_data = (char*)buf; - data_read = buf_len; - } - - /*Start OTA_Writing session*/ - ota_set_needed(); - - /*OTA process and writing for the copied bytes*/ - ota_process_incoming_image(); - - /* Check the status of the bytes after OTA-processing/OTA-writing */ - if(OTA_BYTES_WRITTEN_SUCCESS == ota_bytes) - retval = ESP_OK; - else if(OTA_BYTES_WRITTEN_FAILED == ota_bytes) - retval = ESP_FAIL; - - return retval; -} - -void ota_finish_processing(void) -{ - /*This function should be invoked in the COMMS_STATE_WAIT_MCU_UPDATE state in comms state machine - * (instead of the OTA_terminate_connection() )*/ - - /* Reset data_read variable to 0*/ - data_read = 0; - - /* Rise ota_finish flag*/ - ota_set_finished(); - - /* Rise the bytes_success flag*/ - ota_process_incoming_image(); - - /* End the ota_session by validating the image and then rebooting */ - ota_end_session(); -} - - - - +/* + * ota.c + * + * Created on: Feb 13, 2023 + * Author: Sword + */ + + +/* OTA example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_ota_ops.h" +#include "esp_app_format.h" +#include "esp_log.h" +#include "esp_flash_partitions.h" +#include "esp_partition.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "driver/gpio.h" +#include "ota.h" + + +#define BUFFSIZE 2048 +#define HASH_LEN 32 /* SHA-256 digest length */ +#define LOG_LOCAL_LEVEL ESP_LOG_INFO + +static const char *TAG = "OTA"; + +/*an ota data write buffer ready to write to the flash*/ +static char *ota_write_data; +static ota_bytes_status_t ota_bytes = OTA_BYTES_WRITTEN_WAIT; +static uint32_t ota_file_size = OTA_WITH_SEQUENTIAL_WRITES; + +esp_ota_handle_t update_handle; +const esp_partition_t *update_partition = NULL; +const esp_partition_t *configured = NULL; +const esp_partition_t *running = NULL; + +static uint8_t ota_needed = OTA_NOT_NEEDED; +static int data_read = -1; +int binary_file_length; +bool image_header_was_checked; + +#define OTA_URL_SIZE 256 + + +/******************************************************/ +/********** Static Functions for OTA-Process **********/ +/******************************************************/ +static void print_sha256 (const uint8_t *image_hash, const char *label) +{ + char hash_print[HASH_LEN * 2 + 1]; + hash_print[HASH_LEN * 2] = 0; + for (int i = 0; i < HASH_LEN; ++i) { + sprintf(&hash_print[i * 2], "%02x", image_hash[i]); + } + ESP_LOGI(TAG, "%s: %s", label, hash_print); +} + +static void ota_start_session(void) +{ + /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ + update_handle = 0; + update_partition = NULL; + + /* Get partition info of currently configured boot app (the partition for current app)*/ + configured = esp_ota_get_boot_partition(); + /* Get partition info of currently running app (the partition for current app)*/ + running = esp_ota_get_running_partition(); + + + ESP_LOGI(TAG, "Starting OTA session"); + + /* The result of esp_ota_get_boot_partition() is usually the same as esp_ota_get_running_partition(). + * The two results are not equal if the configured boot partition does not contain a valid app (meaning that + * the running partition will be an app that the bootloader chose via fallback) */ + if (configured != running) { + ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", + (unsigned int)configured->address, (unsigned int)running->address); + ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); + } + ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", + running->type, running->subtype, (unsigned int)running->address); + + /* The following line returns the next OTA app partition which should be written with a new firmware*/ + /* So, update_partition is the partition where the new image will be written*/ + update_partition = esp_ota_get_next_update_partition(NULL); + + assert(update_partition != NULL); + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", + update_partition->subtype, (unsigned int)update_partition->address); + + /*deal with all receive packet*/ + image_header_was_checked = false; + +} + +static void ota_process_incoming_image(void) +{ + esp_err_t err; + + if ((data_read < 0) && (OTA_NEEDED == ota_needed)) { + ESP_LOGE(TAG, "Error: No OTA data have been received yet"); + } + else if ((data_read > 0) && (OTA_NEEDED == ota_needed)) { + if (image_header_was_checked == false) { + esp_app_desc_t new_app_info; + if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { + // check current version with downloading + /* 1- Check the firmware version of the new fetched-app*/ + memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); + + /* 2- Check the firmware version of the current running app*/ + esp_app_desc_t running_app_info; + if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); + } + + /* 3- Check the firmware version of the last disabled/aborted/invalid app (which is an app that )*/ + const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition(); + esp_app_desc_t invalid_app_info; + if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { + /*---> Stop OTA updating*/ + ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); + } + + // check current version with last invalid partition + /* 4- Compare the new fetched-image with the last invalid-image*/ + if (last_invalid_app != NULL) { + if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { + /*---> Stop OTA updating*/ + ESP_LOGW(TAG, "New version is the same as invalid version."); + ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version); + ESP_LOGW(TAG, "The firmware has been rolled back to the previous version."); + + /* EXIT OTA task*/ + ota_bytes = OTA_BYTES_WRITTEN_FAILED; + return; + } + } + + /* 5- Compare the new-fetched-image with the current running-image*/ + if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { + /*---> Stop OTA updating*/ + ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update."); + + /* EXIT OTA task*/ + ota_bytes = OTA_BYTES_WRITTEN_FAILED; + return; + } + + /* 7- Start an OTA-update writing to the specified partition. + The specified partition is erased to the specified image size. + If image size is not yet known, pass OTA_SIZE_UNKNOWN which will cause the entire partition to be erased.*/ + err = esp_ota_begin(update_partition, ota_file_size, &update_handle); + if (err != ESP_OK) { + /*---> Stop OTA updating*/ + ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); + esp_ota_abort(update_handle); + ESP_LOGI(TAG, "Aborting the update-data partition"); + + /* EXIT OTA task*/ + ota_bytes = OTA_BYTES_WRITTEN_FAILED; + return; + } + + /* 6- Set the image_header_checked flag to be true*/ + image_header_was_checked = true; + + ESP_LOGI(TAG, "esp_ota_begin succeeded"); + } else { + /*---> Stop OTA updating*/ + ESP_LOGE(TAG, "received package is not fit len"); + esp_ota_abort(update_handle); + ESP_LOGI(TAG, "Aborting the update-data partition"); + + /* EXIT OTA task*/ + ota_bytes = OTA_BYTES_WRITTEN_FAILED; + return; + } + } + /* 8- Write OTA update data to partition. + * This function can be called multiple times as data is received during the OTA operation. + * Data is written sequentially to the partition */ + err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); + if (err != ESP_OK) { + /*---> Stop OTA updating*/ + esp_ota_abort(update_handle); + ESP_LOGI(TAG, "Aborting the update-data partition"); + + /* EXIT OTA task*/ + ota_bytes = OTA_BYTES_WRITTEN_FAILED; + return; + } + /* 9- Set the binary file length*/ + binary_file_length += data_read; + /* Reset data_read variable to 0*/ + data_read = 0; + ESP_LOGD(TAG, "Written bytes length %d", binary_file_length); + ota_bytes = OTA_BYTES_WRITTEN_SUCCESS; + } + else if ((data_read == 0) && (OTA_FINISHED == ota_needed)) { + ESP_LOGI(TAG, "OTA session finished"); + ota_bytes = OTA_BYTES_WRITTEN_SUCCESS; + return; + } +} + +static void ota_end_session(void) +{ + esp_err_t err; + if(OTA_BYTES_WRITTEN_SUCCESS == ota_bytes) + { + ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length); + /* 10- Checks if entire data in the response has been read without any error */ + if ( OTA_FINISHED != ota_needed ) { + ESP_LOGI(TAG, "OTA session stopped for errors but didn't get finished"); + esp_ota_abort(update_handle); + ESP_LOGI(TAG, "Aborting the update-data partition"); + /* EXIT OTA task*/ + return ; + } + + /* 11- Finish OTA update and validate newly written app image*/ + err = esp_ota_end(update_handle); + if (err != ESP_OK) { + /*---> Stop OTA updating*/ + if (err == ESP_ERR_OTA_VALIDATE_FAILED) { + ESP_LOGI(TAG, "Image validation failed, image is corrupted"); + } else { + ESP_LOGI(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); + } + /* EXIT OTA task*/ + return ; + } + + /* 12- Set the new validated-written image to be the boot partition (Configure OTA data for a new boot partition) + * On the next restart, ESP will boot from that new partition*/ + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + /*Stop OTA update*/ + ESP_LOGI(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); + + /* EXIT OTA task*/ + return ; + } + /* 13- Restart the device (ESP32)*/ + ESP_LOGI(TAG, "Prepare to restart system!"); + esp_restart(); + return ; + } + else if(OTA_BYTES_WRITTEN_FAILED == ota_bytes) + { + ESP_LOGI(TAG,"No Changing in boot_partition"); + } +} + +static bool diagnostic(void) +{ + /* gpio_config_t io_conf; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = (1ULL << CONFIG_EXAMPLE_GPIO_DIAGNOSTIC); + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + gpio_config(&io_conf); + + ESP_LOGI(TAG, "Diagnostics (5 sec)..."); + vTaskDelay(5000 / portTICK_PERIOD_MS); + + bool diagnostic_is_ok = gpio_get_level(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC); + + gpio_reset_pin(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);*/ + return true; +} + + +void ota_set_needed(void) +{ + ota_needed = OTA_NEEDED; +} + +void ota_set_not_needed(void) +{ + ota_needed = OTA_NOT_NEEDED; +} + +void ota_set_finished(void) +{ + ota_needed = OTA_FINISHED; +} + +/******************************************************/ +/* Functions that gonna be used in comms state machine*/ +/******************************************************/ +esp_err_t ota_init(uint32_t fileSize) +{ + /*This function should be invoked in the ota_file_open_cb() in comms.c (instead of the OTA_Offline_Init())*/ + uint8_t sha_256[HASH_LEN] = { 0 }; + esp_partition_t partition; + + // get sha256 digest for the partition table + partition.address = ESP_PARTITION_TABLE_OFFSET; + partition.size = ESP_PARTITION_TABLE_MAX_LEN; + partition.type = ESP_PARTITION_TYPE_DATA; + esp_partition_get_sha256(&partition, sha_256); + print_sha256(sha_256, "SHA-256 for the partition table: "); + + // get sha256 digest for bootloader + partition.address = ESP_BOOTLOADER_OFFSET; + partition.size = ESP_PARTITION_TABLE_OFFSET; + partition.type = ESP_PARTITION_TYPE_APP; + esp_partition_get_sha256(&partition, sha_256); + print_sha256(sha_256, "SHA-256 for bootloader: "); + + // get sha256 digest for running partition + esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256); + print_sha256(sha_256, "SHA-256 for current firmware: "); + + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_img_states_t ota_state; + if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { + if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { + // run diagnostic function ... + bool diagnostic_is_ok = diagnostic(); + if (diagnostic_is_ok) { + ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ..."); + esp_ota_mark_app_valid_cancel_rollback(); + } else { + ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ..."); + esp_ota_mark_app_invalid_rollback_and_reboot(); + + } + } + } + + /*set the ota file size */ + if(0 == fileSize) + fileSize = OTA_WITH_SEQUENTIAL_WRITES; + else + ota_file_size = fileSize; + + /* Initialize OTA session*/ + ota_start_session(); + + /* */ + return ESP_OK; +} + +esp_err_t ota_get_data_to_buffer(const char* buf, int buf_len) +{ + /* This function should be called in comms.c inside the callback function ota_file_data_cb() */ + /* This function should copy the bytes that we get from qfread command via uart*/ + /* handle of qfread cmd stores the incoming bytes from modem via uart in buf */ + /* After that we gonna use ota-buffer in ota_process_incoming_image() function to start ota-session*/ + + esp_err_t retval = ESP_FAIL; + int index = 0; + + /*Check if the number of bytes to be processed is greater than ota-buffer size*/ + /*if(BUFFSIZE < buf_len) + { + ESP_LOGI(TAG, "Number of bytes to be processed is greater than the size of OTA buffer"); + return retval; + }*/ + + /* Set the status of ota-bytes to be processed ---> OTA_BYTES_WRITTEN_WAIT*/ + ota_bytes = OTA_BYTES_WRITTEN_WAIT; + + /* Reset the number of bytes that have been read to 0 (because the initial value is -1)*/ + data_read = 0; + + /*Copy the incoming bytes (from uart) to ota-buffer */ + //for(index = 0; index < buf_len; index++) + { + ota_write_data = (char*)buf; + data_read = buf_len; + } + + /*Start OTA_Writing session*/ + ota_set_needed(); + + /*OTA process and writing for the copied bytes*/ + ota_process_incoming_image(); + + /* Check the status of the bytes after OTA-processing/OTA-writing */ + if(OTA_BYTES_WRITTEN_SUCCESS == ota_bytes) + retval = ESP_OK; + else if(OTA_BYTES_WRITTEN_FAILED == ota_bytes) + retval = ESP_FAIL; + + return retval; +} + +void ota_finish_processing(void) +{ + /*This function should be invoked in the COMMS_STATE_WAIT_MCU_UPDATE state in comms state machine + * (instead of the OTA_terminate_connection() )*/ + + /* Reset data_read variable to 0*/ + data_read = 0; + + /* Rise ota_finish flag*/ + ota_set_finished(); + + /* Rise the bytes_success flag*/ + ota_process_incoming_image(); + + /* End the ota_session by validating the image and then rebooting */ + ota_end_session(); +} + + + + diff --git a/main/ota.h b/main/ota.h index df3ae5d..cde6c56 100644 --- a/main/ota.h +++ b/main/ota.h @@ -1,32 +1,32 @@ -/* - * ota.h - * - * Created on: Feb 13, 2023 - * Author: Sword - */ - -#ifndef MAIN_OTA_H_ -#define MAIN_OTA_H_ - -typedef enum{ - OTA_NEEDED, - OTA_NOT_NEEDED, - OTA_FINISHED -}ota_status_t; - - -typedef enum{ - OTA_BYTES_WRITTEN_SUCCESS, - OTA_BYTES_WRITTEN_FAILED, - OTA_BYTES_WRITTEN_WAIT -}ota_bytes_status_t; - -void ota_set_needed(void); -void ota_set_not_needed(void); -void ota_set_finished(void); - -esp_err_t ota_init(uint32_t fileSize); -esp_err_t ota_get_data_to_buffer(const char* buf, int buf_len); -void ota_finish_processing(void); - -#endif /* MAIN_OTA_H_ */ +/* + * ota.h + * + * Created on: Feb 13, 2023 + * Author: Sword + */ + +#ifndef MAIN_OTA_H_ +#define MAIN_OTA_H_ + +typedef enum{ + OTA_NEEDED, + OTA_NOT_NEEDED, + OTA_FINISHED +}ota_status_t; + + +typedef enum{ + OTA_BYTES_WRITTEN_SUCCESS, + OTA_BYTES_WRITTEN_FAILED, + OTA_BYTES_WRITTEN_WAIT +}ota_bytes_status_t; + +void ota_set_needed(void); +void ota_set_not_needed(void); +void ota_set_finished(void); + +esp_err_t ota_init(uint32_t fileSize); +esp_err_t ota_get_data_to_buffer(const char* buf, int buf_len); +void ota_finish_processing(void); + +#endif /* MAIN_OTA_H_ */ diff --git a/main/wifi_Client.h b/main/wifi_Client.h index c7027ce..c240828 100644 --- a/main/wifi_Client.h +++ b/main/wifi_Client.h @@ -1,50 +1,50 @@ -/* - * tempstick_wifi_client.h - * - * Created on: Jul 28, 2023 - * Author: Sword - */ - -#ifndef MAIN_WIFI_CLIENT_H_ -#define MAIN_WIFI_CLIENT_H_ - -#define WIFI_OK 0 -#define WIFI_FAIL -1 -#define WIFI_MCU_UPDATE_NEEDED 2 - -#define WIFI_OK 0 -#define WIFI_FAIL -1 -#define WIFI_MCU_UPDATE_NEEDED 2 - -typedef enum -{ - GET_CONFIGURATIONS, - GET_MCU_UPDATE_VERSION, - GET_MODEM_UPDATE_VERSION -}get_req_type_t; - -typedef enum -{ - SERVER_ONE, - SERVER_TWO, - SERVER_THREE -}server_type_t; - -#include "wifi_Init.h" -#include "main.h" -#if (WIFI_NEEDED == 1) -esp_err_t http_client_test(char *url); -esp_err_t http_client_post(char *url, char *params, char *response); -void http_client_post_stop(void); -esp_err_t http_client_get(const char *url1, char *response); - -esp_err_t http_client_do_get_request(get_req_type_t target_url, char* device_imei, char *response_buf); -esp_err_t http_client_do_post_request(char *post_params, char *response_buf); -void wifi_set_post_str_type(deviceToServer_msgType_t str);; - -bool registerAcctWithServer(char *typeStr, char *customerAccountIdStr, char *customerAccountPasswordStr, char *customerAccountPasswordAgainStr, char *responseStr, uint16_t responseStrSize); -#endif - - - -#endif /* MAIN_WIFI_CLIENT_H_ */ +/* + * tempstick_wifi_client.h + * + * Created on: Jul 28, 2023 + * Author: Sword + */ + +#ifndef MAIN_WIFI_CLIENT_H_ +#define MAIN_WIFI_CLIENT_H_ + +#define WIFI_OK 0 +#define WIFI_FAIL -1 +#define WIFI_MCU_UPDATE_NEEDED 2 + +#define WIFI_OK 0 +#define WIFI_FAIL -1 +#define WIFI_MCU_UPDATE_NEEDED 2 + +typedef enum +{ + GET_CONFIGURATIONS, + GET_MCU_UPDATE_VERSION, + GET_MODEM_UPDATE_VERSION +}get_req_type_t; + +typedef enum +{ + SERVER_ONE, + SERVER_TWO, + SERVER_THREE +}server_type_t; + +#include "wifi_Init.h" +#include "main.h" +#if (WIFI_NEEDED == 1) +esp_err_t http_client_test(char *url); +esp_err_t http_client_post(char *url, char *params, char *response); +void http_client_post_stop(void); +esp_err_t http_client_get(const char *url1, char *response); + +esp_err_t http_client_do_get_request(get_req_type_t target_url, char* device_imei, char *response_buf); +esp_err_t http_client_do_post_request(char *post_params, char *response_buf); +void wifi_set_post_str_type(deviceToServer_msgType_t str);; + +bool registerAcctWithServer(char *typeStr, char *customerAccountIdStr, char *customerAccountPasswordStr, char *customerAccountPasswordAgainStr, char *responseStr, uint16_t responseStrSize); +#endif + + + +#endif /* MAIN_WIFI_CLIENT_H_ */ diff --git a/main/wifi_Init.h b/main/wifi_Init.h index b723161..626ba9f 100644 --- a/main/wifi_Init.h +++ b/main/wifi_Init.h @@ -1,64 +1,64 @@ -/* - * tempstick_wifi.h - * - * Created on: Jul 28, 2023 - * Author: Sword - */ - -#ifndef MAIN_WIFI_INIT_H_ -#define MAIN_WIFI_INIT_H_ - -#include "main.h" -#if (WIFI_NEEDED == 1) -#include "esp_wifi.h" - -typedef enum -{ - CHECK_IN_STR, - ON_BOARDING_STR -}deviceToServer_msgType_t; - - -#define STORING_TO_NVM - - -#define WIFI_CLIENT_MODE 1 -#define WIFI_AP_MODE 2 -#define WIFI_CLIENT_AP_MODE 3 - - -esp_err_t Connect_wifi_sta(uint8_t mode); -uint8_t wifi_station_connected(void); -bool wifi_isStarted(void); -void Wifi_Init_SoftAp(void); - -esp_err_t wifi_first_init(void); -esp_err_t wifi_stop(void); -void wifi_register_event_handlers(void); -void wifi_sta_disconnecting(void); -void wifi_scan_start(uint16_t *apCount, wifi_ap_record_t **list); - - -void wifi_update_credentials(char *ssid, char *pwd); -char *wifi_get_ssid(void); -char *wifi_get_pswd(void); -void wifi_switchToPrimaryNetwork(void); - - -char *wifi_get_ssidA(void); -char *wifi_get_pswdA(void); -void wifi_set_ssidA(char* ssid); -void wifi_set_pswdA(char* pswd); - -char *wifi_get_ssidB(void); -char *wifi_get_pswdB(void); -void wifi_set_ssidB(char* ssid); -void wifi_set_pswdB(char* pswd); - -bool safeStrCat(char *dest, uint16_t destSize, char *source); - -#endif - - - -#endif /* MAIN_WIFI_INIT_H_ */ +/* + * tempstick_wifi.h + * + * Created on: Jul 28, 2023 + * Author: Sword + */ + +#ifndef MAIN_WIFI_INIT_H_ +#define MAIN_WIFI_INIT_H_ + +#include "main.h" +#if (WIFI_NEEDED == 1) +#include "esp_wifi.h" + +typedef enum +{ + CHECK_IN_STR, + ON_BOARDING_STR +}deviceToServer_msgType_t; + + +#define STORING_TO_NVM + + +#define WIFI_CLIENT_MODE 1 +#define WIFI_AP_MODE 2 +#define WIFI_CLIENT_AP_MODE 3 + + +esp_err_t Connect_wifi_sta(uint8_t mode); +uint8_t wifi_station_connected(void); +bool wifi_isStarted(void); +void Wifi_Init_SoftAp(void); + +esp_err_t wifi_first_init(void); +esp_err_t wifi_stop(void); +void wifi_register_event_handlers(void); +void wifi_sta_disconnecting(void); +void wifi_scan_start(uint16_t *apCount, wifi_ap_record_t **list); + + +void wifi_update_credentials(char *ssid, char *pwd); +char *wifi_get_ssid(void); +char *wifi_get_pswd(void); +void wifi_switchToPrimaryNetwork(void); + + +char *wifi_get_ssidA(void); +char *wifi_get_pswdA(void); +void wifi_set_ssidA(char* ssid); +void wifi_set_pswdA(char* pswd); + +char *wifi_get_ssidB(void); +char *wifi_get_pswdB(void); +void wifi_set_ssidB(char* ssid); +void wifi_set_pswdB(char* pswd); + +bool safeStrCat(char *dest, uint16_t destSize, char *source); + +#endif + + + +#endif /* MAIN_WIFI_INIT_H_ */ diff --git a/main/wifi_OTA.c b/main/wifi_OTA.c index f9e1e64..f55e90b 100644 --- a/main/wifi_OTA.c +++ b/main/wifi_OTA.c @@ -1,283 +1,283 @@ -/* OTA example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_ota_ops.h" -#include "esp_crt_bundle.h" -#include "esp_app_format.h" -#include "esp_http_client.h" -#include "esp_flash_partitions.h" -#include "esp_partition.h" -#include "errno.h" -#include "main.h" -#include "comms.h" -#include "wifi_OTA.h" - -#define BUFFSIZE 1024 -#define HASH_LEN 32 /* SHA-256 digest length */ - -static const char *TAG = "WIFI_OTA"; -/*an ota data write buffer ready to write to the flash*/ -static char ota_write_data[BUFFSIZE + 1] = { 0 }; - -#define OTA_URL_SIZE 256 - -char ota_url[OTA_URL_SIZE]; -wifi_ota_status_t ota_process_state; - -static void http_cleanup(esp_http_client_handle_t client) -{ - esp_http_client_close(client); - esp_http_client_cleanup(client); -} - -static void task_fatal_error(void) -{ - ESP_LOGE(TAG, "Exiting task due to fatal error during ota process..."); - (void)vTaskDelete(NULL); - ota_process_state = OTA_FATAL_ERROR; -} - -static void print_sha256 (const uint8_t *image_hash, const char *label) -{ - char hash_print[HASH_LEN * 2 + 1]; - hash_print[HASH_LEN * 2] = 0; - for (int i = 0; i < HASH_LEN; ++i) { - sprintf(&hash_print[i * 2], "%02x", image_hash[i]); - } - ESP_LOGI(TAG, "%s: %s", label, hash_print); -} - -static void infinite_loop(void) -{ - int i = 0; - ESP_LOGI(TAG, "The firmware that is available on the server is an OLD image\n WIFI-OTA stopped."); - ota_process_state = OTA_FATAL_ERROR; -} - -static void wifi_ota_task(void *pvParameter) -{ - esp_err_t err; - /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ - esp_ota_handle_t update_handle = 0 ; - const esp_partition_t *update_partition = NULL; - - ESP_LOGI(TAG, "Starting WIFI Firmware Update Process"); - - const esp_partition_t *configured = esp_ota_get_boot_partition(); - const esp_partition_t *running = esp_ota_get_running_partition(); - - if (configured != running) { - ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08"PRIx32", but running from offset 0x%08"PRIx32,configured->address, running->address); - ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); - } - ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",running->type, running->subtype, running->address); - - esp_http_client_config_t config = { - .url = ota_url, - .crt_bundle_attach = esp_crt_bundle_attach, - .timeout_ms = 5000, - .keep_alive_enable = true, - }; - - esp_http_client_handle_t client = esp_http_client_init(&config); - if (client == NULL) { - ESP_LOGE(TAG, "Failed to initialise HTTP connection"); - task_fatal_error(); - } - else - { - ESP_LOGI(TAG,"URL is : %s",config.url); - } - - err = esp_http_client_open(client, 0); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); - task_fatal_error(); - } - esp_http_client_fetch_headers(client); - - update_partition = esp_ota_get_next_update_partition(NULL); - assert(update_partition != NULL); - ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32,update_partition->subtype, update_partition->address); - - int binary_file_length = 0; - /*deal with all receive packet*/ - bool image_header_was_checked = false; - while (1) { - int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); - if (data_read < 0) { - ESP_LOGE(TAG, "Error: SSL data read error"); - http_cleanup(client); - task_fatal_error(); - } else if (data_read > 0) { - if (image_header_was_checked == false) { - esp_app_desc_t new_app_info; - if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { - // check current version with downloading - memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); - ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); - - esp_app_desc_t running_app_info; - if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); - } - - const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition(); - esp_app_desc_t invalid_app_info; - if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); - } - - // check current version with last invalid partition - if (last_invalid_app != NULL) { - if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { - ESP_LOGW(TAG, "New version is the same as invalid version."); - ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version); - ESP_LOGW(TAG, "The firmware has been rolled back to the previous version."); - http_cleanup(client); - infinite_loop(); - } - } -#ifndef CONFIG_EXAMPLE_SKIP_VERSION_CHECK - if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { - ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update."); - http_cleanup(client); - infinite_loop(); - } -#endif - - image_header_was_checked = true; - - err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); - http_cleanup(client); - esp_ota_abort(update_handle); - task_fatal_error(); - } - ESP_LOGI(TAG, "esp_ota_begin succeeded"); - } else { - ESP_LOGE(TAG, "received package is not fit len"); - http_cleanup(client); - esp_ota_abort(update_handle); - task_fatal_error(); - } - } - err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); - if (err != ESP_OK) { - http_cleanup(client); - esp_ota_abort(update_handle); - task_fatal_error(); - } - binary_file_length += data_read; - ESP_LOGI(TAG, "Written image length %d", binary_file_length); - } else if (data_read == 0) { - /* - * As esp_http_client_read never returns negative error code, we rely on - * `errno` to check for underlying transport connectivity closure if any - */ - if (errno == ECONNRESET || errno == ENOTCONN) { - ESP_LOGE(TAG, "Connection closed, errno = %d", errno); - break; - } - if (esp_http_client_is_complete_data_received(client) == true) { - ESP_LOGI(TAG, "Connection closed"); - break; - } - } - } - ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length); - if (esp_http_client_is_complete_data_received(client) != true) { - ESP_LOGE(TAG, "Error in receiving complete file"); - http_cleanup(client); - esp_ota_abort(update_handle); - task_fatal_error(); - } - - err = esp_ota_end(update_handle); - if (err != ESP_OK) { - if (err == ESP_ERR_OTA_VALIDATE_FAILED) { - ESP_LOGE(TAG, "Image validation failed, image is corrupted"); - } else { - ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); - } - http_cleanup(client); - task_fatal_error(); - } - - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); - http_cleanup(client); - task_fatal_error(); - } - ESP_LOGI(TAG, "Prepare to restart system!"); - esp_restart(); - return ; -} - -wifi_ota_status_t wifi_ota_get_status(void) -{ - return ota_process_state; -} - -void wifi_ota_start_firmware_update(char* device_imei) -{ - ESP_LOGI(TAG, "/****************** WIFI-OTA ********************/"); - - sprintf(ota_url,MCU_FW_BIN_FILE_URL1,device_imei); - - ota_process_state = OTA_IN_PROGRESS; - - uint8_t sha_256[HASH_LEN] = { 0 }; - esp_partition_t partition; - - // get sha256 digest for the partition table - partition.address = ESP_PARTITION_TABLE_OFFSET; - partition.size = ESP_PARTITION_TABLE_MAX_LEN; - partition.type = ESP_PARTITION_TYPE_DATA; - esp_partition_get_sha256(&partition, sha_256); - print_sha256(sha_256, "SHA-256 for the partition table: "); - - // get sha256 digest for bootloader - partition.address = ESP_BOOTLOADER_OFFSET; - partition.size = ESP_PARTITION_TABLE_OFFSET; - partition.type = ESP_PARTITION_TYPE_APP; - esp_partition_get_sha256(&partition, sha_256); - print_sha256(sha_256, "SHA-256 for bootloader: "); - - // get sha256 digest for running partition - esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256); - print_sha256(sha_256, "SHA-256 for current firmware: "); - - const esp_partition_t *running = esp_ota_get_running_partition(); - esp_ota_img_states_t ota_state; - if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { - if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { - // run diagnostic function ... - bool diagnostic_is_ok = true; - if (diagnostic_is_ok) { - ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ..."); - esp_ota_mark_app_valid_cancel_rollback(); - } else { - ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ..."); - esp_ota_mark_app_invalid_rollback_and_reboot(); - } - } - } - - xTaskCreate(&wifi_ota_task, "wifi_ota_task", 4096, NULL, 5, NULL); -} +/* OTA example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_crt_bundle.h" +#include "esp_app_format.h" +#include "esp_http_client.h" +#include "esp_flash_partitions.h" +#include "esp_partition.h" +#include "errno.h" +#include "main.h" +#include "comms.h" +#include "wifi_OTA.h" + +#define BUFFSIZE 1024 +#define HASH_LEN 32 /* SHA-256 digest length */ + +static const char *TAG = "WIFI_OTA"; +/*an ota data write buffer ready to write to the flash*/ +static char ota_write_data[BUFFSIZE + 1] = { 0 }; + +#define OTA_URL_SIZE 256 + +char ota_url[OTA_URL_SIZE]; +wifi_ota_status_t ota_process_state; + +static void http_cleanup(esp_http_client_handle_t client) +{ + esp_http_client_close(client); + esp_http_client_cleanup(client); +} + +static void task_fatal_error(void) +{ + ESP_LOGE(TAG, "Exiting task due to fatal error during ota process..."); + (void)vTaskDelete(NULL); + ota_process_state = OTA_FATAL_ERROR; +} + +static void print_sha256 (const uint8_t *image_hash, const char *label) +{ + char hash_print[HASH_LEN * 2 + 1]; + hash_print[HASH_LEN * 2] = 0; + for (int i = 0; i < HASH_LEN; ++i) { + sprintf(&hash_print[i * 2], "%02x", image_hash[i]); + } + ESP_LOGI(TAG, "%s: %s", label, hash_print); +} + +static void infinite_loop(void) +{ + int i = 0; + ESP_LOGI(TAG, "The firmware that is available on the server is an OLD image\n WIFI-OTA stopped."); + ota_process_state = OTA_FATAL_ERROR; +} + +static void wifi_ota_task(void *pvParameter) +{ + esp_err_t err; + /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ + esp_ota_handle_t update_handle = 0 ; + const esp_partition_t *update_partition = NULL; + + ESP_LOGI(TAG, "Starting WIFI Firmware Update Process"); + + const esp_partition_t *configured = esp_ota_get_boot_partition(); + const esp_partition_t *running = esp_ota_get_running_partition(); + + if (configured != running) { + ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08"PRIx32", but running from offset 0x%08"PRIx32,configured->address, running->address); + ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); + } + ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",running->type, running->subtype, running->address); + + esp_http_client_config_t config = { + .url = ota_url, + .crt_bundle_attach = esp_crt_bundle_attach, + .timeout_ms = 5000, + .keep_alive_enable = true, + }; + + esp_http_client_handle_t client = esp_http_client_init(&config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); + task_fatal_error(); + } + else + { + ESP_LOGI(TAG,"URL is : %s",config.url); + } + + err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); + task_fatal_error(); + } + esp_http_client_fetch_headers(client); + + update_partition = esp_ota_get_next_update_partition(NULL); + assert(update_partition != NULL); + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32,update_partition->subtype, update_partition->address); + + int binary_file_length = 0; + /*deal with all receive packet*/ + bool image_header_was_checked = false; + while (1) { + int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + if (data_read < 0) { + ESP_LOGE(TAG, "Error: SSL data read error"); + http_cleanup(client); + task_fatal_error(); + } else if (data_read > 0) { + if (image_header_was_checked == false) { + esp_app_desc_t new_app_info; + if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { + // check current version with downloading + memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); + + esp_app_desc_t running_app_info; + if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); + } + + const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition(); + esp_app_desc_t invalid_app_info; + if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); + } + + // check current version with last invalid partition + if (last_invalid_app != NULL) { + if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { + ESP_LOGW(TAG, "New version is the same as invalid version."); + ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version); + ESP_LOGW(TAG, "The firmware has been rolled back to the previous version."); + http_cleanup(client); + infinite_loop(); + } + } +#ifndef CONFIG_EXAMPLE_SKIP_VERSION_CHECK + if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { + ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update."); + http_cleanup(client); + infinite_loop(); + } +#endif + + image_header_was_checked = true; + + err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); + http_cleanup(client); + esp_ota_abort(update_handle); + task_fatal_error(); + } + ESP_LOGI(TAG, "esp_ota_begin succeeded"); + } else { + ESP_LOGE(TAG, "received package is not fit len"); + http_cleanup(client); + esp_ota_abort(update_handle); + task_fatal_error(); + } + } + err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); + if (err != ESP_OK) { + http_cleanup(client); + esp_ota_abort(update_handle); + task_fatal_error(); + } + binary_file_length += data_read; + ESP_LOGI(TAG, "Written image length %d", binary_file_length); + } else if (data_read == 0) { + /* + * As esp_http_client_read never returns negative error code, we rely on + * `errno` to check for underlying transport connectivity closure if any + */ + if (errno == ECONNRESET || errno == ENOTCONN) { + ESP_LOGE(TAG, "Connection closed, errno = %d", errno); + break; + } + if (esp_http_client_is_complete_data_received(client) == true) { + ESP_LOGI(TAG, "Connection closed"); + break; + } + } + } + ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length); + if (esp_http_client_is_complete_data_received(client) != true) { + ESP_LOGE(TAG, "Error in receiving complete file"); + http_cleanup(client); + esp_ota_abort(update_handle); + task_fatal_error(); + } + + err = esp_ota_end(update_handle); + if (err != ESP_OK) { + if (err == ESP_ERR_OTA_VALIDATE_FAILED) { + ESP_LOGE(TAG, "Image validation failed, image is corrupted"); + } else { + ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); + } + http_cleanup(client); + task_fatal_error(); + } + + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); + http_cleanup(client); + task_fatal_error(); + } + ESP_LOGI(TAG, "Prepare to restart system!"); + esp_restart(); + return ; +} + +wifi_ota_status_t wifi_ota_get_status(void) +{ + return ota_process_state; +} + +void wifi_ota_start_firmware_update(char* device_imei) +{ + ESP_LOGI(TAG, "/****************** WIFI-OTA ********************/"); + + sprintf(ota_url,MCU_FW_BIN_FILE_URL1,device_imei); + + ota_process_state = OTA_IN_PROGRESS; + + uint8_t sha_256[HASH_LEN] = { 0 }; + esp_partition_t partition; + + // get sha256 digest for the partition table + partition.address = ESP_PARTITION_TABLE_OFFSET; + partition.size = ESP_PARTITION_TABLE_MAX_LEN; + partition.type = ESP_PARTITION_TYPE_DATA; + esp_partition_get_sha256(&partition, sha_256); + print_sha256(sha_256, "SHA-256 for the partition table: "); + + // get sha256 digest for bootloader + partition.address = ESP_BOOTLOADER_OFFSET; + partition.size = ESP_PARTITION_TABLE_OFFSET; + partition.type = ESP_PARTITION_TYPE_APP; + esp_partition_get_sha256(&partition, sha_256); + print_sha256(sha_256, "SHA-256 for bootloader: "); + + // get sha256 digest for running partition + esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256); + print_sha256(sha_256, "SHA-256 for current firmware: "); + + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_img_states_t ota_state; + if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { + if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { + // run diagnostic function ... + bool diagnostic_is_ok = true; + if (diagnostic_is_ok) { + ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ..."); + esp_ota_mark_app_valid_cancel_rollback(); + } else { + ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ..."); + esp_ota_mark_app_invalid_rollback_and_reboot(); + } + } + } + + xTaskCreate(&wifi_ota_task, "wifi_ota_task", 4096, NULL, 5, NULL); +} diff --git a/main/wifi_OTA.h b/main/wifi_OTA.h index 9c6263a..d9ef8aa 100644 --- a/main/wifi_OTA.h +++ b/main/wifi_OTA.h @@ -1,22 +1,22 @@ -/* - * wifi_OTA.h - * - * Created on: Jul 31, 2023 - * Author: Sword - */ - -#ifndef WIFI_OTA_H_ -#define WIFI_OTA_H_ - -typedef enum -{ - OTA_IS_STOPPED, - OTA_IN_PROGRESS, - OTA_FATAL_ERROR, - OTA_COMPLETED -}wifi_ota_status_t; - -void wifi_ota_start_firmware_update(char* device_imei); -wifi_ota_status_t wifi_ota_get_status(void); - -#endif /* WIFI_OTA_H_ */ +/* + * wifi_OTA.h + * + * Created on: Jul 31, 2023 + * Author: Sword + */ + +#ifndef WIFI_OTA_H_ +#define WIFI_OTA_H_ + +typedef enum +{ + OTA_IS_STOPPED, + OTA_IN_PROGRESS, + OTA_FATAL_ERROR, + OTA_COMPLETED +}wifi_ota_status_t; + +void wifi_ota_start_firmware_update(char* device_imei); +wifi_ota_status_t wifi_ota_get_status(void); + +#endif /* WIFI_OTA_H_ */