RadioShuttle Lib for the STM32 L4 Heltec Board
Dependents: Turtle_RadioShuttle
RadioTest.cpp
00001 /* 00002 * The file is Licensed under the Apache License, Version 2.0 00003 * (c) 2017 Helmut Tschemernjak 00004 * 30826 Garbsen (Hannover) Germany 00005 */ 00006 00007 #include "mbed.h" 00008 #include "PinMap.h" 00009 #include "sx1276-mbed-hal.h" 00010 #include "RadioShuttle.h" 00011 #include "RadioStatus.h" 00012 #include "RadioSecurity.h" 00013 #include "main.h" 00014 #ifdef FEATURE_NVPROPERTY 00015 #include <NVPropertyProviderInterface.h> 00016 #include "NVProperty.h" 00017 #endif 00018 00019 00020 #if defined(FEATURE_LORA) && defined(FEATURE_RADIOTEST) 00021 00022 #define CHECK_ERROR_RET(func, err) { \ 00023 if (err) { \ 00024 dprintf("Error in %s: %s", func, rs->StrError(err)); \ 00025 return err; \ 00026 } \ 00027 } 00028 00029 #ifndef TARGET_STM32L4 00030 #define RADIO_SERVER 1 00031 #endif 00032 00033 00034 bool usePassword = false; // password the can used indepenend of AES 00035 bool server; // automatically being set if radioTypeMode RadioShuttle::RS_Station_Basic 00036 bool useAES = false; // AES needs the usePassword option on 00037 const char *appPassword; 00038 00039 static const int myTempSensorApp = 0x0001; // Must be unique world wide. 00040 #ifdef RADIO_SERVER 00041 int myDeviceID = 1; 00042 int remoteDeviceID = 14; 00043 uint32_t myCode = 0; 00044 RadioShuttle::RadioType radioTypeMode = RadioShuttle::RS_Station_Basic; // 1 = RS_Node_Offline, 3 = RS_Node_Online, 4 = RS_Station_Basic 00045 #else 00046 int myDeviceID = 14; 00047 int remoteDeviceID = 1; 00048 uint32_t myCode = 0; 00049 RadioShuttle::RadioType radioTypeMode = RadioShuttle::RS_Node_Offline; // 1 = RS_Node_Offline, 3 = RS_Node_Online, 4 = RS_Station_Basic 00050 #endif 00051 00052 00053 /* 00054 * For details review: SX1276GenericLib/sx1276/sx1276.h 00055 * Supported spreading factors SF 7,8, 9, 10, 11, (12 does not work well) 00056 * Working frequencies using the 125000 bandwidth which leaves 00057 * sufficient distance to the neighbour channel 00058 * EU: 868.1, 868.3, 868.5 (Default LoRaWAN EU channels) 00059 * EU: 865.1, 865.3, 865.5, 865.7, 865.9 (additional channels) 00060 * EU: 866.1, 866.3, 866.5, 866.7, 866.9 (additional channels) 00061 * EU: 867.1, 867.3, 867.5, 867.7, 867.9 (additional channels) 00062 * Utilisation of these channels should not exceed 1% per hour per node 00063 * Bandwidth changes other than 125k requires different channels distances 00064 */ 00065 RadioShuttle::RadioProfile myProfile[] = { 00066 /* 00067 * Our default profile 00068 * frequency, bandwidth, TX power, spreading factor, frequency-offset 00069 */ 00070 { 868100000, 125000, 14, 7, 0 }, 00071 { 0, 0, 0, 0, 0 }, 00072 }; 00073 00074 00075 struct sensor { 00076 uint8_t version; 00077 uint8_t padding; 00078 uint16_t pm25; 00079 uint16_t pm10; 00080 uint16_t id; 00081 } PMAppData; 00082 00083 00084 void TempSensorRecvHandler(int AppID, RadioShuttle::devid_t stationID, int msgID, int status, void *buffer, int length) 00085 { 00086 switch(status) { 00087 case RadioShuttle::MS_SentCompleted: // A SendMsg has been sent. 00088 dprintf("MSG_SentCompleted: id=%d %d bytes", msgID, length); 00089 break; 00090 case RadioShuttle::MS_SentCompletedConfirmed:// A SendMsg has been sent and confirmed 00091 dprintf("MSG_SentCompletedConfirmed: id=%d %d bytes", msgID, length); 00092 break; 00093 case RadioShuttle::MS_SentTimeout: // A timeout occurred, number of retries exceeded 00094 dprintf("MSG_SentTimeout ID: %d", msgID); 00095 break; 00096 00097 case RadioShuttle::MS_RecvData: // a simple input message 00098 dprintf("MSG_RecvData ID: %d, len=%d", msgID, length); 00099 // dump("MSG_RecvData", buffer, length); 00100 #ifdef PM_SENSOR 00101 { 00102 struct sensor *p = (sensor *)buffer; 00103 if (length == sizeof(struct sensor) && p->version == 1) { 00104 dprintf("ParticalData: PM10: %.1f (μg/m3) PM2.5: %.1f (μg/m3) ID: %d", (float)p->pm10 / 10.0, (float)p->pm25 / 10.0, p->id); 00105 } 00106 } 00107 #endif 00108 break; 00109 case RadioShuttle::MS_RecvDataConfirmed: // received a confirmed message 00110 dprintf("MSG_RecvDataConfirmed ID: %d, len=%d", msgID, length); 00111 // dump("MSG_RecvDataConfirmed", buffer, length); 00112 break; 00113 case RadioShuttle::MS_NoStationFound: 00114 dprintf("MSG_NoStationFound"); 00115 break; 00116 case RadioShuttle::MS_NoStationSupportsApp: 00117 dprintf("MSG_NoStationSupportsApp"); 00118 break; 00119 case RadioShuttle::MS_AuthenicationRequired: // the password does not match. 00120 dprintf("MSG_AuthenicationRequired"); 00121 break; 00122 00123 case RadioShuttle::MS_StationConnected: // a confirmation that the connection was accepted 00124 dprintf("MSG_StationConnected"); 00125 break; 00126 case RadioShuttle::MS_StationDisconnected: // a confirmation that the disconnect was accepted 00127 dprintf("MSG_StationDisconnected"); 00128 break; 00129 default: 00130 break; 00131 } 00132 } 00133 00134 00135 Radio *radio; 00136 RadioShuttle *rs; 00137 RadioStatusInterface *statusIntf; 00138 RadioSecurityInterface *securityIntf; 00139 00140 int InitRadio() 00141 { 00142 Radio *radio; 00143 RSCode err; 00144 00145 #ifdef FEATURE_NVPROPERTY 00146 NVProperty prop; 00147 int value; 00148 00149 myDeviceID = prop.GetProperty(prop.LORA_DEVICE_ID, 0); 00150 myCode = prop.GetProperty(prop.LORA_CODE_ID, 0); 00151 if ((value = prop.GetProperty(prop.LORA_RADIO_TYPE, 0)) != 0) 00152 radioTypeMode = (RadioShuttle::RadioType)value; 00153 remoteDeviceID = 1; 00154 00155 if (myDeviceID == 0 || myCode == 0 || radioTypeMode == 0) { 00156 dprintf("LORA_DEVICE_ID or LORA_CODE_ID or LORA_RADIO_TYPE not set, use PropertyEditor to set this!"); 00157 return -1; 00158 } 00159 /* 00160 * Here are optional properties for custom settings 00161 */ 00162 if ((value = prop.GetProperty(prop.LORA_REMOTE_ID, 0)) != 0) 00163 remoteDeviceID = value; 00164 if ((value = prop.GetProperty(prop.LORA_FREQUENCY, 0)) != 0) 00165 myProfile[0].Frequency = value; 00166 if ((value = prop.GetProperty(prop.LORA_BANDWIDTH, 0)) != 0) 00167 myProfile[0].Bandwidth = value; 00168 if ((value = prop.GetProperty(prop.LORA_SPREADING_FACTOR, 0)) != 0) 00169 myProfile[0].SpreadingFaktor = value; 00170 if ((value = prop.GetProperty(prop.LORA_TXPOWER, 0)) != 0) 00171 myProfile[0].TXPower = value; 00172 if ((value = prop.GetProperty(prop.LORA_FREQUENCY_OFFSET, 0)) != 0) 00173 myProfile[0].FrequencyOffset = value; 00174 appPassword = prop.GetProperty(prop.LORA_APP_PWD, (const char *)NULL); 00175 #endif 00176 00177 if (radioTypeMode >= RadioShuttle::RS_Station_Basic) 00178 server = true; 00179 00180 #ifdef TARGET_DISCO_L072CZ_LRWAN1 00181 radio = new SX1276Generic(NULL, MURATA_SX1276, 00182 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00183 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00184 LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO); 00185 #elif defined(HELTECL432_REV1) 00186 radio = new SX1276Generic(NULL, HELTEC_L4_1276, 00187 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00188 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00189 LORA_ANT_PWR); 00190 #else // RFM95 00191 radio = new SX1276Generic(NULL, RFM95_SX1276, 00192 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00193 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00194 #endif 00195 00196 00197 statusIntf = new MyRadioStatus(); 00198 securityIntf = new RadioSecurity(); 00199 00200 rs = new RadioShuttle("MyRadioShuttle"); 00201 00202 rs->EnablePacketTrace(RadioShuttle::DEV_ID_ANY, true, true); 00203 00204 err = rs->AddLicense(myDeviceID, myCode); 00205 CHECK_ERROR_RET("AddLicense", err); 00206 00207 err = rs->AddRadio(radio, MODEM_LORA, myProfile); 00208 CHECK_ERROR_RET("AddRadio", err); 00209 dprintf("Radio: %.1f MHz, SF%d, %.f kHz", (float)myProfile[0].Frequency/1000000.0, myProfile[0].SpreadingFaktor, (float)myProfile[0].Bandwidth/1000.0); 00210 00211 rs->AddRadioStatus(statusIntf); 00212 CHECK_ERROR_RET("AddRadioStatus", err); 00213 00214 rs->AddRadioSecurity(securityIntf); 00215 CHECK_ERROR_RET("AddRadioSecurity", err); 00216 00217 /* 00218 * The password parameter can be NULL if no password is required 00219 */ 00220 err = rs->RegisterApplication(myTempSensorApp, &TempSensorRecvHandler, (void *)appPassword); 00221 CHECK_ERROR_RET("RegisterApplication", err); 00222 00223 if (server) { 00224 // usually RadioShuttle::RS_Station_Basic, set via properties 00225 err = rs->Startup(radioTypeMode); 00226 dprintf("Startup as a Server: %s ID=%d", rs->GetRadioName(rs->GetRadioType()), myDeviceID); 00227 } else { 00228 // usually RadioShuttle::RS_Node_Online or RadioShuttle, set via properties 00229 err = rs->Startup(radioTypeMode); 00230 dprintf("Startup as a Node: %s ID=%d", rs->GetRadioName(rs->GetRadioType()), myDeviceID); 00231 if (!err && rs->AppRequiresAuthentication(myTempSensorApp) == RS_PasswordSet) { 00232 err = rs->Connect(myTempSensorApp, remoteDeviceID); 00233 } 00234 } 00235 CHECK_ERROR_RET("Startup", err); 00236 return 0; 00237 } 00238 00239 void DeInitRadio() 00240 { 00241 if (securityIntf) { 00242 delete securityIntf; 00243 securityIntf = NULL; 00244 } 00245 if (statusIntf) { 00246 delete statusIntf; 00247 statusIntf = NULL; 00248 } 00249 if (rs) { 00250 delete rs; 00251 rs = NULL; 00252 } 00253 if (radio) { 00254 delete radio; 00255 radio = NULL; 00256 } 00257 } 00258 00259 /* 00260 * this is a example basic loop for RadioShuttle 00261 */ 00262 int RadioTest() 00263 { 00264 extern volatile int pressedCount; 00265 00266 if (InitRadio() != 0) 00267 return -1; 00268 00269 00270 for(;;) { 00271 static int cnt = 0; 00272 if (cnt != pressedCount) { 00273 if (cnt > 0) { 00274 int flags = 0; 00275 flags |= RadioShuttle::MF_NeedsConfirm; // optional 00276 if (useAES && appPassword) 00277 flags |= RadioShuttle::MF_Encrypted; 00278 if (server) { 00279 static char msg[] = "The server feels very good today"; 00280 rs->SendMsg(myTempSensorApp, msg, sizeof(msg), flags, remoteDeviceID); 00281 } else { 00282 static char msg[] = "Hello, the temperature is 26 celsius"; 00283 rs->SendMsg(myTempSensorApp, msg, sizeof(msg), flags, remoteDeviceID); 00284 } 00285 } 00286 cnt = pressedCount; 00287 } 00288 00289 if (rs->Idle() && rs->GetRadioType() == RadioShuttle::RS_Node_Offline) { 00290 sleep(); // uses deepsleep() when idle lowest power mode; 00291 } else { 00292 sleep(); // timer and radio interrupts will wakeup us 00293 } 00294 rs->RunShuttle(); // process all pending events 00295 } 00296 return 0; 00297 } 00298 00299 00300 int RadioUpdate(bool keyPressed) 00301 { 00302 if (!rs) 00303 return 0; 00304 00305 if (keyPressed) { 00306 int flags = 0; 00307 flags |= RadioShuttle::MF_NeedsConfirm; // optional 00308 if (usePassword && useAES) 00309 flags |= RadioShuttle::MF_Encrypted; 00310 if (server) { 00311 static char msg[] = "The server feels very good today"; 00312 rs->SendMsg(myTempSensorApp, msg, sizeof(msg), flags, remoteDeviceID); 00313 } else { 00314 static char msg[] = "Hello, the temperature is 26 celsius"; 00315 rs->SendMsg(myTempSensorApp, msg, sizeof(msg), flags, remoteDeviceID); 00316 } 00317 } 00318 rs->RunShuttle(); 00319 return 0; 00320 } 00321 00322 bool RadioISIdle() 00323 { 00324 if (!rs) 00325 return true; 00326 return rs->Idle(); 00327 } 00328 00329 void InitLoRaChipWithShutdown() 00330 { 00331 #ifdef LORA_CS 00332 if (LORA_CS == NC) 00333 return; 00334 #ifdef HELTECL432_REV1 00335 Radio *radio = new SX1276Generic(NULL, HELTEC_L4_1276, 00336 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00337 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, LORA_ANT_PWR); 00338 #else 00339 Radio *radio = new SX1276Generic(NULL, RFM95_SX1276, 00340 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00341 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00342 #endif 00343 00344 RadioEvents_t radioEvents; 00345 memset(&radioEvents, 0, sizeof(radioEvents)); 00346 if (radio->Init(&radioEvents)) { 00347 radio->Sleep(); 00348 delete radio; 00349 } 00350 #endif 00351 } 00352 00353 void RadioContinuesTX(void) 00354 { 00355 Radio *radio; 00356 00357 #ifdef FEATURE_NVPROPERTY 00358 NVProperty prop; 00359 int value; 00360 00361 /* 00362 * Here are optional properties for custom settings 00363 */ 00364 if ((value = prop.GetProperty(prop.LORA_FREQUENCY, 0)) != 0) 00365 myProfile[0].Frequency = value; 00366 if ((value = prop.GetProperty(prop.LORA_TXPOWER, 0)) != 0) 00367 myProfile[0].TXPower = value; 00368 if ((value = prop.GetProperty(prop.LORA_SPREADING_FACTOR, 0)) != 0) 00369 myProfile[0].SpreadingFaktor = value; 00370 #endif 00371 00372 00373 #ifdef TARGET_DISCO_L072CZ_LRWAN1 00374 radio = new SX1276Generic(NULL, MURATA_SX1276, 00375 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00376 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00377 LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO); 00378 #elif defined(HELTECL432_REV1) 00379 radio = new SX1276Generic(NULL, HELTEC_L4_1276, 00380 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00381 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00382 LORA_ANT_PWR); 00383 #else // RFM95 00384 radio = new SX1276Generic(NULL, RFM95_SX1276, 00385 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00386 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00387 #endif 00388 00389 dprintf("RadioContinuesTX test, press reset to abort"); 00390 while(true) { 00391 int secs = 10; 00392 radio->SetTxContinuousWave(myProfile[0].Frequency, myProfile[0].TXPower, secs); 00393 wait_ms(secs * 1000); 00394 rprintf("."); 00395 } 00396 } 00397 00398 #endif // FEATURE_LORA
Generated on Mon Jul 18 2022 05:09:52 by 1.7.2