/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    yunhorn_sts_process.c      									   *   
  * @author  Yunhorn (r) Technology Limited Application Team	               *
  * @brief   Yunhorn (r) SmarToilets (r) Product configuration file.		   *
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 Yunhorn Technology Limited.
  * Copyright (c) 2022 Shenzhen Yunhorn Technology Co., Ltd.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include "platform.h"
#include "sys_conf.h"
#include "sys_app.h"
#include "stdio.h"
#include "stm32_systime.h"
#include "adc_if.h"
#include "gpio.h"
#include "LmHandler.h"
//#include "app_tof.h"
#include "lora_app.h"
#include "yunhorn_sts_prd_conf.h"
#include "yunhorn_sts_sensors.h"
#include "sts_cmox_hmac_sha.h"

/* USER CODE BEGIN Includes */
extern volatile sts_cfg_nvm_t sts_cfg_nvm;

extern volatile uint8_t sts_ac_code[20];
volatile uint8_t sts_work_mode = STS_UNI_MODE;
#if 0
#if	defined(STS_O7)
volatile uint8_t sts_work_mode = STS_UNI_MODE;
#elif	defined(STS_O6)
volatile uint8_t sts_work_mode = STS_DUAL_MODE;
#elif	defined(STS_O2)
volatile uint8_t sts_work_mode = STS_RSS_MODE;
#endif
#endif
volatile uint8_t sts_service_mask=0;
volatile uint32_t rfac_timer;
volatile uint8_t sensor_data_ready=0;
volatile STS_PRESENCE_SENSOR_Event_Status_t sts_o7_event_status;

// GPIO reed hall pin
extern volatile uint8_t sts_reed_hall_result;
volatile uint8_t last_sts_reed_hall_result;
extern volatile uint8_t sts_hall1_read,sts_hall2_read, sts_hall3_read, sts_hall4_read;
volatile uint8_t sts_reed_hall_1_result=STS_Status_Door_Open,sts_reed_hall_2_result=STS_Status_SOS_Release, last_sts_reed_hall_1_result=STS_Status_Door_Open, last_sts_reed_hall_2_result=STS_Status_SOS_Release;
volatile uint8_t sts_reed_hall_3_result=STS_Status_Door_Open, last_sts_reed_hall_3_result=STS_Status_Door_Open, sts_reed_hall_4_result=STS_Status_Door_Open, last_sts_reed_hall_4_result=STS_Status_Door_Open;

volatile uint8_t sts_soap_level_state;

// RSS motion and distance
volatile STS_OO_SensorStatusDataTypeDef sts_o7_sensorData;
volatile uint16_t sts_distance_rss_distance=0, sts_sensor_install_height=0;//in mm
extern volatile float sts_presence_rss_distance, sts_presence_rss_score;
volatile uint8_t sts_rss_config_updated_flag = STS_RSS_CONFIG_NON;
extern volatile uint8_t sts_occupancy_overtime_state;
extern volatile distance_measure_cfg_t distance_cfg;
extern volatile uint16_t sts_fall_rising_pattern_factor1;
extern volatile uint16_t sts_roc_acc_standard_variance;
volatile uint32_t last_sts_rss_time_stamp=0;

// RSS fall detection
extern volatile uint8_t sts_fall_detection_acc_threshold, sts_fall_detection_depth_threshold, sts_occupancy_overtime_threshold_in_10min;
extern volatile uint8_t sts_fall_rising_detected_result, sts_fall_rising_detected_result_changed_flag;
extern volatile uint8_t sts_presence_fall_detection;
extern volatile uint8_t last_sts_fall_rising_detected_result;

extern volatile uint16_t sts_motionless_duration_threshold_in_min;
extern volatile uint8_t sts_status_color, sts_lamp_bar_color;//puColor
extern volatile uint8_t sts_cloud_netcolor;		//netColor
extern uint8_t luminance_level;
SysTime_t mems_event_time;


volatile uint8_t sts_occupancy_status;
volatile uint8_t sts_hall1_changed_flag=0, sts_hall2_changed_flag=0, last_sts_hall1_result=0, last_sts_hall2_result=0;
volatile uint8_t sts_reed_hall_changed_flag = 0;
extern volatile uint8_t sts_reed_hall_result;
volatile uint8_t sts_water_leakage_result=0;
volatile uint8_t sts_water_leakage_changed_flag=0;
//extern volatile uint8_t sensor_data_ready;
#ifdef YUNHORN_STS_R4_ENABLED
volatile STS_R0_SensorDataTypeDef r4_data;
#endif

#ifdef YUNHORN_STS_O5_ENABLED

#endif
#if	defined(STS_O7)||defined(STS_O6)
extern volatile uint8_t motion_detected_count;
extern volatile uint8_t motion_in_hs_zone[12][10];	//0.4*12=4.8meter high, past 10 measures
extern volatile uint8_t detected_hs_zone;

extern volatile STS_OO_RSS_SensorTuneDataTypeDef sts_presence_rss_config;
volatile uint32_t cnt=0;


volatile uint8_t sts_tof_result_changed_flag = 0;

volatile uint8_t sts_rss_result_changed_flag = 0;
volatile uint8_t sts_rss_result = STS_RESULT_NO_MOTION;
volatile uint8_t sts_rss_2nd_result = STS_RESULT_NO_MOTION;		//2nd RSS sensor status
volatile uint8_t sts_tof_result = STS_RESULT_NO_MOTION;
volatile uint8_t last_sts_rss_result=STS_RESULT_NO_MOTION;

//extern volatile uint8_t last_sts_reed_hall_result;
extern volatile uint8_t last_lamp_bar_color;
extern volatile float sts_presence_rss_distance;
char sts_presence_fall_detection_message[10][20]={
	"State_Normal",
	"State_Fall_Down",
	"State_Rising_Up",
	"State_Laydown",
	"State_Unconscious",
	"State_StayStill",
	"State_No_Movement"
};

#endif   


/*
  	    // UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP4), CFG_SEQ_Prio_0);
	  	// P1    --- REEDSWITCH, HALL ELEMENT, WATER LEAKAGE
	   	// P2    --- SEE ABOVE, RSS PRESENCE
	   	// P3    ----LAMP BAR SCOLLER PROCESS
	   	// P4    --- TOF DISTANCE  VL53L0X simple distance
	   	// P5    --- TOF IN OUT COUNT  VL53L3X in out or duration
	   	// P6    --- SOAP Level, capacitive measurement
	   	// P7    --- UltraSonic, 2nd wave UltraSonic range measure
	   	// P8    --- AIR QUALITY AND ODOR LEVEL, SMOKING DETECTION
*/


/* USER CODE END Includes */

/* External variables ---------------------------------------------------------*/
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
#if (defined(YUNHORN_STS_O6_ENABLED) && defined(USE_ACCONEER_A111))

