O7/LoRaWAN/App/lora_app.c

3044 lines
108 KiB
C

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file lora_app.c
* @author Yunhorn (r) Technology Limited Application Team
* @brief Application of the LRWAN Middleware
******************************************************************************
* @attention
*
* Copyright (c) 2023 Yunhorn Technology Limited.
* Copyright (c) 2023 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 "platform.h"
#include "sys_app.h"
#include "lora_app.h"
#include "stm32_seq.h"
#include "stm32_timer.h"
#include "utilities_def.h"
#include "app_version.h"
#include "lorawan_version.h"
#include "subghz_phy_version.h"
#include "lora_info.h"
#include "LmHandler.h"
#include "adc_if.h"
#include "CayenneLpp.h"
#include "sys_sensors.h"
#include "flash_if.h"
#include "main.h"
#ifdef CLOCK_SYNC
#include "LmhpClockSync.h"
#endif
/* USER CODE BEGIN Includes */
#include "tim.h"
#include "sts_lamp_bar.h"
#include "yunhorn_sts_sensors.h"
#include "sts_cmox_hmac_sha.h"
/* USER CODE END Includes */
/* External variables ---------------------------------------------------------*/
/* USER CODE BEGIN EV */
extern volatile uint8_t sts_service_mask;
extern volatile uint32_t rfac_timer;
volatile uint8_t sts_ac_code[YUNHORN_STS_AC_CODE_SIZE]={0x0};
extern hmac_result_t hmac_result;
extern volatile uint8_t sts_hall1_read, sts_hall2_read, sts_hall3_read, sts_hall4_read;
volatile uint8_t last_sts_hall1_read=STS_Status_Door_Open, last_sts_hall2_read=STS_Status_SOS_Release, last_sts_hall3_read=STS_Status_Door_Open, last_sts_hall4_read=STS_Status_Door_Open ;
volatile uint8_t sts_reed_hall_result =0, sts_emergency_button_pushed=0; // inital 0 = close
extern volatile uint8_t sts_work_mode, sts_cloud_netcolor, sts_lamp_bar_color, sts_status_color;
extern volatile uint8_t sts_lamp_bar_flashing_color;
volatile uint8_t last_sts_lamp_bar_color=STS_DARK;
extern volatile uint8_t sts_rss_result;
extern volatile uint8_t sts_rss_result_changed_flag, sts_hall1_changed_flag, sts_hall2_changed_flag, sts_reed_hall_changed_flag;
volatile uint8_t sts_fall_detection_acc_threshold = 30, //0.3g
sts_fall_detection_depth_threshold=20,
sts_fall_confirm_threshold_in_10sec=1,
sts_occupancy_overtime_threshold_in_10min=2;
volatile uint8_t sts_unconscious_or_motionless_level_threshold=6; //6*128
volatile uint8_t sts_motionless_duration_threshold_in_min=1; // test mode, 1 min, normal 10 min. long occupation 30 min
volatile uint16_t sts_unconscious_level_threshold=600;
volatile uint8_t sts_alarm_mute_reset_timer_in_10sec=6;
extern volatile uint8_t sts_fall_rising_detected_result;
extern volatile uint32_t event_start_time, event_stop_time;
extern volatile uint16_t sts_unconscious_threshold;
volatile uint8_t sts_occupancy_overtime_state = 0;
volatile uint8_t sts_presence_fall_detection=TRUE;
volatile uint32_t SamplingPeriodicity = 3000; //unit ms
volatile uint32_t HeartBeatPeriodicity = 120000; //unit ms
volatile uint8_t STS_LoRa_WAN_Joined = 0;
volatile uint8_t upload_message_timer=0;
volatile uint8_t heart_beat_timer =0;
volatile uint32_t wcnt=0;
volatile bool p2_work_finished=true;
extern volatile uint8_t luminance_level;
uint8_t outbuf[255]={0x0};
volatile static bool r_b=true;
volatile sts_cfg_nvm_t sts_cfg_nvm = {
sts_mtmcode1,
sts_mtmcode2,
sts_version,
sts_hardware_ver,
0x05,
'M', //Uplink data interval for heart-beat uplink
0x03,
'S', //Sampling sensor interval for real-time sensing of MEMS
0x04, // dual mode=4, uni_mode =5
0x00, // sts service mask
0x00, //sts_ioc_mask
0x20, //32 bytes, below start of p[0] 20 BYTES AND 12 BYTES FALL DOWN CFG
{ // below 20 bytes
0x08, //start_m [8]*0.1 meter =0.8
0x19, //lenght_m 0x19=[25]*0.1=2.5f meter
0x0F, //threshold 0X0F=[15]*0.1=1.5f
0x28, //receiver gain 0x28 =[40]*0.01=0.40f max 99=0x63
0x04, //profile [4]=4
0x0A, //rate tracking 0x0A=10= 10U
0x41, //rate presence 0x41=65= 65U
0x3F, //hwaas 0x3F=63 =63U
0x00, //nbr removed pc [0]=0
0x05, //inter frame deviation time const 0x05=[5]*0.1=0.5f
0x0A, //inter frame fast cutoff 0x0A=[10] = 10U
0x01, //inter frame slow cutoff,0x01=1[1]*0.01=0.01f
0x00, //intra frame time const [0]=0
0x00, //intra frame weight, 0x00=[0]*0.1=0.0F
0x05, //output time const 0x05=[5]*0.1=0.5
0x02, //downsampling factor [2]=2
0x03, //power saving mode ACTIVE [3] = 3U
0x00, //reserve --P[17]
0x00, //reserve --P[18]
0x00, //reserve --P[19]
}, // above 20 bytes
0x00, //reserve2
0x00, //reserve3
0x20, //sensor install height in 10 cm, default 32*10=320cm, 3.2meter
0x00, //reserve5 alarm_parameter05
0x06, //reserve6 alarm_mute_or_reset_expire_timer_in_10sec, 60 seconds
0x23, //reserve7 alarm Lamp Bar Flashing color define, 0x20, 2==STS_RED, 0 = STS_DARK, 0x23, 2=STS_RED, 3=STS_BLUE
0x03, //reserve8 occupancy over time threshold 3*10 = 30 minutes
0x09, //reserve8 motionless_duration_threshold_in_min+1, normal: 10 min(0x0A) Minutes (2 min.) 1-9== 2-10min
0x09, //unconscious threshold * 128, 0-9, 9*128=1280 motion level
0x01, //fall_detection_acc_threshold = *10 acceleration measure
0x03, //fall detection_depth_threshold *10cm
0x03, //falldown_confirm_threshold_in_10sec, 0x3=30 sec default
// below 20 bytes for RFAC code
{0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0}
};
#if defined(STS_O6)||defined(STS_O7)
extern volatile uint8_t sensor_data_ready;
extern volatile STS_OO_SensorStatusDataTypeDef sts_o7_sensorData;
extern volatile uint16_t sts_distance_rss_distance, sts_sensor_install_height;
extern volatile uint8_t sts_rss_config_updated_flag;
//#define STS_Status_Door_Close (1) //Normal Close NC:Open **2024-07-15 changed
//#define STS_Status_Door_Open (0) //Normal Close NC:Close **2024-07-15 changed
char sts_door_status_code[2][10]={
"Close",
"Open "
};
char sts_sos_status_code[2][10]={
"PushDown",
"No_Push"
};
char sts_lamp_color_code[15][15]={
"Dark",
"Green",
"Red",
"Blue",
"Yellow",
"Pink",
"Cyan",
"White",
"color_max", //8
"Green_Flash", //0x10 ==16
"Red_Flash", // 0x20 ==32
"Blue_Flash", // 0x30 == 48
"Red_Blue_Flash" //0x23 = 35
};
char sts_work_mode_code[15][25] ={
"NETWORK_MODE",
"WIRED_MODE",
"REEDSWITCH_MODE",
"RSS_MODE",
"DUAL_MODE",
"UNI_MODE",
"REMOTE_REED_RSS_MODE",
"DUAL_RSS_MODE",
"TOF_RSS_MODE",
"TOF_DISTANCE_MODE",
"TOF_PRESENCE_MODE",
"TOF_IN_OUT_MODE",
"FALL_DETECTION_MODE",
"OTHER_MODE1",
"OTHER_MODE2",
};
char sts_fall_mode_code[8][25] = {
"State_Normal",
"State_Fall_Down",
"State_Rising_Up",
"State_Laydown",
"State_Unconscious",
"State_StayStill",
"State_No_Movement"
};
#endif
/* USER CODE END EV */
/* Private typedef -----------------------------------------------------------*/
/**
* @brief LoRa State Machine states
*/
typedef enum TxEventType_e
{
/**
* @brief Appdata Transmission issue based on timer every TxDutyCycleTime
*/
TX_ON_TIMER,
/**
* @brief Appdata Transmission external event plugged on OnSendEvent( )
*/
TX_ON_EVENT
/* USER CODE BEGIN TxEventType_t */
/* USER CODE END TxEventType_t */
} TxEventType_t;
/* USER CODE BEGIN PTD */
#define YUNHORN_STS_RSS_WAKEUP_CHECK_TIME SamplingPeriodicity //3000 ms
#define YUNHORN_STS_SAMPLING_CHECK_TIME SamplingPeriodicity
#define YUNHORN_STS_HEART_BEAT_CHECK_TIME 300000 //300 sec, 5 min
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/**
* LEDs period value of the timer in ms
*/
#define LED_PERIOD_TIME 500
/**
* Join switch period value of the timer in ms
*/
#define JOIN_TIME 2000
/*---------------------------------------------------------------------------*/
/* LoRaWAN NVM configuration */
/*---------------------------------------------------------------------------*/
/**
* @brief LoRaWAN NVM Flash address
* @note last 2 sector of a 128kBytes device
*/
#define LORAWAN_NVM_BASE_ADDRESS ((void *)0x0803F000UL)
/* USER CODE BEGIN PD */
static const char *slotStrings[] = { "1", "2", "C", "C_MC", "P", "P_MC" };
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private function prototypes -----------------------------------------------*/
/**
* @brief LoRa End Node send request
*/
static void SendTxData(void);
/**
* @brief TX timer callback function
* @param context ptr of timer context
*/
static void OnTxTimerEvent(void *context);
/**
* @brief join event callback function
* @param joinParams status of join
*/
static void OnJoinRequest(LmHandlerJoinParams_t *joinParams);
/**
* @brief callback when LoRaWAN application has sent a frame
* @brief tx event callback function
* @param params status of last Tx
*/
static void OnTxData(LmHandlerTxParams_t *params);
/**
* @brief callback when LoRaWAN application has received a frame
* @param appData data received in the last Rx
* @param params status of last Rx
*/
static void OnRxData(LmHandlerAppData_t *appData, LmHandlerRxParams_t *params);
/**
* @brief callback when LoRaWAN Beacon status is updated
* @param params status of Last Beacon
*/
static void OnBeaconStatusChange(LmHandlerBeaconParams_t *params);
/**
* @brief callback when system time has been updated
*/
static void OnSysTimeUpdate(void);
/**
* @brief callback when LoRaWAN application Class is changed
* @param deviceClass new class
*/
static void OnClassChange(DeviceClass_t deviceClass);
/**
* @brief LoRa store context in Non Volatile Memory
*/
static void StoreContext(void);
/**
* @brief stop current LoRa execution to switch into non default Activation mode
*/
static void StopJoin(void);
/**
* @brief Join switch timer callback function
* @param context ptr of Join switch context
*/
static void OnStopJoinTimerEvent(void *context);
/**
* @brief Notifies the upper layer that the NVM context has changed
* @param state Indicates if we are storing (true) or restoring (false) the NVM context
*/
static void OnNvmDataChange(LmHandlerNvmContextStates_t state);
/**
* @brief Store the NVM Data context to the Flash
* @param nvm ptr on nvm structure
* @param nvm_size number of data bytes which were stored
*/
static void OnStoreContextRequest(void *nvm, uint32_t nvm_size);
/**
* @brief Restore the NVM Data context from the Flash
* @param nvm ptr on nvm structure
* @param nvm_size number of data bytes which were restored
*/
static void OnRestoreContextRequest(void *nvm, uint32_t nvm_size);
/**
* Will be called each time a Radio IRQ is handled by the MAC layer
*
*/
static void OnMacProcessNotify(void);
/**
* @brief Change the periodicity of the uplink frames
* @param periodicity uplink frames period in ms
* @note Compliance test protocol callbacks
*/
static void OnTxPeriodicityChanged(uint32_t periodicity);
/**
* @brief Change the confirmation control of the uplink frames
* @param isTxConfirmed Indicates if the uplink requires an acknowledgement
* @note Compliance test protocol callbacks
*/
static void OnTxFrameCtrlChanged(LmHandlerMsgTypes_t isTxConfirmed);
/**
* @brief Change the periodicity of the ping slot frames
* @param pingSlotPeriodicity ping slot frames period in ms
* @note Compliance test protocol callbacks
*/
static void OnPingSlotPeriodicityChanged(uint8_t pingSlotPeriodicity);
/**
* @brief Will be called to reset the system
* @note Compliance test protocol callbacks
*/
static void OnSystemReset(void);
/* USER CODE BEGIN PFP */
/**
* @brief LED Tx timer callback function
* @param context ptr of LED context
*/
static void OnTxTimerLedEvent(void *context);
/**
* @brief LED Rx timer callback function
* @param context ptr of LED context
*/
static void OnRxTimerLedEvent(void *context);
/**
* @brief LED Join timer callback function
* @param context ptr of LED context
*/
static void OnJoinTimerLedEvent(void *context);
/**
* @brief STS Lamp Bar timer callback function
* @param context ptr of Lamp Bar LED context
*/
static void OnYunhornSTSLampBarColorTimerEvent(void *context);
/**
* @brief SYS occupancy, door lock, motion duration check timer callback function
* @param context ptr of duration check context
*/
static void OnYunhornSTSDurationCheckTimerEvent(void *context);
/**
* @brief Yunhorn STS Occupancy RSS WakeUP timer callback function
* @param context ptr of STS RSS WakeUp context
*/
static void OnYunhornSTSOORSSWakeUpTimerEvent(void *context);
/**
* @brief Yunhorn STS Heart beat timer callback function
* @param context ptr of context
*/
static void OnYunhornSTSHeartBeatTimerEvent(void *context);
/**
* @brief Yunhorn STS Heart Beat Periodicity Chagne function
* @param duration of periodicty in ms (1/1000 sec)
*/
static void OnYunhornSTSHeartBeatPeriodicityChanged(uint32_t periodicity);
/**
* @brief Yunhorn STS AC Code handle Process
* @param void
*/
static void STS_YUNHORN_RFAC_HANDLE_PROCESS(void);
/* USER CODE END PFP */
/* Private variables ---------------------------------------------------------*/
/**
* @brief LoRaWAN default activation type
*/
static ActivationType_t ActivationType = LORAWAN_DEFAULT_ACTIVATION_TYPE;
/**
* @brief LoRaWAN force rejoin even if the NVM context is restored
*/
static bool ForceRejoin = LORAWAN_FORCE_REJOIN_AT_BOOT;
/**
* @brief LoRaWAN handler Callbacks
*/
static LmHandlerCallbacks_t LmHandlerCallbacks =
{
.GetBatteryLevel = GetBatteryLevel,
.GetTemperature = GetTemperatureLevel,
.GetUniqueId = GetUniqueId,
.GetDevAddr = GetDevAddr,
.OnRestoreContextRequest = OnRestoreContextRequest,
.OnStoreContextRequest = OnStoreContextRequest,
.OnMacProcess = OnMacProcessNotify,
.OnNvmDataChange = OnNvmDataChange,
.OnJoinRequest = OnJoinRequest,
.OnTxData = OnTxData,
.OnRxData = OnRxData,
.OnBeaconStatusChange = OnBeaconStatusChange,
.OnSysTimeUpdate = OnSysTimeUpdate,
.OnClassChange = OnClassChange,
.OnTxPeriodicityChanged = OnTxPeriodicityChanged,
.OnTxFrameCtrlChanged = OnTxFrameCtrlChanged,
.OnPingSlotPeriodicityChanged = OnPingSlotPeriodicityChanged,
.OnSystemReset = OnSystemReset,
};
/**
* @brief LoRaWAN handler parameters
*/
static LmHandlerParams_t LmHandlerParams =
{
.ActiveRegion = ACTIVE_REGION,
.DefaultClass = LORAWAN_DEFAULT_CLASS,
.AdrEnable = LORAWAN_ADR_STATE,
.IsTxConfirmed = LORAWAN_DEFAULT_CONFIRMED_MSG_STATE,
.TxDatarate = LORAWAN_DEFAULT_DATA_RATE,
.TxPower = LORAWAN_DEFAULT_TX_POWER,
.PingSlotPeriodicity = LORAWAN_DEFAULT_PING_SLOT_PERIODICITY,
.RxBCTimeout = LORAWAN_DEFAULT_CLASS_B_C_RESP_TIMEOUT
};
/**
* @brief Type of Event to generate application Tx
*/
static TxEventType_t EventType = TX_ON_TIMER; //TX_ON_TIMER;//TX_ON_EVENT;
/**
* @brief Timer to handle the application Tx
*/
static UTIL_TIMER_Object_t TxTimer;
/**
* @brief Tx Timer period
*/
static UTIL_TIMER_Time_t TxPeriodicity = APP_TX_DUTYCYCLE;
/**
* @brief Join Timer period
*/
static UTIL_TIMER_Object_t StopJoinTimer;
/* USER CODE BEGIN PV */
/**
* @brief User application buffer
*/
static uint8_t AppDataBuffer[LORAWAN_APP_DATA_BUFFER_MAX_SIZE];
/**
* @brief User application data structure
*/
static LmHandlerAppData_t AppData = { 0, 0, AppDataBuffer };
/**
* @brief Specifies the state of the application LED
*/
static uint8_t AppLedStateOn = RESET;
/**
* @brief Timer to handle the application Tx Led to toggle
*/
static UTIL_TIMER_Object_t TxLedTimer;
/**
* @brief Timer to handle the application Rx Led to toggle
*/
static UTIL_TIMER_Object_t RxLedTimer;
/**
* @brief Timer to handle the application Join Led to toggle
*/
static UTIL_TIMER_Object_t JoinLedTimer;
static volatile bool IsClockSynched = false;
/**
* @brief Timer to handle the Yunhorn STS Lamp Bar Color Led to toggle
*/
static UTIL_TIMER_Object_t STSLampBarColorTimer;
/**
* @brief Timer to handle the Yunhorn STS Lamp Bar Color Led to toggle
*/
static UTIL_TIMER_Object_t STSDurationCheckTimer;
/**
* @brief Timer to handle the YunHorn STS RSS WakeUP Checking
*/
static UTIL_TIMER_Object_t YunhornSTSRSSWakeUpTimer;
/**
* @brief Timer to handle the YunHorn STS Sensor Sampling Process
*/
//static UTIL_TIMER_Object_t YunhornSTSSamplingCheckTimer;
/**
* @brief Timer to handle the YunHorn STS Sensor Heart Beat Process
*/
static UTIL_TIMER_Object_t YunhornSTSHeartBeatTimer;
/* USER CODE END PV */
/* Exported functions ---------------------------------------------------------*/
/* USER CODE BEGIN EF */
/* USER CODE END EF */
void LoRaWAN_Init(void)
{
/* USER CODE BEGIN LoRaWAN_Init_LV */
uint32_t feature_version = 0UL;
/* USER CODE END LoRaWAN_Init_LV */
/* USER CODE BEGIN LoRaWAN_Init_1 */
APP_LOG(TS_OFF, VLEVEL_M, "\r\n\n\n##### YUNHORN_STS_SWV%d HWV:%d MTM:%d.%d R:%d.%d.%d####\r\n\n\n",
sts_version, sts_hardware_ver, sts_mtmcode1,sts_mtmcode2, MajorVer, MinorVer, SubMinorVer);
/* Get LoRaWAN APP version*/
APP_LOG(TS_OFF, VLEVEL_M, "APPLICATION_VERSION: V%X.%X.%X\r\n",
(uint8_t)(APP_VERSION_MAIN),
(uint8_t)(APP_VERSION_SUB1),
(uint8_t)(APP_VERSION_SUB2));
/* Get MW LoRaWAN info */
APP_LOG(TS_OFF, VLEVEL_M, "MW_LORAWAN_VERSION: V%X.%X.%X\r\n",
(uint8_t)(LORAWAN_VERSION_MAIN),
(uint8_t)(LORAWAN_VERSION_SUB1),
(uint8_t)(LORAWAN_VERSION_SUB2));
/* Get MW SubGhz_Phy info */
APP_LOG(TS_OFF, VLEVEL_M, "MW_RADIO_VERSION: V%X.%X.%X\r\n",
(uint8_t)(SUBGHZ_PHY_VERSION_MAIN),
(uint8_t)(SUBGHZ_PHY_VERSION_SUB1),
(uint8_t)(SUBGHZ_PHY_VERSION_SUB2));
/* Get LoRaWAN Link Layer info */
LmHandlerGetVersion(LORAMAC_HANDLER_L2_VERSION, &feature_version);
APP_LOG(TS_OFF, VLEVEL_M, "L2_SPEC_VERSION: V%X.%X.%X\r\n",
(uint8_t)(feature_version >> 24),
(uint8_t)(feature_version >> 16),
(uint8_t)(feature_version >> 8));
/* Get LoRaWAN Regional Parameters info */
LmHandlerGetVersion(LORAMAC_HANDLER_REGION_VERSION, &feature_version);
APP_LOG(TS_OFF, VLEVEL_M, "RP_SPEC_VERSION: V%X-%X.%X.%X\r\n",
(uint8_t)(feature_version >> 24),
(uint8_t)(feature_version >> 16),
(uint8_t)(feature_version >> 8),
(uint8_t)(feature_version));
UTIL_TIMER_Create(&TxLedTimer, LED_PERIOD_TIME, UTIL_TIMER_ONESHOT, OnTxTimerLedEvent, NULL);
UTIL_TIMER_Create(&RxLedTimer, LED_PERIOD_TIME, UTIL_TIMER_ONESHOT, OnRxTimerLedEvent, NULL);
UTIL_TIMER_Create(&JoinLedTimer, LED_PERIOD_TIME, UTIL_TIMER_PERIODIC, OnJoinTimerLedEvent, NULL);
UTIL_TIMER_Create(&STSLampBarColorTimer, LED_PERIOD_TIME, UTIL_TIMER_ONESHOT, OnYunhornSTSLampBarColorTimerEvent, NULL);
UTIL_TIMER_Create(&STSDurationCheckTimer, 20*LED_PERIOD_TIME, UTIL_TIMER_PERIODIC, OnYunhornSTSDurationCheckTimerEvent, NULL);
if (FLASH_IF_Init(NULL) != FLASH_IF_OK)
{
Error_Handler();
}
/* USER CODE END LoRaWAN_Init_1 */
UTIL_TIMER_Create(&StopJoinTimer, JOIN_TIME, UTIL_TIMER_ONESHOT, OnStopJoinTimerEvent, NULL);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_LmHandlerProcess), UTIL_SEQ_RFU, LmHandlerProcess);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), UTIL_SEQ_RFU, SendTxData);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_LoRaStoreContextEvent), UTIL_SEQ_RFU, StoreContext);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_LoRaStopJoinEvent), UTIL_SEQ_RFU, StopJoin);
// TODO XXX 2024-06-04
#ifdef CLOCK_SYNC
LmHandlerPackageRegister( PACKAGE_ID_CLOCK_SYNC, NULL );
IsClockSynched = false;
#endif
/* Init Info table used by LmHandler*/
LoraInfo_Init();
/* Init the Lora Stack*/
LmHandlerInit(&LmHandlerCallbacks, APP_VERSION);
LmHandlerConfigure(&LmHandlerParams);
/* USER CODE BEGIN LoRaWAN_Init_2 */
UTIL_TIMER_Start(&JoinLedTimer);
/* USER CODE END LoRaWAN_Init_2 */
LmHandlerJoin(ActivationType, ForceRejoin);
if (EventType == TX_ON_TIMER)
{
/* send every time timer elapses */
UTIL_TIMER_Create(&TxTimer, TxPeriodicity, UTIL_TIMER_ONESHOT, OnTxTimerEvent, NULL);
UTIL_TIMER_Start(&TxTimer);
}
else
{
/* USER CODE BEGIN LoRaWAN_Init_3 */
/* USER CODE END LoRaWAN_Init_3 */
}
/* USER CODE BEGIN LoRaWAN_Init_Last */
/// **************************************************************************** TO-DO LIST
STS_REBOOT_CONFIG_Init();
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventRFAC), UTIL_SEQ_RFU, STS_YunhornSTSEventRFAC_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), UTIL_SEQ_RFU, STS_YunhornSTSEventP1_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), UTIL_SEQ_RFU, STS_YunhornSTSEventP2_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP3), UTIL_SEQ_RFU, STS_YunhornSTSEventP3_Process);
#if 0
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP4), UTIL_SEQ_RFU, STS_YunhornSTSEventP4_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP5), UTIL_SEQ_RFU, STS_YunhornSTSEventP5_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP6), UTIL_SEQ_RFU, STS_YunhornSTSEventP6_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP7), UTIL_SEQ_RFU, STS_YunhornSTSEventP7_Process);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP8), UTIL_SEQ_RFU, STS_YunhornSTSEventP8_Process);
#endif
#if defined(STS_O7)||defined(STS_O6)
//UTIL_TIMER_Create(&YunhornSTSRSSWakeUpTimer, YUNHORN_STS_RSS_WAKEUP_CHECK_TIME, UTIL_TIMER_ONESHOT, OnYunhornSTSOORSSWakeUpTimerEvent, NULL);
//UTIL_TIMER_Start(&YunhornSTSRSSWakeUpTimer);
UTIL_TIMER_Create(&YunhornSTSHeartBeatTimer, YUNHORN_STS_HEART_BEAT_CHECK_TIME, UTIL_TIMER_PERIODIC, OnYunhornSTSHeartBeatTimerEvent, NULL);
//UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer);
UTIL_TIMER_Start(&STSLampBarColorTimer);
UTIL_TIMER_Start(&STSDurationCheckTimer);
#else
UTIL_TIMER_Create(&YunhornSTSSamplingCheckTimer, YUNHORN_STS_SAMPLING_CHECK_TIME, UTIL_TIMER_PERIODIC, OnYunhornSTSSamplingCheckTimerEvent, NULL);
UTIL_TIMER_Start(&YunhornSTSSamplingCheckTimer);
#endif
/* USER CODE END LoRaWAN_Init_Last */
}
/* USER CODE BEGIN PB_Callbacks */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch (GPIO_Pin)
{
#if defined(STS_O6)||defined(STS_O7)
case HALL1_Pin:
sts_hall1_read = HALL1_STATE;
HAL_Delay(30); //de-bouncing
if ((sts_hall1_read == HALL1_STATE)) // && (sts_hall1_read == STS_Status_Door_Close)) 2024-07-22 only process door close event
{
APP_LOG(TS_OFF, VLEVEL_L, "\n\n Door Contact Read = %02x --%s\r\n", sts_hall1_read, sts_door_status_code[sts_hall1_read]);
OnSensor1StateChanged();
/* Note: when "EventType == TX_ON_TIMER" this GPIO is not initialized */
// if (EventType == TX_ON_EVENT)
{
STS_YunhornSTSEventP1_Process();
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
//SendTxData();
}
last_sts_hall1_read = sts_hall1_read;
}
break;
case HALL2_Pin:
sts_hall2_read = HALL2_STATE;
HAL_Delay(30); //de-bouncing
if (sts_hall2_read == HALL2_STATE)
{
APP_LOG(TS_OFF, VLEVEL_L, "\n\n SOS Button Read = %02x --%s\r\n", sts_hall2_read, sts_sos_status_code[sts_hall2_read]);
OnSensor2StateChanged();
//sensor_data_ready =1;
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), CFG_SEQ_Prio_0);
{
STS_YunhornSTSEventP1_Process();
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
}
last_sts_hall2_read = sts_hall2_read;
}
break;
case HALL3_Pin:
sts_hall3_read = HALL3_STATE;
HAL_Delay(30); //de-bouncing
if (sts_hall3_read == HALL3_STATE)
{
APP_LOG(TS_OFF, VLEVEL_L, "\n\n ALARM MUTE Button Read = %02x --%s\r\n", sts_hall3_read, sts_sos_status_code[sts_hall3_read]);
OnSensor3StateChanged();
//sensor_data_ready =1;
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), CFG_SEQ_Prio_0);
{
STS_YunhornSTSEventP1_Process();
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
}
last_sts_hall3_read = sts_hall3_read;
}
break;
case HALL4_Pin:
sts_hall4_read = HALL4_STATE;
HAL_Delay(30); //de-bouncing
if (sts_hall4_read == HALL4_STATE)
{
APP_LOG(TS_OFF, VLEVEL_L, "\n\n ALARM RESET Button Read = %02x --%s\r\n", sts_hall4_read, sts_sos_status_code[sts_hall4_read]);
OnSensor4StateChanged();
//sensor_data_ready =1;
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), CFG_SEQ_Prio_0);
{
STS_YunhornSTSEventP1_Process();
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
}
last_sts_hall4_read = sts_hall4_read;
}
break;
#else
case BUT1_Pin:
HAL_Delay(20); //de-bouncing
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), CFG_SEQ_Prio_0);
/* Note: when "EventType == TX_ON_TIMER" this GPIO is not initialized */
// if (EventType == TX_ON_EVENT)
{
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
}
break;
case BUT2_Pin:
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaStopJoinEvent), CFG_SEQ_Prio_0);
break;
case BUT3_Pin:
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaStoreContextEvent), CFG_SEQ_Prio_0);
break;
#endif
default:
break;
}
}
/* USER CODE END PB_Callbacks */
/* Private functions ---------------------------------------------------------*/
/* USER CODE BEGIN PrFD */
/* USER CODE END PrFD */
static void OnRxData(LmHandlerAppData_t *appData, LmHandlerRxParams_t *params)
{
/* USER CODE BEGIN OnRxData_1 */
uint8_t RxPort = 0;
if (params != NULL)
{
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); /* LED_BLUE */
#endif
UTIL_TIMER_Start(&RxLedTimer);
if (params->IsMcpsIndication)
{
if (appData != NULL)
{
RxPort = appData->Port;
if (appData->Buffer != NULL)
{
switch (appData->Port)
{
case LORAWAN_SWITCH_CLASS_PORT:
/*this port switches the class*/
if (appData->BufferSize == 1)
{
switch (appData->Buffer[0])
{
case 0:
{
LmHandlerRequestClass(CLASS_A);
break;
}
case 1:
{
LmHandlerRequestClass(CLASS_B);
break;
}
case 2:
{
LmHandlerRequestClass(CLASS_C);
break;
}
default:
break;
}
}
DeviceClass_t deviceClass = CLASS_A;
LmHandlerGetCurrentClass( &deviceClass );
uint8_t i=0;
outbuf[i++] = (uint8_t) 'L';
outbuf[i++] = (uint8_t) sts_mtmcode1;
outbuf[i++] = (uint8_t) sts_mtmcode2;
outbuf[i++] = (uint8_t) sts_version;
outbuf[i++] = (uint8_t) (0x41+ deviceClass); //translate to 'A','B','C'
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
break;
case LORAWAN_USER_APP_PORT:
if (appData->BufferSize == 1)
{
AppLedStateOn = appData->Buffer[0] & 0x01;
if (AppLedStateOn == RESET)
{
APP_LOG(TS_OFF, VLEVEL_H, "LED OFF\r\n");
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
#endif
}
else
{
APP_LOG(TS_OFF, VLEVEL_H, "LED ON\r\n");
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); /* LED_RED */
#endif
}
}
break;
case LORAWAN_USER_APP_CTRL_PORT:
if (appData->BufferSize != 1)
{
if (appData->BufferSize < 128) {
USER_APP_AUTO_RESPONDER_Parse((char*)appData->Buffer, appData->BufferSize);
}
}
break;
default:
break;
}
}
}
}
if (params->RxSlot < RX_SLOT_NONE)
{
APP_LOG(TS_OFF, VLEVEL_H, "###### D/L FRAME:%04d | PORT:%d | DR:%d | SLOT:%s | RSSI:%d | SNR:%d\r\n",
params->DownlinkCounter, RxPort, params->Datarate, slotStrings[params->RxSlot],
params->Rssi, params->Snr);
}
}
/* USER CODE END OnRxData_1 */
}
static void SendTxData(void)
{
/* USER CODE BEGIN SendTxData_1 */
LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
uint8_t batteryLevel = GetBatteryLevel();
//sensor_t sensor_data;
STS_OO_SensorStatusDataTypeDef sensorData;
UTIL_TIMER_Time_t nextTxIn = 0;
if (LmHandlerIsBusy() == false)
{
uint32_t i = 0;
APP_LOG(TS_OFF, VLEVEL_M, "\r\n STS_WORK_MODE = %02x \r\n", sts_work_mode);
STS_PRESENCE_SENSOR_Prepare_Send_Data(&sensorData);
if (sts_work_mode == STS_DUAL_MODE)
{
AppData.Port = (uint8_t)YUNHORN_STS_O6_LORA_APP_DATA_PORT;
} else if (sts_work_mode == STS_UNI_MODE)
{
AppData.Port = (uint8_t)YUNHORN_STS_O7_LORA_APP_DATA_PORT;
} else if ((sts_work_mode == STS_RSS_MODE)||(sts_work_mode == STS_REEDSWITCH_MODE)||(sts_work_mode == STS_NETWORK_MODE)||(sts_work_mode == STS_WIRED_MODE))
{
AppData.Port = (uint8_t)YUNHORN_STS_O2_LORA_APP_DATA_PORT;
}
AppLedStateOn = LED1_STATE;
if ((heart_beat_timer != 0L)) // sensor data OVERWRITE heart-beat message, 2024-05-12
{
heart_beat_timer=0;
if (sts_work_mode == STS_DUAL_MODE)
AppData.Port = (uint8_t)YUNHORN_STS_O6_LORA_APP_HTBT_PORT; //LORAWAN_USER_APP_PORT+1;
else if (sts_work_mode == STS_UNI_MODE)
AppData.Port = (uint8_t)YUNHORN_STS_O7_LORA_APP_HTBT_PORT; //LORAWAN_USER_APP_PORT+1;
else if ((sts_work_mode == STS_RSS_MODE)||(sts_work_mode == STS_REEDSWITCH_MODE)||(sts_work_mode == STS_NETWORK_MODE)||(sts_work_mode == STS_WIRED_MODE))
AppData.Port = (uint8_t)YUNHORN_STS_O2_LORA_APP_HTBT_PORT; //LORAWAN_USER_APP_PORT+1;
//AppData.Port = (uint8_t)sts_sendhtbtport; //LORAWAN_USER_APP_PORT+1;
AppData.Buffer[i++] = (uint8_t)(AppLedStateOn|0x80)&0x0ff;
AppData.Buffer[i++] = (uint8_t)(99*batteryLevel/254)&0xff; //#05
} else if ((sensor_data_ready!= 0U)) //sensor_data_ready for manual push button-1 trigger)
{
sensor_data_ready =0;
if (sts_work_mode > STS_RSS_MODE) // keep compatible with previous version, PIXEL-NETWORK
{
AppData.Buffer[i++] = (uint8_t)(AppLedStateOn|0x80)&0x0ff; //00 ************ MUST KEEP IT HERE, NON-ZERO ******
}
AppData.Buffer[i++] = (uint8_t)(sensorData.lamp_bar_color)&0xff; //01
AppData.Buffer[i++] = (uint8_t)(sensorData.workmode)&0xff; //02 WORK MODE
if (sts_work_mode == STS_REEDSWITCH_MODE)
{
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor1_on_off)&0xff; //03 Sensor head #1 status reed switch
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor2_on_off)&0xff; //04 Sensor head #2 status reed switch
} else if (sts_work_mode == STS_RSS_MODE)
{
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor1_on_off)&0xff; //03 Sensor head #1 status reed switch
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor3_on_off)&0xff; //04 Sensor head #3 status RSS motion
}
else if (sts_work_mode == STS_DUAL_MODE)
{
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor1_on_off)&0xff; //03 Sensor head #1 status reed switch
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor2_on_off)&0xff; //04 Sensor head #2 status SOS button
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor3_on_off)&0xff; //05 Sensor head #3 status RSS motion
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_state)&0xff; //06 occupancy over time or not
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_duration>>8)&0xff; //07 occupancy over stay duration MSB
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_duration)&0xff; //08 occupancy over stay duration LSB
} else if (sts_work_mode == STS_UNI_MODE)
{
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor1_on_off)&0xff; //03 Sensor head #1 status reedswitch
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor2_on_off)&0xff; //04 Sensor head #2 status SOS button
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor3_on_off)&0xff; //05 Sensor head #3 status RSS motion
AppData.Buffer[i++] = (uint8_t)(sensorData.state_sensor4_on_off)&0xff; //06 Sensor head #4 status reserved
AppData.Buffer[i++] = (uint8_t)(sensorData.rss_presence_distance>>8)&0xff; //07 MSB distance
AppData.Buffer[i++] = (uint8_t)(sensorData.rss_presence_distance)&0xff; //08 LSB distance
AppData.Buffer[i++] = (uint8_t)(sensorData.rss_presence_score>>8)&0xff; //09 MSB score
AppData.Buffer[i++] = (uint8_t)(sensorData.rss_presence_score)&0xff; //10 LSB score
AppData.Buffer[i++] = (uint8_t)(sensorData.unconscious_state)&0xff; //11 unconscious state detected or not
AppData.Buffer[i++] = (uint8_t)(sensorData.fall_state)&0xff; //12 fall detected or not
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_state)&0xff; //13 occupancy over time or not
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_duration>>8)&0xff; //14 occupancy over stay duration MSB
AppData.Buffer[i++] = (uint8_t)(sensorData.over_stay_duration)&0xff; //15 occupancy over stay duration LSB
AppData.Buffer[i++] = (uint8_t)(sensorData.no_movement_duration>>8)&0xff; //16 occupancy over stay duration LSB
AppData.Buffer[i++] = (uint8_t)(sensorData.no_movement_duration)&0xff; //17 occupancy over stay duration LSB
AppData.Buffer[i++] = (uint8_t)(sensorData.fall_speed)&0xff; //18 fall detected speed
AppData.Buffer[i++] = (uint8_t)(sensorData.fall_gravity)&0xff; //19 fall detected gravity
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_start_timestamp>>24)&0xff; //20 SOS start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_start_timestamp>>16)&0xff; //21 SOS start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_start_timestamp>>8)&0xff; //22 SOS start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_start_timestamp)&0xff; //23 SOS start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_stop_timestamp>>24)&0xff; //24 SOS stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_stop_timestamp>>16)&0xff; //25 SOS stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_stop_timestamp>>8)&0xff; //26 SOS stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor2_stop_timestamp)&0xff; //27 SOS stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_start_time_stamp>>24)&0xff; //28 fall start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_start_time_stamp>>16)&0xff; //29 fall start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_start_time_stamp>>8)&0xff; //30 fall start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_start_time_stamp)&0xff; //31 fall start time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_stop_time_stamp>>24)&0xff; //32 fall stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_stop_time_stamp>>16)&0xff; //33 fall stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_stop_time_stamp>>8)&0xff; //34 fall stop time stamp
AppData.Buffer[i++] = (uint8_t)(sensorData.event_sensor3_fall_stop_time_stamp)&0xff; //35 fall stop time stamp
}
uint8_t ich= (sts_lamp_bar_color>>4 & 0x0f);
uint8_t icl= (sts_lamp_bar_color & 0x0f);
char colorshow[30]="";
strcpy(colorshow, (ich==0)?"":sts_lamp_color_code[ich]);
APP_LOG(TS_OFF, VLEVEL_L,
"\r\n######| Color = %s%s | Mode = %5s |\r\n",(char *)colorshow, sts_lamp_color_code[icl], (char*)sts_work_mode_code[sensorData.workmode]);
if (sts_work_mode == STS_UNI_MODE)
{
APP_LOG(TS_OFF, VLEVEL_L,
"\r\n######| S1-Door | S2-SOS | S3-Motion | S4 |Distance(mm) | MotionScore| Unconscious | Over_Stay_(min) | Fall Detected|"
"\r\n######| %s | %s | %d | %1d | %04d | %04d | %1d | %4d | %s |\r\n",
sts_door_status_code[sensorData.state_sensor1_on_off],
sts_sos_status_code[sensorData.state_sensor2_on_off],
sensorData.state_sensor3_on_off,
sensorData.state_sensor4_on_off,
(uint16_t)sensorData.rss_presence_distance,(uint16_t)sensorData.rss_presence_score,
sensorData.unconscious_state, sensorData.over_stay_duration, sts_fall_mode_code[sensorData.fall_state]);
} else if (sts_work_mode == STS_DUAL_MODE) {
APP_LOG(TS_OFF, VLEVEL_L,
"\r\n######| S1-Door | S2-SOS | S3-Motion |\r\n"
"\r\n######| %s | %s | %d |\r\n",
sts_door_status_code[sensorData.state_sensor1_on_off],
sts_sos_status_code[sensorData.state_sensor2_on_off],
sensorData.state_sensor3_on_off);
} else if (sts_work_mode == STS_RSS_MODE) {
APP_LOG(TS_OFF, VLEVEL_L,
"\r\n######| S3-Motion |\r\n"
"\r\n######| %d |\r\n",sensorData.state_sensor3_on_off);
}
}
AppData.BufferSize = (uint8_t)(sts_service_mask > STS_SERVICE_MASK_L1? 0:i)&0xff;;
#ifdef CLOCK_SYNC
if( IsClockSynched == false )
{
status = LmhpClockSyncAppTimeReq( );
if (LORAMAC_HANDLER_SUCCESS == status) {
OnSysTimeUpdate();
}
}
#endif
if ((JoinLedTimer.IsRunning) && (LmHandlerJoinStatus() == LORAMAC_HANDLER_SET))
{
UTIL_TIMER_Stop(&JoinLedTimer);
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
#endif
}
status = LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed, false);
if (LORAMAC_HANDLER_SUCCESS == status)
{
APP_LOG(TS_ON, VLEVEL_M, "SEND REQUEST \r\n");
}
else if (LORAMAC_HANDLER_DUTYCYCLE_RESTRICTED == status)
{
nextTxIn = LmHandlerGetDutyCycleWaitTime();
if (nextTxIn > 0)
{
APP_LOG(TS_ON, VLEVEL_H, "Next Tx in : ~%d second(s)\r\n", (nextTxIn / 1000));
}
}
}
if (EventType == TX_ON_TIMER)
{
UTIL_TIMER_Stop(&TxTimer);
UTIL_TIMER_SetPeriod(&TxTimer, MAX(nextTxIn, TxPeriodicity));
UTIL_TIMER_Start(&TxTimer);
}
/* USER CODE END SendTxData_1 */
}
static void OnTxTimerEvent(void *context)
{
/* USER CODE BEGIN OnTxTimerEvent_1 */
/* USER CODE END OnTxTimerEvent_1 */
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
/*Wait for next tx slot*/
UTIL_TIMER_Start(&TxTimer);
/* USER CODE BEGIN OnTxTimerEvent_2 */
/* USER CODE END OnTxTimerEvent_2 */
}
/* USER CODE BEGIN PrFD_LedEvents */
static void OnTxTimerLedEvent(void *context)
{
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); /* LED_GREEN */
#endif
}
static void OnRxTimerLedEvent(void *context)
{
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); /* LED_BLUE */
#endif
}
static void OnJoinTimerLedEvent(void *context)
{
#ifndef STM32WLE5xx
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin); /* LED_RED */
#endif
//HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); /* STS GREEN */
if ((sts_work_mode != STS_WIRED_MODE))
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP3), CFG_SEQ_Prio_0);
}
/* USER CODE END PrFD_LedEvents */
static void OnYunhornSTSLampBarColorTimerEvent(void *context)
{
//uint8_t lum=DEFAULT_LUMINANCE_LEVEL;
//HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); /* STS GREEN */
//if ((sts_work_mode != STS_WIRED_MODE))
uint8_t high4=(sts_lamp_bar_color>>4)&0x0f, low4=sts_lamp_bar_color&0x0f;
#if 0
luminance_level += 10;
luminance_level %= 60;
luminance_level = MAX(10,luminance_level);
#endif
//if (STSLampBarColorTimer.IsRunning)
{
UTIL_TIMER_Stop(&STSLampBarColorTimer);
if (high4==0)
{
//if (last_sts_lamp_bar_color != sts_lamp_bar_color)
{
//__disable_irq();
STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level);
//__enable_irq();
//STS_WS2812B_Refresh();
last_sts_lamp_bar_color = sts_lamp_bar_color;
}
} else {
if (r_b)
{
//__disable_irq();
STS_Lamp_Bar_Set_STS_RGB_Color(high4, luminance_level);
//__enable_irq();
//last_sts_lamp_bar_color = high4;
//STS_WS2812B_Refresh();
}
else {
//__disable_irq();
STS_Lamp_Bar_Set_STS_RGB_Color(low4, luminance_level);
//__enable_irq();
//last_sts_lamp_bar_color = low4;
//STS_WS2812B_Refresh();
}
r_b = !r_b;
}
UTIL_TIMER_Start(&STSLampBarColorTimer);
}
}
static void OnYunhornSTSDurationCheckTimerEvent(void *context)
{
static bool over_threshold = FALSE;
SysTime_t current_time = SysTimeGetMcuTime();
if (STS_Status_Door_Close==sts_hall1_read)
{
sts_o7_sensorData.event_sensor1_duration = current_time.Seconds - sts_o7_sensorData.event_sensor1_start_time;
//if (sts_o7_sensorData.event_sensor1_duration > sts_occupancy_overtime_threshold_in_10min*600)
if (sts_o7_sensorData.event_sensor1_duration > (sts_occupancy_overtime_threshold_in_10min*60)) //for debug
{
sts_o7_sensorData.over_stay_state = 1;
sts_o7_sensorData.over_stay_duration = sts_o7_sensorData.event_sensor1_duration;
over_threshold = TRUE;
APP_LOG(TS_OFF, VLEVEL_L, "\r\nSensor 1 Over Stay State=%d, Duration= %d Sec, Threshold =%u \r\n",
sts_o7_sensorData.over_stay_state,
(sts_o7_sensorData.over_stay_duration),
(sts_occupancy_overtime_threshold_in_10min*60) );
sts_lamp_bar_color = STS_RED_DARK;
//sts_lamp_bar_flashing_color = 0x20;
//volatile uint8_t sts_lamp_bar_color = STS_GREEN; //puColor
//volatile uint8_t sts_lamp_bar_flashing_color = 0x23; // RED_BLUE;
}
} else {
sts_o7_sensorData.event_sensor1_duration =0;
sts_o7_sensorData.over_stay_state = 0;
}
// to be defined later for SOS threshold TODO XXXX
if (STS_Status_SOS_Pushdown==sts_hall2_read)
{
sts_o7_sensorData.event_sensor2_duration = current_time.Seconds - sts_o7_sensorData.event_sensor2_start_time;
if (sts_o7_sensorData.event_sensor2_duration > sts_occupancy_overtime_threshold_in_10min*60) //for debug
{
sts_o7_sensorData.over_stay_state = 1;
// 2024-07-15 update, no overwrite sensor1 duration value
//sts_o7_sensorData.over_stay_duration = sts_o7_sensorData.event_sensor2_duration;
//
over_threshold = TRUE;
}
// to be defiend later for SOS threshold TODO XXXX
} else {
sts_o7_sensorData.event_sensor2_duration =0;
//sts_o7_sensorData.over_stay_state = 0;
}
if (sts_rss_result==STS_RESULT_MOTION)
{
sts_o7_sensorData.event_sensor3_motion_duration = current_time.Seconds - sts_o7_sensorData.event_sensor3_motion_start_time;
//if (sts_o7_sensorData.event_sensor3_motion_duration > sts_occupancy_overtime_threshold_in_10min*600)
if (sts_o7_sensorData.event_sensor3_motion_duration > sts_occupancy_overtime_threshold_in_10min*60) //for debug
{
sts_o7_sensorData.occupancy_over_stay_state = 1;
sts_o7_sensorData.occupancy_duration =sts_o7_sensorData.event_sensor3_motion_duration;
over_threshold = TRUE;
}
} else {
sts_o7_sensorData.event_sensor3_motion_duration =0;
//sts_o7_sensorData.occupancy_over_stay_state = 0;
}
/*
STS_PRESENCE_NONE=0,
STS_PRESENCE_FALL,
STS_PRESENCE_RISING,
STS_PRESENCE_LAYDOWN,
STS_PRESENCE_UNCONSCIOUS,
STS_PRESENCE_STAYSTILL
*/
uint32_t time_stamp=STS_Get_Date_Time_Stamp(); //uint8_t datetimestamp[8]={0};
//(&time_stamp, datetimestamp);
switch (sts_fall_rising_detected_result){
case STS_PRESENCE_NORMAL:
sts_o7_sensorData.fall_state = STS_PRESENCE_NORMAL;
sts_o7_sensorData.fall_laydown_duration=0;
sts_o7_sensorData.unconscious_state =STS_PRESENCE_NORMAL;
sts_o7_sensorData.unconscious_duration =0;
sts_o7_sensorData.no_movement_duration =0;
break;
case STS_PRESENCE_FALL:
// sts_fall_confirm_threshold_in_10sec
sts_o7_sensorData.event_sensor3_fall_duration = current_time.Seconds - sts_o7_sensorData.event_sensor3_fall_start_time;
if (sts_o7_sensorData.event_sensor3_fall_duration > 10*sts_cfg_nvm.fall_confirm_threshold_in_10sec)
{
//sts_o7_sensorData.occupancy_over_stay_state = 1;
//sts_o7_sensorData.event_sensor3_fall_start_time_stamp = time_stamp;
sts_o7_sensorData.fall_state = sts_fall_rising_detected_result;
sts_o7_sensorData.fall_laydown_duration =sts_o7_sensorData.event_sensor3_fall_duration;
over_threshold = TRUE;
} else { // still laydown, but not over fall down confirmation threshold
sts_o7_sensorData.fall_state = STS_PRESENCE_LAYDOWN;
sts_o7_sensorData.fall_laydown_duration =sts_o7_sensorData.event_sensor3_fall_duration;
over_threshold = FALSE;
}
break;
case STS_PRESENCE_RISING:
sts_o7_sensorData.event_sensor3_fall_stop_time_stamp = time_stamp;
over_threshold = FALSE;
break;
case STS_PRESENCE_LAYDOWN:
break;
case STS_PRESENCE_UNCONSCIOUS:
case STS_PRESENCE_STAYSTILL:
case STS_PRESENCE_NO_MOVEMENT:
sts_o7_sensorData.fall_state = sts_fall_rising_detected_result;
sts_o7_sensorData.event_sensor3_no_movement_duration = current_time.Seconds - sts_o7_sensorData.event_sensor3_no_movement_start_time;
sts_o7_sensorData.event_sensor3_unconcious_duration = current_time.Seconds - sts_o7_sensorData.event_sensor3_unconcious_start_time;
// sts_motionless_duration_threshold_in_min
if ((sts_o7_sensorData.event_sensor3_no_movement_duration > sts_cfg_nvm.motionless_duration_threshold_in_min*60)||
(sts_o7_sensorData.unconscious_duration > sts_cfg_nvm.motionless_duration_threshold_in_min*60))
{
sts_o7_sensorData.unconscious_state = 1;
over_threshold = TRUE;
}
break;
}
#if 0
if (sts_xxx_result == xxx)
sts_o7_sensorData.event_sensor3_event_duration = sensor_event_time.Seconds - sts_o7_sensorData.event_sensor4_start_time;
#endif
if (over_threshold == TRUE)
{
if (sts_o7_sensorData.fall_state == STS_PRESENCE_LAYDOWN)
{
sts_status_color = sts_lamp_bar_flashing_color; //STS_RED_BLUE;
sts_lamp_bar_color = sts_lamp_bar_flashing_color; //STS_RED_BLUE;
} else {
sts_status_color = STS_RED_DARK;
sts_lamp_bar_color = STS_RED_DARK; //sts_lamp_bar_flashing_color;
}
sensor_data_ready = 1;
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
over_threshold = FALSE;
}
}
static void OnTxData(LmHandlerTxParams_t *params)
{
/* USER CODE BEGIN OnTxData_1 */
if ((params != NULL))
{
/* Process Tx event only if its a mcps response to prevent some internal events (mlme) */
if (params->IsMcpsConfirm != 0)
{
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); /* LED_GREEN */
#endif
UTIL_TIMER_Start(&TxLedTimer);
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### ========== MCPS-Confirm =============\r\n");
APP_LOG(TS_OFF, VLEVEL_H, "###### U/L FRAME:%04d | PORT:%d | DR:%d | PWR:%d", params->UplinkCounter,
params->AppData.Port, params->Datarate, params->TxPower);
APP_LOG(TS_OFF, VLEVEL_H, " | MSG TYPE:");
if (params->MsgType == LORAMAC_HANDLER_CONFIRMED_MSG)
{
APP_LOG(TS_OFF, VLEVEL_H, "CONFIRMED [%s]\r\n", (params->AckReceived != 0) ? "ACK" : "NACK");
}
else
{
APP_LOG(TS_OFF, VLEVEL_H, "UNCONFIRMED\r\n");
}
}
}
/* USER CODE END OnTxData_1 */
}
static void OnJoinRequest(LmHandlerJoinParams_t *joinParams)
{
/* USER CODE BEGIN OnJoinRequest_1 */
if (joinParams != NULL)
{
if (joinParams->Status == LORAMAC_HANDLER_SUCCESS)
{
UTIL_TIMER_Stop(&JoinLedTimer);
sts_lamp_bar_color = STS_GREEN;
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
#endif
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### = JOINED = ");
if (joinParams->Mode == ACTIVATION_TYPE_ABP)
{
APP_LOG(TS_OFF, VLEVEL_M, "ABP ======================\r\n");
}
else
{
APP_LOG(TS_OFF, VLEVEL_M, "OTAA =====================\r\n");
}
STS_LoRa_WAN_Joined = (uint8_t) joinParams->Mode;
APP_LOG(TS_OFF, VLEVEL_L,"\r\n STS_LoRa_WAN_Joined = %s \r\n", (STS_LoRa_WAN_Joined == 1)?"ABP":"OTAA");
}
else
{
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### = JOIN FAILED\r\n");
}
APP_LOG(TS_OFF, VLEVEL_H, "###### U/L FRAME:JOIN | DR:%d | PWR:%d\r\n", joinParams->Datarate, joinParams->TxPower);
}
if (STS_LoRa_WAN_Joined)
{
heart_beat_timer = 1;
SendTxData();
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
//UTIL_TIMER_Start(&TxTimer);
//UTIL_TIMER_Start(&STSDurationCheckTimer);
OnYunhornSTSHeartBeatPeriodicityChanged(HeartBeatPeriodicity);
UTIL_TIMER_Create(&YunhornSTSRSSWakeUpTimer, YUNHORN_STS_RSS_WAKEUP_CHECK_TIME, UTIL_TIMER_PERIODIC, OnYunhornSTSOORSSWakeUpTimerEvent, NULL);
UTIL_TIMER_Start(&YunhornSTSRSSWakeUpTimer);
STS_SENSOR_Distance_Test_Process();
APP_LOG(TS_OFF, VLEVEL_H, "\r\nRSS Measured Distance=[%u] mm \r\n", (uint16_t)sts_distance_rss_distance);
}
/* USER CODE END OnJoinRequest_1 */
}
static void OnBeaconStatusChange(LmHandlerBeaconParams_t *params)
{
/* USER CODE BEGIN OnBeaconStatusChange_1 */
if (params != NULL)
{
switch (params->State)
{
default:
case LORAMAC_HANDLER_BEACON_LOST:
{
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### BEACON LOST\r\n");
break;
}
case LORAMAC_HANDLER_BEACON_RX:
{
APP_LOG(TS_OFF, VLEVEL_M,
"\r\n###### BEACON RECEIVED | DR:%d | RSSI:%d | SNR:%d | FQ:%d | TIME:%d | DESC:%d | "
"INFO:02X%02X%02X %02X%02X%02X\r\n",
params->Info.Datarate, params->Info.Rssi, params->Info.Snr, params->Info.Frequency,
params->Info.Time.Seconds, params->Info.GwSpecific.InfoDesc,
params->Info.GwSpecific.Info[0], params->Info.GwSpecific.Info[1],
params->Info.GwSpecific.Info[2], params->Info.GwSpecific.Info[3],
params->Info.GwSpecific.Info[4], params->Info.GwSpecific.Info[5]);
break;
}
case LORAMAC_HANDLER_BEACON_NRX:
{
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### BEACON NOT RECEIVED\r\n");
break;
}
}
}
/* USER CODE END OnBeaconStatusChange_1 */
}
static void OnSysTimeUpdate(void)
{
/* USER CODE BEGIN OnSysTimeUpdate_1 */
IsClockSynched = true;
/* USER CODE END OnSysTimeUpdate_1 */
}
static void OnClassChange(DeviceClass_t deviceClass)
{
/* USER CODE BEGIN OnClassChange_1 */
APP_LOG(TS_OFF, VLEVEL_H, "Switch to Class %c done\r\n", "ABC"[deviceClass]);
/* USER CODE END OnClassChange_1 */
}
static void OnMacProcessNotify(void)
{
/* USER CODE BEGIN OnMacProcessNotify_1 */
/* USER CODE END OnMacProcessNotify_1 */
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LmHandlerProcess), CFG_SEQ_Prio_0);
/* USER CODE BEGIN OnMacProcessNotify_2 */
/* USER CODE END OnMacProcessNotify_2 */
}
static void OnTxPeriodicityChanged(uint32_t periodicity)
{
/* USER CODE BEGIN OnTxPeriodicityChanged_1 */
/* USER CODE END OnTxPeriodicityChanged_1 */
TxPeriodicity = periodicity;
if (TxPeriodicity == 0)
{
/* Revert to application default periodicity */
TxPeriodicity = APP_TX_DUTYCYCLE;
}
/* Update timer periodicity */
UTIL_TIMER_Stop(&TxTimer);
UTIL_TIMER_SetPeriod(&TxTimer, TxPeriodicity);
UTIL_TIMER_Start(&TxTimer);
/* USER CODE BEGIN OnTxPeriodicityChanged_2 */
APP_LOG(TS_OFF, VLEVEL_H,"**************** TxPeriodicity = %u (sec)\r\n", (TxPeriodicity/1000) );
/* USER CODE END OnTxPeriodicityChanged_2 */
}
static void OnTxFrameCtrlChanged(LmHandlerMsgTypes_t isTxConfirmed)
{
/* USER CODE BEGIN OnTxFrameCtrlChanged_1 */
/* USER CODE END OnTxFrameCtrlChanged_1 */
LmHandlerParams.IsTxConfirmed = isTxConfirmed;
/* USER CODE BEGIN OnTxFrameCtrlChanged_2 */
/* USER CODE END OnTxFrameCtrlChanged_2 */
}
static void OnPingSlotPeriodicityChanged(uint8_t pingSlotPeriodicity)
{
/* USER CODE BEGIN OnPingSlotPeriodicityChanged_1 */
/* USER CODE END OnPingSlotPeriodicityChanged_1 */
LmHandlerParams.PingSlotPeriodicity = pingSlotPeriodicity;
/* USER CODE BEGIN OnPingSlotPeriodicityChanged_2 */
/* USER CODE END OnPingSlotPeriodicityChanged_2 */
}
static void OnSystemReset(void)
{
/* USER CODE BEGIN OnSystemReset_1 */
/* USER CODE END OnSystemReset_1 */
if ((LORAMAC_HANDLER_SUCCESS == LmHandlerHalt()) && (LmHandlerJoinStatus() == LORAMAC_HANDLER_SET))
{
NVIC_SystemReset();
}
/* USER CODE BEGIN OnSystemReset_Last */
/* USER CODE END OnSystemReset_Last */
}
static void StopJoin(void)
{
/* USER CODE BEGIN StopJoin_1 */
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); /* LED_BLUE */
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); /* LED_GREEN */
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); /* LED_RED */
#endif
/* USER CODE END StopJoin_1 */
UTIL_TIMER_Stop(&TxTimer);
if (LORAMAC_HANDLER_SUCCESS != LmHandlerStop())
{
APP_LOG(TS_OFF, VLEVEL_M, "LmHandler Stop on going ...\r\n");
}
else
{
APP_LOG(TS_OFF, VLEVEL_M, "LmHandler Stopped\r\n");
if (LORAWAN_DEFAULT_ACTIVATION_TYPE == ACTIVATION_TYPE_ABP)
{
ActivationType = ACTIVATION_TYPE_OTAA;
APP_LOG(TS_OFF, VLEVEL_M, "LmHandler switch to OTAA mode\r\n");
}
else
{
ActivationType = ACTIVATION_TYPE_ABP;
APP_LOG(TS_OFF, VLEVEL_M, "LmHandler switch to ABP mode\r\n");
}
LmHandlerConfigure(&LmHandlerParams);
LmHandlerJoin(ActivationType, true);
UTIL_TIMER_Start(&TxTimer);
}
UTIL_TIMER_Start(&StopJoinTimer);
/* USER CODE BEGIN StopJoin_Last */
/* USER CODE END StopJoin_Last */
}
static void OnStopJoinTimerEvent(void *context)
{
/* USER CODE BEGIN OnStopJoinTimerEvent_1 */
/* USER CODE END OnStopJoinTimerEvent_1 */
if (ActivationType == LORAWAN_DEFAULT_ACTIVATION_TYPE)
{
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaStopJoinEvent), CFG_SEQ_Prio_0);
}
/* USER CODE BEGIN OnStopJoinTimerEvent_Last */
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); /* LED_BLUE */
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); /* LED_GREEN */
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
#endif
/* USER CODE END OnStopJoinTimerEvent_Last */
}
static void StoreContext(void)
{
LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
/* USER CODE BEGIN StoreContext_1 */
/* USER CODE END StoreContext_1 */
status = LmHandlerNvmDataStore();
if (status == LORAMAC_HANDLER_NVM_DATA_UP_TO_DATE)
{
APP_LOG(TS_OFF, VLEVEL_M, "NVM DATA UP TO DATE\r\n");
}
else if (status == LORAMAC_HANDLER_ERROR)
{
APP_LOG(TS_OFF, VLEVEL_M, "NVM DATA STORE FAILED\r\n");
}
/* USER CODE BEGIN StoreContext_Last */
/* USER CODE END StoreContext_Last */
}
static void OnNvmDataChange(LmHandlerNvmContextStates_t state)
{
/* USER CODE BEGIN OnNvmDataChange_1 */
/* USER CODE END OnNvmDataChange_1 */
if (state == LORAMAC_HANDLER_NVM_STORE)
{
APP_LOG(TS_OFF, VLEVEL_M, "NVM DATA STORED\r\n");
}
else
{
APP_LOG(TS_OFF, VLEVEL_M, "NVM DATA RESTORED\r\n");
}
/* USER CODE BEGIN OnNvmDataChange_Last */
/* USER CODE END OnNvmDataChange_Last */
}
static void OnStoreContextRequest(void *nvm, uint32_t nvm_size)
{
/* USER CODE BEGIN OnStoreContextRequest_1 */
/* USER CODE END OnStoreContextRequest_1 */
/* store nvm in flash */
if (FLASH_IF_Erase(LORAWAN_NVM_BASE_ADDRESS, FLASH_PAGE_SIZE) == FLASH_IF_OK)
{
FLASH_IF_Write(LORAWAN_NVM_BASE_ADDRESS, (const void *)nvm, nvm_size);
}
/* USER CODE BEGIN OnStoreContextRequest_Last */
/* USER CODE END OnStoreContextRequest_Last */
}
static void OnRestoreContextRequest(void *nvm, uint32_t nvm_size)
{
/* USER CODE BEGIN OnRestoreContextRequest_1 */
/* USER CODE END OnRestoreContextRequest_1 */
FLASH_IF_Read(nvm, LORAWAN_NVM_BASE_ADDRESS, nvm_size);
/* USER CODE BEGIN OnRestoreContextRequest_Last */
/* USER CODE END OnRestoreContextRequest_Last */
}
/**
* @brief Yunhorn STS Occupancy RSS WakeUP timer callback function, act as sampling process
* @param context ptr of STS RSS WakeUp context
*/
static void OnYunhornSTSOORSSWakeUpTimerEvent(void *context)
{
if ((sts_work_mode == STS_RSS_MODE)||(sts_work_mode == STS_DUAL_MODE)||(sts_work_mode == STS_UNI_MODE))
{
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), CFG_SEQ_Prio_0);
APP_LOG(TS_OFF,VLEVEL_M,"\r\n Wakeup Timer ======== RSS result changed flag=%d \r\n", sts_rss_result_changed_flag);
if ((STS_LoRa_WAN_Joined != 0)&&(sts_rss_result_changed_flag==1))
{
sts_rss_result_changed_flag = 0;
APP_LOG(TS_OFF,VLEVEL_M,"\r\n Wakeup Timer ======== Send Tx Result\r\n");
SendTxData();
//UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
//if ((last_sts_rss_result ==STS_RESULT_NO_MOTION)&& (sts_rss_result==STS_RESULT_MOTION))
{
//OnSensor3StateChanged();
}
}
}
//UTIL_TIMER_Start(&YunhornSTSRSSWakeUpTimer);
}
/**
* @brief Yunhorn STS Sensor Heart Beat Timer callback function
* @param context ptr of STS Sampling Check context
*/
static void OnYunhornSTSHeartBeatTimerEvent(void *context)
{
heart_beat_timer = 1;
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
if ((STS_LoRa_WAN_Joined ) && (sts_ac_code[0]==0x0) && (sts_ac_code[19]==0x0))
{
/* RFAC Challenge */
if (rfac_timer < (STS_BURN_IN_RFAC+3)) {
rfac_timer ++;
}
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventRFAC), CFG_SEQ_Prio_0);
}
UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer);
}
/**
* @brief Yunhorn STS Sensor Live Heart Beat Periodicity/interval Change callback function
* @param context ptr of STS Live Heart Beat context
* YL x x x
* */
static void OnYunhornSTSHeartBeatPeriodicityChanged(uint32_t periodicity)
{
/* USER CODE BEGIN OnTxPeriodicityChanged_1 */
/* USER CODE END OnTxPeriodicityChanged_1 */
HeartBeatPeriodicity = periodicity;
if (HeartBeatPeriodicity == 0)
{
/* Revert to application default periodicity */
HeartBeatPeriodicity = 10*APP_TX_DUTYCYCLE;
}
/* Update timer periodicity */
UTIL_TIMER_Stop(&YunhornSTSHeartBeatTimer);
UTIL_TIMER_SetPeriod(&YunhornSTSHeartBeatTimer, HeartBeatPeriodicity);
UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer);
/* USER CODE BEGIN OnTxPeriodicityChanged_2 */
APP_LOG(TS_OFF, VLEVEL_H,"**************** HeartBeatPeriodicity = %u (sec)\r\n", HeartBeatPeriodicity/1000 );
/* USER CODE END OnTxPeriodicityChanged_2 */
}
/**
* @brief Yunhorn STS Sensor Sampling Periodicity/interval Change callback function
* @param context ptr of STS RSS WakeUp context
*/
static void OnYunhornSTSSamplingPeriodicityChanged(uint32_t periodicity)
{
/* USER CODE BEGIN OnTxPeriodicityChanged_1 */
/* USER CODE END OnTxPeriodicityChanged_1 */
SamplingPeriodicity = periodicity;
if (SamplingPeriodicity == 0)
{
/* Revert to application default periodicity */
SamplingPeriodicity = APP_TX_DUTYCYCLE;
}
/* Update timer periodicity */
#if defined(STS_O6)||defined(STS_O7)
if (STS_LoRa_WAN_Joined !=0)
{
UTIL_TIMER_Stop(&YunhornSTSRSSWakeUpTimer);
UTIL_TIMER_SetPeriod(&YunhornSTSRSSWakeUpTimer, SamplingPeriodicity);
UTIL_TIMER_Start(&YunhornSTSRSSWakeUpTimer);
APP_LOG(TS_OFF, VLEVEL_M,"**************** Sampling Timer Periodicity = %u (sec)\r\n", (SamplingPeriodicity/1000) );
}
#else
UTIL_TIMER_Stop(&YunhornSTSSamplingCheckTimer);
UTIL_TIMER_SetPeriod(&YunhornSTSSamplingCheckTimer, SamplingPeriodicity);
UTIL_TIMER_Start(&YunhornSTSSamplingCheckTimer);
APP_LOG(TS_OFF, VLEVEL_M,"**************** SamplingPeriodicity = %u (sec)\r\n", (SamplingPeriodicity/1000) );
#endif
/* USER CODE BEGIN OnTxPeriodicityChanged_2 */
/* USER CODE END OnTxPeriodicityChanged_2 */
}
/**
* @brief Yunhorn STS Sensor Sampling Check Timer callback function
* @param context ptr of STS Sampling Check context
*/
/*
static void OnYunhornSTSSamplingCheckTimerEvent(void *context)
{
// P1 --- REEDSWITCH, HALL ELEMENT, WATER LEAKAGE, ********** NOT FOR THIS EVENT TRIGGER PROCESS
// 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 ****** NOT FOR THIS REAL-TIME FULL BLOCKED DETECTION
// P6 ---
// P7 ---
// P8 --- AIR QUALITY AND ODOR LEVEL, SMOKING DETECTION
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), CFG_SEQ_Prio_0);
if (STS_LoRa_WAN_Joined != 0)
{
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
}
}
*/
/*
* YUNHORN STS PRODUCT BOARD LEVEL CONTROL OR REPORT
* --Y
* --Z BOARD LEVEL
* --H 'YZH' Hardware REBOOT [YZH] WVpI
* --C 'YZC' LoRa-WAN CLASS A/B/C [YZC] WVpD
* --S 'YZS' SELF-TEST FUNCTION TEST [YZS] WVpT
* --D 'YZD' DISTANCE MEASURE [YZD] WVpE
*
*
* --V VERSION
* --H 'YVH' HARDWARE/FIRMWARE VERSION [YVH] WVZI
* --C 'YVC' NVM CONFIG VERSION [YVC] WVZD
*
* --O POWER-ON
* --# 'YO1', 'YO2','YO3' [YO0] WU8w, [YO1] WU8x, [YO2] WU8y
*
* --F POWER-OFF
* --# 'YF1', 'YF2','YF3' [YF0] WUYw, [YF1] WUYx, [YF2] WUYy
*
* --H MEMS RESET
* --# 'YH0','YH1','YH2' [YH0] WUgw, [YH1] WUgx, [YH2] WUgy
*
* --M SERVICE LEVEL MASK
* --# 'YM0', 'YM1','YM2', 'YM3' [YM0] WU0w [YM1]WU0x [YM2]WU0y [YM3]WU0z
*
* --D UPLINK DURATION OR PERIODICITY Periodicity of Tx interval or Heart-Beat interval for real-time occupancy status update 2023-04-28
* --#
* --#
* --U UNIT (S, M, H) SECONDS, MINUTES, HOURS
* --S SAMPLING INTERVAL OR PERIODICITY periodicity for real-time sensing
* --#
* --#
* --U UNIT (S, M, H) SECONDS, MINUTES, HOURS
*
* --P ***** WORKMODE AND NETWORK COLOR
* --# MTM-VER 1
* --# STS-VER 1
* --M WORK MODE
*
* --N NETWORK WORK MODE {0,1,2,3,4,5,6}
* --C NETWORK COLOR, {0,1,2,3,4,5,6,7,8,9}
*
* --P ***** SIMPLE CONFIG PARAMETER FOR RSS (8 DIGITS)
* --# MTM-VER 1
* --# STS-VER 1
*
* --## START #.# meter
* --## LENGTH #.# meter
* --## THRESHOLD #.#*1000
* --## GAIN 0.##
*
* --P ***** DISTANCE MEASURE CONFIG PARAMETER FOR RSS (7 DIGITS)
* --# MTM-VER 1
* --# STS-VER 1
* --## START #.# meter
* --## LENGTH #.# meter
* --# PROFILE #
* --## HWAAS ##
*
** --P ***** FULL CONFIG PARAMETER FOR RSS (30 DIGITS)
* --# MTM-VER 1
* --# STS-VER 1
* --30{#} FULL CONFIG PARAMETER
* --A ***** AC CODE (22 BYTES)
* --C
* --#
* --20{#} AC CODE 20 BYTES
*
*/
void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, uint8_t tlv_buf_size)
{
uint8_t i=0, mems_ver, invalid_flag=1;
UTIL_MEM_set_8((void*)outbuf,0x0, sizeof(outbuf));
if (((char)tlv_buf[CFG_CMD1] == 'Y') && (tlv_buf_size <=5)) // BEGIN OF *** BOARD LEVEL CONTROL OR REPORT
{
switch ((char)tlv_buf[CFG_CMD2])
{
case 'Z': //"YZ"
if ((char)tlv_buf[CFG_CMD3] == 'H') { //BOARD SOFT RESET, REVIVE "YZH"
//BOARD REVIVE
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 20, (uint8_t*)"!YunHorn STS Revive!");
HAL_Delay(5000);
APP_LOG(TS_OFF, VLEVEL_H, "\r\n Yunhorn STS Node Revive ... \r\n");
HAL_Delay(3000);
__set_FAULTMASK(1);
OnSystemReset();
} else if ((char)tlv_buf[CFG_CMD3] == 'S') { // Self Function Testing "YZS"
i=0;
//outbuf[i++] = (uint8_t) 'Y';
//outbuf[i++] = (uint8_t) 'Z';
//outbuf[i++] = (uint8_t) 'S';
//STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
i=0;
STS_SENSOR_Function_Test_Process();
#if 0
HAL_Delay(5000);
i=21;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
#endif
} else if ((char)tlv_buf[CFG_CMD3] == 'C') { // Lora-WAN Class "YZC" LORAWAN CLASS A/B/C
DeviceClass_t deviceClass = CLASS_A;
LmHandlerGetCurrentClass( &deviceClass );
i=0;
outbuf[i++] = (uint8_t) 'L';
outbuf[i++] = (uint8_t) sts_mtmcode1;
outbuf[i++] = (uint8_t) sts_mtmcode2;
outbuf[i++] = (uint8_t) sts_version;
outbuf[i++] = (uint8_t) (0x41+ deviceClass); //translate to 'A','B','C'
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
} else if ((char)tlv_buf[CFG_CMD3] == 'D') { // Distance Measure "YZD"
//i=0;
//outbuf[i++] = (uint8_t) 'Y';
//outbuf[i++] = (uint8_t) 'Z';
//outbuf[i++] = (uint8_t) 'D';
//STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
STS_SENSOR_Distance_Test_Process();
APP_LOG(TS_OFF, VLEVEL_H, "\r\nRSS Measured Distance=[%u] mm \r\n", (uint16_t)sts_distance_rss_distance);
// Store valid installation height value
sts_cfg_nvm.mtmcode1 = (uint8_t)sts_mtmcode1;
sts_cfg_nvm.mtmcode2 = (uint8_t)sts_mtmcode2;
sts_cfg_nvm.version = (uint8_t)sts_version;
sts_cfg_nvm.hardware_ver = (uint8_t)sts_hardware_ver;
sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
sts_cfg_nvm.sensor_install_height_in_10cm = sts_sensor_install_height/100; //in 10 cm
OnStoreSTSCFGContextRequest();
i=0;
//memset((void*)outbuf,0x0, sizeof(outbuf));
outbuf[i++] = (uint8_t)'D';
outbuf[i++] = (uint8_t)sts_mtmcode1;
outbuf[i++] = (uint8_t)sts_mtmcode2;
outbuf[i++] = (uint8_t)sts_version;
outbuf[i++] = (uint8_t)sts_hardware_ver;
outbuf[i++] = (uint8_t)(99*((GetBatteryLevel()/254)&0xff));
#if defined(STS_O7)||defined(STS_O6)
outbuf[i++] = (uint8_t)0x04; //length of following data
outbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/1000)%10+0x30)&0xff;
outbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/100)%10+0x30)&0xff;
outbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/10)%10+0x30)&0xff;
outbuf[i++] = (uint8_t) (((uint16_t)sts_distance_rss_distance)%10+0x30)&0xff;
#endif
#if (defined(YUNHORN_STS_R0_ENABLED)||defined(YUNHORN_STS_R5_ENABLED)||defined(YUNHORN_STS_R1_ENABLED))
#ifdef TOF_1
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[0])/100)&0xff;
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[0])%100)&0xff;
#endif
#ifdef TOF_2
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[1])/100)&0xff;
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[1])%100)&0xff;
#endif
#ifdef TOF_3
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[2])/100)&0xff;
outbuf[i++] = (uint8_t) (((uint16_t)sts_tof_distance_data[2])%100)&0xff;
#endif
#endif
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
}
break;
case 'M': //"YM"
if ((char)tlv_buf[CFG_CMD3] >= '0' && (char)tlv_buf[CFG_CMD3]<='9') // Service Mask "YZM"
{
i=0;
sts_service_mask = (uint8_t)(tlv_buf[CFG_CMD3]-0x30)&0xFF;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
outbuf[i++] = (uint8_t) 'Y';
outbuf[i++] = (uint8_t) 'M';
outbuf[i++] = (uint8_t) (sts_service_mask+0x30);
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
APP_LOG(TS_OFF, VLEVEL_L, ">>>>>>>>>>>>>>>>>>>>> Mask = [ %02x ] \r\n", sts_service_mask);
OnStoreSTSCFGContextRequest();
if (sts_service_mask != STS_SERVICE_MASK_L0) STS_Lamp_Bar_Set_Dark();
//STS_Combined_Status_Processing();
}
break;
case 'V': //"YV"
if ((char)tlv_buf[CFG_CMD3] == 'H') { // "YVH" REPORT FIRMWARE VERSION "YVH"
// FIRMWARE VERSION REPORT
i=0;
outbuf[i++] = (uint8_t) 'V';
outbuf[i++] = (uint8_t) sts_mtmcode1;
outbuf[i++] = (uint8_t) sts_mtmcode2;
outbuf[i++] = (uint8_t) sts_version;
outbuf[i++] = (uint8_t) sts_hardware_ver;
outbuf[i++] = (uint8_t) MajorVer;
outbuf[i++] = (uint8_t) MinorVer;
outbuf[i++] = (uint8_t) SubMinorVer;
struct tm localtime;
SysTime_t UnixEpoch = SysTimeGet();
UnixEpoch.Seconds -= 18; /*removing leap seconds*/
//UnixEpoch.Seconds += 3600 * 2; /*adding 2 hours*/
SysTimeLocalTime(UnixEpoch.Seconds, &localtime);
APP_LOG(TS_OFF, VLEVEL_M, "LTIME:%02dh%02dm%02ds on %02d/%02d/%04d\r\n",
localtime.tm_hour, localtime.tm_min, localtime.tm_sec,
localtime.tm_mday, localtime.tm_mon + 1, localtime.tm_year + 1900);
#if 0
LmhPackage_t LmhpClockSyncPackageFactory;
LmhpClockSyncPackageFactory.Init;
if (LmhpClockSyncPackageFactory.IsInitialized)
LmhpClockSyncPackageFactory.Process;
if (LORAMAC_HANDLER_SUCCESS == LmhpClockSyncAppTimeReq()) {
APP_LOG(TS_OFF, VLEVEL_M, "\r\n Clock Sync Success \r\n");
}
SysTime_t mytime=SysTimeGet();
struct tm mylocal;
SysTimeLocalTime((uint32_t)mytime.Seconds, &mylocal);
APP_LOG(TS_OFF, VLEVEL_M, "\r\nTime YYYYMMDD=%4d:%2d:%2d HHMMSS=%2d:%2d:%2d \r\n",
mylocal.tm_year, mylocal.tm_mon, mylocal.tm_mday, mylocal.tm_hour, mylocal.tm_min, mylocal.tm_sec);
#endif
i=0;
outbuf[i++] = (uint8_t) 'V';
outbuf[i++] = (uint8_t) sts_mtmcode1;
outbuf[i++] = (uint8_t) sts_mtmcode2;
outbuf[i++] = (uint8_t) sts_version;
outbuf[i++] = (uint8_t) sts_hardware_ver;
outbuf[i++] = (uint8_t) MajorVer;
outbuf[i++] = (uint8_t) MinorVer;
outbuf[i++] = (uint8_t) SubMinorVer;
uint16_t year = localtime.tm_year+1900;
outbuf[i++] = (uint8_t) ((year)>>8);
outbuf[i++] = (uint8_t) (year)&0xff;
outbuf[i++] = (uint8_t) localtime.tm_mon+1;
outbuf[i++] = (uint8_t) localtime.tm_mday;
outbuf[i++] = (uint8_t) localtime.tm_hour;
outbuf[i++] = (uint8_t) localtime.tm_min;
outbuf[i++] = (uint8_t) localtime.tm_sec;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
APP_LOG(TS_OFF, VLEVEL_M, "###### YUNHORN Report Version [ %10x ] \r\n", (uint8_t *)outbuf);
}
else
if ((char)tlv_buf[CFG_CMD3] == 'C') { // "YVC" REPORT NVM STORED CONFIG PARAMETERS "YVC"
uint8_t cfg_in_nvm[YUNHORN_STS_MAX_NVM_CFG_SIZE]="";
OnRestoreSTSCFGContextRequest((uint8_t *)cfg_in_nvm);
i=0;
outbuf[i++] = (uint8_t) 'C';
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_MTM1]; //MTM Code
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_MTM2]; //MTM Code
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_VER]; //STS Version
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_HWV]; //STS Version
outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_PERIODICITY]); //UPLINK Periodicity
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_UNIT]; //UPLINK Periodicity unit
outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_SAMPLING]); //Heart-beat or SAMPLING Periodicity
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_S_UNIT]; //Heart-beat or SAMPLING Periodicity unit
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_WORK_MODE]; // STS WORK MODE
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_SERVICE_MASK]; //service mask
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_IOC_MASK]; //sts ioc mask
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN]; //length of following cfg value
for (uint8_t j=0; j < cfg_in_nvm[NVM_LEN]; j++) {
outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_CFG_START+j]);
}
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
}
break;
// "YO#","YF#","YH#","YD##L" ##={0,9} L={S,M,H}
case 'O':
// TODO # of modules
if (((uint8_t)(tlv_buf[CFG_CMD3]-0x30) >= 0) && ((uint8_t)tlv_buf[CFG_CMD3]-0x30) <=9)
{
//STS_SENSOR_Power_ON((uint8_t)(tlv_buf[CFG_CMD3]-0x30));
PME_ON;
// 2024-07-31
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf,tlv_buf_size);
i = tlv_buf_size;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
} else {
STS_SENSOR_Upload_Config_Invalid_Message();
}
break;
case 'F':
// TODO # of modules
if (((uint8_t)(tlv_buf[CFG_CMD3]-0x30) >= 0) && ((uint8_t)tlv_buf[CFG_CMD3]-0x30) <=9) {
//STS_SENSOR_Power_OFF((tlv_buf[CFG_CMD3]-0x30));
PME_OFF;
// 2024-07-31
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf,tlv_buf_size);
i = tlv_buf_size;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
} else {
STS_SENSOR_Upload_Config_Invalid_Message();
}
break;
case 'H':
// TODO # of modules
if (((uint8_t)(tlv_buf[CFG_CMD3]-0x30) >= 0) && ((uint8_t)tlv_buf[CFG_CMD3]-0x30) <=9) {
PME_ON;
PME_OFF;
PME_ON;
// 2024-07-31
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf,tlv_buf_size);
i = tlv_buf_size;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
} else {
STS_SENSOR_Upload_Config_Invalid_Message();
}
break;
case 'D': //periodicity UPLINK, ACT AS HEART-BEAT MESSAGE
if ((((char)tlv_buf[CFG_CMD3] >= '0') && ((char)tlv_buf[CFG_CMD3] <='9')
&& ((char)tlv_buf[CFG_CMD4] >='0') && ((char)tlv_buf[CFG_CMD4] <='9')) &&
(((char)tlv_buf[CFG_CMD5] == 'M' || ((char)tlv_buf[CFG_CMD5] =='H') ||((char)tlv_buf[CFG_CMD5] =='S'))))
{
uint32_t periodicity_length = (tlv_buf[CFG_CMD3]-0x30)*10+ (tlv_buf[CFG_CMD4]-0x30);
if ((char)tlv_buf[CFG_CMD5] == 'M') {
periodicity_length *= 60;
} else if ((char)tlv_buf[CFG_CMD5] == 'H') {
periodicity_length *= 3600;
}
periodicity_length = periodicity_length*1000; //translate to 1000ms=1s
//OnTxPeriodicityChanged(TxPeriodicity);
#if defined(STS_O6)||defined(STS_O7)
HeartBeatPeriodicity = periodicity_length;
OnYunhornSTSHeartBeatPeriodicityChanged(periodicity_length);
#endif
// 2024-07-31
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf,tlv_buf_size);
i = tlv_buf_size;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
// Save config to NVM
sts_cfg_nvm.mtmcode1 = (uint8_t)sts_mtmcode1;
sts_cfg_nvm.mtmcode2 = (uint8_t)sts_mtmcode2;
sts_cfg_nvm.version = (uint8_t)sts_version;
sts_cfg_nvm.hardware_ver = (uint8_t)sts_hardware_ver;
sts_cfg_nvm.periodicity = (uint8_t)((tlv_buf[CFG_CMD3]-0x30)*10+(tlv_buf[CFG_CMD4]-0x30));
sts_cfg_nvm.unit = (uint8_t)tlv_buf[CFG_CMD5];
sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
OnStoreSTSCFGContextRequest();
//APP_LOG(TS_OFF, VLEVEL_M, "###### YUNHORN Periodicity Changed to [ %d ] Seconds\r\n", periodicity_length);
} else {
STS_SENSOR_Upload_Config_Invalid_Message();
}
break;
case 'S': // SAMPLING INTERVAL OR DURATION
if ((((char)tlv_buf[CFG_CMD3] >= '0') && ((char)tlv_buf[CFG_CMD3] <='9')
&& ((char)tlv_buf[CFG_CMD4] >='0') && ((char)tlv_buf[CFG_CMD4] <='9')) &&
(((char)tlv_buf[CFG_CMD5] == 'M' || ((char)tlv_buf[CFG_CMD5] =='H') ||((char)tlv_buf[CFG_CMD5] =='S'))))
{
uint32_t heart_beat_or_sampling_periodicity_length = (tlv_buf[CFG_CMD3]-0x30)*10+ (tlv_buf[CFG_CMD4]-0x30);
if ((char)tlv_buf[CFG_CMD5] == 'M') {
heart_beat_or_sampling_periodicity_length *= 60;
} else if ((char)tlv_buf[CFG_CMD5] == 'H') {
heart_beat_or_sampling_periodicity_length *= 3600;
}
#ifdef YUNHORN_STS_E0_ENABLED
SamplingPeriodicity = heart_beat_or_sampling_periodicity_length*1000; //translate to 1000ms=1s
OnYunhornSTSSamplingPeriodicityChanged(SamplingPeriodicity);
#endif
#if defined(YUNHORN_STS_R0_ENABLED)||defined(YUNHORN_STS_R5_ENABLED)
HeartBeatPeriodicity = heart_beat_or_sampling_periodicity_length*1000; //translate to 1000ms=1s
OnYunhornSTSHeartBeatPeriodicityChanged(HeartBeatPeriodicity);
#endif
#if defined(STS_O6)||defined(STS_O7)
SamplingPeriodicity = heart_beat_or_sampling_periodicity_length*1000; //translate to 1000ms=1s
OnYunhornSTSSamplingPeriodicityChanged(SamplingPeriodicity);
#endif
// 2024-07-31
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf,tlv_buf_size);
i = tlv_buf_size;
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
// Save config to NVM
sts_cfg_nvm.mtmcode1 = (uint8_t)sts_mtmcode1;
sts_cfg_nvm.mtmcode2 = (uint8_t)sts_mtmcode2;
sts_cfg_nvm.version = (uint8_t)sts_version;
sts_cfg_nvm.hardware_ver = (uint8_t)sts_hardware_ver;
sts_cfg_nvm.sampling = (uint8_t)((tlv_buf[CFG_CMD3]-0x30)*10+(tlv_buf[CFG_CMD4]-0x30));
sts_cfg_nvm.s_unit = (uint8_t)tlv_buf[CFG_CMD5];
sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
OnStoreSTSCFGContextRequest();
//APP_LOG(TS_OFF, VLEVEL_M, "###### YUNHORN HeartBeat or Sampling Interval Changed to [ %d ] msec\r\n", (SamplingPeriodicity));
} else {
STS_SENSOR_Upload_Config_Invalid_Message();
}
break;
default:
//STS_SENSOR_Upload_Config_Invalid_Message();
break;
} // END OF switch switch ((char)tlv_buf[CFG_CMD2])
} // end of if END OF *** BOARD LEVEL CONTROL OR REPORT
else if (((char)tlv_buf[CFG_CMD1] == 'P') && (tlv_buf_size >= 3)) // BEGIN OF PARAMETER CONFIG
{
/*
* YUNHORN STS PRODUCT SUBMODULE, MEMS OR SENSOR HEAD LEVEL PARAMETER TUNING SECTION
*/
//i = P_MEM_CFG; //start of parameter
switch ((char)tlv_buf[CFG_CMD2]) //BEGIN OF SWITCH TVL_BUF_P_MEMS_NO
{ //#1 No. of MEMS components
//default first sensor head or MEMS component, default 1 sensor heads
case '0': //default sensor head or MEMS component
case '1': //first sensor head or MEMS component
mems_ver = (uint8_t)(tlv_buf[CFG_CMD3]-0x30);
uint8_t j=0;
if (mems_ver == sts_version)
{ // Firmware version or Variation of MEMS/component
if (tlv_buf_size == 5 && tlv_buf[CFG_CMD4]=='0') //switch network mode color
{
invalid_flag = 0;
sts_work_mode = (uint8_t)(tlv_buf[CFG_CMD4] - 0x30);
if (sts_work_mode == STS_NETWORK_MODE)
{ //network mode
sts_cloud_netcolor = (uint8_t)(tlv_buf[CFG_CMD5]-0x30);
if (sts_cloud_netcolor == STS_COLOR_MAX) sts_cloud_netcolor = STS_RED_BLUE;
else if (sts_cloud_netcolor > STS_COLOR_MAX)
{
#if 1
switch((uint8_t)tlv_buf[CFG_CMD5])
{
case STS_GREENDARK:
sts_lamp_bar_color = STS_GREEN_DARK;
sts_cloud_netcolor = STS_GREEN_DARK;
break;
case STS_REDDARK:
sts_lamp_bar_color = STS_RED_DARK;
sts_cloud_netcolor = STS_RED_DARK;
break;
case STS_REDBLUE:
sts_lamp_bar_color = STS_RED_BLUE;
sts_cloud_netcolor = STS_RED_BLUE;
break;
case STS_BLUEDARK:
sts_lamp_bar_color = STS_BLUE_DARK;
sts_cloud_netcolor = STS_BLUE_DARK;
break;
case STS_REDGREEN:
sts_lamp_bar_color = STS_RED_GREEN;
sts_cloud_netcolor = STS_RED_GREEN;
break;
case STS_BLUEGREEN:
sts_lamp_bar_color = STS_BLUE_GREEN;
sts_cloud_netcolor = STS_BLUE_GREEN;
break;
}
}
#endif
APP_LOG(TS_OFF, VLEVEL_L, "\r\n Cloud Color Set to 0X%02X \r\n",sts_cloud_netcolor);
}
sts_service_mask = STS_SERVICE_MASK_L0;
sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
OnStoreSTSCFGContextRequest();
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
STS_Combined_Status_Processing();
} else if (tlv_buf_size == 7 && tlv_buf[CFG_CMD4]=='F') // Change fall detection
{
invalid_flag = 0; // P 1 1 F A B C
if (((tlv_buf[CFG_CMD5] >='0') && (tlv_buf[CFG_CMD5]<='9')) && ((tlv_buf[CFG_CMD6]<='9') && (tlv_buf[CFG_CMD6]>='0'))
&& ((tlv_buf[CFG_CMD7]<='9') && (tlv_buf[CFG_CMD7]>='0'))) //&& ((tlv_buf[CFG_CMD8]<='9') && (tlv_buf[CFG_CMD8]>='0')))
{
sts_fall_detection_acc_threshold = (uint8_t)(tlv_buf[CFG_CMD5] - 0x30)*10; //A: acc *10 mg/s2
sts_fall_detection_depth_threshold = (uint8_t)(tlv_buf[CFG_CMD6] - 0x30)*10; //D: depth *10 in cm
sts_fall_confirm_threshold_in_10sec = (uint8_t)(tlv_buf[CFG_CMD7] - 0x30)*10; //C: fall_confirm_threshold_in_10sec
//sts_occupancy_overtime_threshold_in_10min = (uint8_t)(tlv_buf[CFG_CMD8] - 0x30)*10; //T: overtime *10 min
sts_cfg_nvm.fall_detection_acc_threshold = (uint8_t)(tlv_buf[CFG_CMD5] - 0x30);
sts_cfg_nvm.fall_detection_depth_threshold = (uint8_t)(tlv_buf[CFG_CMD6] - 0x30);
sts_cfg_nvm.fall_confirm_threshold_in_10sec = (uint8_t)(tlv_buf[CFG_CMD7] - 0x30);
//sts_cfg_nvm.occupancy_overtime_threshold_in_10min = (uint8_t)(tlv_buf[CFG_CMD8] - 0x30);
if (sts_work_mode == STS_UNI_MODE) // fall detection threshold only effective in Uni_mode
{
if ((sts_fall_detection_acc_threshold ==0)&&(sts_fall_detection_depth_threshold==0))
{
sts_presence_fall_detection = FALSE;
} else {
sts_presence_fall_detection = TRUE;
}
}
OnStoreSTSCFGContextRequest();
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
APP_LOG(TS_OFF, VLEVEL_L, "###### Fall detection CFG = %s\r\n",(char*)outbuf);
STS_Combined_Status_Processing();
}
}else if (tlv_buf_size == 8 && tlv_buf[CFG_CMD4]=='O') // Change occupancy/motionless/ unconscious overtime threshold
{
invalid_flag = 0; // P 1 1 O A B C D
if (((tlv_buf[CFG_CMD5] >='0') && (tlv_buf[CFG_CMD5]<='9')) && ((tlv_buf[CFG_CMD6]<='9') && (tlv_buf[CFG_CMD6]>='0'))
&& ((tlv_buf[CFG_CMD7]<='9') && (tlv_buf[CFG_CMD7]>='0'))&& ((tlv_buf[CFG_CMD8]<='9') && (tlv_buf[CFG_CMD8]>='0')))
{
sts_motionless_duration_threshold_in_min = (uint8_t)(tlv_buf[CFG_CMD5] - 0x30); //Motionless duration in min
sts_occupancy_overtime_threshold_in_10min = (uint8_t)(tlv_buf[CFG_CMD6] - 0x30)*10; //Long occupation in min
sts_unconscious_level_threshold = (uint8_t)(tlv_buf[CFG_CMD7] - 0x30+1)*128; //motion level threshold less than 1280
sts_alarm_mute_reset_timer_in_10sec = (uint8_t)(tlv_buf[CFG_CMD8] - 0x30)*10; //alarm mute reset timer in 10 sec
sts_cfg_nvm.motionless_duration_threshold_in_min = (uint8_t)(tlv_buf[CFG_CMD5] - 0x30);
sts_cfg_nvm.occupancy_overtime_threshold_in_10min = (uint8_t)(tlv_buf[CFG_CMD6] - 0x30);
sts_cfg_nvm.unconscious_or_motionless_level_threshold = (uint8_t)(tlv_buf[CFG_CMD7] - 0x30+1);
sts_cfg_nvm.alarm_mute_reset_timer_in_10sec = (uint8_t)(tlv_buf[CFG_CMD8] - 0x30)*10;
OnStoreSTSCFGContextRequest();
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
APP_LOG(TS_OFF, VLEVEL_L, "###### Occupancy/Overstay/unconscious config changed =%s\r\n",(char *)outbuf);
STS_Combined_Status_Processing();
}
}
else if (tlv_buf_size == 4 ) // P WORK mode switch
{
invalid_flag = 0;
if (((tlv_buf[CFG_CMD4] >='0') && (tlv_buf[CFG_CMD4]<='9')) || ((tlv_buf[CFG_CMD4]<='Z') && (tlv_buf[CFG_CMD4]>='A')))
{
if ((tlv_buf[CFG_CMD4] >='0') && (tlv_buf[CFG_CMD4]<='9'))
{
sts_work_mode = (uint8_t)((tlv_buf[CFG_CMD4] - 0x30));
} else if ((tlv_buf[CFG_CMD4]<='Z') && (tlv_buf[CFG_CMD4]>='A'))
{
sts_work_mode = (uint8_t)((tlv_buf[CFG_CMD4] - 0x41) + 10);
}
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
APP_LOG(TS_OFF, VLEVEL_L, "###### P Work mode switched =%s\r\n",(char *)outbuf);
//sts_service_mask = STS_SERVICE_MASK_L0;
//sts_lamp_bar_color = STS_GREEN;
sts_presence_fall_detection=FALSE;
sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
switch (sts_work_mode) {
case STS_NETWORK_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_0_MASK;
break;
case STS_WIRED_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_1_MASK;
break;
case STS_REEDSWITCH_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_2_MASK;
break;
case STS_RSS_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_3_MASK;
sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
break;
case STS_DUAL_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_4_MASK;
sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT;
break;
case STS_UNI_MODE:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MODE_5_MASK;
sts_rss_config_updated_flag = STS_RSS_CONFIG_FALL_DETECTION;
sts_presence_fall_detection=TRUE;
break;
default:
sts_cfg_nvm.sts_ioc_mask = STS_IOC_MASK_NONE;
break;
}
sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode;
sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask;
OnStoreSTSCFGContextRequest();
STS_Combined_Status_Processing();
HAL_Delay(2000);
//OnSystemReset();
} else {
invalid_flag = 1;
}
} else if (tlv_buf_size == CFG_CMD_RSS_FULL_SIZE)
{
invalid_flag = 0;
for (j =0; j < CFG_CMD_RSS_FULL_SIZE-3; j++)
{
if ((tlv_buf[CFG_CMD4+j] >='0') && (tlv_buf[CFG_CMD4+j]<='9'))
{
//sts_cfg_nvm.p[j] = (uint8_t)((tlv_buf[CFG_CMD4+j] - 0x30)&0xFF);
//APP_LOG(TS_OFF,VLEVEL_H,"\r\n tlv_buf %d = %02x cfg->p[%d]=%02x \r\n",j,tlv_buf[CFG_CMD4+j], j, sts_cfg_nvm.p[j]);
} else {
invalid_flag = 1;
}
}
i=0;
sts_cfg_nvm.p[RSS_CFG_START_M] = (uint8_t)((tlv_buf[CFG_CMD4] - 0x30)*10+(tlv_buf[CFG_CMD5] - 0x30));
sts_cfg_nvm.p[RSS_CFG_LENGTH_M] = (uint8_t)((tlv_buf[CFG_CMD6] - 0x30)*10+(tlv_buf[CFG_CMD7] - 0x30));
sts_cfg_nvm.p[RSS_CFG_THRESHOLD] = (uint8_t)((tlv_buf[CFG_CMD8] - 0x30)*10+(tlv_buf[CFG_CMD9] - 0x30));
sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN] = (uint8_t)((tlv_buf[CFG_CMD10]- 0x30)*10+(tlv_buf[CFG_CMD11]- 0x30));
sts_cfg_nvm.p[RSS_CFG_PROFILE] = (uint8_t)((tlv_buf[CFG_CMD12]- 0x30));
sts_cfg_nvm.p[RSS_CFG_RATE_TRACKING] = (uint8_t)((tlv_buf[CFG_CMD13]- 0x30)*10+(tlv_buf[CFG_CMD14]- 0x30));
sts_cfg_nvm.p[RSS_CFG_RATE_PRESENCE] = (uint8_t)((tlv_buf[CFG_CMD15]- 0x30)*10+(tlv_buf[CFG_CMD16]- 0x30));
sts_cfg_nvm.p[RSS_CFG_HWAAS] = (uint8_t)((tlv_buf[CFG_CMD17]- 0x30)*10+(tlv_buf[CFG_CMD18]- 0x30));
sts_cfg_nvm.p[RSS_CFG_NBR_REMOVED_PC] = (uint8_t)((tlv_buf[CFG_CMD19]- 0x30));
sts_cfg_nvm.p[RSS_CFG_ITE_DEVIATION] = (uint8_t)((tlv_buf[CFG_CMD20]- 0x30)*10+(tlv_buf[CFG_CMD21]- 0x30));
sts_cfg_nvm.p[RSS_CFG_ITE_FAST_CUTOFF] = (uint8_t)((tlv_buf[CFG_CMD22]- 0x30)*10+(tlv_buf[CFG_CMD23]- 0x30));
sts_cfg_nvm.p[RSS_CFG_ITE_SLOW_CUTOFF] = (uint8_t)((tlv_buf[CFG_CMD24]- 0x30)*10+(tlv_buf[CFG_CMD25]- 0x30));
sts_cfg_nvm.p[RSS_CFG_ITR_TIME] = (uint8_t)((tlv_buf[CFG_CMD26]- 0x30)*10+(tlv_buf[CFG_CMD27]- 0x30));
sts_cfg_nvm.p[RSS_CFG_ITR_WEIGHT] = (uint8_t)((tlv_buf[CFG_CMD28]- 0x30)*10+(tlv_buf[CFG_CMD29]- 0x30));
sts_cfg_nvm.p[RSS_CFG_OUTPUT_TIME] = (uint8_t)((tlv_buf[CFG_CMD30]- 0x30)*10+(tlv_buf[CFG_CMD31]- 0x30));
sts_cfg_nvm.p[RSS_CFG_DOWNSAMPLING_FACTOR] = (uint8_t)((tlv_buf[CFG_CMD32]- 0x30));
sts_cfg_nvm.p[RSS_CFG_POWER_MODE] = (uint8_t)((tlv_buf[CFG_CMD33]- 0x30));
if (invalid_flag == 0)
{
STS_PRESENCE_SENSOR_NVM_CFG();
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
APP_LOG(TS_OFF, VLEVEL_L, "###### RSS Full CFG=%s\r\n",(char *)outbuf);
// Step 2: Save valid config to NVM
sts_cfg_nvm.mtmcode1 = sts_mtmcode1;
sts_cfg_nvm.mtmcode2 = sts_mtmcode2;
sts_cfg_nvm.version = sts_version;
sts_cfg_nvm.hardware_ver = sts_hardware_ver;
sts_cfg_nvm.work_mode = sts_work_mode;
sts_cfg_nvm.sts_service_mask = sts_service_mask;
//sts_cfg_nvm.length = CFG_CMD_RSS_FULL_SIZE;
OnStoreSTSCFGContextRequest();
}
} else if (tlv_buf_size == CFG_CMD_RSS_SIMPLE_SIZE)
{
//Validation check
invalid_flag = 0;
#if 1
for (j =0; j < CFG_CMD_RSS_SIMPLE_SIZE-3; j++)
{
if ((tlv_buf[CFG_CMD4+j] >='0') && (tlv_buf[CFG_CMD4+j]<='9'))
{
//sts_cfg_nvm.p[j] = (uint8_t)((tlv_buf[CFG_CMD4+j] - 0x30)&0xff);
//APP_LOG(TS_OFF,VLEVEL_H,"\r\n tlv_buf %d = %02x cfg->p[%d]=%02x \r\n",j,tlv_buf[CFG_CMD4+j], j, sts_cfg_nvm.p[j]);
} else {
invalid_flag = 1;
}
}
#endif
sts_cfg_nvm.p[RSS_CFG_START_M] = (uint8_t)((tlv_buf[CFG_CMD4] - 0x30)*10+(tlv_buf[CFG_CMD5] - 0x30));
sts_cfg_nvm.p[RSS_CFG_LENGTH_M] = (uint8_t)((tlv_buf[CFG_CMD6] - 0x30)*10+(tlv_buf[CFG_CMD7] - 0x30));
sts_cfg_nvm.p[RSS_CFG_THRESHOLD] = (uint8_t)((tlv_buf[CFG_CMD8] - 0x30)*10+(tlv_buf[CFG_CMD9] - 0x30));
sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN] = (uint8_t)((tlv_buf[CFG_CMD10]- 0x30)*10+(tlv_buf[CFG_CMD11]- 0x30));
if (invalid_flag == 0)
{
STS_PRESENCE_SENSOR_NVM_CFG_SIMPLE();
i=0; // Step 1: Prepare status update message
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
i = tlv_buf_size;
APP_LOG(TS_OFF, VLEVEL_M, "###### RSS Simple CFG=%s\r\n",(char*)outbuf);
// Step 2: Save valid config to NVM
sts_cfg_nvm.mtmcode1 = sts_mtmcode1;
sts_cfg_nvm.mtmcode2 = sts_mtmcode2;
sts_cfg_nvm.version = sts_version;
sts_cfg_nvm.hardware_ver = sts_hardware_ver;
sts_cfg_nvm.work_mode = sts_work_mode;
sts_cfg_nvm.sts_service_mask = sts_service_mask;
//sts_cfg_nvm.length = CFG_CMD_RSS_SIMPLE_SIZE;
OnStoreSTSCFGContextRequest();
}
}
// Invalid parameters
// Step 1/2: Prepare status update message
if (invalid_flag == 1)
{
STS_SENSOR_Upload_Config_Invalid_Message();
APP_LOG(TS_OFF, VLEVEL_L, "###### MTM VER Invalid or Mismatch\r\n");
} else {
// Step 3: Upload status update message
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
}
}
break;
// for multiple sensor heads or MEMS components, TODO 2022-10-21 PARK HERE
case 2:
#ifdef YUNHORN_STS_O2_ENABLED
// for 2nd sensor heads such as 2x Presence radar, 2 reed-switch or hall elements
#endif
break;
default:
// for multiple sensor heads or MEMS components, TODO 2022-10-21 PARK HERE
//STS_SENSOR_Upload_Config_Invalid_Message();
break;
} //END OF SWITCH TVL_BUF_P_MEMS_NO
//END OF PARAMETER CONFIG
} else if (((char)tlv_buf[CFG_CMD1] == 'A') && ((char)tlv_buf[CFG_CMD2] == 'C') && (tlv_buf_size == (YUNHORN_STS_AC_CODE_SIZE+2))) // BEGIN OF *** BOARD LEVEL AUTHORIZATION CODE
{
// 'AC'+ AC_CODE(20bytes)
//UTIL_MEM_cpy_8(sts_ac_code, tlv_buf+2,YUNHORN_STS_AC_CODE_SIZE);
for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++)
{
sts_ac_code[j] = (uint8_t) tlv_buf[2+j];
}
STS_YUNHORN_RFAC_HANDLE_PROCESS();
if ((hmac_result.ac_pass == 1U))
{
//UTIL_MEM_cpy_8(sts_cfg_nvm.ac, sts_ac_code,YUNHORN_STS_AC_CODE_SIZE);
for (uint8_t j=0; j < YUNHORN_STS_AC_CODE_SIZE; j++)
{
sts_cfg_nvm.ac[j] = sts_ac_code[j];
}
sts_service_mask = STS_SERVICE_MASK_L0;
sts_cfg_nvm.sts_service_mask = sts_service_mask;
OnStoreSTSCFGContextRequest();
} else {
sts_service_mask = STS_SERVICE_MASK_L2;
}
i=0;
UTIL_MEM_set_8((void*)outbuf, 0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf,(void*)tlv_buf, tlv_buf_size);
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t *)outbuf);
}
} // END OF USER_APP_AUTO_RESPONDER_Parse
void STS_SENSOR_Upload_Config_Invalid_Message(void)
{
if (sts_service_mask == STS_SERVICE_MASK_L0)
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 5, (uint8_t*)"PVXXX");
}
static void STS_YUNHORN_RFAC_HANDLE_PROCESS(void)
{
STS_YunhornAuthenticationCode_Process();
}
void STS_SENSOR_Upload_Message(uint8_t appDataPort, uint8_t appBufferSize, uint8_t *appDataBuffer)
{
LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
UTIL_TIMER_Time_t nextTxIn = 0;
if (LmHandlerIsBusy() == false)
{
for (uint8_t i=0; i<appBufferSize; i++) {
AppData.Buffer[i] = appDataBuffer[i];
}
//UTIL_MEM_cpy_8(AppData.Buffer, appDataBuffer, appBufferSize);
AppData.Port = appDataPort;
AppData.BufferSize = (sts_service_mask >1 ?0:appBufferSize);
APP_LOG(TS_OFF, VLEVEL_L, "###########Service Mask = %d Buffer Size =%d \r\n", sts_service_mask, AppData.BufferSize);
if ((JoinLedTimer.IsRunning) && (LmHandlerJoinStatus() == LORAMAC_HANDLER_SET))
{
UTIL_TIMER_Stop(&JoinLedTimer);
#ifndef STM32WLE5xx
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
#endif
}
status = LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed, false);
if (LORAMAC_HANDLER_SUCCESS == status)
{
APP_LOG(TS_ON, VLEVEL_H, "SEND REQUEST\r\n");
}
else if (LORAMAC_HANDLER_DUTYCYCLE_RESTRICTED == status)
{
nextTxIn = LmHandlerGetDutyCycleWaitTime();
if (nextTxIn > 0)
{
APP_LOG(TS_ON, VLEVEL_H, "Next Tx in : ~%d second(s)\r\n", (nextTxIn / 1000));
}
}
}
if (EventType == TX_ON_TIMER)
{
UTIL_TIMER_Stop(&TxTimer);
UTIL_TIMER_SetPeriod(&TxTimer, MAX(nextTxIn, TxPeriodicity));
UTIL_TIMER_Start(&TxTimer);
}
}
void OnStoreSTSCFGContextRequest(void)
{
/* USER CODE BEGIN OnStoreContextRequest_1 */
uint8_t i=0,j=0,nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0};
//#if (defined(STS_O7)||defined(STS_O5) || defined(STS_O6) || defined(STS_R0) || defined(STS_R5)|| defined(STS_R4)|| defined(STS_R1D))
sts_cfg_nvm.length = STS_O7_NVM_CFG_SIZE;
nvm_store_value[i++] = sts_cfg_nvm.mtmcode1;
nvm_store_value[i++] = sts_cfg_nvm.mtmcode2;
nvm_store_value[i++] = sts_cfg_nvm.version;
nvm_store_value[i++] = sts_cfg_nvm.hardware_ver;
nvm_store_value[i++] = sts_cfg_nvm.periodicity;
nvm_store_value[i++] = sts_cfg_nvm.unit;
nvm_store_value[i++] = sts_cfg_nvm.sampling;
nvm_store_value[i++] = sts_cfg_nvm.s_unit;
nvm_store_value[i++] = sts_cfg_nvm.work_mode;
nvm_store_value[i++] = sts_cfg_nvm.sts_service_mask;
nvm_store_value[i++] = sts_cfg_nvm.sts_ioc_mask;
nvm_store_value[i++] = sts_cfg_nvm.length; //(uint8_t) STS_O7_NVM_CFG_SIZE; //sts_cfg_nvm.length;
for (j = 0; j < STS_O7_CFG_PCFG_SIZE; j++) {
nvm_store_value[i++] = (sts_cfg_nvm.p[j]);
}
nvm_store_value[i++] = sts_cfg_nvm.reserve02;
nvm_store_value[i++] = sts_cfg_nvm.reserve03;
nvm_store_value[i++] = sts_cfg_nvm.sensor_install_height_in_10cm;
nvm_store_value[i++] = sts_cfg_nvm.alarm_parameter05;
nvm_store_value[i++] = sts_cfg_nvm.alarm_mute_reset_timer_in_10sec;
nvm_store_value[i++] = sts_cfg_nvm.alarm_lamp_bar_flashing_color;
nvm_store_value[i++] = sts_cfg_nvm.occupancy_overtime_threshold_in_10min;
nvm_store_value[i++] = sts_cfg_nvm.motionless_duration_threshold_in_min;
nvm_store_value[i++] = sts_cfg_nvm.unconscious_or_motionless_level_threshold;
nvm_store_value[i++] = sts_cfg_nvm.fall_detection_acc_threshold;
nvm_store_value[i++] = sts_cfg_nvm.fall_detection_depth_threshold;
nvm_store_value[i++] = sts_cfg_nvm.fall_confirm_threshold_in_10sec;
if ((sts_cfg_nvm.ac[0]!=0x0) && (sts_cfg_nvm.ac[19]!=0x0)) {
for (j = 0; j < YUNHORN_STS_AC_CODE_SIZE; j++) {
nvm_store_value[i++] = (sts_cfg_nvm.ac[j]);
}
}
//#endif
/* USER CODE END OnStoreContextRequest_1 */
/* store nvm in flash */
if (FLASH_IF_Erase(STS_CONFIG_NVM_BASE_ADDRESS, FLASH_PAGE_SIZE) == FLASH_IF_OK)
{
FLASH_IF_Write(STS_CONFIG_NVM_BASE_ADDRESS, (const void *)nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE);
}
/* USER CODE BEGIN OnStoreContextRequest_Last */
/* USER CODE END OnStoreContextRequest_Last */
}
void OnRestoreSTSCFGContextRequest(void *cfg_in_nvm)
{
/* USER CODE BEGIN OnRestoreSTSCFGContextRequest_1 */
// uint8_t nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]="", nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE;
APP_LOG(TS_OFF, VLEVEL_M, "Restore NVM start\r\n");
/* USER CODE END OnRestoreSTSCFGContextRequest_1 */
FLASH_IF_Read(cfg_in_nvm, STS_CONFIG_NVM_BASE_ADDRESS, YUNHORN_STS_MAX_NVM_CFG_SIZE);
//UTIL_MEM_cpy_8(cfg_in_nvm, (void *)STS_CONFIG_NVM_BASE_ADDRESS, YUNHORN_STS_MAX_NVM_CFG_SIZE);
/* USER CODE BEGIN OnRestoreSTSCFGContextRequest_Last */
//memcpy(cfg_in_nvm, nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE);
/* USER CODE END OnRestoreSTSCFGContextRequest_Last */
}
void STS_REBOOT_CONFIG_Init(void)
{
/* USER CODE BEGIN OnRestoreContextRequest_1 */
uint8_t nvm_stored_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0};
/* USER CODE END OnRestoreContextRequest_1 */
//UTIL_MEM_cpy_8(nvm_stored_value, (void *)STS_CONFIG_NVM_BASE_ADDRESS, YUNHORN_STS_MAX_NVM_CFG_SIZE);
FLASH_IF_Read(nvm_stored_value, STS_CONFIG_NVM_BASE_ADDRESS, YUNHORN_STS_MAX_NVM_CFG_SIZE);
/* USER CODE BEGIN OnRestoreContextRequest_Last */
//#if (defined(STS_O7)||defined(STS_O5) || defined(STS_O6) || defined(STS_R0) || defined(STS_R5)|| defined(STS_R4)|| defined(STS_R1D))
if ((nvm_stored_value[NVM_MTM1] != sts_mtmcode1) || (nvm_stored_value[NVM_MTM2] != sts_mtmcode2) || (nvm_stored_value[NVM_VER] != sts_version))
{
APP_LOG(TS_OFF, VLEVEL_M, "Initial Boot with Empty Config, Flash with default config....\r\n");
OnStoreSTSCFGContextRequest();
//UTIL_MEM_set_8((void *)sts_ac_code, 0x00, YUNHORN_STS_AC_CODE_SIZE);
HAL_Delay(1000);
} else
{
sts_cfg_nvm.mtmcode1 = (uint8_t)nvm_stored_value[NVM_MTM1];
sts_cfg_nvm.mtmcode2 = (uint8_t)nvm_stored_value[NVM_MTM2];
sts_cfg_nvm.version = (uint8_t)nvm_stored_value[NVM_VER];
sts_cfg_nvm.hardware_ver = (uint8_t)nvm_stored_value[NVM_HWV];
sts_cfg_nvm.periodicity = (uint8_t)(nvm_stored_value[NVM_PERIODICITY]);
sts_cfg_nvm.unit = (uint8_t)(nvm_stored_value[NVM_UNIT]);
sts_cfg_nvm.sampling = (uint8_t)(nvm_stored_value[NVM_SAMPLING]);
sts_cfg_nvm.s_unit = (uint8_t)(nvm_stored_value[NVM_S_UNIT]);
sts_cfg_nvm.work_mode = (uint8_t)(nvm_stored_value[NVM_WORK_MODE]);
sts_cfg_nvm.sts_service_mask = (uint8_t)(nvm_stored_value[NVM_SERVICE_MASK]);
sts_cfg_nvm.sts_ioc_mask = (uint8_t)(nvm_stored_value[NVM_IOC_MASK]);
sts_cfg_nvm.length = (uint8_t)(nvm_stored_value[NVM_LEN]&0x3F); //MAX 32 bytes
for (uint8_t j=0; j< STS_O7_CFG_PCFG_SIZE; j++) { // P RSS CONFIG SIZE= 20U
sts_cfg_nvm.p[j] = (uint8_t)nvm_stored_value[NVM_CFG_START+j];
}
sts_cfg_nvm.reserve02 =(uint8_t)nvm_stored_value[NVM_RESERVE02];
sts_cfg_nvm.reserve03 =(uint8_t)nvm_stored_value[NVM_RESERVE03];
sts_cfg_nvm.sensor_install_height_in_10cm =(uint8_t)nvm_stored_value[NVM_SENSOR_INSTALL_HEIGHT];
sts_cfg_nvm.alarm_parameter05 =(uint8_t)nvm_stored_value[NVM_ALARM_PARAMETER05];
sts_cfg_nvm.alarm_mute_reset_timer_in_10sec = (uint8_t)nvm_stored_value[NVM_ALARM_MUTE_RESET_TIMER];
sts_cfg_nvm.alarm_lamp_bar_flashing_color = (uint8_t)nvm_stored_value[NVM_ALARM_LAMP_BAR_FLASHING_COLOR];
sts_cfg_nvm.occupancy_overtime_threshold_in_10min = (uint8_t)nvm_stored_value[NVM_OCCUPANCY_OVERTIME_THRESHOLD];
sts_cfg_nvm.motionless_duration_threshold_in_min= (uint8_t)nvm_stored_value[NVM_MOTIONLESS_DURATION_THRESHOLD];
sts_cfg_nvm.unconscious_or_motionless_level_threshold = (uint8_t)nvm_stored_value[NVM_UNCONSCIOUS_LEVEL_THRESHOLD];
sts_cfg_nvm.fall_detection_acc_threshold = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_ACC_THRESHOLD];
sts_cfg_nvm.fall_detection_depth_threshold = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_DEPTH_THRESHOLD];
sts_cfg_nvm.fall_confirm_threshold_in_10sec = (uint8_t)nvm_stored_value[NVM_FALL_CONFIRM_THRESHOLD];
//sts_cfg_nvm.occupancy_overtime_threshold = (uint8_t)nvm_stored_value[NVM_OCCUPANCY_OVERTIME_THRESHOLD];
for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++) {
sts_cfg_nvm.ac[j] = (uint8_t)nvm_stored_value[NVM_AC_CODE_START +j];
}
}
//#endif
OnRestoreSTSCFGContextProcess();
/* USER CODE END OnRestoreContextRequest_Last */
}
void OnRestoreSTSCFGContextProcess(void)
{
uint32_t periodicity = (sts_cfg_nvm.periodicity);
if ((char)sts_cfg_nvm.unit =='M') {
periodicity *= 60;
} else if ((char) sts_cfg_nvm.unit =='H') {
periodicity *= 3600;
} else if ((char) sts_cfg_nvm.unit =='S') {
periodicity *= 1;
}
periodicity *= 1000; // to ms
uint32_t sampling = (sts_cfg_nvm.sampling);
if ((char)sts_cfg_nvm.s_unit =='M') {
sampling *= 60;
} else if ((char) sts_cfg_nvm.s_unit =='H') {
sampling *= 3600;
} else if ((char) sts_cfg_nvm.s_unit =='S') {
sampling *= 1;
}
sampling= sampling*1000; // to ms
if ((sts_cfg_nvm.ac[0] ==0x0 )&& (sts_cfg_nvm.ac[19]==0x0))
{ // ensure it's not in production yet
OnTxPeriodicityChanged(APP_TX_DUTYCYCLE); // in msec unit
OnYunhornSTSHeartBeatPeriodicityChanged(HeartBeatPeriodicity);
OnYunhornSTSSamplingPeriodicityChanged(sampling); // in m-sec unit
} else
{
//OnTxPeriodicityChanged(TxPeriodicity); // in msec unit
//Heart-beat or Sampling interval
#ifdef STS_E0
samplingperiodicity = (samplingperiodicity > 0)? samplingperiodicity : 1; // in seconds unit
HeartBeatPeriodicity = samplingperiodicity*1000;
#endif
#if defined(STS_O7)|| defined(STS_O6) ||defined(STS_O5)
HeartBeatPeriodicity = periodicity;
OnYunhornSTSHeartBeatPeriodicityChanged(HeartBeatPeriodicity);
OnYunhornSTSSamplingPeriodicityChanged(sampling); // in m-sec unit
#endif
#if defined(YUNHORN_STS_R0_ENABLED)||defined(YUNHORN_STS_R5_ENABLED)||defined(YUNHORN_STS_R4_ENABLED)
OnYunhornSTSHeartBeatPeriodicityChanged(HeartBeatPeriodicity);
#endif
}
sts_work_mode = sts_cfg_nvm.work_mode;
sts_lamp_bar_color = STS_GREEN;
sts_service_mask = sts_cfg_nvm.sts_service_mask;
sts_lamp_bar_flashing_color = sts_cfg_nvm.alarm_lamp_bar_flashing_color;
if (sts_work_mode == STS_UNI_MODE){
sts_presence_fall_detection =TRUE;
} else {
sts_presence_fall_detection =FALSE;
}
sts_sensor_install_height = sts_cfg_nvm.sensor_install_height_in_10cm*100; //10cm translate to mm
sts_fall_detection_acc_threshold = (uint8_t)sts_cfg_nvm.fall_detection_acc_threshold*10;
sts_fall_detection_depth_threshold = (uint8_t)sts_cfg_nvm.fall_detection_depth_threshold*10; //in cm
sts_fall_confirm_threshold_in_10sec = (uint8_t)sts_cfg_nvm.fall_confirm_threshold_in_10sec*10;
sts_unconscious_or_motionless_level_threshold = (uint8_t)(sts_cfg_nvm.unconscious_or_motionless_level_threshold+1)*128; // unconscious threshold
sts_motionless_duration_threshold_in_min = (uint8_t)sts_cfg_nvm.motionless_duration_threshold_in_min;
sts_occupancy_overtime_threshold_in_10min = (uint8_t)sts_cfg_nvm.occupancy_overtime_threshold_in_10min; // minutes
for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++)
{
sts_ac_code[j] = sts_cfg_nvm.ac[j];
}
#if defined(STS_O7)||defined(STS_O6)
// if ((sts_version == sts_cfg_nvm.version)&& (NVM_CFG_PARAMETER_SIZE == sts_cfg_nvm.length))
{
STS_PRESENCE_SENSOR_Init();
STS_PRESENCE_SENSOR_RSS_Init();
}
#endif
//STS_SENSOR_Distance_Test_Process();
//APP_LOG(TS_OFF, VLEVEL_L, "\r\nDistance Measured =%u mm, Ceiling Height=%u \r\n", (uint16_t)sts_distance_rss_distance, (uint16_t)sts_sensor_install_height);
}
void STS_SENSOR_Distance_Test_Process(void)
{
#if defined(STS_O6)||defined(STS_O7)
STS_PRESENCE_SENSOR_Distance_Measure_Process();
#endif
#if defined(YUNHORN_STS_R0_ENABLED)||defined(YUNHORN_STS_R5_ENABLED)
MX_TOF_Process();
#endif
}
void STS_SENSOR_Function_Test_Process(void)
{
char tstbuf[128] =""; uint8_t i=0, count = 1;
uint8_t mems_Dev_ID[2] = {0x0};
tstbuf[i++] = (uint8_t) 'S';
tstbuf[i++] = (uint8_t) sts_mtmcode1;
tstbuf[i++] = (uint8_t) sts_mtmcode2;
tstbuf[i++] = (uint8_t) sts_version;
tstbuf[i++] = (uint8_t) sts_hardware_ver;
tstbuf[i++] = (uint8_t) (99*((GetBatteryLevel()/254)&0xff));
APP_LOG(TS_OFF, VLEVEL_H, "\r\nStart Function Test \r\n");
STS_SENSOR_MEMS_Get_ID(mems_Dev_ID);
if ((mems_Dev_ID[0]==0X0) && (mems_Dev_ID[1]==0x0)) {
tstbuf[i++] = (uint8_t) 'X'; // Slave MEMS Not Avaliable
}
else
{
tstbuf[i++] = (uint8_t)14; //length of following data
#if defined(STS_O7)||defined(STS_O6)
uint8_t self_test_result[10]={0x0};
STS_PRESENCE_SENSOR_Function_Test_Process(self_test_result, count);
for (uint8_t j=0; j < 10; j++)
tstbuf[i++] = (uint8_t) (self_test_result[j])&0xff;
//STS_PRESENCE_SENSOR_Distance_Measure_Process();
tstbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/1000)%10+0x30)&0xff;
tstbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/100)%10+0x30)&0xff;
tstbuf[i++] = (uint8_t) ((((uint16_t)sts_distance_rss_distance)/10)%10+0x30)&0xff;
tstbuf[i++] = (uint8_t) (((uint16_t)sts_distance_rss_distance)%10+0x30)&0xff;
#endif
#if (defined(YUNHORN_STS_R0_ENABLED)||defined(YUNHORN_STS_R5_ENABLED)||defined(YUNHORN_STS_R1_ENABLED))
tstbuf[i++] = (uint8_t) (count)&0xff;
//MX_TOF_Process();
STS_TOF_VL53L0X_Range_Process();
#ifdef TOF_1
tstbuf[i++] = (uint8_t) ((sts_tof_distance_data[0] >>8 ) &0xff);
tstbuf[i++] = (uint8_t) (sts_tof_distance_data[0] &0xff);
#endif
#ifdef TOF_2
tstbuf[i++] = (uint8_t) ((sts_tof_distance_data[1] >>8 ) &0xff);
tstbuf[i++] = (uint8_t) (sts_tof_distance_data[1] &0xff);
#endif
#ifdef TOF_3
tstbuf[i++] = (uint8_t) ((sts_tof_distance_data[2] >>8 ) &0xff);
tstbuf[i++] = (uint8_t) (sts_tof_distance_data[2] &0xff);
#endif
#endif
}
//memset((void*)outbuf,0x0, sizeof(outbuf));
UTIL_MEM_cpy_8((void*)outbuf, (void*)tstbuf, i);
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (uint8_t*)outbuf);
}
uint32_t STS_Get_Date_Time_Stamp(void)
{
struct tm localtime;
SysTime_t UnixEpoch = SysTimeGet();
UnixEpoch.Seconds -= 18; /*removing leap seconds*/
SysTimeLocalTime(UnixEpoch.Seconds, &localtime);
APP_LOG(TS_OFF, VLEVEL_M, "UTC TIME:%02dh%02dm%02ds on %02d/%02d/%04d\r\n",
localtime.tm_hour, localtime.tm_min, localtime.tm_sec,
localtime.tm_mday, localtime.tm_mon + 1, localtime.tm_year + 1900);
return (uint32_t)UnixEpoch.Seconds;
}