Remote_Wifi_Switch/main/wifi_Client.c
2025-02-21 15:26:53 +05:30

644 lines
19 KiB
C

/*
* tempstick_wifi_client.c
*
* Created on: Jul 28, 2023
* Author: Sword
*/
#include <string.h>
#include <stdlib.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_http_client.h"
#include "wifi_Client.h"
#include "wifi_Init.h"
#include "comms.h"
#include "modem.h"
#include "wifi_OTA.h"
#include "esp_mac.h"
#include "data_processing.h"
#include "hmi.h"
#if (WIFI_NEEDED == 1)
static const char* TAG = "CLIENT";
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
extern uint32_t g_version;
extern uint32_t g_McuUpdate;
bool isDataNeeded = false;
bool getBinFile;
static char *output_buffer;
static server_type_t selected_server;
deviceToServer_msgType_t post_msg_type;
char url[200];
//char onboarding_host[] = ON_BOARDING_SERVER_DOMAIN_NAME;
char *params;
uint8_t http_client_test_task_end = 0;
uint8_t http_client_post_task_end = 0;
uint8_t http_client_get_task_end = 0;
esp_err_t http_client_test_err;
esp_err_t http_client_post_err;
esp_err_t http_client_get_err;
esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
//static char *output_buffer; // Buffer to store response of http request from event handler
//static int output_len; // Stores number of bytes read
switch(evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
/*
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
* However, event handler can also be used in case chunked encoding is used.
*/
/*if (!esp_http_client_is_chunked_response(evt->client))
{
// If user_data buffer is configured, copy the response into the buffer
if (evt->user_data)
{
memcpy(evt->user_data + output_len, evt->data, evt->data_len);
}
else
{
if (output_buffer == NULL)
{
output_buffer = (char *)pvPortMalloc(esp_http_client_get_content_length(evt->client));
output_len = 0;
if (output_buffer == NULL)
{
ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
return ESP_FAIL;
}
}
memcpy(output_buffer + output_len, evt->data, evt->data_len);
}
output_len += evt->data_len;
}*/
if(isDataNeeded && (evt->data_len > 0))
{
//output_buffer = (char *)pvPortMalloc(evt->data_len);
memcpy(output_buffer, evt->data, evt->data_len);
output_buffer[evt->data_len] = 0;
isDataNeeded = false;
//ESP_LOGI(TAG, "%s\n", output_buffer);
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
/*if (output_buffer != NULL)
{
ESP_LOGI(TAG, "HTTP Response:\n%s", output_buffer);
vPortFree(output_buffer);
output_buffer = NULL;
}
output_len = 0;*/
break;
case HTTP_EVENT_DISCONNECTED:
//isDataNeeded = false;
//vPortFree(output_buffer);
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
int mbedtls_err = 0;
esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL);
if (err != 0)
{
ESP_LOGI(TAG, "Last esp error code: 0x%x\nLast mbedtls failure: 0x%x", err, mbedtls_err);
}
/*if (output_buffer != NULL)
{
vPortFree(output_buffer);
output_buffer = NULL;
}
output_len = 0;*/
break;
case HTTP_EVENT_REDIRECT:
ESP_LOGI(TAG, "HTTP_EVENT_REDIRECTED");
break;
}
return ESP_OK;
}
static int sum_digits(int digit)
{
int sum = 0;
while (digit > 0)
{
sum = sum + digit % 10;
digit = digit / 10;
}
return sum;
}
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);
}
/*SP5 866349048889004 1676395843 FW_2002 EP */
static void wifi_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;
int ret_sp5 = -1;
/**********************************************************************************************************/
/*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");
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\nBoard Firmware version: %ld",new_fw_version,g_version); //logging/printing FR_version message for tracing
/**********************************************************************************************************/
/*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");
}
else
{
/*Logging/printing this message*/
ESP_LOGI(TAG,"F/W Update NEEDED\nGET MCU UPDATE");
/*reading OTA files*/
getBinFile = true;
/*reading OTA files*/
}
}
static void http_client_test_task(void *pvParameters)
{
esp_http_client_config_t config = {
.url = (const char*)url,
.crt_bundle_attach = esp_crt_bundle_attach,
.event_handler = http_event_handler
};
//config.event_handler = http_event_handler;
//config.url = (char *)pvPortMalloc((1 + strlen(url))*sizeof(char));
//strcpy((char *)config.url, url);
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %lld", esp_http_client_get_status_code(client), esp_http_client_get_content_length(client));
}
else
{
ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err));
}
//vPortFree((char *)config.url);
esp_http_client_cleanup(client);
http_client_test_err = err;
http_client_test_task_end = 1;
vTaskDelete(NULL);
}
esp_http_client_handle_t client_post;
static void http_client_post_task(void *pvParameters)
{
/* make sure that the client_post is not initialized before (to be able to initialized it without any problems) */
if(!client_post)
{
/* Set the configurations */
esp_http_client_config_t config = {
.url = (const char*)url,
.method = HTTP_METHOD_POST,
.buffer_size = 2560,
.crt_bundle_attach = esp_crt_bundle_attach,
.event_handler = http_event_handler
};
/* Initialize client_post with the entered configurations */
client_post = esp_http_client_init(&config);
}
/* Set the header of the post message */
if(post_msg_type == CHECK_IN_STR)
{
esp_http_client_set_header(client_post, "Authorization", AUTHERIZATION_VALUE);
//esp_http_client_set_header(client, "Host", "testdevice.tempstickapi.com");
esp_http_client_set_header(client_post, "User-Agent", USER_AGENT_VALUE);
esp_http_client_set_header(client_post, "Content-Type", CONTENT_TYPE_VALUE);
}
else if(post_msg_type == ON_BOARDING_STR)
{
esp_http_client_set_header(client_post, "Authorization", AUTHERIZATION_VALUE_ONBOARDING);
//esp_http_client_set_header(client, "Host", ON_BOARDING_SERVER_DOMAIN_NAME);
esp_http_client_set_header(client_post, "User-Agent", USER_AGENT_ONBOARDING);
esp_http_client_set_header(client_post, "Content-Type", CONTENT_TYPE_VALUE_ONBOARDING);
}
/* Set the check-in message */
esp_http_client_set_post_field(client_post, params, strlen(params));
esp_err_t err = esp_http_client_perform(client_post);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %lld", esp_http_client_get_status_code(client_post), esp_http_client_get_content_length(client_post));
}
else
{
ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err));
}
//esp_http_client_cleanup(client_post);
http_client_post_err = err;
http_client_post_task_end = 1;
vTaskDelete(NULL);
}
static void http_client_get_task(void *pvParameters)
{
esp_http_client_config_t config = {
.url = (const char*)url, // Replace with your desired URL
.method = HTTP_METHOD_GET,
.cert_pem = NULL,
.event_handler = http_event_handler
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK) {
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %lld",
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
} else {
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
}
esp_http_client_cleanup(client);
http_client_get_err = err;
http_client_get_task_end = 1;
vTaskDelete(NULL);
}
esp_err_t http_client_test(char *url1)
{
strcpy(url,url1);
isDataNeeded = false;
http_client_test_task_end = 0;
xTaskCreate(http_client_test_task, "http_client_test_task", 4096, NULL, 17, NULL);
while(!http_client_test_task_end)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
}
return http_client_test_err;
}
esp_err_t http_client_post(char *url1, char *params1, char *response)
{
http_client_post_task_end = 0;
strcpy(url,url1);
params = params1;
output_buffer = response;
isDataNeeded = true;
xTaskCreate(http_client_post_task, "http_client_post_task", 4096, NULL, 17, NULL);
while(!http_client_post_task_end)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
}
return http_client_post_err;
}
void http_client_post_stop(void)
{
esp_http_client_cleanup(client_post);
client_post = NULL;
}
esp_err_t http_client_get(const char *url1, char *response)
{
http_client_get_task_end = 0;
strcpy(url,url1);
output_buffer = response;
isDataNeeded = true;
xTaskCreate(http_client_get_task, "http_client_get_task", 4096, NULL, 17, NULL);
while(!http_client_get_task_end)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
}
return http_client_get_err;
}
esp_err_t http_client_do_get_request(get_req_type_t target_url, char* device_imei, char *response_buf)
{
uint8_t retval = WIFI_FAIL;
char server_url[200];
switch(target_url)
{
case GET_CONFIGURATIONS:
ESP_LOGI(TAG,"/******** Configuration -SP3- GET request ********/");
/* Try with server-1 */
if(selected_server == SERVER_ONE)
{
sprintf(server_url, MCU_GET_CONFIG_FLAGS_URL1, device_imei);
retval = http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
ESP_LOGI(TAG,"Server-1 fails to connect. Switching to Server-2");
selected_server = SERVER_TWO;
}
}
/* Try with server-2 if & only if server-1 fails to connect */
if(selected_server == SERVER_TWO)
{
sprintf(server_url, MCU_GET_CONFIG_FLAGS_URL2, device_imei);
http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_THREE;
ESP_LOGI(TAG,"Server-2 fails to connect. Switching to Server-3");
}
}
/* Try with server-3 if & only if server-2 fails to connect */
if(selected_server == SERVER_THREE)
{
sprintf(server_url, MCU_GET_CONFIG_FLAGS_URL3, device_imei);
http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_ONE;
ESP_LOGI(TAG,"Server-3 fails to connect. Stopping WIFI-Client.");
retval = WIFI_FAIL;
}
}
/* Parse the SP3 response */
if(retval == ESP_OK)
data_parsing_config(response_buf, strlen(response_buf));
else
break;
/* IF MCU-Update flag is set then continue to the next case. if not then break */
if(!g_McuUpdate)
{
break;
}
case GET_MCU_UPDATE_VERSION:
ESP_LOGI(TAG,"/******** MCU_Update -SP5- GET request ********/");
/* Try with server-1 */
if(selected_server == SERVER_ONE)
{
sprintf(server_url, MCU_FW_VERSION_URL1, device_imei);
retval = http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_TWO;
ESP_LOGI(TAG,"Server-1 fails to connect. Switching to Server-2");
}
}
/* Try with server-2 if & only if server-1 fails to connect */
if(selected_server == SERVER_TWO)
{
sprintf(server_url, MCU_FW_VERSION_URL2, device_imei);
http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
ESP_LOGI(TAG,"Server-2 fails to connect. Switching to Server-3");
selected_server = SERVER_THREE;
}
}
/* Try with server-3 if & only if server-2 fails to connect */
if(selected_server == SERVER_THREE)
{
sprintf(server_url, MCU_FW_VERSION_URL3, device_imei);
http_client_get((const char*)server_url,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_ONE;
ESP_LOGI(TAG,"Server-3 fails to connect. Stopping WIFI-Client.");
retval = WIFI_FAIL;
}
}
/* Parse the SP5 response */
if(retval == ESP_OK)
wifi_Parse_SP5(response_buf, strlen(response_buf));
/* Enable WIFI-OTA if MCU-FW is less than the one in SP5 message */
if(getBinFile)
{
wifi_ota_start_firmware_update(device_imei);
hmi_set_leds_state(BLUE_LED_FLASHING_OTA);
while(OTA_IN_PROGRESS == wifi_ota_get_status())
{
vTaskDelay(100/portTICK_PERIOD_MS);
}
/* LOG this error message */
hmi_stop_ota_event();
ESP_LOGE(TAG,"Error in WIFI-OTA process. continuing on the current firmware.");
retval = ESP_FAIL;
}
break;
case GET_MODEM_UPDATE_VERSION:
break;
default:
}
return retval;
}
esp_err_t http_client_do_post_request(char *post_params, char *response_buf)
{
uint8_t retval = WIFI_FAIL;
selected_server = SERVER_ONE;
/* Try with server-1 */
if(selected_server == SERVER_ONE)
{
/* Set the POST-URL to be Server1 */
data_set_postToServer(TEMPSTICK_SERVER1);
/* Create the Check-in message */
data_create_checkin_string(post_params,2304);
/* Printing the check-in string */
ESP_LOGI(TAG,"%s",post_params);
/* Post that Check-in message to the target server */
retval = http_client_post((char*)MCU_POST_URL1,post_params,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_TWO;
ESP_LOGI(TAG,"Server-1 fails to connect. Switching to Server-2");
}
}
/* Try with server-2 if & only if server-1 fails to connect */
if(selected_server == SERVER_TWO)
{
/* Set the POST-URL to be Server2 */
data_set_postToServer(TEMPSTICK_SERVER2);
/* Create the Check-in message */
data_create_checkin_string(post_params,2304);
/* Post that Check-in message to the target server */
retval = http_client_post((char*)MCU_POST_URL2,post_params,response_buf);
if(retval != WIFI_OK)
{
ESP_LOGI(TAG,"Server-2 fails to connect. Switching to Server-3");
selected_server = SERVER_THREE;
}
}
/* Try with server-3 if & only if server-2 fails to connect */
if(selected_server == SERVER_THREE)
{
/* Set the POST-URL to be Server3 */
data_set_postToServer(TEMPSTICK_SERVER3);
/* Create the Check-in message */
data_create_checkin_string(post_params,2304);
/* Post that Check-in message to the target server */
retval = http_client_post((char*)MCU_POST_URL3,post_params,response_buf);
if(retval != WIFI_OK)
{
selected_server = SERVER_ONE;
ESP_LOGI(TAG,"Server-3 fails to connect. Stopping WIFI-Client.");
retval = WIFI_FAIL;
}
}
return retval;
}
void wifi_set_post_str_type(deviceToServer_msgType_t str)
{
post_msg_type = str;
}
#endif