1813 lines
59 KiB
C
1813 lines
59 KiB
C
/* USER CODE BEGIN Header */
|
|
/**
|
|
******************************************************************************
|
|
* @file lora_app.c
|
|
* @author MCD Application Team
|
|
* @brief Application of the LRWAN Middleware
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* Copyright (c) 2021 STMicroelectronics.
|
|
* 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 "lora_app_version.h"
|
|
#include "lorawan_version.h"
|
|
#include "subghz_phy_version.h"
|
|
#include "lora_info.h"
|
|
#include "LmHandler.h"
|
|
#include "stm32_lpm.h"
|
|
#include "adc_if.h"
|
|
#include "CayenneLpp.h"
|
|
#include "sys_sensors.h"
|
|
#include "flash_if.h"
|
|
|
|
/* USER CODE BEGIN Includes */
|
|
#include "yunhorn_sts_sensors.h"
|
|
#include "yunhorn_sts_motion_sensor.h"
|
|
#include "sts_cmox_hmac_sha.h"
|
|
/* USER CODE END Includes */
|
|
|
|
/* External variables ---------------------------------------------------------*/
|
|
/* USER CODE BEGIN EV */
|
|
volatile uint8_t mems_int1_detected = 0;
|
|
volatile uint32_t periodicity_length=0;
|
|
volatile uint8_t sts_service_mask;
|
|
volatile uint32_t rfac_timer=0;
|
|
extern hmac_result_t hmac_result;
|
|
volatile uint8_t sts_work_mode =0;
|
|
volatile uint8_t sts_ac_code[YUNHORN_STS_AC_CODE_SIZE]={0x0};
|
|
volatile uint8_t heart_beat_timer=0, sts_lorawan_joined=0;
|
|
volatile sts_cfg_nvm_t sts_cfg_nvm={sts_mtmcode1,sts_mtmcode2, sts_version, sts_hardware_ver,
|
|
0x3C,'M', 0x60,'M', 0x04,0x00,0x00,0x20,
|
|
{0x0,0x0,0x0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
|
|
0x01,0x03,0x00,0x02,
|
|
{0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF}
|
|
};
|
|
volatile uint32_t SamplingPeriodicity = 1000; //unit ms
|
|
volatile uint32_t HeartBeatPeriodicity = 3600000; //unit ms
|
|
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
extern volatile uint8_t sensor_data_ready;
|
|
extern volatile STS_M7_SensorDataTypeDef sts_m7_sensorData;
|
|
extern volatile uint8_t act_threshold, inact_threshold, inact_duration, do_fft_flag;
|
|
#endif
|
|
char outbuf[64]="";
|
|
/* 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 */
|
|
|
|
/* 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 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 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 Heart Beat callback function
|
|
* @param context ptr of STS Sampling Check context
|
|
*/
|
|
static void OnYunhornSTSHeartBeatTimerEvent(void *context);
|
|
|
|
|
|
/**
|
|
* @brief Yunhorn STS Uploading Message periodically
|
|
* @param context ptr of context
|
|
*/
|
|
//static void OnYunhornSTSUploadingMessageEvent(void *context);
|
|
|
|
/**
|
|
* @brief Yunhorn RFAC 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,
|
|
.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,
|
|
.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_EVENT; //TX_ON_EVENT; //TX_ON_TIMER
|
|
|
|
/**
|
|
* @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;
|
|
|
|
/**
|
|
* @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_H, "\r\n\n\n##### YUNHORN_STS_FW:%d SWV%d HWV:%d MTM:%d.%d R:%d.%d.%d####\r\n\n\n",
|
|
FirmwareVersion, 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);
|
|
|
|
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);
|
|
|
|
/* 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 */
|
|
|
|
STS_REBOOT_CONFIG_Init();
|
|
|
|
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), UTIL_SEQ_RFU, STS_MOTION_SENSOR_WakeUp_Process);
|
|
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), UTIL_SEQ_RFU, STS_SENSOR_Function_Test_Process);
|
|
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventRFAC), UTIL_SEQ_RFU, STS_YunhornSTSEventRFAC_Process);
|
|
|
|
|
|
UTIL_TIMER_Create(&YunhornSTSHeartBeatTimer, HeartBeatPeriodicity, UTIL_TIMER_ONESHOT, OnYunhornSTSHeartBeatTimerEvent, NULL);
|
|
UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer);
|
|
/* 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(USE_STM32WLE5)
|
|
case MEMS_EXTI2_Pin:
|
|
//APP_LOG(TS_OFF, VLEVEL_M, "\r\n(3) Vibration Sensor EXTI 2 Event \r\n"); //YUNHORN_STS_TODO
|
|
break;
|
|
#endif
|
|
|
|
#if defined(USE_STM32WL55)
|
|
HAL_Delay(150); //for de-bouncing eliminate
|
|
mems_int1_detected=1;
|
|
/* Note: when "EventType == TX_ON_TIMER" this GPIO is not initialized */
|
|
if (EventType == TX_ON_EVENT)
|
|
{
|
|
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), CFG_SEQ_Prio_0);
|
|
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n(1) Vibration Sensor EXTI Event BUT1 1 \r\n"); //YUNHORN_STS_TODO
|
|
mems_int1_detected=0;
|
|
}
|
|
|
|
break;
|
|
#endif
|
|
|
|
#if defined(USE_STM32WL55)
|
|
case BUT3_Pin:
|
|
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaStopJoinEvent), CFG_SEQ_Prio_0);
|
|
//mems_int1_detected=1;
|
|
// UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0);
|
|
//APP_LOG(TS_OFF, VLEVEL_M, "\r\n(1) Vibration Sensor EXTI Event BUT2 2 2 \r\n"); //YUNHORN_STS_TODO
|
|
|
|
break;
|
|
#endif
|
|
#if defined(USE_STM32WLE5)
|
|
case MEMS_EXTI1_Pin:
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n(3) Vibration Sensor EXTI 1 Event \r\n"); //YUNHORN_STS_TODO
|
|
mems_int1_detected=1;
|
|
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), CFG_SEQ_Prio_0);
|
|
|
|
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), 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)
|
|
{
|
|
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); /* LED_BLUE */
|
|
|
|
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;
|
|
}
|
|
}
|
|
break;
|
|
case LORAWAN_USER_APP_PORT:
|
|
if (appData->BufferSize == 1)
|
|
{
|
|
AppLedStateOn = (appData->Buffer[0] -0x30) & 0x01;
|
|
if (AppLedStateOn == RESET)
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_H, "LED OFF\r\n");
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
|
|
}
|
|
else
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_H, "LED ON\r\n");
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); /* LED_RED */
|
|
}
|
|
}
|
|
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 */
|
|
}
|
|
|
|
/**
|
|
* @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);
|
|
UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer);
|
|
|
|
if ((sts_lorawan_joined ) && (sts_ac_code[0]==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);
|
|
}
|
|
}
|
|
|
|
void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size)
|
|
{
|
|
uint8_t i=0;
|
|
|
|
|
|
/*
|
|
* YUNHORN STS PRODUCT BOARD LEVEL CONTROL OR REPORT
|
|
*/
|
|
|
|
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, "!YunHorn STS Revive!");
|
|
HAL_Delay(5000);
|
|
|
|
OnSystemReset();
|
|
} else if ((char)tlv_buf[CFG_CMD3] == 'S') { // Self Function Testing "YZS"
|
|
i=0;
|
|
memset(outbuf,0x30,sizeof(outbuf));
|
|
|
|
STS_SENSOR_Function_Test_Process();
|
|
|
|
HAL_Delay(5000);
|
|
i=21;
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
|
|
} else if ((char)tlv_buf[CFG_CMD3] == 'C') { // Self Function Testing "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, outbuf);
|
|
}
|
|
break;
|
|
case 'M': //"YM"
|
|
if ((char)tlv_buf[CFG_CMD3] >= '0' && (char)tlv_buf[CFG_CMD3]<='9') // Service Mask "YZM"
|
|
{
|
|
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, outbuf);
|
|
//APP_LOG(TS_OFF, VLEVEL_H, ">>>>>>>>>>>>>>>>>>>>> Mask = [ %02x ] \r\n", sts_service_mask);
|
|
OnStoreSTSCFGContextRequest();
|
|
#ifdef YUNHORN_STS_O6_ENABLED
|
|
if (sts_service_mask != STS_SERVICE_MASK_L0) STS_Lamp_Bar_Set_Dark();
|
|
STS_Combined_Status_Processing();
|
|
#endif
|
|
}
|
|
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) FirmwareVersion;
|
|
outbuf[i++] = (uint8_t) MajorVer;
|
|
outbuf[i++] = (uint8_t) MinorVer;
|
|
outbuf[i++] = (uint8_t) SubMinorVer;
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
//APP_LOG(TS_OFF, VLEVEL_L, "###### YUNHORN Report Version [ %10x ] \r\n", 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]={0x0};
|
|
OnRestoreSTSCFGContextRequest((uint8_t *)cfg_in_nvm);
|
|
i = 0;
|
|
memset(outbuf,0x30,sizeof(outbuf));
|
|
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_RESERVE01]; //service mask
|
|
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN]; //length of following cfg value
|
|
|
|
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN+1];
|
|
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN+2];
|
|
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN+3];
|
|
outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN+4];
|
|
|
|
// for (uint8_t j=0; j < 4; j++) {
|
|
// outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_LEN+j]);
|
|
// }
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
//APP_LOG(TS_OFF, VLEVEL_H, "###### YUNHORN Report Config in NVM [ %10x ] \r\n", 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));
|
|
i=0;
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD1];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD2];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD3];
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, 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));
|
|
i=0;
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD1];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD2];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD3];
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, 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) {
|
|
STS_SENSOR_MEMS_Reset((tlv_buf[CFG_CMD3]-0x30));
|
|
i=0;
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD1];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD2];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD3];
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
} else {
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
}
|
|
break;
|
|
|
|
case 'D':
|
|
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'))))
|
|
{
|
|
periodicity_length = (tlv_buf[CFG_CMD3]-0x30)*10+ (tlv_buf[CFG_CMD4]-0x30);
|
|
uint8_t periodicity_unit = (char)tlv_buf[CFG_CMD5];
|
|
if ((char)tlv_buf[CFG_CMD5] == 'M') {
|
|
periodicity_length *= 60;
|
|
} else if ((char)tlv_buf[CFG_CMD5] == 'H') {
|
|
periodicity_length *= 3600;
|
|
}
|
|
TxPeriodicity = periodicity_length*1000; //translate to 1000ms=1s
|
|
HeartBeatPeriodicity = TxPeriodicity;
|
|
|
|
OnTxPeriodicityChanged(TxPeriodicity);
|
|
i = 0;
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD1];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD2];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD3];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD4];
|
|
outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD5];
|
|
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, 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_L, "###### YUNHORN Periodicity Changed to [ %d ] Seconds\r\n", periodicity_length);
|
|
|
|
} else {
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
break;
|
|
}
|
|
} // 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
|
|
*/
|
|
|
|
uint8_t tlv_h2_cnt = 0x00, mems_ver=0x00;
|
|
i = P_MEM_CFG; //start of parameter
|
|
|
|
switch (tlv_buf[P_MEMS_NO]-0x30) { //#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
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
mems_ver = (tlv_buf[P_MTM_VER]-0x30); // #2 MTM-ver
|
|
if (mems_ver == sts_version) { // Firmware version or Variation of MEMS/component
|
|
if (tlv_buf_size == CFG_CMD_PARAMETER_SIZE) { //Validation check
|
|
act_threshold = (uint8_t) (tlv_buf[i++]-0x30)*10; // "P 1 0 0 8" -> 0*10
|
|
act_threshold += (uint8_t) (tlv_buf[i++]-0x30); // "P 1 0 0 8" -> 0*10 + 8
|
|
inact_threshold = (uint8_t) (tlv_buf[i++]-0x30)*10; // "P 1 0 0 8 0 4" -> 0*10
|
|
inact_threshold += (uint8_t) (tlv_buf[i++]-0x30); // "P 1 0 0 8 0 4" -> 0*10 + 4
|
|
inact_duration = (uint8_t) (tlv_buf[i++]-0x30)*10; // "P 1 0 0 8 0 4 0 3" -> 0*10
|
|
inact_duration += (uint8_t) (tlv_buf[i++]-0x30); // "P 1 0 0 8 0 4 0 3" -> 0*10+3
|
|
do_fft_flag = (uint8_t) (tlv_buf[i++]-0x30); // "P 1 0 0 8 0 4 0 3 1" fft flag
|
|
|
|
if (act_threshold <= inact_threshold)
|
|
act_threshold += 2;
|
|
}
|
|
|
|
STS_MOTION_SENSOR_ACT_INACT_DURATION_Init();
|
|
|
|
i=0; // Step 1: Prepare status update message
|
|
outbuf[i++] = (char) 'P';
|
|
outbuf[i++] = sts_mtmcode1;
|
|
outbuf[i++] = sts_mtmcode2;
|
|
outbuf[i++] = sts_version;
|
|
outbuf[i++] = sts_hardware_ver;
|
|
outbuf[i++] = (uint8_t) act_threshold;
|
|
outbuf[i++] = (uint8_t) inact_threshold;
|
|
outbuf[i++] = (uint8_t) inact_duration;
|
|
outbuf[i++] = (uint8_t) do_fft_flag;
|
|
|
|
// 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.length = NVM_CFG_PARAMETER_SIZE;
|
|
|
|
sts_cfg_nvm.p[0] = (uint8_t) act_threshold;
|
|
sts_cfg_nvm.p[1] = (uint8_t) inact_threshold;
|
|
sts_cfg_nvm.p[2] = (uint8_t) inact_duration;
|
|
sts_cfg_nvm.p[3] = (uint8_t) do_fft_flag;
|
|
|
|
|
|
OnStoreSTSCFGContextRequest();
|
|
|
|
} else { // Invalid parameters
|
|
// Step 1/2: Prepare status update message
|
|
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
APP_LOG(TS_OFF, VLEVEL_H, "###### MTM VER Invalid or Mismatch\r\n");
|
|
}
|
|
#endif
|
|
// Step 3: Upload status update message
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
|
|
#if defined(YUNHORN_STS_R1_ENABLED) || defined(YUNHORN_STS_R2_ENABLED)|| defined(YUNHORN_STS_R3_ENABLED) || defined(YUNHORN_STS_R5_ENABLED)
|
|
#endif
|
|
#ifdef YUNHORN_STS_O1_ENABLED
|
|
#endif
|
|
|
|
break;
|
|
|
|
// for multipul 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 reedswitch or hall elements
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
// for multipul sensor heads or MEMS components, TODO 2022-10-21 PARK HERE
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
break;
|
|
}
|
|
} 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)
|
|
|
|
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))
|
|
{
|
|
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;
|
|
for (uint8_t j=0; j <(tlv_buf_size) ; j++) {
|
|
outbuf[i++] = (uint8_t) tlv_buf[j];
|
|
}
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, (char*)outbuf);
|
|
|
|
} else {
|
|
STS_SENSOR_Upload_Config_Invalid_Message();
|
|
}
|
|
|
|
} // END OF USER_APP_AUTO_RESPONDER_Parse
|
|
|
|
void STS_SENSOR_Upload_Config_Invalid_Message(void)
|
|
{
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 5, "PVXXX");
|
|
}
|
|
|
|
static void STS_YUNHORN_RFAC_HANDLE_PROCESS(void)
|
|
{
|
|
|
|
STS_YunhornAuthenticationCode_Process();
|
|
|
|
}
|
|
|
|
void STS_SENSOR_Upload_Message(uint8_t appDataPort, uint8_t appBufferSize, char *appDataBuffer)
|
|
{
|
|
LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
|
|
UTIL_TIMER_Time_t nextTxIn = 0;
|
|
|
|
for (uint8_t i=0;i<appBufferSize; i++) {
|
|
AppData.Buffer[i] = appDataBuffer[i];
|
|
}
|
|
AppData.Port = appDataPort;
|
|
AppData.BufferSize = appBufferSize;
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void STS_SENSOR_Auto_Responder_Process(uint8_t tlv_ver,uint8_t tlv_type, uint8_t tlv_length, uint8_t *tlv_content)
|
|
{
|
|
uint8_t sensor_mems_type=(tlv_content[0]-0x30); //sensor_mems_type defined in sts_sensors.h
|
|
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
uint8_t fm_version = FirmwareVersion; //MajorVer+MinorVer+SubMinorVer;
|
|
|
|
#endif
|
|
|
|
switch (sensor_mems_type)
|
|
{
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
case sts_mtmcode2:
|
|
//TODO
|
|
break;
|
|
#endif
|
|
#ifdef YUNHORN_STS_R0_ENABLED
|
|
case STS_CTRL_CMD_MEMS_TUNE_TOF_VL53L0X:
|
|
|
|
break;
|
|
#endif
|
|
#ifdef YUNHORN_STS_P1_ENABLED
|
|
case STS_CTRL_CMD_MEMS_TUNE_FMCW_TI68X:
|
|
|
|
break;
|
|
#endif
|
|
#ifdef YUNHORN_STS_OO_ENABLED
|
|
case STS_CTRL_CMD_MEMS_TUNE_PCR_A12X:
|
|
|
|
break;
|
|
|
|
case STS_CTRL_CMD_PRESENCE_SETTING:
|
|
|
|
break;
|
|
#endif
|
|
#ifdef YUNHORN_STS_M3_ENABLED
|
|
case STS_CTRL_CMD_MEMS_TUNE_DIGITAL_RELAY:
|
|
|
|
break;
|
|
#endif
|
|
#ifdef YUNHORN_STS_M5_ENABLED
|
|
case STS_CTRL_CMD_MEMS_TUNE_FAN_CONTROL:
|
|
|
|
break;
|
|
#endif
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void SendTxData(void)
|
|
{
|
|
/* USER CODE BEGIN SendTxData_1 */
|
|
LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
|
|
uint8_t batteryLevel = GetBatteryLevel();
|
|
// sensor_t sensor_data;
|
|
STS_M7_SensorDataTypeDef m7_data;
|
|
UTIL_TIMER_Time_t nextTxIn = 0;
|
|
// APP_LOG(TS_ON, VLEVEL_H, "\r\n Flag: Heart-beat-timer = %u \r\n sensor_data_ready = %u \r\n",
|
|
// heart_beat_timer, sensor_data_ready);
|
|
|
|
uint32_t i = 0;
|
|
|
|
//EnvSensors_Read(&sensor_data);
|
|
STS_MOTION_SENSOR_Read(&m7_data);
|
|
|
|
AppData.Port = LORAWAN_USER_APP_PORT;
|
|
AppData.Buffer[i++] = AppLedStateOn; //#0
|
|
|
|
//if (sensor_data_ready == 0L) return ;
|
|
if (heart_beat_timer != 0U)
|
|
{
|
|
heart_beat_timer = 0U;
|
|
AppData.Port = YUNHORN_STS_M7_LORA_APP_HTBT_PORT;
|
|
AppData.Buffer[i++] = (uint8_t)(99*batteryLevel/254); //#01
|
|
}
|
|
if (sensor_data_ready !=0U)
|
|
{
|
|
sensor_data_ready = 0U;
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & sts_mtmcode1); //mtmcode1; //#01
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & sts_mtmcode2); //mtmcode2; //#02
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & sts_hardware_ver); //hardware_Ver; //#03
|
|
AppData.Buffer[i++] = (uint8_t)(99*batteryLevel/254); //#04 /* 99% (very low) to 254 (fully charged) */
|
|
AppData.Buffer[i++] = 0x0D; //temp //#05
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vibration_duration); //06
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_x_freq >> 8); //07 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_x_freq); //08 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_y_freq >> 8); //09 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_y_freq); //10 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_z_freq >> 8); //11 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_z_freq); //12 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_x_rms >> 8 ); //13 Freq Max 256 Hz Given sample rate & FFT Length 512
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_x_rms); //14
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_y_rms >> 8); //15
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_y_rms); //16
|
|
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_z_rms >>8 ); //17
|
|
AppData.Buffer[i++] = (uint8_t)(0xFF & m7_data.vb_z_rms); //18
|
|
|
|
|
|
|
|
APP_LOG(TS_OFF, VLEVEL_H, "###### Duration: %02d seconds | FREQ_X:%d Hz | FREQ_Y:%d Hz | FREQ_Z:%d Hz |\r\n###### | RMS_X:%d | RMS_Y:%d | RMS_Z:%d | BATTERY_B:%02d%% |\r\n",
|
|
AppData.Buffer[6], (AppData.Buffer[7]*255+AppData.Buffer[8]), (AppData.Buffer[9]*255+AppData.Buffer[10]), (AppData.Buffer[11]*255+AppData.Buffer[12]),
|
|
(AppData.Buffer[13]*255+AppData.Buffer[14]),(AppData.Buffer[15]*255+AppData.Buffer[16]),(AppData.Buffer[17]*255+AppData.Buffer[18]),AppData.Buffer[04]);
|
|
}
|
|
|
|
/*
|
|
if ((LmHandlerParams.ActiveRegion == LORAMAC_REGION_US915) || (LmHandlerParams.ActiveRegion == LORAMAC_REGION_AU915)
|
|
|| (LmHandlerParams.ActiveRegion == LORAMAC_REGION_AS923))
|
|
{ }
|
|
else
|
|
{ }
|
|
|
|
*/
|
|
|
|
AppData.BufferSize = (sts_service_mask >1?0:i);
|
|
|
|
if ((JoinLedTimer.IsRunning) && (LmHandlerJoinStatus() == LORAMAC_HANDLER_SET))
|
|
{
|
|
UTIL_TIMER_Stop(&JoinLedTimer);
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
|
|
}
|
|
if (i>1)
|
|
{
|
|
status = LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed, false);
|
|
if (LORAMAC_HANDLER_SUCCESS == status)
|
|
{
|
|
APP_LOG(TS_ON, VLEVEL_L, "SEND REQUEST\r\n");
|
|
}
|
|
else if (LORAMAC_HANDLER_DUTYCYCLE_RESTRICTED == status)
|
|
{
|
|
nextTxIn = LmHandlerGetDutyCycleWaitTime();
|
|
if (nextTxIn > 0)
|
|
{
|
|
APP_LOG(TS_ON, VLEVEL_L, "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 */
|
|
heart_beat_timer = 1U;
|
|
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)
|
|
{
|
|
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); /* LED_GREEN */
|
|
}
|
|
|
|
static void OnRxTimerLedEvent(void *context)
|
|
{
|
|
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); /* LED_BLUE */
|
|
}
|
|
|
|
static void OnJoinTimerLedEvent(void *context)
|
|
{
|
|
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin); /* LED_RED */
|
|
}
|
|
|
|
/* USER CODE END PrFD_LedEvents */
|
|
|
|
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)
|
|
{
|
|
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); /* LED_GREEN */
|
|
UTIL_TIMER_Start(&TxLedTimer);
|
|
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### ========== MCPS-Confirm =============\r\n");
|
|
APP_LOG(TS_OFF, VLEVEL_M, "###### U/L FRAME:%04d | PORT:%d | DR:%d | PWR:%d", params->UplinkCounter,
|
|
params->AppData.Port, params->Datarate, params->TxPower);
|
|
|
|
APP_LOG(TS_OFF, VLEVEL_M, " | MSG TYPE:");
|
|
if (params->MsgType == LORAMAC_HANDLER_CONFIRMED_MSG)
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_M, "CONFIRMED [%s]\r\n", (params->AckReceived != 0) ? "ACK" : "NACK");
|
|
}
|
|
else
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_M, "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);
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); /* LED_RED */
|
|
|
|
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_lorawan_joined = (uint8_t) joinParams->Mode;
|
|
OnTxPeriodicityChanged(HeartBeatPeriodicity);
|
|
APP_LOG(TS_OFF, VLEVEL_H, "\r\n==================== Tx Periodicity changed to = %d (ms) \r\n", (int)HeartBeatPeriodicity);
|
|
}
|
|
else
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n###### = JOIN FAILED\r\n");
|
|
}
|
|
}
|
|
/* 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 OnClassChange(DeviceClass_t deviceClass)
|
|
{
|
|
/* USER CODE BEGIN OnClassChange_1 */
|
|
APP_LOG(TS_OFF, VLEVEL_M, "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,"\r\n TxPeriodicity changed to %u (msec) \r\n", TxPeriodicity);
|
|
/* 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 */
|
|
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 */
|
|
/* 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 */
|
|
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 */
|
|
/* 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 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_M,"**************** HeartBeatPeriodicity Changed to: %u (ms)\r\n", HeartBeatPeriodicity );
|
|
/* USER CODE END OnTxPeriodicityChanged_2 */
|
|
}
|
|
|
|
void OnStoreSTSCFGContextRequest(void)
|
|
{
|
|
/* USER CODE BEGIN OnStoreContextRequest_1 */
|
|
uint8_t i=0, j=0, nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0}, nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE;
|
|
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
sts_cfg_nvm.length = STS_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.reseve01;
|
|
nvm_store_value[i++] = (uint8_t) STS_NVM_CFG_SIZE; //sts_cfg_nvm.length;
|
|
|
|
for (j = 0; j < STS_CFG_PCFG_SIZE; j++) {
|
|
nvm_store_value[i++] = (sts_cfg_nvm.p[j]);
|
|
}
|
|
|
|
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_detection_reserve;
|
|
nvm_store_value[i++] = sts_cfg_nvm.occupancy_overtime_threshold;
|
|
|
|
for (j = 0; j < YUNHORN_STS_AC_CODE_SIZE; j++) {
|
|
nvm_store_value[i++] = (sts_cfg_nvm.ac[j]);
|
|
}
|
|
#endif
|
|
|
|
#ifdef YUNHORN_STS_O0_ENABLED
|
|
|
|
#endif
|
|
|
|
#ifdef YUNHORN_STS_R0_ENABLED
|
|
|
|
#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 */
|
|
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
|
|
|
|
|
|
#endif
|
|
/* USER CODE END OnStoreContextRequest_Last */
|
|
}
|
|
|
|
void OnRestoreSTSCFGContextRequest(uint8_t *cfg_in_nvm)
|
|
{
|
|
/* USER CODE BEGIN OnRestoreSTSCFGContextRequest_1 */
|
|
uint8_t i=0, nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]="", nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE;
|
|
|
|
/* USER CODE END OnRestoreSTSCFGContextRequest_1 */
|
|
UTIL_MEM_cpy_8(nvm_store_value, (void *)STS_CONFIG_NVM_BASE_ADDRESS, nvm_store_size);
|
|
/* USER CODE BEGIN OnRestoreSTSCFGContextRequest_Last */
|
|
|
|
memcpy(cfg_in_nvm, nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE);
|
|
/*
|
|
APP_LOG(TS_OFF, VLEVEL_M, "CFG IN NVM =%02x %02x %02x %02x \r\n",
|
|
cfg_in_nvm[0],cfg_in_nvm[1],cfg_in_nvm[2],cfg_in_nvm[3]);
|
|
*/
|
|
/* USER CODE END OnRestoreSTSCFGContextRequest_Last */
|
|
}
|
|
|
|
|
|
void STS_REBOOT_CONFIG_Init(void)
|
|
{
|
|
/* USER CODE BEGIN OnRestoreContextRequest_1 */
|
|
uint8_t i=0, nvm_stored_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0}, nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE;
|
|
|
|
/* USER CODE END OnRestoreContextRequest_1 */
|
|
UTIL_MEM_cpy_8(nvm_stored_value, (void *)STS_CONFIG_NVM_BASE_ADDRESS, nvm_store_size);
|
|
/* USER CODE BEGIN OnRestoreContextRequest_Last */
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
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, "\r\nInitial 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.periodicity = (uint8_t)(nvm_stored_value[NVM_PERIODICITY]); //TxPeriodicity interval
|
|
sts_cfg_nvm.unit = (uint8_t)(nvm_stored_value[NVM_UNIT]);
|
|
sts_cfg_nvm.sampling = (uint8_t)(nvm_stored_value[NVM_SAMPLING]); //Heart-beat or sampling interval
|
|
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.reseve01 = (uint8_t)(nvm_stored_value[NVM_RESERVE01]);
|
|
sts_cfg_nvm.length = (uint8_t)(nvm_stored_value[NVM_LEN]&0x3F); //MAX 32 bytes
|
|
|
|
for (uint8_t j=0; j< sts_cfg_nvm.length; j++) {
|
|
sts_cfg_nvm.p[j] = (uint8_t)nvm_stored_value[NVM_LEN+j];
|
|
}
|
|
|
|
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_detection_reserve = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_RESERVE];
|
|
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
|
|
|
|
#ifdef YUNHORN_STS_O0_ENABLED
|
|
|
|
#endif
|
|
|
|
#ifdef YUNHORN_STS_R0_ENABLED
|
|
|
|
#endif
|
|
|
|
OnRestoreSTSCFGContextProcess();
|
|
|
|
/* USER CODE END OnRestoreContextRequest_Last */
|
|
}
|
|
|
|
void OnRestoreSTSCFGContextProcess(void)
|
|
{
|
|
periodicity_length = (sts_cfg_nvm.periodicity);
|
|
if ((char)sts_cfg_nvm.unit =='M') {
|
|
periodicity_length *= 60;
|
|
} else if ((char) sts_cfg_nvm.unit =='H') {
|
|
periodicity_length *= 3600;
|
|
} else if ((char) sts_cfg_nvm.unit =='S') {
|
|
periodicity_length *= 1;
|
|
}
|
|
|
|
periodicity_length = (periodicity_length>10)? periodicity_length : 10;
|
|
if (sts_lorawan_joined)
|
|
{
|
|
OnTxPeriodicityChanged(periodicity_length*1000);
|
|
} else
|
|
{
|
|
OnTxPeriodicityChanged(TxPeriodicity);
|
|
}
|
|
|
|
sts_work_mode = sts_cfg_nvm.work_mode;
|
|
sts_service_mask = sts_cfg_nvm.sts_service_mask;
|
|
|
|
for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++)
|
|
{
|
|
sts_ac_code[j] = sts_cfg_nvm.ac[j];
|
|
}
|
|
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
if ((sts_version == sts_cfg_nvm.version)&& (NVM_CFG_PARAMETER_SIZE == sts_cfg_nvm.length)) {
|
|
|
|
act_threshold = sts_cfg_nvm.p[0];
|
|
inact_threshold = sts_cfg_nvm.p[1];
|
|
inact_duration = sts_cfg_nvm.p[2];
|
|
do_fft_flag = sts_cfg_nvm.p[3];
|
|
|
|
STS_MOTION_SENSOR_ACT_INACT_DURATION_Init();
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
void STS_SENSOR_Function_Test_Process(void)
|
|
{
|
|
char outbuf[32] =""; uint8_t i=0, count=10;
|
|
uint8_t i2c_Slave_Dev_ID = 0x00;
|
|
|
|
outbuf[i++] = (uint8_t) 'S';
|
|
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 (STS_SENSOR_MEMS_Get_ID(&i2c_Slave_Dev_ID) == 0x00) {
|
|
outbuf[i++] = (uint8_t) 0X01; //SIZE OF FOLLOWING DATA
|
|
outbuf[i++] = (uint8_t) 'X'; // Slave MEMS Not Avaliable
|
|
} else
|
|
{
|
|
#ifdef YUNHORN_STS_M7_ENABLED
|
|
int16_t self_test_result[9]={0,0,0,0, 0,0,0, 0,0};
|
|
|
|
STS_MOTION_SENSOR_Function_Test_Process(&self_test_result[0], count);
|
|
|
|
outbuf[i++] = (uint8_t) 0X12; //SIZE OF FOLLOWING DATA
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[0]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[0])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[1]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[1])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[2]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[2])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[3]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[3])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[4]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[4])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[5]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[5])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[6]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[6])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[7]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[7])&0xff;
|
|
|
|
outbuf[i++] = (uint8_t) (self_test_result[8]>>8)&0xff;
|
|
outbuf[i++] = (uint8_t) (self_test_result[8])&0xff;
|
|
#endif
|
|
|
|
}
|
|
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf);
|
|
|
|
}
|
|
|
|
void STS_YunhornAuthenticationCode_Process(void)
|
|
{
|
|
if (sts_ac_code[0] == 0x00) {
|
|
APP_LOG(TS_OFF,VLEVEL_M, "Initial AC CODE blank... \r\n");
|
|
return;
|
|
}
|
|
|
|
sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0;
|
|
if (sts_service_mask == STS_SERVICE_MASK_L2) {
|
|
sts_ac_code[0] = 0x0;
|
|
}
|
|
APP_LOG(TS_OFF, VLEVEL_M, "STS_SERVICE_MASK:%d \r\n",sts_service_mask);
|
|
}
|
|
|
|
void STS_YunhornSTSEventRFAC_Process(void)
|
|
{
|
|
if (sts_ac_code[0] ==0x0)
|
|
{
|
|
if ((rfac_timer >= STS_BURN_IN_RFAC) && (rfac_timer < (STS_BURN_IN_RFAC +3)))
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n -------------------RFAC Process\r\n");
|
|
STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 4, "RFAC");
|
|
}
|
|
if ((rfac_timer > (STS_BURN_IN_RFAC + 2)))
|
|
{
|
|
APP_LOG(TS_OFF, VLEVEL_M, "\r\n -------------------Verify RFAC Success or Not\r\n");
|
|
sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0;
|
|
if (sts_service_mask == STS_SERVICE_MASK_L2) {
|
|
sts_ac_code[0] = 0x0;
|
|
}
|
|
}
|
|
}
|
|
|
|
} |