#endif

/* USER CODE END PFP */

/* Exported functions --------------------------------------------------------*/

void STS_YunhornAuthenticationCode_Process(void)
{
	if ((sts_ac_code[0] == 0x00) && (sts_ac_code[19]== 0x0)) {
		APP_LOG(TS_OFF,VLEVEL_M, "Initial AC CODE blank... \r\n");
		return;
	}

	sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0;
	if (sts_service_mask == STS_SERVICE_MASK_L2) {
		sts_ac_code[0] = 0x0;
		sts_ac_code[19]= 0x0;
	}
	APP_LOG(TS_OFF, VLEVEL_H, "STS_SERVICE_MASK:%d \r\n",sts_service_mask);
}

void STS_YunhornSTSEventRFAC_Process(void)
{
	if ((sts_ac_code[0] ==0x0)&& (sts_ac_code[19]== 0x0))
	{
		if ((rfac_timer >= STS_BURN_IN_RFAC) && (rfac_timer < (STS_BURN_IN_RFAC +3)))
		{
			APP_LOG(TS_OFF, VLEVEL_M, "\r\n -------------------RFAC Process\r\n");
			STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 4, (uint8_t *)"RFAC");
		}
		if ((rfac_timer > (STS_BURN_IN_RFAC + 2)))
		{
			APP_LOG(TS_OFF, VLEVEL_M, "\r\n -------------------Verify RFAC Success or Not\r\n");
			sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0;
			if (sts_service_mask == STS_SERVICE_MASK_L2) {
				sts_ac_code[0] = 0x0;
				sts_ac_code[19] = 0x0;
			}
		}
	}

}

/*
 *  STS-P1    --- REEDSWITCH, HALL ELEMENT, WATER LEAKAGE
 */

void STS_YunhornSTSEventP1_Process(void)
{

		sts_reed_hall_1_result = HALL1_STATE;  //sts_hall1_read;
		if (sts_reed_hall_1_result != last_sts_reed_hall_1_result)
		{
					sts_reed_hall_changed_flag |= 0x01;
		}
		last_sts_reed_hall_1_result = sts_reed_hall_1_result;

		sts_reed_hall_2_result = HALL2_STATE;// sts_hall2_read;
		if (sts_reed_hall_2_result != last_sts_reed_hall_2_result)
		{
				sts_reed_hall_changed_flag |= 0x02;
		}
		last_sts_reed_hall_2_result = sts_reed_hall_2_result;

		sts_reed_hall_3_result = sts_hall3_read;//HALL3_STATE;// sts_hall3_read;
		if (sts_reed_hall_3_result != last_sts_reed_hall_3_result)
		{
			sts_reed_hall_changed_flag |= 0x04;
		}
		last_sts_reed_hall_3_result = sts_reed_hall_3_result;

		sts_reed_hall_4_result = sts_hall4_read;//HALL4_STATE;// sts_hall3_read;
		if (sts_reed_hall_4_result != last_sts_reed_hall_4_result)
		{
			sts_reed_hall_changed_flag |= 0x08;
		}
		last_sts_reed_hall_4_result = sts_reed_hall_4_result;


		STS_Combined_Status_Processing();
}

extern volatile uint32_t wcnt;

/*
 *  STS-P2    --- RSS PRESENCE
 */
void STS_YunhornSTSEventP2_Process(void)
{

	//STS_Lamp_Bar_Refresh();  //TODO XXX eliminate refresh every second.... try
	if ((sts_work_mode >= STS_RSS_MODE) && (sts_work_mode <= STS_TOF_RSS_MODE))
	{
		switch (sts_work_mode) {
		case STS_RSS_MODE:
			sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
			break;
		case STS_DUAL_MODE:
			sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
			break;
		case STS_UNI_MODE:
			sts_rss_config_updated_flag = STS_RSS_CONFIG_FALL_DETECTION;
			break;
		default:
			break;
		}

		sts_presence_rss_fall_rise_detection();

		sts_rss_result_changed_flag = (sts_rss_result == last_sts_rss_result)? 0:1;

		last_sts_rss_result = sts_rss_result;

		//sts_fall_rising_detected_result_changed_flag = (sts_fall_rising_detected_result == last_sts_fall_rising_detected_result)?0:1;
		//sts_fall_rising_detected_result_changed_flag = (sts_fall_rising_detected_result != last_sts_fall_rising_detected_result)?1:0;


		last_sts_fall_rising_detected_result = sts_fall_rising_detected_result;

		if (sts_service_mask > 0 ) {
			sts_rss_result_changed_flag =0;
			sts_reed_hall_changed_flag = 0;
			sts_fall_rising_detected_result_changed_flag =0;
		}

		STS_Combined_Status_Processing();
	}

}

void STS_Reed_Hall_Presence_Detection(void)
{
//	HAL_Delay(50);										// BOUNCING ELIMIATION
	sts_reed_hall_1_result = (sts_hall1_read==0)?STS_Status_Door_Close:STS_Status_Door_Open;
	sts_reed_hall_2_result = (sts_hall2_read==0)?STS_Status_Door_Close:STS_Status_Door_Open;
	sts_reed_hall_3_result = (sts_hall3_read==0)?STS_Status_Door_Close:STS_Status_Door_Open;

	//sts_reed_hall_result = ((STS_Reed_Hall_State)&STS_Status_Door_Open);

//	HAL_Delay(20);										// BOUNCING ELIMIATION

	sts_reed_hall_changed_flag = 0;



}

/*
 *  STS P3 process, Lamp Bar Scoller
 */
void STS_YunhornSTSEventP3_Process(void)
{
#if (defined(STS_O6) ||defined(STS_O7))
		if (STS_Reed_Hall_State == STS_Status_Door_Open)
		{
			sts_lamp_bar_color =STS_GREEN;
		}
		else
		{
			sts_lamp_bar_color =STS_RED;
		}
		STS_Lamp_Bar_Scoller(sts_lamp_bar_color, luminance_level);
#endif
}


/*
 * STS SOAP Level detection Process, STS_CAP_Sensor_Detection Process
 * STS_CAP_SWITCH(ON) Boost Voltage to 5V, then hold for 1000 ms
 * HAL_Delay(1000) (ms)
 * STS_CAP_Read_Data()	Read STS_CAP_DATA state
 * STS_CAP_SWITCH(OFF)   Switch Off Boosted Voltage
 */
/*
 *  STS-P4 Detection ToF distance (VL53L0X)
 *
 */
