Added LoRa Stress test example

pull/193/head
Jeff Lehman 3 months ago
parent 0c5129461c
commit 745aedcec7

@ -0,0 +1,161 @@
// FARM DATA RELAY SYSTEM
//
// LoRa Stress Tester or "Spammer"
//
//
#include "fdrs_node_config.h"
#include <fdrs_node.h>
#define PING_TIME_DELAY 300
#define REQ_TIME_DELAY 300
#define LOAD_TIME_DELAY 1000
#define CYCLES 15
unsigned long lastruntime = 0;
int test = 0;
unsigned long lastCycle = 0;
void setup() {
beginFDRS();
}
void loop() {
loopFDRS();
switch (test) {
case 0:
DBG("Sending pings in quick succession.");
delay(4000);
for(int i=1; i < CYCLES + 1; i) {
if(TDIFF(lastruntime,PING_TIME_DELAY)) {
lastruntime = millis();
Serial.println();
DBG("--- Test #" + String(i) + " ---");
Serial.println();
pingFDRS(1000);
i++;
}
loopFDRS();
}
while(millis()-lastruntime < 1000) {
loopFDRS();
}
test++;
Serial.println();
Serial.println();
break;
case 1:
DBG("Sending time requests in quick succession.");
delay(4000);
for(int i=1; i < CYCLES + 1; i) {
if(TDIFF(lastruntime,REQ_TIME_DELAY)) {
lastruntime = millis();
Serial.println();
DBG("--- Test #" + String(i) + " ---");
Serial.println();
reqTimeFDRS();
i++;
}
loopFDRS();
}
while(millis()-lastruntime < 1000) {
loopFDRS();
}
test++;
Serial.println();
Serial.println();
break;
case 2:
DBG("No ACK - data cycles in quick succession.");
ack = false;
delay(4000);
for(int i=1; i < CYCLES + 1; i) {
if(TDIFF(lastruntime,LOAD_TIME_DELAY)) {
lastruntime = millis();
Serial.println();
DBG("--- Test #" + String(i) + " ---");
Serial.println();
for(int j=0; j < i; j++) {
loadFDRS(READING_ID + j, STATUS_T);
}
if(sendFDRS()){
DBG("Big Success!");
} else {
DBG("Nope, not so much.");
}
i++;
}
loopFDRS();
}
while(millis()-lastruntime < 1000) {
loopFDRS();
}
test++;
Serial.println();
Serial.println();
break;
case 3:
DBG("ACK - data cycles in quick succession.");
ack = true;
delay(4000);
for(int i=1; i < CYCLES + 1; i) {
if(TDIFF(lastruntime,LOAD_TIME_DELAY)) {
lastruntime = millis();
Serial.println();
DBG("--- Test #" + String(i) + " ---");
Serial.println();
for(int j=0; j < i; j++) {
loadFDRS(READING_ID + j, STATUS_T);
}
if(sendFDRS()){
DBG("Big Success!");
} else {
DBG("Nope, not so much.");
}
i++;
}
loopFDRS();
}
while(millis()-lastruntime < 1000) {
loopFDRS();
}
test++;
Serial.println();
Serial.println();
break;
case 4:
DBG("Combination of commands in quick succession.");
delay(4000);
for(int i=1; i < CYCLES + 1; i) {
if(TDIFF(lastruntime,5000)) {
lastruntime = millis();
Serial.println();
DBG("--- Test #" + String(i) + " ---");
Serial.println();
pingFDRS(1000);
reqTimeFDRS();
subscribeFDRS(READING_ID);
i++;
}
loopFDRS();
}
while(millis()-lastruntime < 2000) {
loopFDRS();
}
test++;
Serial.println();
Serial.println();
break;
default:
DBG("DONE! Starting over again soon.");
Serial.println();
Serial.println();
delay(4000);
test = 0;
break;
}
}

