/* 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" /* 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 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, 0x00,0x05,'M',0x03,0x08,0x04,0x02}; #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; #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 */ /* 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 ((uint32_t)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); /* 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_TIMER; //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; /* 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_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); APP_LOG(TS_OFF, VLEVEL_M,"\r\n\n ========================== V12 =======================\r\n"); /* 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); /* 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 */ 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); STS_REBOOT_CONFIG_Init(); /* 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: 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_L, "\r\n(3) Vibration Sensor EXTI Event BUT3 3 3 3 \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 */ } void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) { uint8_t i=0; char outbuf[64]=""; /* * 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" STS_SENSOR_Function_Test_Process(); } 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 'V': //"YV" if ((char)tlv_buf[CFG_CMD3] == 'H') { // "YVH" REPORT FIRMWARE VERSION "YVH" // FIRMWARE VERSION REPORT 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]=""; OnRestoreSTSCFGContextRequest((uint8_t *)cfg_in_nvm); 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_PERIODICITY_H]; //Periodicity count high outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_PERIODICITY_L]; //Periodicity count low outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_UNIT]; //Periodicity unit outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN]; //length of following cfg value for (uint8_t j=1; j <= cfg_in_nvm[NVM_LEN]; 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_L, "###### 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; } else if ((char)tlv_buf[CFG_CMD5] == 'S') { if (periodicity_length < 10) periodicity_length = 10; } OnTxPeriodicityChanged(periodicity_length*1000); //translate to 1000ms=1s 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 = 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.periodicity_h = (tlv_buf[CFG_CMD3]-0x30); sts_cfg_nvm.periodicity_l = (tlv_buf[CFG_CMD4]-0x30); if (((char)tlv_buf[CFG_CMD5] == 'S') && (periodicity_length == 10)) { sts_cfg_nvm.periodicity_h = 0X01; sts_cfg_nvm.periodicity_l = 0X00; } sts_cfg_nvm.unit = periodicity_unit; 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 >= 4)) // 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 += (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 += (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 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; // 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; OnStoreSTSCFGContextRequest(); } else { // Invalid parameters // Step 1/2: Prepare status update message STS_SENSOR_Upload_Config_Invalid_Message(); APP_LOG(TS_OFF, VLEVEL_L, "###### 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 { 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"); } 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 0) { APP_LOG(TS_ON, VLEVEL_L, "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; 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_M, "###### 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 = 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_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); 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(periodicity_length*1000); APP_LOG(TS_OFF, VLEVEL_L, "\r\n==================== Tx Periodicity changed to = %d second(s) \r\n", (int)periodicity_length); } 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 */ /* 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 (HAL_FLASH_Unlock() == HAL_OK) { if (FLASH_IF_EraseByPages(PAGE(LORAWAN_NVM_BASE_ADDRESS), 1, 0U) == FLASH_OK) { FLASH_IF_Write(LORAWAN_NVM_BASE_ADDRESS, (uint8_t *)nvm, nvm_size, NULL); } HAL_FLASH_Lock(); } /* 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 */ UTIL_MEM_cpy_8(nvm, (void *)LORAWAN_NVM_BASE_ADDRESS, nvm_size); /* USER CODE BEGIN OnRestoreContextRequest_Last */ /* USER CODE END OnRestoreContextRequest_Last */ } void OnStoreSTSCFGContextRequest(void) { /* USER CODE BEGIN OnStoreContextRequest_1 */ uint8_t i=0, nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]="", nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE; #ifdef YUNHORN_STS_M7_ENABLED sts_cfg_nvm.length = (uint8_t) NVM_CFG_PARAMETER_SIZE; nvm_store_value[i++] = (uint8_t) sts_mtmcode1; nvm_store_value[i++] = (uint8_t) sts_mtmcode2; nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.version; nvm_store_value[i++] = (uint8_t) sts_hardware_ver; nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.periodicity_h; nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.periodicity_l; nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.unit; nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.length; for (uint8_t j=0;j< NVM_CFG_PARAMETER_SIZE; j++) { nvm_store_value[i+j] = (uint8_t) (sts_cfg_nvm.p[j]); } #endif #ifdef YUNHORN_STS_O0_ENABLED #endif #ifdef YUNHORN_STS_R0_ENABLED #endif /* USER CODE END OnStoreContextRequest_1 */ /* store nvm in flash */ if (HAL_FLASH_Unlock() == HAL_OK) { if (FLASH_IF_EraseByPages(PAGE(STS_CONFIG_NVM_BASE_ADDRESS), 1, 0U) == FLASH_OK) { FLASH_IF_Write(STS_CONFIG_NVM_BASE_ADDRESS, nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE, NULL); } HAL_FLASH_Lock(); } /* 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]="", 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[0] == 0xFF) || (nvm_stored_value[1] == 0xFF) ||(nvm_stored_value[2] == 0xFF)) { APP_LOG(TS_OFF, VLEVEL_L, "Initial Boot with Empty Config, Flash with default config....\r\n"); OnStoreSTSCFGContextRequest(); } 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_h = (uint8_t)(nvm_stored_value[NVM_PERIODICITY_H]); sts_cfg_nvm.periodicity_l = (uint8_t)(nvm_stored_value[NVM_PERIODICITY_L]); sts_cfg_nvm.unit = (uint8_t)(nvm_stored_value[NVM_UNIT]); sts_cfg_nvm.length = (uint8_t)(nvm_stored_value[NVM_LEN]&0x1F); //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+1+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_h)*10+(sts_cfg_nvm.periodicity_l); 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); } #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]; 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); }