void STS_YunhornSTSEventP4_Process(void)
{
	PME_ON;
#ifdef	LED_ONBOARD
	LED_ON;
	HAL_Delay(10);
	LED_OFF;
#endif
#if defined(TOF_1)||defined(TOF_2)
	APP_LOG(TS_OFF, VLEVEL_H, "\r\n TOF_1, TOF_2 RANGING Process\r\n");
	STS_TOF_VL53L0X_Range_Process();
#endif

#ifdef TOF_3
	APP_LOG(TS_OFF, VLEVEL_H, "\r\n TOF 3 RANGING Process ---- TOF250 Ranging \r\n");
	STS_TOF250_Range_Process();
#endif

	PME_OFF;

}


/*
 *  STS P5 Process, Detection ToF IN-OUT PEOPLE COUNT (VL53L3X)
 *
 */
void STS_YunhornSTSEventP5_Process(void)
{
	APP_LOG(TS_OFF, VLEVEL_L, "\r\n P5 Testing Process\r\n");
}

/*
 * STS-P6	--- SOAP Level, capacitive measurement
 * STS Soap Level Detection Process, STS_CAP_Sensor_Detection Process
 * STS_CAP_SWITCH(ON) Boost Voltage to 5V, then hold for 1000 ms
 * HAL_Delay(1000) (ms)
 * STS_CAP_Read_Data()	Read STS_CAP_DATA state
 * STS_CAP_SWITCH(OFF)   Switch Off Boosted Voltage
 */
void STS_YunhornSTSEventP6_Process(void)
{
	APP_LOG(TS_OFF, VLEVEL_H, "\r\n P6 Testing Process\r\n");
	PME_ON;
	HAL_Delay(50);
#ifdef LED_ONBOARD
	LED_ON;
	HAL_Delay(20);
	LED_OFF;
#endif
/* 1. Sensor  Power On */
#if defined(SOAP_LEVEL_SENSOR)
	HAL_GPIO_WritePin(SOAP_SWITCH_GPIO_Port, SOAP_SWITCH_Pin, GPIO_PIN_SET);

	HAL_Delay(1000);
	/* 2. Read sensor state */

	sts_soap_level_state = HAL_GPIO_ReadPin(SOAP_STATUS_GPIO_Port,SOAP_STATUS_Pin);
	APP_LOG(TS_OFF, VLEVEL_L, "\r\n Soap State = %s \r\n", (sts_soap_level_state==0x0)?"  +++  Liquid Detected":"  ---  No Liquid");

	HAL_GPIO_WritePin(SOAP_SWITCH_GPIO_Port, SOAP_SWITCH_Pin, GPIO_PIN_RESET);

	if (sts_soap_level_state == 0x0)
	{
#ifdef LED_ONBOARD
		LED_ON;
		HAL_Delay(20);
		LED_OFF;
#endif
	}

#endif
/* 3. Sensor  Power Off */
	PME_OFF;
}


/*
 *  STS P7 Process, Detection IAQ Sensors
 *  air quality and odor level sensors
 */
void STS_YunhornSTSEventP7_Process(void)
{
	APP_LOG(TS_OFF, VLEVEL_L, "\r\n P7 Testing Process\r\n");
	PME_ON;

	PME_OFF;
}


/*
 *  STS P8 Process, Detection ETR Sensors, Water flow sensors, pulse counting
 *  PA5 sensors , TIM2_ETR, STS-M4
 */
void STS_YunhornSTSEventP8_Process(void)
{
	APP_LOG(TS_OFF, VLEVEL_L, "\r\n P8 Testing Process\r\n");

}

/*
 *  STS P_IO_RS485 Process, Send Out Sensor Data Via RS485 interface
 *  sensors
 */

void STS_YunhornSTSEventPIORS485_Process(void)
{
	APP_LOG(TS_OFF, VLEVEL_L, "\r\n P_IO_RS485 Process\r\n");
}


void STS_PRESENCE_SENSOR_WakeUp_Process_Sampling(void)
{
#if 0
	if ((sensor_data_ready ==0)) {
		STS_PRESENCE_SENSOR_GetValue();
	}
#endif
}

void STS_PRESENCE_SENSOR_After_Wake_Up()
{

}


void STS_FallDetection_LampBarProcess(void)
{

}

void STS_YunhornSTSFallDetection(void)
{
	//APP_LOG(TS_OFF, VLEVEL_M, "\r\n YUNHORN STS FALL DETECTION \r\n");

	//STS_YunhornCheckStandardDeviation();

}

void STS_Combined_Status_Processing(void)
{
	switch (sts_work_mode)
	{
		case STS_NETWORK_MODE:
			sts_status_color = sts_cloud_netcolor;
			sts_lamp_bar_color = sts_cloud_netcolor;

			break;
		case STS_WIRED_MODE:				// NO LAMP BAR FOR THOSE WATER LEAKAGE SENSOR OR SOAP CAPACITY SENSORS
			sts_status_color = STS_DARK;
#ifdef 	STS_M1
			sts_water_leakage_result = (sts_reed_hall_result == STS_Status_Door_Open )?STS_RESULT_WATER_LEAKAGE_YES:STS_RESULT_WATER_LEAKAGE_NO;
			sts_water_leakage_changed_flag = 1;
#endif
			break;
		case STS_REEDSWITCH_MODE:

			sts_status_color = (sts_reed_hall_1_result == STS_Status_Door_Open )? STS_GREEN: STS_RED;
			if (sts_reed_hall_2_result == STS_Status_SOS_Pushdown )
			{
				sts_status_color = STS_RED_BLUE;
			}
			break;
		case STS_RSS_MODE:
			if (sts_rss_result == STS_RESULT_NO_MOTION){
				sts_status_color = STS_GREEN;
			} else if ((sts_rss_result == STS_RESULT_MOTION))
			{
				sts_status_color = STS_RED;
			}
			break;
		case STS_DUAL_MODE:		// FOR STS_O6
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_1_result == STS_Status_Door_Open )&& (sts_reed_hall_2_result == STS_Status_SOS_Release ))
			{
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_1_result == STS_Status_Door_Close )||(sts_reed_hall_2_result == STS_Status_SOS_Pushdown ))
			{
				sts_status_color = STS_RED;

				if (sts_reed_hall_2_result == STS_Status_SOS_Pushdown )
				{
					sts_status_color = STS_RED_BLUE;
				}
			 }
			break;

		case STS_UNI_MODE:		//FOR STS-O7
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_1_result == STS_Status_Door_Open )&& (sts_reed_hall_2_result == STS_Status_SOS_Release )
					&& (sts_reed_hall_3_result == STS_Status_Alarm_Mute_Release )&& (sts_reed_hall_4_result == STS_Status_Alarm_Reset_Release ))
			{
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_1_result == STS_Status_Door_Close )||(sts_reed_hall_2_result == STS_Status_SOS_Pushdown )
					|| (sts_reed_hall_3_result == STS_Status_Alarm_Mute_Pushdown )|| (sts_reed_hall_4_result == STS_Status_Alarm_Reset_Pushdown ))
			{
				sts_status_color = STS_RED;

				if (sts_reed_hall_2_result == STS_Status_SOS_Pushdown )
				{
					sts_status_color = STS_RED_BLUE;
				}
			}

			switch(sts_fall_rising_detected_result)
			{
				case STS_PRESENCE_NORMAL:
					//do nothing
				break;

				case STS_PRESENCE_LAYDOWN:
						sts_lamp_bar_color = STS_YELLOW;
					    sts_status_color = STS_YELLOW;
				break;

				case STS_PRESENCE_FALL:		//RED_BLUE FLASH
						sts_lamp_bar_color = STS_RED_BLUE;
						sts_status_color = STS_RED_BLUE;
				break;

				case STS_PRESENCE_RISING:  //NORMAL OCCUPANCY STATUS
						sts_lamp_bar_color = STS_RED;
						sts_status_color = STS_RED;
				break;

				default:
//						sts_lamp_bar_color = STS_RED;
//						sts_status_color = STS_RED;
				break;
			}

		break;

		case STS_REMOTE_REED_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_result == STS_Status_Door_Open ))
			{
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_result == STS_Status_Door_Close ))
			{
				sts_status_color = STS_RED;
			}
			break;
		case STS_DUAL_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_rss_2nd_result == STS_RESULT_NO_MOTION))
			{
				sts_status_color = STS_GREEN;
			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_rss_2nd_result == STS_RESULT_MOTION))
			{
				sts_status_color = STS_RED;
			}

			break;
		case STS_TOF_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_tof_result == STS_RESULT_NO_PRESENCE)){
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_tof_result == STS_RESULT_PRESENCE))
			{
				sts_status_color = STS_RED;
			}

			break;