@ -0,0 +1,47 @@
// FARM DATA RELAY SYSTEM
//
// Sensor Configuration
#include <fdrs_globals.h>
#define READING_ID 5 //Unique ID for this sensor
#define GTWY_MAC 0x01 //Address of the nearest gateway
// #define USE_ESPNOW
#define USE_LORA
//#define DEEP_SLEEP
//#define POWER_CTRL 14
#define FDRS_DEBUG
//
// I2C - OLED or RTC
#define I2C_SDA 5
#define I2C_SCL 6
// OLED -- Displays console debugging messages on an SSD1306 I²C OLED
// #define USE_OLED
#define OLED_HEADER "FDRS"
#define OLED_PAGE_SECS 30
#define OLED_RST -1
// LoRa Configuration
#define RADIOLIB_MODULE SX1276 //Tested on SX1276
#define LORA_SS 18
#define LORA_RST 14
#define LORA_DIO 26
#define LORA_BUSY 33
//#define USE_SX126X
//#define CUSTOM_SPI
#define LORA_SPI_SCK 5
#define LORA_SPI_MISO 19
#define LORA_SPI_MOSI 27
#define LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define LORA_ACK // Request LoRa acknowledgment.
// Time settings
#define USDST
// #define EUDST
#define STD_OFFSET (-6) // Local standard time offset in hours from UTC - if unsure, check https://time.is
#define DST_OFFSET (STD_OFFSET + 1) // Local savings time offset in hours from UTC - if unsure, check https://time.is
#define TIME_PRINTTIME 15 // Time, in minutes, between printing local time to debug

@ -99,7 +99,7 @@ RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, LORA_BUSY, SPI);
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, LORA_BUSY);
#endif // CUSTOM_SPI
#ifdef LORA_ACK
#ifdef FDRS_LORA_ACK
bool ack = true;
#else
bool ack = false;

