A demo application for HXC900 LoRaWAN module using Nucleo-L053R8.

Dependencies:   mbed

Committer:
fahadmirza
Date:
Mon Dec 10 19:54:23 2018 +0000
Revision:
31:174c745f921c
Parent:
30:c58316bab0fb
Child:
32:2d0678039a09
FWversion and battery level are added to the payload from the application layer instead of from the lora driver;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fahadmirza 0:a0c5877bd360 1 /*
fahadmirza 0:a0c5877bd360 2 _ _ _____ _______
fahadmirza 0:a0c5877bd360 3 | | | | |_ _| |__ __|
fahadmirza 0:a0c5877bd360 4 | |__| | __ ___ __ | | ___ | |
fahadmirza 0:a0c5877bd360 5 | __ |/ _` \ \/ / | | / _ \| |
fahadmirza 0:a0c5877bd360 6 | | | | (_| |> < _| || (_) | |
fahadmirza 0:a0c5877bd360 7 |_| |_|\__,_/_/\_\_____\___/|_|
fahadmirza 0:a0c5877bd360 8 (C)2017 HaxIoT
fahadmirza 0:a0c5877bd360 9 */
fahadmirza 0:a0c5877bd360 10 /*******************************************************************************
fahadmirza 0:a0c5877bd360 11 * @File : lora_driver.c
fahadmirza 0:a0c5877bd360 12 * @Author : Fahad Mirza (Haxiot)
fahadmirza 0:a0c5877bd360 13 * @Version : V1.0.0
fahadmirza 24:f3b987589609 14 * @Modified: 18 October, 2018
fahadmirza 0:a0c5877bd360 15 * @Brief : LoRa Driver
fahadmirza 0:a0c5877bd360 16 ******************************************************************************
fahadmirza 0:a0c5877bd360 17 * @attention
fahadmirza 0:a0c5877bd360 18 *
fahadmirza 0:a0c5877bd360 19 * <h2><center>&copy; COPYRIGHT(c) 2017 Haxiot</center></h2>
fahadmirza 0:a0c5877bd360 20 *
fahadmirza 0:a0c5877bd360 21 * Redistribution and use in source and binary forms, with or without modification,
fahadmirza 0:a0c5877bd360 22 * are permitted provided that the following conditions are met:
fahadmirza 0:a0c5877bd360 23 * 1. Redistributions of source code must retain the above copyright notice,
fahadmirza 0:a0c5877bd360 24 * this list of conditions and the following disclaimer.
fahadmirza 0:a0c5877bd360 25 * 2. Redistributions in binary form must reproduce the above copyright notice,
fahadmirza 0:a0c5877bd360 26 * this list of conditions and the following disclaimer in the documentation
fahadmirza 0:a0c5877bd360 27 * and/or other materials provided with the distribution.
fahadmirza 0:a0c5877bd360 28 * 3. Neither the name of Haxiot nor the names of its contributors
fahadmirza 0:a0c5877bd360 29 * may be used to endorse or promote products derived from this software
fahadmirza 0:a0c5877bd360 30 * without specific prior written permission.
fahadmirza 0:a0c5877bd360 31 *
fahadmirza 0:a0c5877bd360 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
fahadmirza 0:a0c5877bd360 33 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
fahadmirza 0:a0c5877bd360 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
fahadmirza 0:a0c5877bd360 35 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
fahadmirza 0:a0c5877bd360 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
fahadmirza 0:a0c5877bd360 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
fahadmirza 0:a0c5877bd360 38 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
fahadmirza 0:a0c5877bd360 39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
fahadmirza 0:a0c5877bd360 40 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
fahadmirza 0:a0c5877bd360 41 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
fahadmirza 0:a0c5877bd360 42 *
fahadmirza 0:a0c5877bd360 43 ******************************************************************************
fahadmirza 0:a0c5877bd360 44 */
fahadmirza 0:a0c5877bd360 45 /* Includes ------------------------------------------------------------------*/
fahadmirza 0:a0c5877bd360 46 #include <stdio.h>
fahadmirza 0:a0c5877bd360 47 #include "hxc_client.h"
fahadmirza 0:a0c5877bd360 48 #include "debug.h"
fahadmirza 0:a0c5877bd360 49 #include "stm32l0xx_nucleo.h"
fahadmirza 0:a0c5877bd360 50 #include "time_server.h"
fahadmirza 0:a0c5877bd360 51 #include "lora_driver.h"
fahadmirza 0:a0c5877bd360 52 #include "tiny_sscanf.h"
fahadmirza 0:a0c5877bd360 53 #include "utilities.h"
fahadmirza 0:a0c5877bd360 54
fahadmirza 0:a0c5877bd360 55 /* Private Macros ------------------------------------------------------------*/
fahadmirza 0:a0c5877bd360 56 #define JOIN_SEND_DELAY_MAX (10000U) // Randomization range - 10s
fahadmirza 0:a0c5877bd360 57 #define JOIN_STATUS_REQ_DELAY (7000U) // milliseconds. Join req takes 6s.
fahadmirza 0:a0c5877bd360 58
fahadmirza 17:e682a18c3914 59 // Re Authenticate every REJOIN_TIME
fahadmirza 25:50414f44a431 60 #define REJOIN_TIME (1 * 60 * 60 * 1000U) // 1 hour
fahadmirza 17:e682a18c3914 61
fahadmirza 0:a0c5877bd360 62 /* Private global variables --------------------------------------------------*/
fahadmirza 0:a0c5877bd360 63 static sLoraConfig_t *LoraConfigParam;
fahadmirza 0:a0c5877bd360 64 static sLoraDriverParam_t *LoraDriverParam;
fahadmirza 26:176e648c03f6 65 static volatile eDeviceState_t DeviceState = CLIENT_INIT;
fahadmirza 0:a0c5877bd360 66
fahadmirza 0:a0c5877bd360 67 static TimerEvent_t JoinRequestTimer;
fahadmirza 17:e682a18c3914 68 static TimerEvent_t RejoinTimer;
fahadmirza 0:a0c5877bd360 69 static TimerEvent_t SensorMeasureTimer;
fahadmirza 0:a0c5877bd360 70 static TimerEvent_t NucleoLedTimer;
fahadmirza 0:a0c5877bd360 71 static TimerEvent_t JoinStatusDelayTimer;
fahadmirza 0:a0c5877bd360 72
fahadmirza 0:a0c5877bd360 73 // Object definition for data to be sent to loRa application server
fahadmirza 27:517ca3a30ad7 74 static uint8_t DataBinaryBuff[MAX_PAYLOAD_SIZE];
fahadmirza 0:a0c5877bd360 75 static sSendDataBinary_t SendDataBinary = {DataBinaryBuff, 0 , 0, 0};
fahadmirza 0:a0c5877bd360 76
fahadmirza 0:a0c5877bd360 77 // RNG handler declaration
fahadmirza 0:a0c5877bd360 78 RNG_HandleTypeDef RngHandle = {.Instance = RNG};
fahadmirza 0:a0c5877bd360 79
fahadmirza 0:a0c5877bd360 80 /* Private functions ---------------------------------------------------------*/
fahadmirza 17:e682a18c3914 81 static void OnRejoinTimerEvent(void);
fahadmirza 10:19da323c2bc0 82 static void OnLedTimerEvent(void);
fahadmirza 10:19da323c2bc0 83 static void OnJoinRequestTimerEvt(void);
fahadmirza 10:19da323c2bc0 84 static void OnJoinStatusDelayTimerEvt(void);
fahadmirza 10:19da323c2bc0 85 static void OnSensorMeasureTimerEvt(void);
fahadmirza 0:a0c5877bd360 86 static void setJoinRequestTimer(void);
fahadmirza 0:a0c5877bd360 87
fahadmirza 0:a0c5877bd360 88
fahadmirza 0:a0c5877bd360 89 /* Function definitions ------------------------------------------------------*/
fahadmirza 0:a0c5877bd360 90 /******************************************************************************
fahadmirza 0:a0c5877bd360 91 * @Brief : Initialize LoRa Modem
fahadmirza 0:a0c5877bd360 92 * @Param : sLoraConfig_t
fahadmirza 16:2179ec24dff8 93 * @Return : None
fahadmirza 0:a0c5877bd360 94 ******************************************************************************/
fahadmirza 0:a0c5877bd360 95 void Lora_init(sLoraConfig_t *loraConfig, sLoraDriverParam_t *loraDriverParam)
fahadmirza 0:a0c5877bd360 96 {
fahadmirza 0:a0c5877bd360 97
fahadmirza 0:a0c5877bd360 98 LoraConfigParam = loraConfig;
fahadmirza 0:a0c5877bd360 99 LoraDriverParam = loraDriverParam;
fahadmirza 0:a0c5877bd360 100
fahadmirza 0:a0c5877bd360 101 if(Modem_Init() != AT_OK)
fahadmirza 0:a0c5877bd360 102 {
fahadmirza 0:a0c5877bd360 103 DBG_PRINTF("Modem_Init failed\r\n");
fahadmirza 0:a0c5877bd360 104 }
fahadmirza 0:a0c5877bd360 105
fahadmirza 0:a0c5877bd360 106 // Initialize RNG for join request send randomization
fahadmirza 0:a0c5877bd360 107 HAL_RNG_Init(&RngHandle);
fahadmirza 0:a0c5877bd360 108
fahadmirza 0:a0c5877bd360 109
fahadmirza 0:a0c5877bd360 110 // Timer for join request send
fahadmirza 10:19da323c2bc0 111 TimerInit(&JoinRequestTimer, OnJoinRequestTimerEvt);
fahadmirza 0:a0c5877bd360 112 // Timer for join status check
fahadmirza 10:19da323c2bc0 113 TimerInit(&JoinStatusDelayTimer, OnJoinStatusDelayTimerEvt);
fahadmirza 0:a0c5877bd360 114 // Timer for sensor occurrence measure
fahadmirza 10:19da323c2bc0 115 TimerInit(&SensorMeasureTimer, OnSensorMeasureTimerEvt);
fahadmirza 0:a0c5877bd360 116 // Timer for Nucleo LED
fahadmirza 10:19da323c2bc0 117 TimerInit(&NucleoLedTimer, OnLedTimerEvent);
fahadmirza 17:e682a18c3914 118 // Timer for Re Authenticate / Join
fahadmirza 17:e682a18c3914 119 TimerInit(&RejoinTimer, OnRejoinTimerEvent);
fahadmirza 0:a0c5877bd360 120 }
fahadmirza 0:a0c5877bd360 121
fahadmirza 0:a0c5877bd360 122 /******************************************************************************
fahadmirza 0:a0c5877bd360 123 * @Brief : Check if the modem responds
fahadmirza 0:a0c5877bd360 124 * @Param : void
fahadmirza 0:a0c5877bd360 125 * @Return : AT_OK or other eAtStatus_t
fahadmirza 0:a0c5877bd360 126 ******************************************************************************/
fahadmirza 0:a0c5877bd360 127 static eAtStatus_t is_modem_working(void)
fahadmirza 0:a0c5877bd360 128 {
fahadmirza 0:a0c5877bd360 129 return Modem_AT_Cmd(AT_CTRL, AT, NULL);
fahadmirza 0:a0c5877bd360 130 }
fahadmirza 0:a0c5877bd360 131
fahadmirza 0:a0c5877bd360 132 /******************************************************************************
fahadmirza 0:a0c5877bd360 133 * @Brief : Set Device EUI
fahadmirza 0:a0c5877bd360 134 * @Param : Pointer to Device EUI
fahadmirza 0:a0c5877bd360 135 * @Return : AT_OK or other eAtStatus_t
fahadmirza 0:a0c5877bd360 136 ******************************************************************************/
fahadmirza 10:19da323c2bc0 137 static eAtStatus_t Lora_setDevEui(char *devEui)
fahadmirza 0:a0c5877bd360 138 {
fahadmirza 0:a0c5877bd360 139 return Modem_AT_Cmd(AT_SET, AT_DEVEUI, devEui);
fahadmirza 0:a0c5877bd360 140 }
fahadmirza 0:a0c5877bd360 141
fahadmirza 0:a0c5877bd360 142 /******************************************************************************
fahadmirza 27:517ca3a30ad7 143 * @Brief : Print Device EUI
fahadmirza 27:517ca3a30ad7 144 * @Param : None
fahadmirza 27:517ca3a30ad7 145 * @Retval : AT_OK or other eAtStatus_t
fahadmirza 27:517ca3a30ad7 146 ******************************************************************************/
fahadmirza 27:517ca3a30ad7 147 static void Lora_printDevEui(void)
fahadmirza 27:517ca3a30ad7 148 {
fahadmirza 27:517ca3a30ad7 149 char deveui_str[25];
fahadmirza 27:517ca3a30ad7 150
fahadmirza 27:517ca3a30ad7 151 Modem_AT_Cmd(AT_GET, AT_DEVEUI, deveui_str);
fahadmirza 27:517ca3a30ad7 152
fahadmirza 27:517ca3a30ad7 153 DBG_PRINTF("DevEui: %s\n", deveui_str);
fahadmirza 27:517ca3a30ad7 154 }
fahadmirza 27:517ca3a30ad7 155
fahadmirza 27:517ca3a30ad7 156 /******************************************************************************
fahadmirza 2:1ef859bc5cd2 157 * @Brief : Turn on or off ADR
fahadmirza 2:1ef859bc5cd2 158 * @Param : ADR_ON or ADR_OFF
fahadmirza 2:1ef859bc5cd2 159 * @Return : AT_OK or other eAtStatus_t
fahadmirza 2:1ef859bc5cd2 160 ******************************************************************************/
fahadmirza 10:19da323c2bc0 161 static eAtStatus_t Lora_setAdr(eAdrStatus_t adrStatus)
fahadmirza 2:1ef859bc5cd2 162 {
fahadmirza 2:1ef859bc5cd2 163 //char adr = (adrStatus == ADR_ON ? '1' : '0');
fahadmirza 2:1ef859bc5cd2 164 return Modem_AT_Cmd(AT_SET, AT_ADR, (uint8_t *)(&adrStatus));
fahadmirza 2:1ef859bc5cd2 165 }
fahadmirza 2:1ef859bc5cd2 166
fahadmirza 2:1ef859bc5cd2 167 /******************************************************************************
fahadmirza 0:a0c5877bd360 168 * @Brief : Set Application EUI
fahadmirza 0:a0c5877bd360 169 * @Param : Pointer to Application EUI
fahadmirza 0:a0c5877bd360 170 * @Return : AT_OK or other eAtStatus_t
fahadmirza 0:a0c5877bd360 171 ******************************************************************************/
fahadmirza 10:19da323c2bc0 172 static eAtStatus_t Lora_setAppEui(char *appEui)
fahadmirza 0:a0c5877bd360 173 {
fahadmirza 0:a0c5877bd360 174 return Modem_AT_Cmd(AT_SET, AT_APPEUI, appEui);
fahadmirza 0:a0c5877bd360 175 }
fahadmirza 0:a0c5877bd360 176
fahadmirza 0:a0c5877bd360 177 /******************************************************************************
fahadmirza 0:a0c5877bd360 178 * @Brief : Set Application Key
fahadmirza 0:a0c5877bd360 179 * @Param : Pointer to Application Key
fahadmirza 0:a0c5877bd360 180 * @Return : AT_OK or other eAtStatus_t
fahadmirza 0:a0c5877bd360 181 ******************************************************************************/
fahadmirza 10:19da323c2bc0 182 static eAtStatus_t Lora_setAppKey(char *appKey)
fahadmirza 0:a0c5877bd360 183 {
fahadmirza 0:a0c5877bd360 184 return Modem_AT_Cmd(AT_SET, AT_APPKEY, appKey);
fahadmirza 0:a0c5877bd360 185 }
fahadmirza 0:a0c5877bd360 186
fahadmirza 0:a0c5877bd360 187 /******************************************************************************
fahadmirza 0:a0c5877bd360 188 * @Brief : Set join mode
fahadmirza 0:a0c5877bd360 189 * @Param : OTAA or ABP
fahadmirza 0:a0c5877bd360 190 * @Retval : AT_OK if successful, otherwise other eAtStatus_t
fahadmirza 0:a0c5877bd360 191 ******************************************************************************/
fahadmirza 10:19da323c2bc0 192 static eAtStatus_t Lora_setJoinMode(eJoinMode_t joinMode)
fahadmirza 0:a0c5877bd360 193 {
fahadmirza 0:a0c5877bd360 194 if(joinMode == OTAA)
fahadmirza 0:a0c5877bd360 195 {
fahadmirza 0:a0c5877bd360 196 return Modem_AT_Cmd(AT_SET, AT_NJM, "OTAA");
fahadmirza 0:a0c5877bd360 197 }
fahadmirza 0:a0c5877bd360 198
fahadmirza 0:a0c5877bd360 199 return Modem_AT_Cmd(AT_SET, AT_NJM, "ABP");
fahadmirza 0:a0c5877bd360 200 }
fahadmirza 0:a0c5877bd360 201
fahadmirza 0:a0c5877bd360 202 /******************************************************************************
fahadmirza 0:a0c5877bd360 203 * @Brief : Set Class
fahadmirza 0:a0c5877bd360 204 * @Param : CLASS_A or CLASS_C
fahadmirza 0:a0c5877bd360 205 * @Retval : AT_OK if successful, otherwise other eAtStatus_t
fahadmirza 0:a0c5877bd360 206 ******************************************************************************/
fahadmirza 10:19da323c2bc0 207 static eAtStatus_t Lora_setClass(char class)
fahadmirza 0:a0c5877bd360 208 {
fahadmirza 0:a0c5877bd360 209 return Modem_AT_Cmd(AT_SET, AT_CLASS, &class);
fahadmirza 0:a0c5877bd360 210 }
fahadmirza 0:a0c5877bd360 211
fahadmirza 0:a0c5877bd360 212 /******************************************************************************
fahadmirza 0:a0c5877bd360 213 * @Brief : Join network and initiate join sleep transition timer
fahadmirza 0:a0c5877bd360 214 * @Param : None
fahadmirza 0:a0c5877bd360 215 * @Retval : AT_OK or other eAtStatus_t
fahadmirza 0:a0c5877bd360 216 ******************************************************************************/
fahadmirza 0:a0c5877bd360 217 static eAtStatus_t Lora_Join(void)
fahadmirza 0:a0c5877bd360 218 {
fahadmirza 0:a0c5877bd360 219 return Modem_AT_Cmd(AT_CTRL, AT_JOIN, NULL);
fahadmirza 0:a0c5877bd360 220 }
fahadmirza 0:a0c5877bd360 221
fahadmirza 0:a0c5877bd360 222 /******************************************************************************
fahadmirza 0:a0c5877bd360 223 * @Brief : Check JOIN status
fahadmirza 0:a0c5877bd360 224 * @Param : None
fahadmirza 0:a0c5877bd360 225 * @Retval : JOINED or NOT_JOINED
fahadmirza 0:a0c5877bd360 226 ******************************************************************************/
fahadmirza 0:a0c5877bd360 227 static eJoinStatus_t Lora_getJoinStatus(void)
fahadmirza 0:a0c5877bd360 228 {
fahadmirza 0:a0c5877bd360 229 char joinStatus[12]; // "NOT JOINED" is 10 characters + 1 Null char
fahadmirza 0:a0c5877bd360 230
fahadmirza 0:a0c5877bd360 231 Modem_AT_Cmd(AT_GET, AT_NJS, joinStatus);
fahadmirza 0:a0c5877bd360 232
fahadmirza 0:a0c5877bd360 233 if(strncmp("JOINED", joinStatus, 6) == 0)
fahadmirza 0:a0c5877bd360 234 {
fahadmirza 0:a0c5877bd360 235 return JOINED;
fahadmirza 0:a0c5877bd360 236 }
fahadmirza 0:a0c5877bd360 237
fahadmirza 0:a0c5877bd360 238 return NOT_JOINED;
fahadmirza 0:a0c5877bd360 239 }
fahadmirza 0:a0c5877bd360 240
fahadmirza 0:a0c5877bd360 241 /******************************************************************************
fahadmirza 28:c777d977b252 242 * @Brief : Get firmware version
fahadmirza 28:c777d977b252 243 * @Param : None
fahadmirza 28:c777d977b252 244 * @Retval : Integer firmware version
fahadmirza 28:c777d977b252 245 ******************************************************************************/
fahadmirza 31:174c745f921c 246 uint8_t Lora_getFwVersion(void)
fahadmirza 28:c777d977b252 247 {
fahadmirza 28:c777d977b252 248 char fwVersion_str[5];
fahadmirza 28:c777d977b252 249 float fwVer_float;
fahadmirza 28:c777d977b252 250
fahadmirza 28:c777d977b252 251 eAtStatus_t status = Modem_AT_Cmd(AT_GET, AT_VER, fwVersion_str);
fahadmirza 28:c777d977b252 252
fahadmirza 28:c777d977b252 253 if(status != AT_OK)
fahadmirza 28:c777d977b252 254 {
fahadmirza 28:c777d977b252 255 return 0;
fahadmirza 28:c777d977b252 256 }
fahadmirza 28:c777d977b252 257
fahadmirza 28:c777d977b252 258 sscanf(fwVersion_str, "%f", &fwVer_float);
fahadmirza 28:c777d977b252 259 // This weird division was needed. Otherwise, because of
fahadmirza 28:c777d977b252 260 // the floating point calculation the result was rounded.
fahadmirza 28:c777d977b252 261 uint8_t fwVer_int = (uint8_t)(fwVer_float * 1000/10);
fahadmirza 28:c777d977b252 262
fahadmirza 28:c777d977b252 263 return fwVer_int;
fahadmirza 28:c777d977b252 264 }
fahadmirza 28:c777d977b252 265
fahadmirza 28:c777d977b252 266 /******************************************************************************
fahadmirza 29:b48f6176c2cd 267 * @Brief : Get battery level
fahadmirza 29:b48f6176c2cd 268 * @Param : None
fahadmirza 29:b48f6176c2cd 269 * @Retval : Battery level
fahadmirza 29:b48f6176c2cd 270 ******************************************************************************/
fahadmirza 31:174c745f921c 271 uint8_t Lora_getBatteryLevel(void)
fahadmirza 29:b48f6176c2cd 272 {
fahadmirza 29:b48f6176c2cd 273 char batteryLevel_str[5];
fahadmirza 29:b48f6176c2cd 274 uint8_t batteryLevel = 0;
fahadmirza 29:b48f6176c2cd 275
fahadmirza 29:b48f6176c2cd 276 eAtStatus_t status = Modem_AT_Cmd(AT_GET, AT_BAT, batteryLevel_str);
fahadmirza 29:b48f6176c2cd 277
fahadmirza 29:b48f6176c2cd 278 if(status == AT_OK)
fahadmirza 29:b48f6176c2cd 279 {
fahadmirza 29:b48f6176c2cd 280 sscanf(batteryLevel_str, "%hhu", &batteryLevel);
fahadmirza 29:b48f6176c2cd 281 }
fahadmirza 29:b48f6176c2cd 282
fahadmirza 29:b48f6176c2cd 283 return batteryLevel;
fahadmirza 29:b48f6176c2cd 284 }
fahadmirza 29:b48f6176c2cd 285
fahadmirza 29:b48f6176c2cd 286 /******************************************************************************
fahadmirza 0:a0c5877bd360 287 * @Brief : Send uplink packet using binary payload
fahadmirza 0:a0c5877bd360 288 * @Param : Pointer of sSendDataBinary_t variable
fahadmirza 0:a0c5877bd360 289 * @Retval : AT_OK or other eAtStatus_t statuses
fahadmirza 0:a0c5877bd360 290 ******************************************************************************/
fahadmirza 0:a0c5877bd360 291 static eAtStatus_t Lora_SendDataBinary(sSendDataBinary_t *binaryData)
fahadmirza 0:a0c5877bd360 292 {
fahadmirza 0:a0c5877bd360 293 return Modem_AT_Cmd(AT_SET, AT_SENDB, binaryData);
fahadmirza 0:a0c5877bd360 294 }
fahadmirza 0:a0c5877bd360 295
fahadmirza 0:a0c5877bd360 296 /******************************************************************************
fahadmirza 10:19da323c2bc0 297 * @Brief : Read the received downlink packet
fahadmirza 10:19da323c2bc0 298 * @Param : Pointer to sRecvDataBinary_t variable
fahadmirza 16:2179ec24dff8 299 * @Return : None
fahadmirza 10:19da323c2bc0 300 ******************************************************************************/
fahadmirza 10:19da323c2bc0 301 static void Lora_ReadData(sRecvDataBinary_t *receivedData)
fahadmirza 10:19da323c2bc0 302 {
fahadmirza 27:517ca3a30ad7 303 char receiveString[MAX_PAYLOAD_SIZE];
fahadmirza 10:19da323c2bc0 304
fahadmirza 10:19da323c2bc0 305 Modem_AT_Cmd(AT_GET, AT_RECVB, receiveString);
fahadmirza 10:19da323c2bc0 306
fahadmirza 10:19da323c2bc0 307 tiny_sscanf(receiveString, "%hhu,%hhu", &(receivedData->Ack), &(receivedData->Port));
fahadmirza 10:19da323c2bc0 308
fahadmirza 10:19da323c2bc0 309 // Find the position after the second comma
fahadmirza 10:19da323c2bc0 310 char *hexString = strchr((strchr(receiveString,',') + 1),',') + 1;
fahadmirza 10:19da323c2bc0 311
fahadmirza 27:517ca3a30ad7 312 receivedData->DataSize = stringHexToByteArray(hexString, receivedData->Buffer, MAX_PAYLOAD_SIZE);
fahadmirza 10:19da323c2bc0 313 }
fahadmirza 10:19da323c2bc0 314
fahadmirza 10:19da323c2bc0 315 /******************************************************************************
fahadmirza 10:19da323c2bc0 316 * @Brief : Change Lora_fsm() DeviceState
fahadmirza 10:19da323c2bc0 317 * @Param : Any of eDeviceState_t type
fahadmirza 10:19da323c2bc0 318 * @Return : None
fahadmirza 10:19da323c2bc0 319 ******************************************************************************/
fahadmirza 31:174c745f921c 320 static void Lora_ChangeDeviceState(eDeviceState_t newDeviceState)
fahadmirza 10:19da323c2bc0 321 {
fahadmirza 10:19da323c2bc0 322 //ToDo: Check for valid eDeviceState_t states
fahadmirza 10:19da323c2bc0 323 DeviceState = newDeviceState;
fahadmirza 10:19da323c2bc0 324 }
fahadmirza 10:19da323c2bc0 325
fahadmirza 10:19da323c2bc0 326 /******************************************************************************
fahadmirza 0:a0c5877bd360 327 * @Brief : LoRa Modem state machine
fahadmirza 0:a0c5877bd360 328 * @Param : Void
fahadmirza 0:a0c5877bd360 329 * @Return : None
fahadmirza 0:a0c5877bd360 330 ******************************************************************************/
fahadmirza 0:a0c5877bd360 331 void Lora_fsm(void)
fahadmirza 0:a0c5877bd360 332 {
fahadmirza 0:a0c5877bd360 333 switch(DeviceState)
fahadmirza 0:a0c5877bd360 334 {
fahadmirza 26:176e648c03f6 335 case CLIENT_INIT:
fahadmirza 0:a0c5877bd360 336 {
fahadmirza 0:a0c5877bd360 337 if(is_modem_working() != AT_OK)
fahadmirza 0:a0c5877bd360 338 {
fahadmirza 1:168a6afffbff 339 DBG_PRINTF("AT failed. Resetting HW...\r\n");
fahadmirza 0:a0c5877bd360 340 // Modem isn't responding. Execute hard reset.
fahadmirza 0:a0c5877bd360 341 Modem_HardReset();
fahadmirza 27:517ca3a30ad7 342 // We stay in CLIENT_INIT state and try again.
fahadmirza 0:a0c5877bd360 343 }
fahadmirza 0:a0c5877bd360 344 else
fahadmirza 0:a0c5877bd360 345 {
fahadmirza 26:176e648c03f6 346 DeviceState = CLIENT_CONFIG;
fahadmirza 0:a0c5877bd360 347 }
fahadmirza 0:a0c5877bd360 348
fahadmirza 0:a0c5877bd360 349 break;
fahadmirza 0:a0c5877bd360 350 }
fahadmirza 26:176e648c03f6 351 case CLIENT_CONFIG:
fahadmirza 0:a0c5877bd360 352 {
fahadmirza 24:f3b987589609 353 eAtStatus_t loraModemRetCode = Lora_setDevEui(LoraConfigParam->DevEui);
fahadmirza 24:f3b987589609 354 loraModemRetCode |= Lora_setAppEui(LoraConfigParam->AppEui);
fahadmirza 24:f3b987589609 355 loraModemRetCode |= Lora_setAppKey(LoraConfigParam->AppKey);
fahadmirza 24:f3b987589609 356 loraModemRetCode |= Lora_setJoinMode(LoraConfigParam->JoinMode);
fahadmirza 24:f3b987589609 357 loraModemRetCode |= Lora_setClass(LoraConfigParam->Class);
fahadmirza 28:c777d977b252 358 loraModemRetCode |= Lora_setAdr(LoraConfigParam->AdrStatus);
fahadmirza 0:a0c5877bd360 359
fahadmirza 0:a0c5877bd360 360 if(loraModemRetCode == AT_OK)
fahadmirza 0:a0c5877bd360 361 {
fahadmirza 28:c777d977b252 362 // If users use AUTO as Device EUI, print the DevEUI
fahadmirza 28:c777d977b252 363 // so that they can add that on X-ON
fahadmirza 28:c777d977b252 364 Lora_printDevEui();
fahadmirza 28:c777d977b252 365
fahadmirza 0:a0c5877bd360 366 setJoinRequestTimer();
fahadmirza 26:176e648c03f6 367 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 368 }
fahadmirza 0:a0c5877bd360 369 else if(loraModemRetCode == AT_TIMEOUT)
fahadmirza 0:a0c5877bd360 370 {
fahadmirza 26:176e648c03f6 371 DeviceState = CLIENT_INIT;
fahadmirza 0:a0c5877bd360 372 }
fahadmirza 0:a0c5877bd360 373 else
fahadmirza 0:a0c5877bd360 374 {
fahadmirza 0:a0c5877bd360 375 DBG_PRINTF("Check your keys\r\n");
fahadmirza 27:517ca3a30ad7 376 while(1);
fahadmirza 0:a0c5877bd360 377 }
fahadmirza 0:a0c5877bd360 378
fahadmirza 0:a0c5877bd360 379 break;
fahadmirza 0:a0c5877bd360 380 }
fahadmirza 26:176e648c03f6 381 case CLIENT_JOIN:
fahadmirza 0:a0c5877bd360 382 {
fahadmirza 1:168a6afffbff 383 DBG_PRINTF("Joining...\r\n");
fahadmirza 0:a0c5877bd360 384 // Indicate a Join request using Nucleo LED
fahadmirza 0:a0c5877bd360 385 BSP_LED_On(LED_GREEN);
fahadmirza 0:a0c5877bd360 386 TimerStart(&NucleoLedTimer, 200);
fahadmirza 0:a0c5877bd360 387
fahadmirza 0:a0c5877bd360 388 switch(Lora_Join())
fahadmirza 0:a0c5877bd360 389 {
fahadmirza 0:a0c5877bd360 390 case AT_OK:
fahadmirza 0:a0c5877bd360 391 {
fahadmirza 0:a0c5877bd360 392 // Start the Join status request timer and go to sleep
fahadmirza 0:a0c5877bd360 393 TimerStart(&JoinStatusDelayTimer, JOIN_STATUS_REQ_DELAY);
fahadmirza 26:176e648c03f6 394 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 395 break;
fahadmirza 0:a0c5877bd360 396 }
fahadmirza 0:a0c5877bd360 397 case AT_TIMEOUT:
fahadmirza 0:a0c5877bd360 398 {
fahadmirza 21:f1d561ed31a1 399 // The modem isn't responding. Execute hard reset
fahadmirza 26:176e648c03f6 400 DeviceState = CLIENT_INIT;
fahadmirza 0:a0c5877bd360 401 break;
fahadmirza 0:a0c5877bd360 402 }
fahadmirza 0:a0c5877bd360 403 default:
fahadmirza 0:a0c5877bd360 404 {
fahadmirza 0:a0c5877bd360 405 DBG_PRINTF("Join cmd failed\n");
fahadmirza 27:517ca3a30ad7 406 // We stay in CLIENT_JOIN state and redo Lora_Join()
fahadmirza 0:a0c5877bd360 407 break;
fahadmirza 0:a0c5877bd360 408 }
fahadmirza 0:a0c5877bd360 409 }
fahadmirza 0:a0c5877bd360 410
fahadmirza 0:a0c5877bd360 411 break;
fahadmirza 0:a0c5877bd360 412 }
fahadmirza 26:176e648c03f6 413 case CLIENT_JOIN_STATUS_CHECK:
fahadmirza 0:a0c5877bd360 414 {
fahadmirza 0:a0c5877bd360 415 if(Lora_getJoinStatus() == JOINED)
fahadmirza 0:a0c5877bd360 416 {
fahadmirza 12:f1fd61aa85e0 417 // Inidicate Join status using LED
fahadmirza 12:f1fd61aa85e0 418 GPIO_InitTypeDef GPIO_InitStruct;
fahadmirza 12:f1fd61aa85e0 419
fahadmirza 12:f1fd61aa85e0 420 GPIO_InitStruct.Pin = GPIO_PIN_6;
fahadmirza 12:f1fd61aa85e0 421 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
fahadmirza 12:f1fd61aa85e0 422 GPIO_InitStruct.Pull = GPIO_NOPULL;
fahadmirza 12:f1fd61aa85e0 423 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
fahadmirza 12:f1fd61aa85e0 424
fahadmirza 30:c58316bab0fb 425 GPIO_InitStruct.Pin = GPIO_PIN_7;
fahadmirza 30:c58316bab0fb 426 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
fahadmirza 30:c58316bab0fb 427 GPIO_InitStruct.Pull = GPIO_NOPULL;
fahadmirza 30:c58316bab0fb 428 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
fahadmirza 30:c58316bab0fb 429
fahadmirza 12:f1fd61aa85e0 430 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
fahadmirza 30:c58316bab0fb 431 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
fahadmirza 12:f1fd61aa85e0 432
fahadmirza 0:a0c5877bd360 433 DBG_PRINTF("Nwk Joined\n");
fahadmirza 17:e682a18c3914 434
fahadmirza 17:e682a18c3914 435 // Start timer for Re-Authentication
fahadmirza 17:e682a18c3914 436 TimerStart(&RejoinTimer, REJOIN_TIME);
fahadmirza 17:e682a18c3914 437
fahadmirza 0:a0c5877bd360 438 // Start timer for uplink transmission for sensor-data
fahadmirza 17:e682a18c3914 439 TimerStart(&SensorMeasureTimer, LoraDriverParam->SensorMeasureTime);
fahadmirza 26:176e648c03f6 440 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 441 }
fahadmirza 0:a0c5877bd360 442 else
fahadmirza 0:a0c5877bd360 443 {
fahadmirza 0:a0c5877bd360 444 // Try joining again
fahadmirza 0:a0c5877bd360 445 setJoinRequestTimer();
fahadmirza 26:176e648c03f6 446 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 447 }
fahadmirza 0:a0c5877bd360 448 break;
fahadmirza 0:a0c5877bd360 449 }
fahadmirza 26:176e648c03f6 450 case CLIENT_SLEEP:
fahadmirza 0:a0c5877bd360 451 {
fahadmirza 0:a0c5877bd360 452 /* Wake up through RTC events or asynchronous event coming from HXC modem*/
fahadmirza 0:a0c5877bd360 453 if(Modem_IsNewDataReceived() == true)
fahadmirza 0:a0c5877bd360 454 {
fahadmirza 26:176e648c03f6 455 DeviceState = CLIENT_DATA_RECEIVED;
fahadmirza 0:a0c5877bd360 456 }
fahadmirza 0:a0c5877bd360 457 break;
fahadmirza 0:a0c5877bd360 458 }
fahadmirza 26:176e648c03f6 459 case CLIENT_SEND:
fahadmirza 0:a0c5877bd360 460 {
fahadmirza 0:a0c5877bd360 461 // Read sensor data and populate payload
fahadmirza 31:174c745f921c 462 SendDataBinary.DataSize = LoraDriverParam->SendDataHandler(\
fahadmirza 31:174c745f921c 463 SendDataBinary.Buffer ,\
fahadmirza 31:174c745f921c 464 MAX_PAYLOAD_SIZE ,\
fahadmirza 31:174c745f921c 465 &SendDataBinary.Ack ,\
fahadmirza 31:174c745f921c 466 &SendDataBinary.Port );
fahadmirza 28:c777d977b252 467
fahadmirza 0:a0c5877bd360 468 // Initiate uplink transmission
fahadmirza 0:a0c5877bd360 469 eAtStatus_t status = Lora_SendDataBinary(&SendDataBinary);
fahadmirza 28:c777d977b252 470
fahadmirza 0:a0c5877bd360 471 if (status == AT_OK)
fahadmirza 0:a0c5877bd360 472 {
fahadmirza 25:50414f44a431 473 DBG_PRINTF("Uplink sent\n");
fahadmirza 0:a0c5877bd360 474 // Schedule the next packet
fahadmirza 25:50414f44a431 475 TimerStart(&SensorMeasureTimer, LoraDriverParam->SensorMeasureTime);
fahadmirza 26:176e648c03f6 476 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 477 }
fahadmirza 0:a0c5877bd360 478 else if(status == AT_TIMEOUT)
fahadmirza 0:a0c5877bd360 479 {
fahadmirza 0:a0c5877bd360 480 // Device isn't responding. Go to init.
fahadmirza 26:176e648c03f6 481 DeviceState = CLIENT_INIT;
fahadmirza 0:a0c5877bd360 482 }
fahadmirza 25:50414f44a431 483 else
fahadmirza 25:50414f44a431 484 {
fahadmirza 25:50414f44a431 485 DBG_PRINTF("Uplink Failed (Error: %d)\n", (uint8_t)status);
fahadmirza 25:50414f44a431 486 }
fahadmirza 0:a0c5877bd360 487
fahadmirza 0:a0c5877bd360 488 break;
fahadmirza 0:a0c5877bd360 489 }
fahadmirza 26:176e648c03f6 490 case CLIENT_DATA_RECEIVED:
fahadmirza 0:a0c5877bd360 491 {
fahadmirza 0:a0c5877bd360 492 uint8_t rBuffer[64];
fahadmirza 0:a0c5877bd360 493 sRecvDataBinary_t rxPacket = {.Buffer = rBuffer};
fahadmirza 0:a0c5877bd360 494
fahadmirza 0:a0c5877bd360 495 Lora_ReadData(&rxPacket);
fahadmirza 0:a0c5877bd360 496
fahadmirza 0:a0c5877bd360 497 // Execute users ReceivedPacketHandler function
fahadmirza 0:a0c5877bd360 498 LoraDriverParam->ReceiveDataHandler(rxPacket.Buffer, rxPacket.DataSize, rxPacket.Ack, rxPacket.Port);
fahadmirza 0:a0c5877bd360 499
fahadmirza 26:176e648c03f6 500 DeviceState = CLIENT_SLEEP;
fahadmirza 0:a0c5877bd360 501 break;
fahadmirza 0:a0c5877bd360 502 }
fahadmirza 0:a0c5877bd360 503 default:
fahadmirza 0:a0c5877bd360 504 {
fahadmirza 26:176e648c03f6 505 DeviceState = CLIENT_INIT;
fahadmirza 0:a0c5877bd360 506 break;
fahadmirza 0:a0c5877bd360 507 }
fahadmirza 0:a0c5877bd360 508 }
fahadmirza 0:a0c5877bd360 509 }
fahadmirza 0:a0c5877bd360 510
fahadmirza 16:2179ec24dff8 511 /******************************************************************************
fahadmirza 16:2179ec24dff8 512 * @Brief : Set Join request timer
fahadmirza 16:2179ec24dff8 513 * @Param : none
fahadmirza 16:2179ec24dff8 514 * @Return : none
fahadmirza 16:2179ec24dff8 515 ******************************************************************************/
fahadmirza 0:a0c5877bd360 516 static void setJoinRequestTimer(void)
fahadmirza 0:a0c5877bd360 517 {
fahadmirza 0:a0c5877bd360 518 // Use a random delay to avoid synchronized join request from all LoRa node after power up
fahadmirza 0:a0c5877bd360 519 uint32_t joinDelay = (HAL_RNG_GetRandomNumber(&RngHandle) % JOIN_SEND_DELAY_MAX) + 1;
fahadmirza 19:0c90e38fc9c5 520
fahadmirza 25:50414f44a431 521 TimerStart(&JoinRequestTimer, joinDelay);
fahadmirza 0:a0c5877bd360 522 }
fahadmirza 0:a0c5877bd360 523
fahadmirza 0:a0c5877bd360 524 /******************************************************************************
fahadmirza 0:a0c5877bd360 525 * @Brief : Function executed on JoinStatusDelayTimer Timeout event
fahadmirza 0:a0c5877bd360 526 * @Param : none
fahadmirza 0:a0c5877bd360 527 * @Return : none
fahadmirza 0:a0c5877bd360 528 ******************************************************************************/
fahadmirza 10:19da323c2bc0 529 static void OnJoinRequestTimerEvt(void)
fahadmirza 0:a0c5877bd360 530 {
fahadmirza 0:a0c5877bd360 531 TimerStop(&JoinRequestTimer);
fahadmirza 27:517ca3a30ad7 532
fahadmirza 27:517ca3a30ad7 533 // If this is a re-join SensorMeasureTimer is active
fahadmirza 27:517ca3a30ad7 534 TimerStop(&SensorMeasureTimer);
fahadmirza 27:517ca3a30ad7 535
fahadmirza 26:176e648c03f6 536 DeviceState = CLIENT_JOIN;
fahadmirza 0:a0c5877bd360 537 }
fahadmirza 0:a0c5877bd360 538
fahadmirza 0:a0c5877bd360 539 /******************************************************************************
fahadmirza 0:a0c5877bd360 540 * @Brief : Function executed on NucleoLedTimer Timeout event
fahadmirza 0:a0c5877bd360 541 * @Param : none
fahadmirza 0:a0c5877bd360 542 * @Return : none
fahadmirza 0:a0c5877bd360 543 ******************************************************************************/
fahadmirza 10:19da323c2bc0 544 static void OnLedTimerEvent(void)
fahadmirza 0:a0c5877bd360 545 {
fahadmirza 0:a0c5877bd360 546 TimerStop(&NucleoLedTimer);
fahadmirza 0:a0c5877bd360 547 BSP_LED_Off(LED_GREEN);
fahadmirza 0:a0c5877bd360 548 }
fahadmirza 0:a0c5877bd360 549
fahadmirza 0:a0c5877bd360 550 /******************************************************************************
fahadmirza 0:a0c5877bd360 551 * @Brief : Function executed on JoinStatusDelayTimer Timeout event
fahadmirza 0:a0c5877bd360 552 * @Param : none
fahadmirza 0:a0c5877bd360 553 * @Return : none
fahadmirza 0:a0c5877bd360 554 ******************************************************************************/
fahadmirza 10:19da323c2bc0 555 static void OnJoinStatusDelayTimerEvt(void)
fahadmirza 0:a0c5877bd360 556 {
fahadmirza 25:50414f44a431 557 TimerStop(&JoinStatusDelayTimer);
fahadmirza 26:176e648c03f6 558 DeviceState = CLIENT_JOIN_STATUS_CHECK;
fahadmirza 0:a0c5877bd360 559 }
fahadmirza 0:a0c5877bd360 560
fahadmirza 0:a0c5877bd360 561 /******************************************************************************
fahadmirza 0:a0c5877bd360 562 * @Brief : Function executed on SensorMeasureTimer Timeout event
fahadmirza 0:a0c5877bd360 563 * @Param : none
fahadmirza 0:a0c5877bd360 564 * @Return : none
fahadmirza 0:a0c5877bd360 565 ******************************************************************************/
fahadmirza 10:19da323c2bc0 566 static void OnSensorMeasureTimerEvt(void)
fahadmirza 0:a0c5877bd360 567 {
fahadmirza 25:50414f44a431 568 TimerStop(&SensorMeasureTimer);
fahadmirza 26:176e648c03f6 569 DeviceState = CLIENT_SEND;
fahadmirza 0:a0c5877bd360 570 }
fahadmirza 0:a0c5877bd360 571
fahadmirza 0:a0c5877bd360 572 /******************************************************************************
fahadmirza 17:e682a18c3914 573 * @Brief : Function executed on RejoinTimer Timeout event
fahadmirza 17:e682a18c3914 574 * @Param : none
fahadmirza 17:e682a18c3914 575 * @Return : none
fahadmirza 17:e682a18c3914 576 ******************************************************************************/
fahadmirza 17:e682a18c3914 577 static void OnRejoinTimerEvent(void)
fahadmirza 17:e682a18c3914 578 {
fahadmirza 27:517ca3a30ad7 579 TimerStop(&RejoinTimer);
fahadmirza 17:e682a18c3914 580 setJoinRequestTimer();
fahadmirza 17:e682a18c3914 581 }
fahadmirza 17:e682a18c3914 582
fahadmirza 17:e682a18c3914 583 /******************************************************************************
fahadmirza 0:a0c5877bd360 584 * @brief RNG MSP Initialization
fahadmirza 0:a0c5877bd360 585 * This function configures the hardware resources used in this example:
fahadmirza 0:a0c5877bd360 586 * - Peripheral's clock enable
fahadmirza 0:a0c5877bd360 587 * @param hrng: RNG handle pointer
fahadmirza 0:a0c5877bd360 588 * @retval None
fahadmirza 0:a0c5877bd360 589 ******************************************************************************/
fahadmirza 0:a0c5877bd360 590 void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
fahadmirza 0:a0c5877bd360 591 {
fahadmirza 0:a0c5877bd360 592 /* RNG Peripheral clock enable */
fahadmirza 0:a0c5877bd360 593 __HAL_RCC_RNG_CLK_ENABLE();
fahadmirza 0:a0c5877bd360 594 }
fahadmirza 0:a0c5877bd360 595
fahadmirza 0:a0c5877bd360 596