Azuma_wifi_switch/main/comms.c

2106 lines
61 KiB
C

#include "esp_app_desc.h"
#include "main.h"
#include "rtc.h"
#include "hmi.h"
#include "wifi_Init.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/_types.h>
#include <time.h>
#include "modem.h"
#include "ota.h"
#include "comms.h"
#include "wifi_Client.h"
#include "mqtt_client.h"
#include "data_processing.h"
#include "driver/gpio.h"
#include "port.h"
#include "wifi_Client.h"
#include "wifi_OTA.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 CUSTOMER_SERVER 1
#define TESTING_SERVER 0
#define NEW_SERVER 0
#define COMMS_TIMER_ID 1
#define OTA_STATUS_OK 0
#if CUSTOMER_SERVER
/* definitions */
/*For developement: dev.api.mywirelessfence.com*/
/*For production: api.mywirelessfence.com*/
#define SERVER_URL_BASE "https://api.mywirelessfence.com/api/v1/trackers/tracker/%s/" //Partha - March 16, 2022
#define UPDATE_URL SERVER_URL_BASE "update"
//#define MCU_CONFIG_URL "https://api.mywirelessfence.com/api/v2/trackers/tracker/%s/mcu_config_download" //Partha - March
/*customer (Laxmana's endpoint)*/
#define MCU_CONFIG_URL "https://ops.azuma.com/SMSListener/api/DeviceInfo/%s/update"
/*customer (Laxmana's endpoint)*/
#define MCU_SP4_URL "http://54.204.230.201:8081/hae/azuma/%s/mcu_config_download"
/*customer endpoint*/
#define MCU_SP5_URL "http://54.204.230.201:8081/hae/azuma/%s/mcu_pgm_download/version"
/*customer endpoint*/
#define MCU_SP6_URL "https://ops.azuma.com/SMSListener/api/DeviceInfo/%s/modem_pgm_download/version"
/* 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 MODEM_FW_UPDATE_FILE "Update_BG77LAR02A04_01.009.01.009-R02A04_01.006.01.006.zip"
//#define MCU_PROG_URL_HIGHER "https://parthasarathimishra.com/hae/azuma/%s/mcu_pgm_download/lrsm0005_fw_ota_image_higher.bin"
//#define MCU_PROG_URL_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_PROG_URL 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"
/*Laxmana's server*/
#define MCU_PROG_URL "https://ops.azuma.com/CSW/HAEMcuUpdates/New/" MCU_FW_UPDATE_FILE
//#define MODEM_PROG_URL "https://parthasarathimishra.com/hae/azuma/%s/modem_pgm_download/Update_BG77LAR02A04_01.009.01.009-R02A04_01.006.01.006.zip"
/*Laxmana's server*/
#define MODEM_PROG_URL "https://ops.azuma.com/CSW/HAEModemUpdates/New/Update_BG77.bin"
/*customer endpoint*/
#define MQTT_HOST "azumamqtt1.cedalo.cloud"
#define MQTT_PORT 1883
#endif
#define MQTT_CLIENTID (BG96_deviceID) // TODO: Put ESP MAC ID here
/* "unwired/862061049756488" (modem's IMEI) */
#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 5
#define HTTP_RETRY_WAIT 20000
#define HOURS_TO_SECONDS_COEFF 3600
#define HEARTBEAT_TIME_SEC 14400
#define HEARTBEAT_TIME_RST 5
static const char* TAG = "COMMS";
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#define STATUS_ERROR -1
#define MCU_OTA_FILE_LOCAL "OTA.bin"
#define RELAY_ON 1
#define RELAY_OFF 0
extern bool isTestMode;
extern int heartbeat_time;
extern int qmtopen_retries;
extern bool qmtopen_fail;
#define QMTOPEN_RETRY_NUM 3
extern bool qmtclose_fail;
extern bool cops_fail;
extern bool testmode_timeout;
static int cops_reset_num = 0;
bool deviceCfged = false;
int config_heartbeat_time = HEARTBEAT_TIME_SEC;
bool WakeupFlag = false;
bool ConfigFlag = false;
bool McuUpdateFlag = false;
bool ModemUpdateFlag = false;
bool PreviousRelayState = false;
bool RelayState = false;
char time_stamp_str[50];
char mac_address[16];
char SP1[150];
char board_version_no[3]={'0'};
//#define BROCKER_URL_TEST "mqtt://azumamqtt1.cedalo.cloud:1883"
#define BROCKER_URL_TEST "mqtt://broker.mqtt.cool:1883"
#define MQTT_TOPIC_PUB "/topic/qos0"
#define MQTT_TOPIC_SUB "/topic/qos0"
esp_mqtt_client_handle_t client;
// Configure Target brocker URL
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = BROCKER_URL_TEST,
};
void SP1_Mqtt_Tx(int );
/* This function will handle led state depending on previous relay state.
*/
static void update_relay_led()
{
if(PreviousRelayState == true)
{
//board_led_all_off();
//board_led_green_on();
hmi_choose_led(HMI_LED_GREEN, HMI_LED_ON);
}
else
{
//board_led_all_off();
//board_led_red_on();
hmi_choose_led(HMI_LED_RED, HMI_LED_ON);
}
}
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_WIFI,
COMMS_STATE_WAIT_NET_CONNECT,
COMMS_STATE_WAIT_MQTT_CONNECT,
COMMS_STATE_WAIT_MQTT_PUB,
COMMS_STATE_WAIT_MQTT_CLOSE,
COMMS_STATE_WAIT_HTTP_SEND_SP3,
COMMS_STATE_WAIT_HTTP_GET_SP3,
COMMS_STATE_WAIT_HTTP_SEND_SP4,
COMMS_STATE_WAIT_HTTP_GET_SP4,
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_RELAY_WAIT,
COMMS_STATE_WAIT,
COMMS_STATE_WAIT_HTTP_SEND_SP5,
COMMS_STATE_WAIT_HTTP_GET_SP5,
COMMS_STATE_WAIT_BG96_OFF,
} comms_state_t;
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;
/* Local process state */
static comms_t comms;
uint8_t Comms_WF1_Flag = 2; //Partha - 22 March, 2022
//extern void Bypass_Comms_Interval(uint8_t state);
extern void Copy_ScanData(void *src);
//declaration of Comms_Check_TestMode.
static void Comms_Check_TestMode();
/* ------------------------------------------------------------------------- */
/* Comms process:
* 1. Get info from server via HTTP command sequence.
* 2. Publish SP1 record: device status.
* 3. Publish SP2 records: BLE scan data. Each record is one scan event.
*/
/* Record format
*
* To server:
* TYPE IMEI TIMESTAMP <FIELD1> <FIELD2> <FIELD3> ... <FIELDN> EP
*
* Fields are delineated by spaces. Data items within fields must use a comma delineator.
*
* Type: SP1 SP2 ... SPN
*
* Timestamp: epoch time, seconds
* E.g. 1599492628
*
* SP1 fields:
* 1. Firmware version : string, e.g. v1.2.1-5f1ec90
* 2. battery level : int mV reading
* 3. LTE RSSI : int dB
*
* SP1 862061049756488 1599777618 v1.2.1-5f1ec90 3650 -82 EP
*
* SP2 fields:
* 1 Epoch of scan : int
* 2 Array of SCAN_DATA[max 20] where
* SCAN_DATA:
* UUID,MAJOR,MINOR,BLE-RSSI
* UUID : hex string
* MAJOR: hex string
* MINOR: hex string
* RSSI : int dB
*
* Full uplink record example containing 3 SCAN DATA items:
* SP2 862061049756488 1599777618 1599775427 ABCD0123ABCD0123,ABCD,0123,-77 ABCD0123ABCD0123,ABCD,0124,-57 ABCD0123ABCD0123,ABCD,0125,-72 EP
*
* Testing:
* mosquito_pub
* -h 54.90.145.32
* -m "SP2 862061049756488 1599777618 1599775427 ABCD0123ABCD0123,ABCD,0123,-77 ABCD0123ABCD0123,ABCD,0124,-57 ABCD0123ABCD0123,ABCD,0125,-72 EP"
* -t unwired/862061049756488
* -i 862061049756488
*/
/*
static int get_int_arg(void)
{
char* p = strtok(0, " ");
int arg = CONFIG_BAD_INT_VALUE;
if (p)
{
arg = atoi(p);
}
return arg;
}
#*/
/*
static uint32_t get_hex_arg(void)
{
char* p = strtok(0, " ");
uint32_t arg = CONFIG_BAD_HEX_VALUE;
if (p)
{
arg = strtol(p, 0, 16);
}
return arg;
}
*/
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
event_id = 0;
if (event_base == WIFI_EVENT) {
switch (event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGI(TAG, "Wi-Fi started, connecting...");
esp_wifi_connect();
break;
case WIFI_EVENT_STA_CONNECTED:
ESP_LOGI(TAG, "Wi-Fi connected.");
break;
case WIFI_EVENT_STA_DISCONNECTED:
ESP_LOGW(TAG, "Wi-Fi disconnected, reconnecting...");
esp_wifi_connect();
break;
default:
ESP_LOGI(TAG, "Unhandled Wi-Fi event: %ld", event_id);
break;
}
}
else if (event_base == IP_EVENT) {
switch (event_id) {
case IP_EVENT_STA_GOT_IP: {
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
break;
}
}
}
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT Connected!");
comms.poll_timer = true;
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT Message Published!");
comms.poll_timer = true;
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT Broker Disconnected!");
comms.poll_timer = true;
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "Received on topic: %.*s, Message: %.*s", event->topic_len, event->topic, event->data_len, event->data);
ESP_LOGI(TAG, "string copy start");
char tmp[20] = {0}; // Ensure it's properly initialized
strncpy(tmp, event->data, sizeof(tmp) - 1); // Copy message safely
ESP_LOGI(TAG, "string copy value : %s",tmp);
ESP_LOGI(TAG, "string copy end");
comms.poll_timer = true;
break;
default:
break;
}
}
/* ------------------------------------------------------------------------- */
static const char* state_str(comms_state_t s)
{
switch (s) {
case COMMS_STATE_INIT:return "INIT";
case COMMS_STATE_WAIT_WIFI:return "WAIT_WIFI";
case COMMS_STATE_WAIT_NET_CONNECT:return "WAIT_NET_CONNECT";
case COMMS_STATE_WAIT_MQTT_CONNECT:return "WAIT_MQTT_CONNECT";
case COMMS_STATE_WAIT_MQTT_PUB:return "WAIT_MQTT_PUB";
case COMMS_STATE_WAIT_MQTT_CLOSE:return "WAIT_MQTT_CLOSE";
case COMMS_STATE_WAIT_HTTP_SEND_SP3:return "WAIT_HTTP_SEND_CONFIG_STATUS";
case COMMS_STATE_WAIT_HTTP_GET_SP3:return "WAIT_HTTP_GET_CONFIG_STATUS";
case COMMS_STATE_WAIT_HTTP_SEND_SP4:return "WAIT_HTTP_SEND_MCU_CONFIG";
case COMMS_STATE_WAIT_HTTP_GET_SP4:return "WAIT_HTTP_GET_MCU_CONFIG";
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_MCU_UPDATE:return "WAIT_MCU_UPDATE";
case COMMS_STATE_GOING_IDLE: return "COMMS_STATE_GOING_IDLE";
case COMMS_STATE_IDLE:return "IDLE";
default:
return "<unknown>";
}
}
static void transition(comms_state_t state_to)
{
ESP_LOGI(TAG, "Transistion function ");
ESP_LOGD(TAG, "%s->%s\n", state_str(comms.state), state_str(state_to));
ESP_LOGI(TAG, "%s->%s\n", state_str(comms.state), state_str(state_to));
comms.state = state_to;
}
static int start_mqtt_publish_sequence(void) //Partha - March 11, 2022
{
/* We have synchronized the configuration
* trigger the start completed event if we were starting.
*/
if (comms.is_starting) {
comms.is_starting = false;
if (comms.start_cb) {
comms.start_cb(COMMS_STATUS_OK);
comms.start_cb = 0;
}
}
/* Reset the operation status flag */
comms.last_op_success = false;
/* Run the MQTT publish sequence */
int retval = 0;
retval = esp_mqtt_client_start(client); /*Mqtt client connect */
// SP1_Mqtt_Tx(config_heartbeat_time);
if (retval == WIFI_STATUS_OK)
{
/* Indicate offloading data, moved to BG96 init for TFS-7 */
//hmi_set_offload_mode(true);
ESP_LOGI(TAG,"Connecting to MQTT broker\r\n");
transition(COMMS_STATE_WAIT_MQTT_CONNECT);
}
else
{
ESP_LOGE(TAG, "Connecting to MQTT broker failed.\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
return retval;
}
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;
}
/**
This function is used to check if MAC has correct length (15)
to check if the parsed MAC is same as hardware MAC
*/
static bool mac_check_valid(char *message_mac)
{
//find the length of message imei
int len = strlen(message_mac);
ESP_LOGI(TAG, "Parsed MAC : %s\r\n",message_mac);
//check length of MAC field
if (len != 15){
//invalid IMEI
ESP_LOGW(TAG, "Invalid MAC length");
return false;
}
if(!strcmp(message_mac, MAC_ID)){
ESP_LOGI(TAG,"Message MAC matches device MAC\r\n");
return true;
}
else{
ESP_LOGW(TAG, "Message MAC doesn't match device MAC\r\n");
return false;
}
}
/* 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 wifi_event_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* started */
transition(COMMS_STATE_WAIT_NET_CONNECT);
}
else
{
/* Nope - back to init */
ESP_LOGW(TAG, "WiFi startup failed.\r\n");
transition(COMMS_STATE_GOING_IDLE);
}
}
static void net_connect_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* connected */
}
else
{
/* Nope - back to init */
ESP_LOGW(TAG, "Network connection failed.\r\n");
if(cops_fail){
transition(COMMS_STATE_GOING_IDLE);
}
else{
transition(COMMS_STATE_GOING_IDLE);
}
}
update_relay_led();
}
static void mqtt_pub_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* connected */
}
else
{
/* Nope - back to idle */
ESP_LOGW(TAG,"MQTT publish failed.\r\n");
transition(COMMS_STATE_GOING_IDLE);
}
update_relay_led();
}
static void mqtt_close_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* connected */
}
else
{
if(qmtopen_fail){
if(qmtopen_retries >= QMTOPEN_RETRY_NUM){
qmtopen_retries = 0;
qmtopen_fail = false;
ESP_LOGI(TAG,"MQTT open retries exceeded. bypass SP1\r\n");
transition(COMMS_STATE_WAIT_MQTT_CLOSE);
}
else{
qmtopen_fail = false;
ESP_LOGW(TAG,"MQTT close failed.\r\n");
transition(COMMS_STATE_WAIT_NET_CONNECT);
}
}
}
}
static void mqtt_connect_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* connected */
}
else
{
/* Nope - back idle */
ESP_LOGW(TAG,"MQTT connection failed.\r\n");
/*if open fail flag is set then mqtt connection is closed
and then attempt another mqtt sequence*/
if(qmtopen_fail){
//qmtopen_fail = false;
ESP_LOGI(TAG,"Closing connection\r\n");
//GPIO_ResetBits(GPIO_Pin_22);
//heartbeat_time = 5;
transition(COMMS_STATE_WAIT_MQTT_PUB);
}
else{
transition(COMMS_STATE_GOING_IDLE);
}
}
update_relay_led();
}
static void http_op_cb(int status)
{
if (WIFI_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*/
// timer_start(COMMS_TIMER_ID,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;
/*Set the poll_timer to be true*/
comms.poll_timer = true;
/* Nope - back to idle */
ESP_LOGW(TAG,"HTTP operation failed.\r\n");
/* =======_send SP1 message with the count field as 'F'_=======*/
//uint8_t heartbeat_time = 1 ;
SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message
int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */
if(WIFI_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);
}
}
update_relay_led();
}
static void fotadl_op_cb(int status)
{
comms.poll_timer = true;
if (WIFI_STATUS_OK == status)
{
/* completed. */
ESP_LOGI(TAG,"Modem upgrade SUCCESS.\r\n");
}
else
{
/* failed. */
ESP_LOGW(TAG,"Modem upgrade FAILED.\r\n");
}
/* 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;
// char mac_str[15];
/* 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, MAC_ID);
ESP_LOGI(TAG,"URL %s\r\n", comms.mqtt_buf);
/* Download the GET data to modem */
int retval = -1;
char temp[512] = {0};
retval = http_client_get((const char*)comms.mqtt_buf,temp);
ESP_LOGI(TAG,"GET %s\r\n", temp);
if (retval == WIFI_STATUS_OK)
{
// clear_reset_timestamp(); TODO: Track reset & clear it here
ESP_LOGI(TAG,"GET %s\r\n", log_msg);
comms.poll_timer = true;
transition(success_state);
}
else
{
ESP_LOGE(TAG, "GET %s failed.\r\n", log_msg);
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
return retval;
}
static void fwdl_op_cb(int status)
{
if (WIFI_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*/
// timer_start(COMMS_TIMER_ID,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;
/*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");
/* =======_send SP1 message with the count field as 'F'_=======*/
uint8_t heartbeat_time = 1 ;
SP1_Mqtt_Tx(heartbeat_time); //creating sp1 message
int retval = start_mqtt_publish_sequence(); /* Run the MQTT publish sequence if nothing else pending */
if(WIFI_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 (WIFI_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");
comms.last_op_success = false;
/* Restore the LED status */
update_relay_led();
transition(COMMS_STATE_GOING_IDLE);
}
}
//function to prepare SP1, loads the MQTT TX buffer
void SP1_Mqtt_Tx(int config_heartbeat_time){
//char relay_state[3];
//rtc_timestamp_t* gettime;
char build_version[60]={'0'};
char* ptr_version = NULL;
//create the SP1 message
//SP1 IMEI F/W VER DATE_TIME SENS_EN HEARTBEAT_TIME TEST MODE COUNT RSSI EP format
get_time(time_stamp_str, sizeof(time_stamp_str)); // Pass buffer to function
ESP_LOGI(TAG, "Time_Date : %s", time_stamp_str);
// Get firmwae version
strcpy(build_version,BUILD_VERSION_STRING);
ptr_version = strstr(build_version,"_v");
strncpy(board_version_no,ptr_version + 2,3);
// wifi_get_mac_addr(mac_address);
if(PreviousRelayState == 1){
sprintf(SP1,"SP1 %s %s %s %d H_%d T_%d %s %d EP",MAC_ID,BUILD_VERSION_STRING,time_stamp_str,PreviousRelayState,(config_heartbeat_time / HOURS_TO_SECONDS_COEFF) ,isTestMode,"ON",(HTTP_RETRY_COUNT-comms.httpRetryCnt));
}
else{
sprintf(SP1,"SP1 %s %s %s %d H_%d T_%d %s %d EP",MAC_ID,BUILD_VERSION_STRING,time_stamp_str,PreviousRelayState,(config_heartbeat_time / HOURS_TO_SECONDS_COEFF) ,isTestMode,"OFF",(HTTP_RETRY_COUNT-comms.httpRetryCnt));
}
ESP_LOGI(TAG, "SP1 message :%s\r\n",SP1);
//copy sp1 message in mqtt buffer
strcpy(comms.mqtt_buf,SP1);
}
/* function for parsing SP5 message */
// format example
static void Comms_Parse_SP5(char *buf, int len)
{
char messageheader[4] = {0};
char messageMAC[16] = {0};
char timestamp[30] = {0}; //array to store the timestamp from sp5 message
char firmware_version[11] = {0}; //array to store the firmware_version from sp5 message
char *strret = NULL; //temporary pointer to store the address of the searched string (to store the returned address from strstr fn )
float new_fw_version = 0;
float current_fw_version = 0;
char epcheck[2] = {0};
int ret_sp5 = STATUS_ERROR;
strret = strtok(buf, " ");
strcpy(messageheader, strret);
ESP_LOGI(TAG, "%s message is received \r\n",messageheader);
while(strret != NULL){
strret = strtok (NULL," ");
strcpy(messageMAC, strret);
ret_sp5 = mac_check_valid(messageMAC);
if(ret_sp5 != false){
//ok IMEI
ESP_LOGI(TAG, "Fetched MAC matches board.\r\n");
}
else{
ESP_LOGW(TAG, "INVALID MAC!!\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
//return ret_sp5;
}
strret = strtok (NULL," ");
strcpy(timestamp, strret);
ESP_LOGI(TAG,"Time Stamp : %s\r\n",timestamp);
strret = strtok(NULL, "FW_ ");
strcpy(firmware_version,strret);
if((isdigit((unsigned char)firmware_version[0]) > 0) && (isdigit((unsigned char)firmware_version[2]) > 0)){
/*if the MCU version string is numeric proceed*/
/*update the version value*/
new_fw_version = atof(firmware_version);
}
else{
/*keep the board version as the new version so that update is not triggered*/
ESP_LOGI(TAG,"NOT VALID FETCHED MCU FW VERSION VALUE!! \r\n");
new_fw_version = atof(board_version_no);
}
current_fw_version = atof(board_version_no);
strret = strtok (NULL," ");
strcpy(epcheck, strret);
if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){
ESP_LOGI(TAG,"(%s) %s message is terminated\r\n", epcheck,messageheader);
break;
}
else{
ESP_LOGI(TAG,"(%s) %s message is not terminated!! \r\n", epcheck,messageheader);
}
}
// new_fw_version = 1;
if(!(new_fw_version > current_fw_version))
{
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
else
{
/*Logging/printing this message*/
ESP_LOGI(TAG,"F/W Update NEEDED \r\n");
ESP_LOGI(TAG,"GET MCU UPDATE \r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE);
/*reading OTA files*/
}
}
/* function to parsing SP4 message */
// format example
//SP4 862061049734352 2022/10/20_13:10_4 1 H_1 T_0 EP
static int Comms_Parse_SP4(char *buf, int len)
{
char messageheader[4] = {0};
char timestamp[18] = {'0'};
char messageMAC[16] = {'0'};
char testMode[3] = {'0'};
//bool relayState = false;
// char* relayStatePtr = NULL;
int sp4_ret = STATUS_ERROR;
char* strret = NULL;
char hbeat[5] = {'0'};
// char temp[5] = {'0'};
char epcheck[2] = {0};
strret = strtok(buf," ");
strcpy(messageheader, strret);
ESP_LOGI(TAG,"%s message is received \r\n",messageheader);
while(strret != NULL){
strret = strtok (NULL," ");
strcpy(messageMAC, strret);
sp4_ret = mac_check_valid(messageMAC);
if(sp4_ret != false){
//ok IMEI
ESP_LOGI(TAG, "Fetched MAC matches board.\r\n");
}
else{
ESP_LOGW(TAG, "INVALID MAC!!\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
return sp4_ret;
}
/*Parse string for date/time*/
strret = strtok (NULL," ");
strcpy(timestamp, strret);
ESP_LOGI(TAG,"Time Stamp : %s\r\n",timestamp);
strret = strtok (NULL," ");
if(strret[0] == '1'){
RelayState = true;
}
else
{
RelayState = false;
}
ESP_LOGI(TAG,"Relay State : %d\r\n",RelayState);
strret = strtok (NULL," ");
strcpy(hbeat, strret+2);
ESP_LOGI(TAG,"Received Heartbeat Time : %s\r\n",hbeat);
config_heartbeat_time = atoi(hbeat);
strret = strtok(NULL," ");
strcpy(testMode, strret);
if(testMode[2] == '1')
{
if(testmode_timeout){
isTestMode = false;
testmode_timeout = false;
}
else{
isTestMode = true;
}
}
else
{
isTestMode = false;
}
//=====================================
ESP_LOGI(TAG,"Test Mode: %d\r\n",isTestMode);
//_____________________
//maximum heartbeat time is 4 days (96 hours)
if((config_heartbeat_time != 0) && (config_heartbeat_time < 97 && config_heartbeat_time > 0)){
ESP_LOGI(TAG,"Valid fetched Heartbeat time value\r\n");
config_heartbeat_time *= HOURS_TO_SECONDS_COEFF;
deviceCfged = true;
}
else{
config_heartbeat_time = HEARTBEAT_TIME_SEC;
deviceCfged = true;
ESP_LOGI(TAG,"Invalid fetched Heartbeat time value\r\n");
}
ESP_LOGI(TAG,"Heartbeat time in Sec : %d\r\n", config_heartbeat_time);
ESP_LOGI(TAG,"Heartbeat time in Hrs : %d\r\n", (config_heartbeat_time/HOURS_TO_SECONDS_COEFF));
//___________________________
strret = strtok (NULL," ");
strcpy(epcheck, strret);
if(!strcmp(epcheck,"EP\"") || !strcmp(epcheck,"EP")){
ESP_LOGI(TAG,"(%s) %s message is terminated\r\n", epcheck,messageheader);
break;
}
else{
ESP_LOGI(TAG,"(%s) %s message is not terminated!! \r\n", epcheck,messageheader);
}
}
// TODO : Handle system time and print
/*
ESP_LOGI(TAG,"Year: %d\r\n",RTC_DateTime.Year);
ESP_LOGI(TAG,"Month: %d\r\n",RTC_DateTime.Month);
ESP_LOGI(TAG,"MonthDay: %d\r\n",RTC_DateTime.MonthDay);
ESP_LOGI(TAG,"Hour: %d\r\n",RTC_DateTime.Hour);
ESP_LOGI(TAG,"Minute: %d\r\n",RTC_DateTime.Minute);
ESP_LOGI(TAG,"WeekDay: %d\r\n",RTC_DateTime.WeekDay);
RTC_SetTimeDate(&RTC_DateTime);
*/
// update relay state if changed
if(RelayState != PreviousRelayState)
{
ESP_LOGI(TAG,"Previous Relay State :%d \n",PreviousRelayState);
PreviousRelayState = RelayState; /* update PreviousRelayState */
if(RelayState == true)
{
/*============================*/
port_vbatt_sense_enable(RELAY_ON);
ESP_LOGI(TAG,"Board relay state : %d\n",RelayState);
}
else
{
/*============================*/
port_vbatt_sense_enable(RELAY_OFF);
ESP_LOGI(TAG,"Board relay state : %d\n ",RelayState);
}
}
else
{
ESP_LOGI(TAG,"Previous Relay State :%d \n",PreviousRelayState);
ESP_LOGI(TAG,"No changes in Relay State\r\n");
/*Transition to idle state*/
comms.poll_timer = true; //polling the comms_timer
//Comms_Check_TestMode();
}
int retval = COMMS_STATUS_OK;
//creating sp1 message
SP1_Mqtt_Tx(config_heartbeat_time);
/* Run the MQTT publish sequence if nothing else pending */
// retval = start_mqtt_publish_sequence();
if(WIFI_STATUS_OK==retval)
{
ESP_LOGI(TAG,"MQTT Publish SP1 message success");
}
else
{
ESP_LOGI(TAG,"MQTT Publish SP1 message failed");
}
return retval;
}
/* ------------------------------------------------------------------------- */
static esp_err_t data_parse_uint_value(uint32_t *target_buffer, const char needle[], const char *http_resp)
{
esp_err_t retval = ESP_FAIL;
char *ret = NULL;
char *start_add = NULL;
char *end_add = NULL;
char parse_value[] = {'0'};
int len = 0;
/*1- Extract temperature limits*/
ret = strstr(http_resp, needle);
if(ret)
{
/*2- get the starting address of the value*/
start_add = strstr(ret,(char*)":") + 1;
/*3- get the ending address of the value*/
end_add = strstr(ret,(char*)",") + 1;
if((char *)1 == end_add)
end_add = start_add + strlen(start_add) + 1;
/*4- Calculate the length of the value*/
len = end_add - start_add;
/*5- copy the value into the buffer*/
snprintf(parse_value, len, "%s", start_add);
/*6- Assign the double value to the target buffer*/
*target_buffer = atoi(parse_value);
retval = ESP_OK;
}
return retval;
}
/*Handler for COMMS timer*/
static void timer_handler(void* context)
{
comms.poll_timer = true;
}
/* Parsing SP3 Message
The job of the COMM process is to fetch SP3 data from the server
and parse its fields.
Following is a sample for SP3 message, in JSON format.
{
"IMEI": "862061049734352",
"SIMNumber": "862061049734352",
"McuUpdate": 1,
"ModemUpdate": 0,
"ConfigUpdate": 1
}
We need to parse only McuUpdate, ModemUpdate and ConfigUpdate */
static int Comms_Parse_SP3(char *buf, int len)
{
char *strret;
char messageMAC[15];
int retval;
// Configuration global variable
uint32_t g_server_time = 0;
uint32_t g_ID;
uint32_t g_SensorInt;
uint32_t g_ConfigUpdate;
uint32_t g_McuUpdate;
uint32_t g_ModemUpdate;
int ret = STATUS_ERROR;
if(buf != NULL)
strret = strstr(buf, "IMEI");
else
return -1;
strncpy(messageMAC, &strret[7],(sizeof(messageMAC)/sizeof(messageMAC[0])));
messageMAC[15] = '\0';
ret = mac_check_valid(messageMAC);
if(ret != false){
//ok IMEI
ESP_LOGI(TAG,"Fetched IMEI matches board.\r\n");
}
else{
ESP_LOGW(TAG,"INVALID IMEI!!\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
return ret;
}
strret = strstr(buf, "SIMNumber");
/***********/
data_parse_uint_value(&g_ID,"id", buf);
data_parse_uint_value(&g_SensorInt,"SensorInt", buf);
data_parse_uint_value(&g_ConfigUpdate,"ConfigUpdate", buf);
data_parse_uint_value(&g_McuUpdate,"McuUpdate", buf);
data_parse_uint_value(&g_ModemUpdate,"ModemUpdate", buf);
ESP_LOGI(TAG, "ConfigUpdate: %luMcuUpdate: %lu ModemUpdate: %lu", g_ConfigUpdate, g_McuUpdate, g_ModemUpdate);
// teast ota enable
// g_McuUpdate = 1;
if (g_McuUpdate == 1) {
McuUpdateFlag = true;
ESP_LOGI(TAG, "McuUpdateFlag: %d", McuUpdateFlag);
} else if (g_McuUpdate == '0') {
McuUpdateFlag = false;
ESP_LOGI(TAG, "McuUpdateFlag: %d", McuUpdateFlag);
} else
ESP_LOGE(TAG, "not valid value for McuUpdateFlag");
/***********/
// g_ConfigUpdate = 1;
ESP_LOGI(TAG, "g_ConfigUpdate: %lu",g_ConfigUpdate);
if(g_ConfigUpdate == 1)
{
ConfigFlag = true;
ESP_LOGI(TAG,"\ConfigFlag: %d\n", ConfigFlag);
}
else if(g_ConfigUpdate == 0)
{
ConfigFlag = false;
ESP_LOGI(TAG,"\ConfigFlag: %d\n", ConfigFlag);
}
else
{
ESP_LOGE(TAG,"Not valid value for ConfigFlag");
ConfigFlag = false;
}
if(McuUpdateFlag == true){
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP5\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP5);
}
else if(ConfigFlag == true){
deviceCfged = true;
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP4\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP4);
}
else{
ESP_LOGI(TAG,"Going to state COMMS_STATE_GOING_IDLE\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
return 0;
}
//function to check if in test mode if not check : McuUpdateFlag ,ModemUpdateFlag.
//area for improvement
static void Comms_Check_TestMode(){
if(isTestMode == true){
ESP_LOGI(TAG,"Going to COMMS_STATE_WAIT_HTTP_SEND_SP3\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP3);
}
else
if(McuUpdateFlag == true)
{
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP5\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP5);
}
else{
if(ModemUpdateFlag == true)
{
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP6\r\n");
comms.poll_timer = true;
/*36-update-comms.c uncommented the following line to enable the transition to sp6 */
transition(COMMS_STATE_WAIT_HTTP_SEND_SP5);
}
else{
ESP_LOGI(TAG,"Going to state COMMS_STATE_GOING_IDLE\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
}
}
static void Check_SP1_Order(){
if(WakeupFlag){
WakeupFlag = false;
ESP_LOGI(TAG,"Going to COMMS_STATE_WAIT_HTTP_SEND_SP3\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP3);
}
else{
if(isTestMode == true){
ESP_LOGI(TAG,"Going to COMMS_STATE_WAIT_HTTP_SEND_SP3\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP3);
}
else{
if(McuUpdateFlag == true)
{
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP5\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_WAIT_HTTP_SEND_SP5);
}
else
if(ModemUpdateFlag == true)
{
ESP_LOGI(TAG,"Going to state COMMS_STATE_WAIT_HTTP_SEND_SP6\r\n");
comms.poll_timer = true;
/*36-update-comms.c uncommented the following line to enable the transition to sp6 */
transition(COMMS_STATE_WAIT_HTTP_SEND_SP5);
}
else{
ESP_LOGI(TAG,"Going to state COMMS_STATE_GOING_IDLE\r\n");
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
}
}
}
static void Wakeup_Send_SP1(void){
WakeupFlag = true;
int retval = COMMS_STATUS_OK;
//creating sp1 message
SP1_Mqtt_Tx(config_heartbeat_time);
/* Run the MQTT publish sequence if nothing else pending */
retval = start_mqtt_publish_sequence();
if(WIFI_STATUS_OK==retval)
{
ESP_LOGI(TAG,"MQTT Publish SP1 message success");
}
else
{
ESP_LOGI(TAG,"MQTT Publish SP1 message failed");
}
}
static int wifi_check_net_connect(void)
{
ESP_LOGI(TAG, "Attempting connection to google.com :)");
if(ESP_OK == http_client_test("https://www.google.com"))
{
ESP_LOGI(TAG, "Connection to internet successful.");
return WIFI_STATUS_OK;
}
else
{
ESP_LOGI(TAG, "Connection to google.com failed.\n");
return WIFI_STATUS_ERROR;
}
}
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)
{
/* Status is ERROR until cleared by successful completion. */
comms.last_cycle_status = COMMS_STATUS_ERROR;
if (wifi_isStarted())
{
ESP_LOGI(TAG, "Wifi Started");
wifi_event_cb(WIFI_STATUS_OK);
}
else
{
/* start the wifi process */
retval = Connect_wifi_sta(WIFI_MODE_STA);
if (retval == WIFI_STATUS_OK)
{
comms.is_starting = true;
ESP_LOGI(TAG,"Wifi Connected....\n");
transition(COMMS_STATE_WAIT_NET_CONNECT);
comms.poll_timer = true;
}
else
{
comms.is_starting = false;
ESP_LOGI(TAG,"Connecting to WiFi failed\n");
transition(COMMS_STATE_GOING_IDLE);
comms.poll_timer = true;
}
}
}
break;
case COMMS_STATE_WAIT_WIFI:
break;
case COMMS_STATE_WAIT_NET_CONNECT:
ESP_LOGW(TAG,"Net connect .\n");
/* Wait for WiFi network connect event */
if (evt == COMMS_EVENT_TIMER)
{
retval = wifi_check_net_connect();
if(retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"Network connected\r\n");
/* Sync time with NTP */
obtain_time();
client = esp_mqtt_client_init(&mqtt_cfg); /*Client init */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
if (comms.connect_cb) {
comms.connect_cb(COMMS_STATUS_OK);
comms.connect_cb = 0;
}
comms.httpRetryCnt = HTTP_RETRY_COUNT;
ESP_LOGI(TAG,"Sending SP1 message\r\n");
Wakeup_Send_SP1();
}
else
{
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
}
break;
case COMMS_STATE_WAIT_HTTP_SEND_SP3:
ESP_LOGW(TAG,"COMMS_STATE_WAIT_HTTP_SEND_SP3.\n");
/* Wait for ESP-WiFi HTTP setup event */
if (1)
// if (evt == COMMS_EVENT_TIMER)
{
/* Now make the GET request. */
retval = start_http_get_request(COMMS_STATE_WAIT_HTTP_SEND_SP3, MCU_GET_CONFIG_FLAGS_URL1, "configuration", COMMS_STATE_WAIT_HTTP_GET_SP3);
// http_client_do_get_request(0, MAC_ID, response_buf);
}
break;
case COMMS_STATE_WAIT_HTTP_GET_SP3:
ESP_LOGI(TAG,"Start COMMS_STATE_WAIT_HTTP_GET_SP3");
/* Wait for BG96 HTTP GET config event */
if (evt == COMMS_EVENT_TIMER)
{
/* Get the buffer and process the configuration. */
int len = 27;
char buf[512] = {0};
// char *buf = 0;
retval = http_get_response_buf(buf, len);
if (retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"BUF :\n%s\n",buf);
Comms_Parse_SP3(buf, len);
}
else{
comms.poll_timer= true;
transition(COMMS_STATE_GOING_IDLE);
}
}
break;
case COMMS_STATE_WAIT_HTTP_SEND_SP4:
/* Wait for BG96 HTTP setup event */
if (evt == COMMS_EVENT_TIMER)
{
/* Now make the GET request. */
retval = start_http_get_request(COMMS_STATE_WAIT_HTTP_SEND_SP4, MCU_SP4_URL, "configuration", COMMS_STATE_WAIT_HTTP_GET_SP4);
}
break;
case COMMS_STATE_WAIT_HTTP_GET_SP4:
ESP_LOGI(TAG, "COMMS_STATE_WAIT_HTTP_GET_SP4 start");
/* Wait for BG96 HTTP GET config event */
// if (evt == COMMS_EVENT_TIMER)
if (1)
{
/* Get the buffer and process the configuration. */
int len = 0;
char buf[512] ={0};
retval = http_get_response_buf(buf, &len);
if (retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"SP4 BUF :\n%s\n",buf);
//SP4 parsing...
Comms_Parse_SP4(buf, len);
transition(COMMS_STATE_WAIT_MQTT_CONNECT);
comms.poll_timer = true;
}
else
{
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
}
break;
case COMMS_STATE_WAIT_HTTP_SEND_SP5:
/* Wait for BG96 HTTP setup event */
if (evt == COMMS_EVENT_TIMER)
{
/* Now make the GET request. */
retval = start_http_get_request(COMMS_STATE_WAIT_HTTP_SEND_SP5, MCU_SP5_URL, "McuUpdate", COMMS_STATE_WAIT_HTTP_GET_SP5);
}
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[512] = {0};
retval = http_get_response_buf(buf, &len);
if (retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"SP5 BUF :\n%s\n",buf);
//SP5 parsing...
Comms_Parse_SP5(buf, len);
}
else
{
comms.poll_timer = true;
transition(COMMS_STATE_GOING_IDLE);
}
}
break;
case COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE:
ESP_LOGI(TAG, "COMMS_STATE_WAIT_HTTP_GET_MCU_UPDATE start");
/* 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. */
/* Enable WIFI-OTA if MCU-FW is less than the one in SP5 message */
wifi_ota_start_firmware_update(MAC_ID);
while(OTA_IN_PROGRESS == wifi_ota_get_status())
{
if (OTA_FATAL_ERROR == wifi_ota_get_status){
comms.poll_timer= true;
transition(COMMS_STATE_GOING_IDLE);
break;
}
vTaskDelay(100/portTICK_PERIOD_MS);
}
if (OTA_FATAL_ERROR == wifi_ota_get_status){
comms.poll_timer= true;
transition(COMMS_STATE_GOING_IDLE);
break;
}
/*if (retval == WIFI_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");
transition(COMMS_STATE_WAIT_MQTT_CONNECT);
comms.poll_timer = true;
Continue with session
}*/
// hmi_set_leds_state(BLUE_LED_FLASHING_OTA);
// while(OTA_IN_PROGRESS == wifi_ota_get_status())
// {
// vTaskDelay(100/portTICK_PERIOD_MS);
// }
if (retval == WIFI_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_PROG_URL_LOWER, bg96_get_imei());
#elif ST_OTA_LOWER_APPLICATION
// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_PROG_URL_HIGHER, bg96_get_imei());
#else
//// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_PROG_URL_LOWER, bg96_get_imei());
#endif
/*Creating file path and store it in comms.mqtt_buf*/
// char mac_str[15];
// wifi_get_mac_addr(mac_str);
// snprintf(comms.mqtt_buf, sizeof(comms.mqtt_buf), MCU_PROG_URL, mac_str);
/* 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 == WIFI_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 == WIFI_STATUS_OK)
{
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_terminate_connection();
/* 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;
}
// hmi_set_update_mode(false);
//hmi_set_offload_mode(true);
}
break;
case COMMS_STATE_WAIT_MQTT_CONNECT:
/* Wait for MQTT connection event */
if (evt == COMMS_EVENT_TIMER)
{
/* When connected, we will publish everything we've got.
* First is the status message.
* Follow that with all messages in the BLE scan queue.
*/
ESP_LOGI(TAG,"MQTT connected\r\n");
/* Create the pub topic */
memset(comms.mqtt_pub_topic, 0, MQTT_PUB_TOPIC_LEN);
#if COMMS_PUBLISH_WITH_IMEI
snprintf(comms.mqtt_pub_topic, MQTT_PUB_TOPIC_LEN, "unwired/%s", bg96_get_imei());
#else
snprintf(comms.mqtt_pub_topic, MQTT_PUB_TOPIC_LEN, "unwiredct"); /* TF-58 */
#endif
ESP_LOGD(TAG, "pub topic: [%s]\r\n", comms.mqtt_pub_topic);
char mac_str[15]={0};
sprintf(comms.mqtt_pub_topic,"unwired/%s", mac_str);
/* Create the WF1 status message payload */
//memset(comms.mqtt_buf, 0, sizeof(comms.mqtt_buf));
//int len = create_type1_record(comms.mqtt_buf, sizeof(comms.mqtt_buf));
//ESP_LOGD(TAG, "Payload: [%s]\r\n", comms.mqtt_buf);
ESP_LOGI(TAG,"SP1: [%s]\r\n", comms.mqtt_buf);
comms.wf1_msg = true;
//board_led_all_off();
//board_led_blue_on();
hmi_choose_led(HMI_LED_BLUE, HMI_LED_BLINK);
/* Publish the message */
retval = -1;
retval = esp_mqtt_client_publish(client, MQTT_TOPIC_PUB, comms.mqtt_buf, 0, 0, 0); // Publish a message
if (retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"Publishing to MQTT broker\r\n");
transition(COMMS_STATE_WAIT_MQTT_PUB);
comms.poll_timer = true;
}
}
break;
case COMMS_STATE_WAIT_MQTT_PUB:
ESP_LOGI(TAG,"MQTT PUB event start \r\n");
/* Wait for MQTT publish event */
if (evt == COMMS_EVENT_TIMER)
{
if(!qmtopen_fail){
ESP_LOGI(TAG,"Message published\r\n");
/* Indicate success in publishing the messages */
}
if (comms.wf1_msg)
{
/* waiting for 500ms for PUblish to complete.*/
// Clock_Enable();
// uint32_t start = Clock_Time();
// uint32_t now;
// do {
// now = Clock_Time();
// } while (now - start <= 100);
// Clock_Disable();
}
//hmi_set_offload_success();
/* Also use this point to clear the ERROR status for use with retries.
* That is, if offload succeeded, we don't need to retry.
*/
comms.last_cycle_status = COMMS_STATUS_OK;
retval = esp_mqtt_client_disconnect(client);
if (retval == WIFI_STATUS_OK)
{
ESP_LOGI(TAG,"Closing connection\r\n");
transition(COMMS_STATE_WAIT_MQTT_CLOSE);
}
}
break;
case COMMS_STATE_WAIT_MQTT_CLOSE:
/* Wait for MQTT close event */
if (evt == COMMS_EVENT_TIMER)
{
ESP_LOGI(TAG,"Connection closed.\r\n");
/*note: handler is disabled anyway*/
// if(qmtopen_fail == true){
// qmtopen_fail = false;
// //ESP_LOGI(TAG,"Message published\r\n");
// ESP_LOGI(TAG,"Closing connection\r\n");
// comms.poll_timer = true;
// transition(COMMS_STATE_WAIT_NET_CONNECT);
// }
// else{
Check_SP1_Order();
// }
//Comms_Check_TestMode();
}
break;
case COMMS_STATE_GOING_IDLE:
/* Clear offloading data */
//hmi_set_offload_mode(false);
/* Clean up state before going idle */
ESP_LOGI(TAG,"Process going idle.\n");
/*===========================================*/
// retval = bg96_stop();
/*===========================================*/
transition(COMMS_STATE_IDLE);
comms.poll_timer = true;
break;
case COMMS_STATE_IDLE:
if (evt == COMMS_EVENT_TIMER)
{
/* Status is ERROR until cleared by successful completion. */
// comms.last_cycle_status = COMMS_STATUS_ERROR;
//
// ESP_LOGI(TAG,"Connecting to server. battery=%d\r\n", hmi_get_batt_level());
// if (bg96_is_ready())
// {
// /* If modem is started and ready, proceed. */
// wifi_event_cb(WIFI_STATUS_OK);
// }
// else if (!bg96_is_started())
// {
// /* start the bg96 process only if not started. */
// retval = bg96_start(wifi_event_cb);
// if (retval == WIFI_STATUS_OK)
// {
// ESP_LOGI(TAG,"Waiting for modem\r\n");
// transition(COMMS_STATE_WAIT_BG96);
// }
// }
// else
// {
// ESP_LOGW(TAG,("Modem is busy. Comm cycle aborted.\r\n");
// }
/*===========================================*/
/* turn modem off*/
int retval=0;
// retval = bg96_stop();
if(!retval ){
comms.poll_timer = true;
hmi_choose_led(HMI_LED_RED, HMI_LED_ON);
// transition(COMMS_STATE_WAIT_BG96_OFF);
}else
{
ESP_LOGI(TAG,"bg96 faild stop \r\n");
}
/*===========================================*/
// board_led_red_on();
// board_relay_off();
// ESP_LOGI(TAG,"going to http setup\n");
/*===========================================*/
// comms.poll_timer = true;
// transition(COMMS_STATE_WAIT_RELAY_WAIT);
// transition(COMMS_STATE_WAIT_HTTP_SEND_SP3);
// }
// if (evt == COMMS_EVENT_TIMER)
// {
//
// }
// else if (evt == COMMS_EVENT_STOP)
// {
// ESP_LOGI(TAG,"Process stopped.\n");
// transition(COMMS_STATE_INIT);
}
break;
// case COMMS_STATE_RELAY_WAIT:
// if (evt == COMMS_EVENT_TIMER)
// {
// board_led_red_off();
// board_relay_on();
// ESP_LOGI(TAG,"RELAY OFF\n");
// timer_stop(COMMS_TIMER_ID);
// transition(COMMS_STATE_GOING_IDLE);
// /*=========*/
// comms.poll_timer = true;
//
// }
// break;
case COMMS_STATE_WAIT:
// timer_stop(COMMS_TIMER_ID);
comms.poll_timer = true;
transition(comms.http_init_state);
ESP_LOGI(TAG,"Number of remaining HTTP retry is : %d\n", comms.httpRetryCnt);
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 */
// timer_init(COMMS_TIMER_ID, timer_handler);
ESP_LOGI(TAG,"Process initialized.\n");
// register_wifi_callback(wifi_event_cb);
return retval;
}
/* Start the process */
int comms_start(comms_op_cb_t start_cb, comms_op_cb_t connect_cb)
{
ESP_LOGW(TAG, "Comms start ....");
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) { }