//   TO-DO LIST  ***********************************************************
		case STS_TOF_DISTANCE_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
		case STS_TOF_PRESENCE_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
		case STS_TOF_IN_OUT_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
//   TO-DO LIST  ***********************************************************
		default:
			break;
	}

	if ((sts_work_mode == STS_WIRED_MODE) || (sts_service_mask > STS_SERVICE_MASK_L0))
	{
		sts_status_color = STS_DARK;
		sts_lamp_bar_color = STS_DARK;
		last_lamp_bar_color = STS_DARK;
		STS_Lamp_Bar_Set_Dark();
	}
	else
	{

		if ((last_lamp_bar_color != sts_status_color))
		{
			sts_lamp_bar_color = sts_status_color;

			//STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level);

			last_lamp_bar_color = sts_lamp_bar_color;
		}
	}


	if ((sts_rss_result_changed_flag)|| (sts_reed_hall_changed_flag)||(sts_fall_rising_detected_result_changed_flag))
	{
		//sts_rss_result_changed_flag =0;
		//sts_reed_hall_changed_flag =0;
		//sts_fall_rising_detected_result_changed_flag =0;
		//sts_tof_result_changed_flag =0;
		sensor_data_ready = 1;
		//STS_PRESENCE_SENSOR_Prepare_Send_Data();
	}

}



void STS_PRESENCE_SENSOR_NVM_CFG(void)
{
	sts_presence_rss_config.default_start_m 		 				= (float)((float)sts_cfg_nvm.p[RSS_CFG_START_M]*0.1f);
	sts_presence_rss_config.default_length_m 		 				= (float)((float)sts_cfg_nvm.p[RSS_CFG_LENGTH_M]*0.1f);
	sts_presence_rss_config.default_threshold						= (float)((float)sts_cfg_nvm.p[RSS_CFG_THRESHOLD]*0.1f);
	sts_presence_rss_config.default_receiver_gain					= (float)((float)sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN]*0.01f);

	sts_presence_rss_config.default_zone_length_m	 				= DEFAULT_ZONE_LENGTH;
	sts_presence_rss_config.default_profile  		 				= (float)(sts_cfg_nvm.p[RSS_CFG_PROFILE]);
	sts_presence_rss_config.default_update_rate_tracking			= (float)(sts_cfg_nvm.p[RSS_CFG_RATE_TRACKING]);
	sts_presence_rss_config.default_update_rate_presence			= (float)(sts_cfg_nvm.p[RSS_CFG_RATE_PRESENCE]);
	sts_presence_rss_config.default_hwaas							= (float)(sts_cfg_nvm.p[RSS_CFG_HWAAS]);

	sts_presence_rss_config.default_nbr_removed_pc					= (float)(sts_cfg_nvm.p[RSS_CFG_NBR_REMOVED_PC]);

//filter parameter
	sts_presence_rss_config.default_inter_frame_deviation_time_const = (float)(sts_cfg_nvm.p[RSS_CFG_ITE_DEVIATION]*0.1f);
	sts_presence_rss_config.default_inter_frame_fast_cutoff			= (float)(sts_cfg_nvm.p[RSS_CFG_ITE_FAST_CUTOFF]);
	sts_presence_rss_config.default_inter_frame_slow_cutoff			= (float)(sts_cfg_nvm.p[RSS_CFG_ITE_SLOW_CUTOFF]*0.01f);

	sts_presence_rss_config.default_intra_frame_time_const			= (float)(sts_cfg_nvm.p[RSS_CFG_ITR_TIME]);
	sts_presence_rss_config.default_intra_frame_weight				= (float)(sts_cfg_nvm.p[RSS_CFG_ITR_WEIGHT]*0.1f);

	sts_presence_rss_config.default_output_time_const				= (float)(sts_cfg_nvm.p[RSS_CFG_OUTPUT_TIME]*0.1f);
//filter parameter

	sts_presence_rss_config.default_downsampling_factor				= (float)(sts_cfg_nvm.p[RSS_CFG_DOWNSAMPLING_FACTOR]);
	sts_presence_rss_config.default_power_save_mode					= (float)(sts_cfg_nvm.p[RSS_CFG_POWER_MODE]);

	sts_rss_config_updated_flag = STS_RSS_CONFIG_FULL;  //set to 2 for FULL config effect in next detection
}

void STS_PRESENCE_SENSOR_NVM_CFG_SIMPLE(void)
{
	sts_presence_rss_config.default_start_m 		 				= (float)(sts_cfg_nvm.p[RSS_CFG_START_M]*0.1f);
	sts_presence_rss_config.default_length_m 		 				= (float)(sts_cfg_nvm.p[RSS_CFG_LENGTH_M]*0.1f);
	sts_presence_rss_config.default_threshold						= (float)(sts_cfg_nvm.p[RSS_CFG_THRESHOLD]*0.1f);
	sts_presence_rss_config.default_receiver_gain					= (float)(sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN]*0.01f);

	sts_rss_config_updated_flag = STS_RSS_CONFIG_SIMPLE;  //set to 1 for simple config effect in next detection
}