@ -11,7 +11,7 @@
bool is_controller = false;
DataReading theData[256];
uint8_t ln;
uint8_t newData; = event_clear;
uint8_t newData = event_clear;
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
const uint16_t espnow_size = 250 / sizeof(DataReading);
crcResult crcReturned = CRC_NULL;
@ -51,6 +51,7 @@ void sendTimeSerial();
void beginFDRS()
{
delay(10000);
Serial.begin(115200);
// // find out the reset reason
// esp_reset_reason_t resetReason;
@ -186,8 +187,22 @@ bool sendFDRS()
#ifdef USE_LORA
transmitLoRaAsync(&gtwyAddress, fdrsData, data_count);
// DBG(" LoRa sent.");
#ifdef LORA_ACK
if(crcReturned == CRC_OK) {
data_count = 0;
return true;
}
#endif
#ifndef LORA_ACK
if(crcReturned == CRC_OK || crcReturned == CRC_NULL) {
data_count = 0;
return true;
}
#endif
else {
data_count = 0;
return false;
}
#endif
}
@ -229,7 +244,7 @@ void sleepFDRS(uint32_t sleep_time)
#endif
#endif
DBG(" Delaying.");
delay(sleep_time * 1000);
delay(sleep_time * 1000);
}
@ -239,10 +254,6 @@ void loopFDRS()
handleTime();
#ifdef USE_LORA
handleLoRa();
// Ping LoRa time master to estimate time delay in radio link
if(timeSource.tmNetIf == TMIF_LORA && netTimeOffset == UINT32_MAX) {
pingLoRaTimeMaster();
}
#endif
if (is_controller){
handleIncoming();
@ -254,7 +265,7 @@ if (is_controller){
}
#endif
}
// Output time to display if time is valid
// Output time to display if time is valid
if(TDIFFMIN(lastTimePrint,FDRS_TIME_PRINTTIME)) {
lastTimePrint = millis();
printTime();
@ -356,11 +367,10 @@ bool unsubscribeFDRS(uint16_t sub_id)
void pingFDRS(uint32_t timeout)
{
#ifdef USE_ESPNOW
// pingFDRSEspNow is now asynchronous so cannot return a value directly
pingFDRSEspNow(gatewayAddress, timeout);
#endif
#ifdef USE_LORA
pingRequestLoRa(&gtwyAddress, timeout);
pingRequestLoRa(gtwyAddress, timeout);
#endif
return;
}

@ -23,10 +23,9 @@ typedef struct EspNowPing {
EspNowPing espNowPing;
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
crcResult esp_now_ack_flag;
bool is_added = false;
bool pingFlag = false;
uint32_t last_refresh = 0;
uint32_t gtwy_timeout = 300000;
@ -51,18 +50,18 @@ bool reqTimeEspNow() {
void recvTimeEspNow(uint32_t t) {
// Process time if there is no master set yet or if LoRa is the master or if we are already the time master
if(timeSource.tmNetIf < TMIF_ESPNOW || (timeSource.tmNetIf == TMIF_ESPNOW && timeSource.tmAddress == (incMAC[4] << 8 | incMAC[5]))) {
DBG("Received time via ESP-NOW from 0x" + String(incMAC[5], HEX));
DBG1("Received time via ESP-NOW from 0x" + String(incMAC[5], HEX));
if(timeSource.tmNetIf < TMIF_ESPNOW) {
timeSource.tmNetIf = TMIF_ESPNOW;
timeSource.tmSource = TMS_NET;
timeSource.tmAddress = incMAC[4] << 8 & incMAC[5];
DBG("ESP-NOW time source is now 0x" + String(incMAC[5], HEX));
timeSource.tmNetIf = TMIF_ESPNOW;
timeSource.tmSource = TMS_NET;
timeSource.tmAddress = (incMAC[4] << 8 | incMAC[5]);
DBG1("ESP-NOW time source is now 0x" + String(incMAC[5], HEX));
}
setTime(t);
timeSource.tmLastTimeSet = millis();
}
else {
DBG("ESP-NOW 0x" + String(incMAC[5], HEX) + " is not our time source, discarding request");
DBG2("ESP-NOW 0x" + String(incMAC[5], HEX) + " is not our time source, discarding request");
}
return;
}
@ -125,7 +124,7 @@ void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len)
{
#endif
memcpy(&incMAC, mac, sizeof(incMAC));
memcpy(&incMAC, mac, sizeof(incMAC));
if (len == sizeof(SystemPacket))
{
SystemPacket command;
@ -166,8 +165,8 @@ memcpy(&incMAC, mac, sizeof(incMAC));
// Asynchonous call so does not wait for a reply so we do not know how long the ping takes
// ESP-NOW is on the order of 10 milliseconds so happens very quickly. Not sure Async is warranted.
void pingFDRSEspNow(uint8_t *dstaddr, uint32_t timeout) {
SystemPacket sys_packet = {.cmd = cmd_ping, .param = 0};
SystemPacket sys_packet = {.cmd = cmd_ping, .param = ping_request};
// ping function called again after previous ping not received for some reason
if(espNowPing.status == psWaiting) {
espNowPing.status = psNotStarted;

@ -9,6 +9,14 @@
#define TDIFFSEC(prevMs,durationSec) (millis() - prevMs > (durationSec * 1000))
#define TDIFFMIN(prevMs,durationMin) (millis() - prevMs > (durationMin * 60 * 1000))
// select Time, in minutes, between sending out time
#if defined(TIME_SEND_INTERVAL)
#define FDRS_TIME_SEND_INTERVAL TIME_SEND_INTERVAL
#else
#define FDRS_TIME_SEND_INTERVAL GLOBAL_TIME_SEND_INTERVAL
#endif // TIME_PRINTTIME
// select Time, in minutes, between time printed configuration
#if defined(TIME_PRINTTIME)
#define FDRS_TIME_PRINTTIME TIME_PRINTTIME
@ -319,7 +327,7 @@ bool setTime(time_t currentTime) {
// loadFDRS(slewSecs, TIME_T, 111);
// Do not call sendFDRS here. It will not work for some reason.
if(validTime()) {
if(TIME_SEND_INTERVAL == 0 && (TDIFF(lastTimeSend,5000) || lastTimeSend == 0)) { // avoid sending twice on start with RTC and WiFi
if(FDRS_TIME_SEND_INTERVAL == 0 && (TDIFF(lastTimeSend,5000) || lastTimeSend == 0)) { // avoid sending twice on start with RTC and WiFi
sendTime();
lastTimeSend = millis();
}
@ -350,7 +358,7 @@ void handleTime() {
#endif // USE_RTC
// Send out time to other devices if we have exceeded the time send interval
if(validTimeFlag && (TIME_SEND_INTERVAL != 0) && TDIFFMIN(lastTimeSend,TIME_SEND_INTERVAL)) {
if(validTimeFlag && (FDRS_TIME_SEND_INTERVAL != 0) && TDIFFMIN(lastTimeSend,FDRS_TIME_SEND_INTERVAL)) {
lastTimeSend = millis();
sendTime();
}

Loading…
Cancel
Save