Remote_Wifi_Switch/main/hmi.c

735 lines
20 KiB
C

/*
* hmi.c
*
* Created on: Feb 13, 2023
* Author: Sword
*/
#include <stdio.h>
#include "nvs_flash.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_timer.h"
#include "uart_ifx.h"
#include "esp_task_wdt.h"
#include "modem.h"
#include "comms.h"
#include "port.h"
#include "adc_ifx.h"
<<<<<<< HEAD
#include "i2c_sensors.h"
=======
>>>>>>> 4ea13f8 (Added azuma wifi switch backup code)
#include "data_processing.h"
#include "hmi.h"
static const char* TAG = "HMI";
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#define HMI_BUF_SIZE 20
#define HMI_EVENTS_ITERATION_COUNTS 8
#define LED_SOLID_DURATION 300
#define OTA_UPDATE_DURATION 1000 // Duration for BLUE_FLASHING event when OTA session is happening
#define BLUE_FLASHING_DURARION 500 // Duration for BLUE_FLASHING led_event
#define RED_FLASHING_DURARION 1000 // Duration for RED_FLASHING led_event
#define BLUE_RED_FLASHING_1SEC_DURARION 1000 // Duration for BLUE_RED_FLASHING led_event
#define BLUE_RED_SOLID_CHARGED_DURARION 9700 // Duration for BLUE_RED_SOLID_CHARGED led_event
#define BLUE_RED_FLASHING_CHARGED_DURARION 100 // Duration for BLUE_RED_FLASHING_CHARGING led_event
#define BLUE_RED_FLASHING_200ms_DURARION 200 // Duration for BLUE_RED_FLASHING led_event
#define NORMAL_HMI_DURATION 1000 // Duration for NORMAL_HMI cycle (cycle without triggered events)
<<<<<<< HEAD
=======
/*LED definitions*/
#define RED_TRI_LED 0
#define GREEN_TRI_LED 1
#define BLUE_TRI_LED 2
>>>>>>> 4ea13f8 (Added azuma wifi switch backup code)
static QueueHandle_t hmi_queue; // FIFO queue that stores the leds event
static bool usb_connection_state = false; // USB connection state flag (true--> connected, false--> disconnected)
static bool continue_current_leds_state; // Led_event Continuing flag
static bool pushbutton_state = false; // pushbutton state flag
static bool blue_red_sync = false; // Synchronization flag when usb_charging is the current usb_led_event
static bool device_failure_state = false;
static bool device_not_onboarded_state = false; // ON-BOARDED flag when device data didn't get sent to server
static bool ota_update_session = false; // OTA-Update flag to indicate that firmware update is happening right now
static bool alternate_cycle_for_both = false; // A flag to make both LEDs blink in an alternating cycle
static hmi_leds_state_t continued_leds_state; // Chosen led_event to be continued after 5 times of execution
static hmi_leds_state_t leds_state = BLUE_RED_LEDS_OFF; // Led_event when usb is not connected
static hmi_leds_state_t prev_leds_state = BLUE_RED_LEDS_OFF; // prev Led_event when usb is not connected
static hmi_leds_state_t usb_leds_state = BLUE_RED_LEDS_OFF; // Led_event when usb is connected
static uint8_t num_events_in_queue; // Number of Events in hmi_queue
static uint16_t hmi_duration = NORMAL_HMI_DURATION; // Duration for each Led_event cycle
static uint8_t fully_charged_counter;
/************* STATIC FUNCTIONS ****************/
/* This function should be executed when the pushbutton is pressed (HIGHEST priority)*/
static void hmi_pushbutton_pressed_task(void)
{
/* 1- Execute the BLUE_LED_SOLID event*/
hmi_duration = LED_SOLID_DURATION;
port_blue_led_on();
port_red_led_off();
/* 2- Delay duration is equal to BLUE_FLASHING_DURARION*/
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
/* 3- Check if the pushbutton is not pressed*/
if(port_is_pushbuttonNotPressed())
{
/* If yes ---> reset pushbutton_state flag*/
pushbutton_state = false;
}
}
/* This function should be executed when the device failure is occurred (second HIGHEST priority)*/
static void hmi_device_failure_task(void)
{
/* 1- Execute the RED_LED_SOLID event*/
hmi_duration = LED_SOLID_DURATION;
port_blue_led_off();
port_red_led_on();
/* 2- Delay duration is equal to BLUE_FLASHING_DURARION*/
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
}
/* This function should be executed when the device is not on-boarded yet (Third HIGHEST priority)*/
static void hmi_device_not_onboarded_task(void)
{
/* 1- Execute the RED_LED_FLASHING event*/
hmi_duration = RED_FLASHING_DURARION;
port_blue_led_off();
port_red_led_toggle();
/* 2- Delay duration is equal to BLUE_FLASHING_DURARION*/
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
}
/* This function should be executed when OTA Update is happening ( device_not_onboarded > priority > events_in_queue)*/
static void hmi_ota_firmware_update_task(void)
{
/* 1- Execute the RED_LED_FLASHING event*/
hmi_duration = OTA_UPDATE_DURATION;
port_blue_led_toggle();
port_red_led_toggle();
alternate_cycle_for_both = true;
/* 2- Delay duration is equal to BLUE_FLASHING_DURARION*/
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
}
/* This function should be executed when USB is not connected ( device_failure > priority > USB)*/
static void hmi_events_in_queue_task(void)
{
int counter = 0;
/*Check if the current led_event shall be continued or not */
if((true == continue_current_leds_state) && (continued_leds_state == prev_leds_state))
{
/*if true: the new led_state is the same as the old led state */
leds_state = prev_leds_state;
}
else
{
/*Extract the event from the queue (if exists)*/
xQueueReceive(hmi_queue, &leds_state, (TickType_t)100);
/*Set the previous led_state*/
prev_leds_state = leds_state;
/*Reduce number of led_events in queue by 1*/
num_events_in_queue--;
/*Log*/
ESP_LOGI(TAG,"Extracting LED_EVENT = %d from HMI-QUEUE to execute it",leds_state);
}
/*Check if BLUE & RED LED should be synchronized*/
if((BLUE_RED_LEDS_FLASHING_200ms == leds_state) && (false == blue_red_sync))
{
/*Turn off both leds for synchronization*/
port_red_led_off();
port_blue_led_off();
blue_red_sync = true;
}
/*Each event should occur 5 times to observe it clearly*/
for(counter = 0; counter < HMI_EVENTS_ITERATION_COUNTS; counter++)
{
/* 1- Evaluate the extracted event*/
switch(leds_state)
{
case BLUE_LED_FLASHING: //LTE_connecting
hmi_duration = BLUE_FLASHING_DURARION;
port_blue_led_toggle();
port_red_led_off();
break;
case BLUE_LED_SOLID: //pushbutton_pressed
break;
case RED_LED_FLASHING: //Device has not been on-boarded
break;
case RED_LED_SOLID: //Device Failure. Need to reset
break;
case BLUE_RED_LEDS_FLASHING_200ms: //low battery warning
hmi_duration = BLUE_RED_FLASHING_200ms_DURARION;
port_red_led_toggle();
port_blue_led_toggle();
break;
case BLUE_RED_LEDS_FLASHING_1SEC: //USB_PLUGGED_CHARGING
case BLUE_RED_LEDS_SOLD: //USB_PLUGGED_CHARGED
case BLUE_RED_LEDS_USB_OFF:
case BLUE_LED_FLASHING_OTA: // OTA-SESSION is happening
break;
case BLUE_RED_LEDS_OFF:
hmi_duration = NORMAL_HMI_DURATION;
port_red_led_off();
port_blue_led_off();
break;
}
/* 2- Delay duration is dynamic according the extracted led_event*/
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
/* 3- Check the pushbutton state and device failure state*/
if((true == pushbutton_state) || (true == device_failure_state))
{
/*If yes then break the for-loop*/
break;
}
}
/*Reset the Synchronization flag*/
blue_red_sync = false;
}
/* This function should be executed when USB is connected (LOWEST priority)*/
static void hmi_usb_connected_task(void)
{
/*Evaluate the extracted event*/
switch(usb_leds_state)
{
case BLUE_LED_FLASHING:
case BLUE_LED_SOLID:
case RED_LED_FLASHING:
case RED_LED_SOLID:
case BLUE_LED_FLASHING_OTA:
case BLUE_RED_LEDS_FLASHING_200ms:
break;
/* Charging LED-event is violate toggling each one second (on, off, on, off and continue like this) */
case BLUE_RED_LEDS_FLASHING_1SEC:
hmi_duration = BLUE_RED_FLASHING_1SEC_DURARION;
port_red_led_toggle();
port_blue_led_toggle();
break;
/* Charged LED-event is violate toggling 2 times each 100ms and then of for 9.7 second */
case BLUE_RED_LEDS_SOLD:
if(fully_charged_counter < 3)
{
/* Increase the fully_charged_counter by 1 */
fully_charged_counter++;
hmi_duration = BLUE_RED_FLASHING_CHARGED_DURARION;
port_red_led_toggle();
port_blue_led_toggle();
}
else
{
/* Reset the fully_charged_counter to 0 */
fully_charged_counter = 0;
hmi_duration = BLUE_RED_SOLID_CHARGED_DURARION;
port_red_led_off();
port_blue_led_off();
}
break;
case BLUE_RED_LEDS_USB_OFF:
hmi_duration = BLUE_RED_FLASHING_1SEC_DURARION;
port_red_led_off();
port_blue_led_off();
break;
case BLUE_RED_LEDS_OFF:
break;
}
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
}
/************ NON-STATIC FUNCTIONS *************/
/* This function is to initialize HMI service (Creating hmi_queu and turn off both leds)*/
void hmi_init(void)
{
/* 1- Create the HMI-QUEUE*/
hmi_queue = xQueueCreate(HMI_BUF_SIZE, sizeof(uint8_t));
/* 2- Set the hmi_duration to normal and turn off both leds*/
hmi_duration = NORMAL_HMI_DURATION;
num_events_in_queue = 0;
continue_current_leds_state = false;
port_red_led_off();
port_blue_led_off();
ESP_LOGI(TAG,"HMI-Service has been initialized successfully");
}
/* This function is used to set the state of USB-CONNECTION*/
void hmi_set_usb_connection_state(bool usb_state)
{
usb_connection_state = usb_state;
}
#if 0
void hmi_do_usb_event_inside_hmi(bool decision)
{
do_it_inside_hmi = decision;
}
void hmi_exception_usb_event(void)
{
/* Check if to do the USB event inside hmi-task or outside it (inside pausing-task) */
if(do_it_inside_hmi)
{
/* Check the USB-LED-event */
if(usb_leds_state == BLUE_RED_LEDS_FLASHING_1SEC)
{
/* Turn off both LEDs */
port_red_led_off();
port_blue_led_off();
/* Wait for about 300ms (to simulate the measurement time) */
vTaskDelay(300/portTICK_PERIOD_MS);
/* Turn on both LEDs */
port_red_led_on();
port_blue_led_on();
/* Wait for about 333ms */
vTaskDelay(333/portTICK_PERIOD_MS);
/* Turn off both LEDs */
port_red_led_off();
port_blue_led_off();
/* Wait for about 333ms */
vTaskDelay(333/portTICK_PERIOD_MS);
/* Turn on both LEDs */
port_red_led_on();
port_blue_led_on();
/* Wait for about 333ms */
vTaskDelay(333/portTICK_PERIOD_MS);
/* Turn off both LEDs */
port_red_led_off();
port_blue_led_off();
}
else if(usb_leds_state == BLUE_RED_LEDS_SOLD)
{
/* Turn off both LEDs */
port_red_led_off();
port_blue_led_off();
/* Wait for about 300ms (to simulate the measurement time) */
vTaskDelay(300/portTICK_PERIOD_MS);
/* Turn on both LEDs */
port_red_led_on();
port_blue_led_on();
/* Wait for about 1000ms */
vTaskDelay(1000/portTICK_PERIOD_MS);
/* Turn off both LEDs */
port_red_led_off();
port_blue_led_off();
}
}
else
{
if(usb_leds_state == BLUE_RED_LEDS_FLASHING_1SEC)
{
port_red_led_on();
port_blue_led_on();
vTaskDelay(333/portTICK_PERIOD_MS);
port_red_led_off();
port_blue_led_off();
vTaskDelay(333/portTICK_PERIOD_MS);
port_red_led_on();
port_blue_led_on();
vTaskDelay(333/portTICK_PERIOD_MS);
port_red_led_off();
port_blue_led_off();
}
else if(usb_leds_state == BLUE_RED_LEDS_SOLD)
{
port_red_led_on();
port_blue_led_on();
vTaskDelay(1000/portTICK_PERIOD_MS);
port_red_led_off();
port_blue_led_off();
}
}
}
#endif
/* This function is used to set which Led_event should be executed next time*/
void hmi_set_leds_state(hmi_leds_state_t status)
{
uint32_t batt_mv;
float g_voltage ;
/*Check if the led-event should be pushed to the hmi_queue*/
switch(status)
{
case BLUE_LED_FLASHING: //Should be pushed to hmi_queue
/*Continue executing this led_event till it's stopped by hmi_stop_continued_led_state() function */
continue_current_leds_state = true; // RISE the led_event continuing_Flag
continued_leds_state = BLUE_LED_FLASHING; // Set the flag to be continued to be BLUE_LED_FLASHING
num_events_in_queue++; // increase the number of events in hmi_queue by 1
xQueueSend(hmi_queue, &status, 100); // Push the new led_state to the hmi_queue (if possible)
blue_red_sync = false; // reset synchronization flag
ESP_LOGI(TAG,"BLUE Flashing (continuing) has been added to hmi_queue");
break;
case RED_LED_FLASHING: //Should not be pushed to hmi_queue(it has its own function --> hmi_device_not_onboarded_task())
device_not_onboarded_state = true; //Set the device_not_onboarded_state flag to be true
blue_red_sync = false; //reset synchronization flag
ESP_LOGI(TAG,"RED LED should Flashes now (if no higher-priority event is occurred)");
break;
case BLUE_LED_SOLID: //Should not be pushed to hmi_queue(it has its own function --> hmi_pushbutton_pressed_task())
pushbutton_state = true; //Set the pushbutton_state flag to be true
blue_red_sync = false; //reset synchronization flag
break;
case RED_LED_SOLID: //Should not be pushed to hmi_queue(it has its own function --> hmi_device_failure_task())
device_failure_state = true; //Set the device_failure_state flag to be true
blue_red_sync = false; //reset synchronization flag
break;
case BLUE_RED_LEDS_OFF: //Should be pushed to hmi_queue
xQueueSend(hmi_queue, &status, 100); // Push the new led_state to the hmi_queue (if possible)
num_events_in_queue++; // increase the number of events in hmi_queue by 1
blue_red_sync = false; // reset synchronization flag
break;
case BLUE_RED_LEDS_FLASHING_200ms:
num_events_in_queue++; // increase the number of events in hmi_queue by 1
xQueueSend(hmi_queue, &status, 100); // Push the new led_state to the hmi_queue (if possible)
ESP_LOGI(TAG,"BLUE_RED_LED_FLASHING_200ms has been added to hmi_queue");
break;
case BLUE_RED_LEDS_FLASHING_1SEC: //Should not be pushed to hmi_queue(it has its own function --> hmi_usb_connected_task())
/* Check if the USB is plugged and the battery is existed */
if((true == usb_connection_state))
{
/*Update the current usb_leds_state*/
usb_leds_state = status;
ESP_LOGI(TAG,"Voilate Flashing has been set");
}
else
{
ESP_LOGI(TAG,"Voilate Flashing can't be set. Battery may not be connected");
}
break;
case BLUE_RED_LEDS_SOLD: //Should not be pushed to hmi_queue(it has its own function --> hmi_usb_connected_task())
/* Check if the USB is plugged and the battery is existed and its voltage level is fine */
if((true == usb_connection_state))
{
/*Update the current usb_leds_state*/
usb_leds_state = status;
/*reset synchronization flag*/
blue_red_sync = false;
ESP_LOGI(TAG,"Voilate Solid has been set");
}
else
{
ESP_LOGI(TAG,"Voilate Solid can't be set. Battery may not be connected or its volt. level is too low");
}
break;
case BLUE_LED_FLASHING_OTA: //Should not be pushed to hmi_queue(it has its own function --> hmi_ota_firmware_update_task())
/*reset synchronization flag*/
blue_red_sync = false;
/* set ota_flag*/
ota_update_session = true;
break;
case BLUE_RED_LEDS_USB_OFF:
/* Check if the USB is plugged and the battery is existed and its voltage level is fine */
if((true == usb_connection_state))
{
/*Update the current usb_leds_state*/
usb_leds_state = status;
/*reset synchronization flag*/
blue_red_sync = false;
//ESP_LOGI(TAG,"Voilate Solid/Flashing has been stopped");
}
}
/*Exit the critical shared section between different tasks*/
//taskEXIT_CRITICAL(&hmi_mutex);
}
/* This function is used to stop the continuing led_event*/
void hmi_stop_continued_led_state(hmi_leds_state_t led_event)
{
/* Check if the led_event that should be stopped is the same as the current continuing led_event*/
if(continued_leds_state == led_event)
{
/*If yes then : */
/* 1- Disallow continuing the current running Led_event */
continue_current_leds_state = false;
/* 2- Set the continued Led_event to be BLUE_RED_LEDS_OFF (and it won't executed because the continue flag is false)*/
continued_leds_state = BLUE_RED_LEDS_OFF;
/*Log*/
ESP_LOGI(TAG,"Stopping the current continued LED_EVENT = %d",led_event);
}
}
/* This function is used to stop red flashing*/
void hmi_stop_red_flashing(void)
{
device_not_onboarded_state = false;
}
/* This function is used to stop ota_LED-event */
void hmi_stop_ota_event(void)
{
ota_update_session = false;
}
bool leds_enabled = true;
<<<<<<< HEAD
=======
>>>>>>> 4ea13f8 (Added azuma wifi switch backup code)
void set_leds_enable(bool status)
{
leds_enabled = status;
if(status == false)
{
port_red_led_off();
port_blue_led_off();
}
}
<<<<<<< HEAD
=======
/* State of the hmi process */
typedef enum
{
HMI_STATE_INIT,
HMI_STATE_RUN,
} hmi_state_t;
typedef struct
{
hmi_state_t state;
/* Timer */
bool poll_timer;
/* General 1 sec timer */
int sec_timer;
int active_led;
bool red_led_on;
bool green_led_on;
bool blue_led_on;
uint8_t led_state;
int** blink_pattern;
} hmi_t;
static hmi_t hmi;
int hmi_choose_led(int led_color,uint8_t op_mode)
{
// int retval=HMI_STATUS_OK;
hmi.led_state = op_mode; /*led state ( on,off or blinking).*/
switch (led_color)
{
case RED_TRI_LED:
hmi.red_led_on = 1;
hmi.green_led_on = 0;
hmi.blue_led_on = 0;
break;
case GREEN_TRI_LED:
hmi.red_led_on = 0;
hmi.green_led_on = 1;
hmi.blue_led_on = 0;
break;
case BLUE_TRI_LED:
hmi.red_led_on = 0;
hmi.green_led_on = 0;
hmi.blue_led_on = 1;
break;
default:
hmi.red_led_on = 0;
hmi.green_led_on = 0;
hmi.blue_led_on = 0;
break;
}
return 0;
}
>>>>>>> 4ea13f8 (Added azuma wifi switch backup code)
/* This is the hmi_task that will be executed periodically*/
void hmi_task(void *pvParameters)
{
for(;;)
{
while(leds_enabled == false)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
port_red_led_off();
port_blue_led_off();
blue_red_sync = false;
}
if(true == pushbutton_state) // 1) Check if the pushbutton is pressed
{
/* reset the alternating flag */
alternate_cycle_for_both = false;
/*If pushbutton is pressed then do the following task*/
hmi_pushbutton_pressed_task();
}
else if(true == device_failure_state) // 2) Check if the device failure is occurred
{
/* reset the alternating flag */
alternate_cycle_for_both = false;
/*If device failure is occurred then do the following task*/
hmi_device_failure_task();
}
else if(true == device_not_onboarded_state) // 3) Check if the device failure is occurred
{
/* reset the alternating flag */
alternate_cycle_for_both = false;
/*If device has not been onBoarded yet then do the following task*/
hmi_device_not_onboarded_task();
}
else if(true == ota_update_session) // 4) Check if the OTA-Session is happening now
{
/*Check if the alternating flag is false*/
if(false == alternate_cycle_for_both)
{
/*Turn on the BLUE and turn off the RED*/
port_red_led_off();
port_blue_led_on();
alternate_cycle_for_both = true;
}
/*If device is doing OTA-Update session now then do the following task*/
hmi_ota_firmware_update_task();
}
else
{
if((0 < num_events_in_queue) || (true == continue_current_leds_state)) // 5) Check if there are led_events in the hmi_queue
{
/* reset the alternating flag */
alternate_cycle_for_both = false;
/*If there are led_events inside the hmi_queue then do the following task*/
hmi_events_in_queue_task();
}
else
{
if(true == usb_connection_state) // 6) Check if the USB is plugged
{
/*Check if the synchronization flag is false*/
if(false == blue_red_sync)
{
/*Turn off both leds for synchronization*/
port_red_led_off();
port_blue_led_off();
blue_red_sync = true;
}
/*If USB is connected then do the following task*/
hmi_usb_connected_task();
}
else
{
// If none of the previous conditions were true then turn off both leds
hmi_duration = NORMAL_HMI_DURATION;
port_red_led_off();
port_blue_led_off();
vTaskDelay(hmi_duration / portTICK_PERIOD_MS);
}
}
}
}
vTaskDelete(NULL);
}