void STS_PRESENCE_SENSOR_Init_Send_Data(void)
{
	//sts_o7_sensorData.lamp_bar_color			= STS_GREEN;
	sts_o7_sensorData.workmode					= sts_work_mode; //STS_DUAL_MODE;

	sts_o7_sensorData.state_sensor1_on_off		= 0x0;
	sts_o7_sensorData.state_sensor2_on_off		= 0x0;
	sts_o7_sensorData.state_sensor3_on_off		= 0x0;
	sts_o7_sensorData.state_sensor4_on_off		= 0x0;
	sts_o7_sensorData.rss_presence_distance		= 0x0;
	sts_o7_sensorData.rss_presence_score		= 0x0;
	sts_o7_sensorData.fall_state				= STS_PRESENCE_NORMAL;
	sts_o7_sensorData.fall_speed				= 0x0;
	sts_o7_sensorData.fall_gravity				= 0x0;
	sts_o7_sensorData.over_stay_state			= 0x0;
	sts_o7_sensorData.over_stay_duration		= 0x0;
	sts_o7_sensorData.unconscious_state			= 0x0;
	sts_o7_sensorData.no_movement_state			= 0x0;
	sts_o7_sensorData.unconscious_duration		= 0x0;
	sts_o7_sensorData.no_movement_duration		= 0x0;

	sts_o7_sensorData.event_sensor1_start_time				= 0x0;
	sts_o7_sensorData.event_sensor1_duration				= 0x0;

	sts_o7_sensorData.event_sensor2_start_time  			= 0x0;
	sts_o7_sensorData.event_sensor2_duration				= 0x0;
	sts_o7_sensorData.event_sensor2_start_timestamp  		= 0x0;
	sts_o7_sensorData.event_sensor2_stop_timestamp  		= 0x0;

	sts_o7_sensorData.event_sensor3_motion_start_time  		= 0x0;
	sts_o7_sensorData.event_sensor3_motion_duration			= 0x0;
	sts_o7_sensorData.event_sensor3_fall_start_time  		= 0x0;
	sts_o7_sensorData.event_sensor3_fall_start_time_stamp  	= 0x0;
	sts_o7_sensorData.event_sensor3_fall_duration			= 0x0;
	sts_o7_sensorData.event_sensor3_fall_stop_time_stamp	= 0x0;
	sts_o7_sensorData.event_sensor4_start_time  			= 0x0;
	sts_o7_sensorData.event_sensor4_duration				= 0x0;
	sts_o7_sensorData.event_sensor3_fall_distance 			= 0x0;
	sts_o7_sensorData.event_sensor3_fall_motionscore		= 0x0;


	sts_o7_sensorData.battery_Pct 				= 99; // 99% as init value
	sts_o7_sensorData.dutycycletimelevel		= 1;
	sensor_data_ready							= 0;
}

void STS_PRESENCE_SENSOR_Prepare_Send_Data(STS_OO_SensorStatusDataTypeDef *sensor_data)
{
	sensor_data->lamp_bar_color				= sts_lamp_bar_color;
	sensor_data->workmode					= sts_work_mode;

// #1 for HALL_ELEMENT, DOOR CONTACT, SENSOR STATE PROCESS
	sensor_data->state_sensor1_on_off		= HALL1_STATE;//sts_hall1_read; //sts_hsts_reed_hall_result;		// sts_hall1_read
	sensor_data->state_sensor2_on_off		= HALL2_STATE;//sts_hall2_read; //sts_emergency_button_pushed;		//sts_hall2_read
	sensor_data->state_sensor3_on_off		= sts_rss_result;
	sensor_data->state_sensor4_on_off		= sts_hall3_read;		//for alarm mute button
	sensor_data->state_sensor5_on_off		= sts_hall4_read;		//for alarm reset button

    if (sensor_data->state_sensor2_on_off==STS_Status_SOS_Pushdown)
    {
		sensor_data->event_sensor2_start_timestamp = sts_o7_sensorData.event_sensor2_start_timestamp;
		sensor_data->event_sensor2_stop_timestamp = sts_o7_sensorData.event_sensor2_stop_timestamp;
		sts_o7_sensorData.event_sensor2_start_timestamp = 0;
    } else {
		sensor_data->event_sensor2_start_timestamp = 0;
		sensor_data->event_sensor2_stop_timestamp  = 0;
		sensor_data->event_sensor2_stop_timestamp = sts_o7_sensorData.event_sensor2_stop_timestamp;
		sts_o7_sensorData.event_sensor2_stop_timestamp = 0;
    }

// #2 for MOTION RELATED SENSOR STATE PROCESS, OCCUPY/VACANT/OVERSTAY/LONGSTAY/UNCONSCIOUS
	if (sts_rss_result == STS_RESULT_MOTION)
	{
		sensor_data->rss_presence_distance	= (uint16_t)(sts_presence_rss_distance);
		sensor_data->rss_presence_score		= (uint16_t)(sts_presence_rss_score);
		// uint8_t  sts_unconscious_state;
		// uint16_t sts_unconscious_threshold, sts_unconscious_threshold_duration;
	}
	//else {
	//		sensor_data->rss_presence_distance	= 0x0;
	//		sensor_data->rss_presence_score		= 0x0;
	//	}

	// no_movement or unconscious duration
	sensor_data->unconscious_state				= ((sts_fall_rising_detected_result == STS_PRESENCE_UNCONSCIOUS) ||
			(sts_fall_rising_detected_result==STS_PRESENCE_STAYSTILL) ||
			(sts_fall_rising_detected_result==STS_PRESENCE_NO_MOVEMENT))? 1:0;
	sensor_data->unconscious_duration			= sts_o7_sensorData.event_sensor3_unconcious_duration;

	sensor_data->no_movement_state				=  sensor_data->unconscious_state;
	sensor_data->no_movement_duration			= sts_o7_sensorData.event_sensor3_no_movement_duration;
	if (sensor_data->unconscious_state !=0)
	{
		APP_LOG(TS_OFF,VLEVEL_M,"\r\n ... Unconscious or No Movement Duration = %u Sec [Threshold: %u Seconds]\r\n",
				sensor_data->unconscious_duration, sts_motionless_duration_threshold_in_min*60);
	}

	// Over stay, long stay duration and state
	sensor_data->over_stay_state 				= sts_o7_sensorData.over_stay_state;
	sensor_data->over_stay_duration 			= sts_o7_sensorData.event_sensor1_duration;
	if (sensor_data->over_stay_state !=0)
	{
		APP_LOG(TS_OFF,VLEVEL_M,"\r\n ... Over Stay Duration = %u Sec [Threshold: %u Seconds]\r\n",
				sensor_data->over_stay_duration,
				sts_occupancy_overtime_threshold_in_10min*60);
	}

// #3 for FALL DETECTION, FALL, RISING, LAYDOWN DURATION CONFIRMATION STATE PROCESS
	sensor_data->fall_state				= sts_fall_rising_detected_result;
	if ((sts_fall_rising_detected_result == STS_PRESENCE_FALL)||
			(sts_fall_rising_detected_result == STS_PRESENCE_RISING)||
			(sts_fall_rising_detected_result == STS_PRESENCE_LAYDOWN))
	{
		APP_LOG(TS_OFF, VLEVEL_M, "\r\n......FALL RISING DETECTION RESULT: %25s \r\n",
				(char*)sts_presence_fall_detection_message[sts_fall_rising_detected_result] );
		sensor_data->fall_speed				= (uint8_t)sts_fall_rising_pattern_factor1;
		sensor_data->fall_gravity			= (uint8_t)sts_roc_acc_standard_variance;
		sensor_data->event_sensor3_fall_start_time_stamp = sts_o7_sensorData.event_sensor3_fall_start_time_stamp;
		sensor_data->event_sensor3_fall_stop_time_stamp  = sts_o7_sensorData.event_sensor3_fall_stop_time_stamp;
		sensor_data->event_sensor3_fall_distance		= (uint16_t)(sts_o7_sensorData.event_sensor3_fall_distance);
		sensor_data->event_sensor3_fall_motionscore		= (uint16_t)(sts_o7_sensorData.event_sensor3_fall_motionscore);
	} else {
		sensor_data->fall_speed				= 0;
		sensor_data->fall_gravity			= 0;
		sensor_data->event_sensor3_fall_start_time_stamp = 0;
		sensor_data->event_sensor3_fall_stop_time_stamp =0;
	}


#if 0
	// TODO XXXX
	// FOR ALARM MUTE AND RESET
	if ((sts_occupancy_overtime_threshold_in_10min != 0) && (event_start_time !=0))
	{
				if (sts_occupancy_overtime_state == 1U) {
					sts_status_color = STS_RED_BLUE;
					sts_lamp_bar_color = STS_RED_BLUE;
				}
				//STS_Lamp_Bar_Refresh();
	}
#endif

    sensor_data_ready = 1;
}


/**
  * @brief  Initializes the motion sensors
  * @param  Instance Motion sensor instance
  * @param  Functions Motion sensor functions. Could be :
  *         - MOTION_ACCELERO for instance
  * @retval BSP status
  */
void STS_PRESENCE_SENSOR_Init(void)
{
	APP_LOG(TS_ON, VLEVEL_M, "##### YunHorn SmarToilets(r) Presence Sensor Started\r\n");

	sts_o7_sensorData.workmode										= (uint8_t)sts_work_mode; //STS_DUAL_MODE;
	sts_o7_sensorData.lamp_bar_color 								= (uint8_t)STS_GREEN;
	sts_o7_sensorData.battery_Pct 									= 99;
	sts_o7_sensorData.dutycycletimelevel 							= 1;
	sts_o7_sensorData.event_sensor1_start_time						= 0;
	sts_o7_sensorData.event_sensor1_stop_time						= 0;
	sts_o7_sensorData.event_sensor1_duration						= 0;

	sts_o7_sensorData.event_sensor2_start_time						= 0;
	sts_o7_sensorData.event_sensor2_stop_time						= 0;
	sts_o7_sensorData.event_sensor2_duration						= 0;
	sts_o7_sensorData.event_sensor2_start_timestamp  				= 0;
	sts_o7_sensorData.event_sensor2_stop_timestamp  				= 0;

	sts_o7_sensorData.event_sensor3_motion_start_time				= 0;
	sts_o7_sensorData.event_sensor3_motion_stop_time				= 0;
	sts_o7_sensorData.event_sensor3_motion_duration					= 0;

	sts_o7_sensorData.event_sensor3_fall_start_time					= 0;
	sts_o7_sensorData.event_sensor3_fall_start_time_stamp  			= 0;
	sts_o7_sensorData.event_sensor3_fall_stop_time					= 0;
	sts_o7_sensorData.event_sensor3_fall_stop_time_stamp			= 0;
	sts_o7_sensorData.event_sensor3_fall_duration					= 0;

	sts_o7_sensorData.event_sensor4_start_time						= 0;
	sts_o7_sensorData.event_sensor4_stop_time						= 0;
	sts_o7_sensorData.event_sensor4_duration						= 0;

	sts_o7_sensorData.over_stay_state								= 0;
	sts_o7_sensorData.over_stay_duration							= 0;

	sts_o7_sensorData.no_movement_state								= 0;
	sts_o7_sensorData.no_movement_duration							= 0;

	sts_o7_sensorData.unconscious_state								= 0;
	sts_o7_sensorData.unconscious_duration							= 0;

	//PME_ON;
	//STS_PRESENCE_SENSOR_REEDSWITCH_HALL_Init();
	//STS_PRESENCE_SENSOR_TOF_Init();
	//HAL_Delay(2000);
	//STS_PRESENCE_SENSOR_Distance_Measure_Process();


}

void STS_PRESENCE_SENSOR_TOF_Init(void)
{
	APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) MEMS TOF Initializing \r\n");

}
void STS_PRESENCE_SENSOR_REEDSWITCH_HALL_Init(void)
{

	APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) REED SWITCH HALL ELEMENT Initializing \r\n");

}
void STS_PRESENCE_SENSOR_RSS_Init(void)
{
	APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) MEMS RSS Initializing \r\n");

//	PME_ON;

	//if ((sts_distance_rss_distance==0)&&(sts_sensor_install_height==0))
	{
		uint8_t exit_status =0;
		do {
			exit_status=sts_distance_rss_detector_distance();
			if (exit_status ==0) {
			APP_LOG(TS_ON, VLEVEL_H, "##### RSS Installation Height =%u \r\n", (uint16_t)sts_distance_rss_distance);
			}
			else {
			APP_LOG(TS_ON, VLEVEL_H, "##### RSS Installation Height  Error \r\n");
			HAL_Delay(100);
			}
		} while((0));

		sts_sensor_install_height = (uint16_t)sts_distance_rss_distance;
	}

	STS_PRESENCE_SENSOR_NVM_CFG();

	switch (sts_work_mode)
	{
		case STS_RSS_MODE:
			sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
			break;
		case STS_DUAL_MODE:
			sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
		break;

		case STS_UNI_MODE:
		sts_rss_config_updated_flag = STS_RSS_CONFIG_FALL_DETECTION;
		break;
		default:
		break;
	}

}


void STS_PRESENCE_SENSOR_Distance_Measure_Process(void)
{
	uint8_t exit_status = EXIT_SUCCESS, i=0;

	APP_LOG(TS_OFF, VLEVEL_L, "\r\n ****start_m=%u length_m=%u profile=%u hwaas=%u \r\n",
					(unsigned int)(distance_cfg.start_m*1000),(unsigned int)(distance_cfg.length_m*1000),
					(unsigned int)(distance_cfg.acc_profile),(unsigned int)(distance_cfg.hwaas));
	do
	{
		exit_status = sts_distance_rss_detector_distance();
		HAL_Delay(100);
		i++;
	} while ((exit_status == EXIT_FAILURE) && (i < 2));

}



void STS_PRESENCE_SENSOR_Function_Test_Process(uint8_t *self_test_result, uint8_t count)
{
	uint8_t bring_up_result[20];
	PME_ON;
	HAL_Init();
	MX_GPIO_Init();
	HAL_Delay(150);		//wait for sensor ready

	for (uint8_t i=0;i < count; i++) //while(1)
	{
		STS_Lamp_Bar_Self_Test_Simple();
		sts_lamp_bar_color = STS_PINK;
		STS_Lamp_Bar_Refresh();
		HAL_Delay(1000);
		sts_presence_rss_bring_up_test(bring_up_result);

		HAL_Delay(1000);

		STS_PRESENCE_SENSOR_Distance_Measure_Process();

	}
	HAL_Delay(1000);

	UTIL_MEM_cpy_8(self_test_result, bring_up_result, 10);

}

uint8_t STS_SENSOR_MEMS_Get_ID(uint8_t *devID)
{
	uint8_t scanned_id[2] = {0x0,0x0};

#if	defined(STS_O7)||defined(STS_O6)
	if (hal_test_spi_read_chipid(scanned_id))
	{
		devID[0] = scanned_id[0];
		devID[1] = scanned_id[1];
		APP_LOG(TS_OFF, VLEVEL_H,"\r\n--------------devID = %02x %02x \r\n",devID[0], devID[1]);
		return true;
	}
	else
	{
		return false;
	}
#endif

}

#ifdef	STS_R4
void YUNHORN_STS_R4_SENSOR_Read(STS_R0_SensorDataTypeDef *r4_data)
{
#ifdef	SOAP_LEVEL_SENSOR
	r4_data->on_off_event = (sts_soap_level_state==0x0)? 1:0;
	r4_data->measure_tech = 0x0;	// capacity measure
#endif

	sensor_data_ready = 0x1;
}

void YUNHORN_STS_R4_SENSOR_Init(void)
{
	r4_data.on_off_event = 0x0;
	r4_data.measure_tech = 0x0;
	sensor_data_ready = 0x0;
}
#endif

#if	defined(YUNHORN_STS_R4_ENABLED)
void STS_R0_SENSOR_Read(STS_R0_SensorDataTypeDef *r0_data)
{
#ifdef SOAP_LEVEL_SENSOR
	r0_data->on_off_event = sts_soap_level_state;
	r0_data->measure_tech = 0;  /* 0: capacit, 1:dTof, 2: ultrasonic  */
#elif defined(TOF_1)||defined(TOF_2)||defined(TOF_3)
	r0_data->measure_tech = 1;  /* 0: capacit, 1:dTof, 2: ultrasonic  */
	r0_data->distance_mm  = sts_tof_distance_data[0];
	r0_data->distance1_mm = sts_tof_distance_data[1];
	r0_data->distance2_mm = sts_tof_distance_data[2];
#elif 	defined(ROCTEC_R5)
	r0_data->distance1_mm = sts_tof_distance_data[0]+sts_tof_distance_data[1]+sts_tof_distance_data[2];
#endif

	sensor_data_ready = 1;
}
#endif

void STS_SENSOR_NVM_CFG(void)
{

}

void STS_SENSOR_NVM_CFG_SIMPLE(void)
{

}

#if	defined(YUNHORN_STS_O5_ENABLED)
void STS_O5_SENSOR_Read(STS_OO_SensorDataTypeDef *oo_data)
{

	oo_data->state_sensor1_on_off  = sts_reed_hall_result;


	sensor_data_ready = 1;
}
#endif


/* reedswitch 1 on off */
void OnSensor1StateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	if (sts_hall1_read == STS_Status_Door_Close)
	{
		sts_o7_sensorData.event_sensor1_start_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor1_duration = 0;
		APP_LOG(TS_OFF, VLEVEL_L, "Door Closed ---Timer start: %u\r\n",sts_o7_sensorData.event_sensor1_start_time );
	} else if (sts_hall1_read==STS_Status_Door_Open)
	{
			sts_o7_sensorData.event_sensor1_start_time = 0;
			sts_o7_sensorData.event_sensor1_stop_time = sensor_event_time.Seconds;
			//sts_o7_sensorData.event_sensor1_duration = 0;
			sts_o7_sensorData.over_stay_state = 0;
	}

}

/* SOS emergency button on off */
void OnSensor2StateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	uint32_t time_stamp=STS_Get_Date_Time_Stamp();

	if (sts_hall2_read==STS_Status_SOS_Pushdown)
	{
		sts_o7_sensorData.event_sensor2_start_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor2_start_timestamp = time_stamp;
		sts_o7_sensorData.event_sensor2_stop_time 		= 0;
		sts_o7_sensorData.event_sensor2_duration 		= 0;
		APP_LOG(TS_OFF, VLEVEL_L, "SOS PushDown ---Timer start: %u\r\n",sts_o7_sensorData.event_sensor2_start_time );
	}else if (sts_hall2_read==STS_Status_SOS_Release)
	{
		sts_o7_sensorData.event_sensor2_start_time 		= 0;
		sts_o7_sensorData.event_sensor2_start_timestamp = 0;
		sts_o7_sensorData.event_sensor2_stop_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor2_stop_timestamp 	= time_stamp;
		//sts_o7_sensorData.over_stay_state = 0;
			//sts_o7_sensorData.event_sensor2_duration = 0;
	}
}

/* motion sensor RSS ON-OFF */
void OnSensorRSS3StateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
#if 0
	if ((sensor_event_time.Seconds - last_sts_rss_time_stamp) < 3 )	//less than 3 seconds ... return for flipping filter
		{
			return ;
		}
#endif
	if (sts_rss_result == STS_RESULT_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_start_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor3_motion_duration = 0;
	} else 	if (sts_rss_result == STS_RESULT_NO_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_stop_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor3_start_timestamp = 0;
		//sts_o7_sensorData.event_sensor3_motion_duration = 0;

	}


	last_sts_rss_time_stamp = sensor_event_time.Seconds;

}

/* motion sensor A: Motion/No-Motion Detection, Unconscious Detection */
void OnSensorRSS3AStateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
#if 0
	if ((sensor_event_time.Seconds - last_sts_rss_time_stamp) < 3 )	//less than 3 seconds ... return for flipping filter
		{
			return ;
		}
#endif
	if (sts_rss_result == STS_RESULT_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_start_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor3_motion_duration = 0;
	} else 	if (sts_rss_result == STS_RESULT_NO_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_stop_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor3_start_timestamp = 0;
		//sts_o7_sensorData.event_sensor3_motion_duration = 0;
	}


	last_sts_rss_time_stamp = sensor_event_time.Seconds;

}

/* motion sensor B, Fall Detection suggestionF */
void OnSensorRSS3BStateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	uint32_t time_stamp=STS_Get_Date_Time_Stamp();

#if 0
	if ((sensor_event_time.Seconds - last_sts_rss_time_stamp) < 3 )	//less than 3 seconds ... return for flipping filter
		{
			return ;
		}
#endif
	switch (sts_fall_rising_detected_result)
	{
		case	STS_PRESENCE_NORMAL:
				sts_o7_sensorData.event_sensor3_motion_stop_time = sensor_event_time.Seconds;
		break;

		case	STS_PRESENCE_FALL:
				//if (motion_in_hs_zone[0][motion_detected_count])
				{
					sts_o7_sensorData.event_sensor3_fall_start_time_stamp = time_stamp;
					sts_o7_sensorData.event_sensor3_fall_start_time = sensor_event_time.Seconds;

					//start counter of fall after rising up or other release actions/states
					sts_o7_sensorData.event_sensor3_fall_duration = 0;
					sts_o7_sensorData.event_sensor3_fall_stop_time_stamp = 0;
					sts_o7_sensorData.event_sensor3_fall_stop_time = 0;
				}
		break;

		case	STS_PRESENCE_RISING:
					sts_o7_sensorData.event_sensor3_fall_stop_time_stamp = time_stamp;
					sts_o7_sensorData.event_sensor3_fall_stop_time = sensor_event_time.Seconds;
		break;

		case	STS_PRESENCE_LAYDOWN:
		break;

		case	STS_PRESENCE_STAYSTILL:
		case 	STS_PRESENCE_NO_MOVEMENT:
		case	STS_PRESENCE_UNCONSCIOUS:
				sts_o7_sensorData.event_sensor3_no_movement_start_time = sensor_event_time.Seconds;
				sts_o7_sensorData.event_sensor3_unconcious_start_time = sensor_event_time.Seconds;
				//sts_o7_sensorData.event_sensor3_unconcious_duration = 0;
				//sts_o7_sensorData.event_sensor3_no_movement_duration = 0;
				//sts_o7_sensorData.fall_laydown_duration = 0;
		break;

		default:
		break;

	}

	last_sts_rss_time_stamp = sensor_event_time.Seconds;


}

/* motion sensor C: Over stay detection */
void OnSensorRSS3CStateChanged(void)
{
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
#if 0
	if ((sensor_event_time.Seconds - last_sts_rss_time_stamp) < 3 )	//less than 3 seconds ... return for flipping filter
		{
			return ;
		}
#endif
	if (sts_rss_result == STS_RESULT_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_start_time = sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor3_motion_duration = 0;
	} else 	if (sts_rss_result == STS_RESULT_NO_MOTION)
	{
		sts_o7_sensorData.event_sensor3_motion_stop_time = sensor_event_time.Seconds;
		//sts_o7_sensorData.event_sensor3_motion_duration = 0;
	}


	last_sts_rss_time_stamp = sensor_event_time.Seconds;

}


void OnSensor3StateChanged(void)
{
#if 0
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	// reserved... to be finalized	2024-06-03

	if (sts_xxx_result)
		sts_o7_sensorData.event_sensor4_start_time = sensor_event_time.Seconds;
	else
		sts_o7_sensorData.event_sensor4_stop_time = sensor_event_time.Seconds;
#endif
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	uint32_t time_stamp=STS_Get_Date_Time_Stamp();

	if (sts_hall3_read==STS_Status_Alarm_Mute_Pushdown)
	{
		sts_o7_sensorData.event_sensor4_start_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor4_start_timestamp = time_stamp;
		sts_o7_sensorData.event_sensor4_stop_time 		= 0;
		sts_o7_sensorData.event_sensor4_duration 		= 0;
		APP_LOG(TS_OFF, VLEVEL_L, "Alarm Mute PushDown ---Timer start: %u\r\n",sts_o7_sensorData.event_sensor4_start_time );
	}else if (sts_hall3_read==STS_Status_Alarm_Mute_Release)
	{
		sts_o7_sensorData.event_sensor4_start_time 		= 0;
		sts_o7_sensorData.event_sensor4_start_timestamp = 0;
		sts_o7_sensorData.event_sensor4_stop_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor4_stop_timestamp 	= time_stamp;
		//sts_o7_sensorData.over_stay_state = 0;
			//sts_o7_sensorData.event_sensor2_duration = 0;
	}
}

void OnSensor4StateChanged(void)
{
#if 0
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	// reserved... to be finalized	2024-06-03

	if (sts_xxx_result)
		sts_o7_sensorData.event_sensor4_start_time = sensor_event_time.Seconds;
	else
		sts_o7_sensorData.event_sensor4_stop_time = sensor_event_time.Seconds;
#endif
	SysTime_t sensor_event_time = SysTimeGetMcuTime();
	uint32_t time_stamp=STS_Get_Date_Time_Stamp();

	if (sts_hall4_read==STS_Status_Alarm_Mute_Pushdown)
	{
		sts_o7_sensorData.event_sensor5_start_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor5_start_timestamp = time_stamp;
		sts_o7_sensorData.event_sensor5_stop_time 		= 0;
		sts_o7_sensorData.event_sensor5_duration 		= 0;
		APP_LOG(TS_OFF, VLEVEL_L, "Alarm RESET PushDown ---Timer start: %u\r\n",sts_o7_sensorData.event_sensor5_start_time );
	}else if (sts_hall4_read==STS_Status_Alarm_Mute_Release)
	{
		sts_o7_sensorData.event_sensor5_start_time 		= 0;
		sts_o7_sensorData.event_sensor5_start_timestamp = 0;
		sts_o7_sensorData.event_sensor5_stop_time 		= sensor_event_time.Seconds;
		sts_o7_sensorData.event_sensor5_stop_timestamp 	= time_stamp;
		//sts_o7_sensorData.over_stay_state = 0;
			//sts_o7_sensorData.event_sensor2_duration = 0;
	}
}


//卡尔曼滤波
float KalmanFilter(float inData)
{
		static float prevData = 0;                                 //先前数值
		static float p = 10, q = 0.001, r = 0.001, kGain = 0;      // q控制误差  r控制响应速度

		p = p + q;
		kGain = p / ( p + r );                                     //计算卡尔曼增益
		inData = prevData + ( kGain * ( inData - prevData ) );     //计算本次滤波估计值
		p = ( 1 - kGain ) * p;                                     //更新测量方差
		prevData = inData;
		return inData;                                             //返回滤波值


}

/* USER CODE BEGIN EF */

/* USER CODE END EF */

/* Private Functions Definition -----------------------------------------------*/
/* USER CODE BEGIN PrFD */

/* USER CODE END PrFD */