Lora buffering and other minor changes

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

@ -31,7 +31,7 @@ enum cmd_t {
cmd_ping,
cmd_add,
cmd_ack,
cmd_time, // Time is sent across the network calling cmd_time on the receiving device
cmd_time
};
enum ping_t {
@ -39,6 +39,15 @@ enum ping_t {
ping_reply
};
enum state_t {
stReady,
stInProcess,
stCrcMismatch,
stCrcMatch,
stCompleted
};
enum
{
event_clear,
@ -52,6 +61,7 @@ enum
event_lora2,
event_internal
};
// Interface type that is the time source
enum TmNetIf {
TMIF_NONE,
@ -69,38 +79,36 @@ enum TmSource {
TMS_GPS,
};
typedef struct TimeSource {
struct TimeSource {
TmNetIf tmNetIf;
uint16_t tmAddress;
TmSource tmSource;
unsigned long tmLastTimeSet;
} TimeSource;
};
enum LoRaState {
stReady,
stInProcess,
stCrcMismatch,
stCrcMatch,
stCompleted
struct DRRingBuffer {
DataReading *dr;
uint16_t *address;
uint startIdx;
uint endIdx;
uint size;
};
typedef struct LoRaPing {
LoRaState status = stReady;
struct SPRingBuffer {
SystemPacket *sp;
uint16_t *address;
uint startIdx;
uint endIdx;
uint size;
};
struct Ping {
state_t status = stReady;
unsigned long start;
uint timeout;
uint16_t address;
uint32_t response = __UINT32_MAX__;
} LoRaPing;
typedef struct LoRaTaskSP {
SystemPacket data;
uint16_t dstAddress;
} tskLoRaTaskSP;
typedef struct LoRaTaskDR {
DataReading data;
uint16_t dstAddress;
} tskLoRaTaskDR;
};
#ifndef ESP32
typedef int esp_err_t;

@ -50,6 +50,8 @@ uint8_t newCmd = cmd_clear;
DataReading fdrsData[256]; // buffer for loadFDRS()
uint8_t data_count = 0;
TimeSource timeSource;
// Function Prototypes needed due to #ifdefs being moved outside of function definitions in header files
void broadcastLoRa();
void sendLoRaNbr(uint8_t);
@ -88,7 +90,7 @@ void printFDRS(DataReading*, int);
#ifdef USE_WIFI
#include "fdrs_gateway_wifi.h"
#include "fdrs_gateway_mqtt.h"
#include "fdrs_gateway_ota.h"
#include "fdrs_gateway_ota.h"
#endif
#ifdef DEBUG_CONFIG
@ -124,7 +126,7 @@ void sendFDRS()
void loadFDRS(float d, uint8_t t, uint16_t id)
{
// guard against buffer overflow
// guard against buffer overflow
if(data_count > 253) {
sendFDRS();
}
@ -162,7 +164,7 @@ void beginFDRS()
DBG("Address:" + String(UNIT_MAC, HEX));
#ifdef USE_LORA
begin_lora();
#endif
#endif
#ifdef USE_WIFI
begin_wifi();
DBG("Connected.");
@ -205,7 +207,7 @@ void handleCommands()
#ifdef USE_ESPNOW
recvTimeEspNow(theCmd.param);
#endif // USE_ESPNOW
}
}
else if(theCmd.param == 0) {
#ifdef USE_ESPNOW
sendTimeESPNow(incMAC);
@ -278,7 +280,7 @@ void loopFDRS()
void timeFDRSLoRa(uint8_t *address) {} // fdrs_gateway_lora.h
void sendTimeLoRa() { return; } // fdrs_gateway_time.h
void handleLoRa() { return; } // fdrs_gateway_lora.h
bool pingLoRaTimeMaster() { return false; } //fdrs_gateway_lora.h
bool pingLoRaTimeSource() { return false; } //fdrs_gateway_lora.h
#endif
#ifndef USE_ESPNOW
void sendESPNowNbr(uint8_t interface) { }

@ -14,6 +14,7 @@ const uint8_t espnow_size = 250 / sizeof(DataReading);
#ifdef ESP32
esp_now_peer_info_t peerInfo;
#endif
bool esp_now_sent_flag;
const uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
@ -31,14 +32,14 @@ bool pingFlagEspNow = false;
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus)
{
esp_now_sent_flag = true;
esp_now_sent_flag = true;
}
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len)
{
#elif defined(ESP32)
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
esp_now_sent_flag = true;
esp_now_sent_flag = true;
}
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len)
{
@ -205,7 +206,7 @@ if(validTimeFlag){
// Sends ping reply to sender
void pingback_espnow()
{
DBG("Ping back to sender");
DBG("Sending ESP-NOW Ping Reply");
SystemPacket sys_packet;
sys_packet = { .cmd = cmd_ping, .param = ping_reply };
if (!esp_now_is_peer_exist(incMAC))
@ -240,7 +241,7 @@ void sendESPNowNbr(uint8_t interface)
{
case 1:
{ // These brackets are required!
DBG("Sending to ESP-NOW Neighbor #1");
DBG("Sending DR to ESP-NOW Neighbor #1");
#if defined(ESP32)
esp_now_peer_info_t peerInfo;
peerInfo.ifidx = WIFI_IF_STA;
@ -273,7 +274,7 @@ void sendESPNowNbr(uint8_t interface)
} // These brackets are required!
case 2:
{
DBG("Sending to ESP-NOW Neighbor #2");
DBG("Sending DR to ESP-NOW Neighbor #2");
#if defined(ESP32)
esp_now_peer_info_t peerInfo;
peerInfo.ifidx = WIFI_IF_STA;
@ -308,7 +309,7 @@ void sendESPNowNbr(uint8_t interface)
void sendESPNowPeers()
{
DBG("Sending to ESP-NOW peers.");
DBG("Sending DR to ESP-NOW peers.");
DataReading thePacket[ln];
int j = 0;
for (int i = 0; i < ln; i++)
@ -438,7 +439,7 @@ esp_err_t sendESPNow(uint8_t *dest, DataReading *data) {
void sendESPNow(uint8_t address)
{
DBG("Sending ESP-NOW.");
DBG("Sending ESP-NOW DR.");
uint8_t temp_peer[] = {MAC_PREFIX, address};
#if defined(ESP32)
esp_now_peer_info_t peerInfo;
@ -473,7 +474,7 @@ void sendESPNow(uint8_t address)
void recvTimeEspNow(uint32_t t) {
// Process time if there is no time source set yet or if LoRa is the time source or if we are already the time source
if(timeSource.tmNetIf <= TMIF_ESPNOW ) {
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.tmAddress = incMAC[4] << 8 | incMAC[5];
@ -487,7 +488,7 @@ void recvTimeEspNow(uint32_t t) {
}
}
else {
DBG("ESP-NOW 0x" + String(incMAC[5], HEX) + " is not time source, discarding request");
DBG2("ESP-NOW 0x" + String(incMAC[5], HEX) + " is not time source, discarding request");
}
return;
}
@ -499,14 +500,14 @@ esp_err_t sendTimeESPNow() {
SystemPacket sys_packet = { .cmd = cmd_time, .param = now };
if((timeSource.tmAddress != (ESPNOW1[4] << 8 | ESPNOW1[5])) && ESPNOW1[5] != 0x00) {
DBG("Sending time to ESP-NOW Peer 1");
DBG1("Sending time to ESP-NOW Peer 1");
result1 = sendESPNow(ESPNOW1, &sys_packet);
}
if((timeSource.tmAddress != (ESPNOW2[4] << 8 | ESPNOW2[5])) && ESPNOW2[5] != 0x00) {
DBG("Sending time to ESP-NOW Peer 2");
DBG1("Sending time to ESP-NOW Peer 2");
result2 = sendESPNow(ESPNOW2, &sys_packet);
}
DBG("Sending time to ESP-NOW registered peers");
DBG1("Sending time to ESP-NOW registered peers");
result3 = sendESPNow(nullptr, &sys_packet);
if(result1 != ESP_OK || result2 != ESP_OK || result3 != ESP_OK){

@ -6,21 +6,24 @@
#ifndef __FDRS_GLOBALS_h__
#define __FDRS_GLOBALS_h__
#define GLOBAL_WIFI_SSID "Your SSID"
#define GLOBAL_WIFI_PASS "Password"
#define GLOBAL_DBG_LEVEL 0
#define GLOBAL_WIFI_SSID "Your SSID"
#define GLOBAL_WIFI_PASS "Password"
#define GLOBAL_DNS1_IPADDRESS "8.8.8.8" // Default to Google Primary DNS
#define GLOBAL_DNS2_IPADDRESS "8.8.4.4" // Default to Google Secondary DNS
#define GLOBAL_MQTT_ADDR "192.168.0.8"
#define GLOBAL_MQTT_PORT 1883
//#define GLOBAL_MQTT_AUTH //uncomment to enable MQTT authentication
//#define GLOBAL_MQTT_AUTH //uncomment to enable MQTT authentication
#define GLOBAL_MQTT_USER "Your MQTT Username"
#define GLOBAL_MQTT_PASS "Your MQTT Password"
// MQTT Topics
#define TOPIC_DATA "fdrs/data"
#define TOPIC_STATUS "fdrs/status"
#define TOPIC_COMMAND "fdrs/command"
#define TOPIC_DATA_BACKLOG "fdrs/databacklog" // Used in filesystem module
// NTP Time Server
#define GLOBAL_TIME_SERVER "0.us.pool.ntp.org"
@ -29,6 +32,7 @@
#define GLOBAL_TIME_PRINTTIME 15 // Time in minutes between printing local time
#define GLOBAL_TIME_SEND_INTERVAL 60 // Time in minutes between sending out time
#define GLOBAL_LORA_FREQUENCY 915.0 // Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz (varies by chip).
#define GLOBAL_LORA_SF 7 // LoRa link spreading factor. Allowed values range from 6 to 12.
#define GLOBAL_LORA_BANDWIDTH 125.0 // LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.

@ -8,13 +8,15 @@
#define GLOBAL_LORA_RETRIES 2 // LoRa ACK automatic retries [0 - 3]
#define GLOBAL_LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define TXWINDOWMS 300
#define TXDELAYMS 300
#define SPBUFFSIZE 10
#define DRBUFFSIZE lora_size
#define DRQUEUEEMPTY ((startIdxDR == endIdxDR) ? true: false)
#define SPQUEUEEMPTY ((startIdxSP == endIdxSP) ? true: false)
#define DRQUEUEFULL (((startIdxDR + 1) % DRBUFFSIZE) == endIdxDR ? true: false)
#define SPQUEUEFULL (((startIdxSP + 1) % SPBUFFSIZE) == endIdxSP ? true: false)
#define LORASIZE (250 / sizeof(DataReading))
#define DRBUFFSIZE LORASIZE
#define ISBUFFEMPTY(buff) ((buff.endIdx == buff.startIdx) ? true: false)
#define ISBUFFFULL(buff) (((buff.endIdx + 1) % buff.size) == buff.startIdx ? true: false)
#define BUFFINCSTART(buff) (buff.startIdx = (buff.startIdx + 1) % buff.size)
#define BUFFINCEND(buff) (buff.endIdx = (buff.endIdx + 1) % buff.size)
#define BUFFCLEAR(buff) (buff.startIdx = buff.endIdx)
// select LoRa band configuration
#if defined(LORA_FREQUENCY)
@ -103,18 +105,15 @@ RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, LORA_BUSY);
bool ack = false;
#endif // LORA_ACK
LoRaPing loraPing;
Ping loraPing;
const uint8_t lora_size = 250 / sizeof(DataReading);
DRRingBuffer drBuff = {.dr = (DataReading*)calloc(DRBUFFSIZE,sizeof(DataReading)), \
.address = (uint16_t*)calloc(DRBUFFSIZE,sizeof(uint16_t)), .startIdx = 0, .endIdx = 0, .size = DRBUFFSIZE};
SPRingBuffer spBuff = {.sp = (SystemPacket*)calloc(SPBUFFSIZE,sizeof(SystemPacket)), \
.address = (uint16_t*)calloc(SPBUFFSIZE,sizeof(uint16_t)), .startIdx = 0, .endIdx = 0, .size = SPBUFFSIZE};
tskLoRaTaskSP loraSPBuffTx[SPBUFFSIZE];
tskLoRaTaskDR loraDRBuffTx[DRBUFFSIZE];
int loraTxState = stReady;
int loraAckState = stReady;
int startIdxDR = 0;
int endIdxDR = 0;
int startIdxSP = 0;
int endIdxSP = 0;
#ifdef FDRS_GATEWAY
@ -334,52 +333,62 @@ void begin_lora()
}
}
bool transmitLoRaAsync(uint16_t *destMAC, SystemPacket *packet, uint8_t len)
bool transmitLoRaAsync(uint16_t *destAddr, SystemPacket *sp, uint8_t len)
{
for(int i=0; i < len; i++)
{
//check for full buffer
if(SPQUEUEFULL) {
if(ISBUFFFULL(spBuff)) {
DBG("Lora SP Buffer Overflow!");
return false;
BUFFINCSTART(spBuff);
}
//add packet to buffer
loraSPBuffTx[startIdxSP].data = *(packet + i);
loraSPBuffTx[startIdxSP].dstAddress = *destMAC;
startIdxSP = (startIdxSP + 1) % SPBUFFSIZE;
*(spBuff.sp + spBuff.endIdx) = *(sp + i);
*(spBuff.address + spBuff.endIdx) = *destAddr;
BUFFINCEND(spBuff);
}
DBG2("SP added to LoRa buffer. start: " + String(startIdxSP) + " end: " + String(endIdxSP));
DBG2("SP added to LoRa buffer. start: " + String(spBuff.startIdx) + " end: " + String(spBuff.endIdx));
return true;
}
// Wrapper for transmitLoRa for DataReading type packets to handle processing Receiving CRCs and retransmitting packets
bool transmitLoRaAsync(uint16_t *destMAC, DataReading *packet, uint8_t len)
bool transmitLoRaAsync(uint16_t *destAddr, DataReading *dr, uint8_t len)
{
// we need to prevent modifying index while waiting
// for an ack
if(loraAckState == stReady) {
//add packet to buffer
for(int i=0; i < len; i++)
// Write as much as needed and just flush out the older data if too much data writing to buffer
//add packet to buffer
for(int i=0; i < len; i++)
{
if(ISBUFFFULL(drBuff))
{
if(DRQUEUEFULL)
{
DBG("Lora DR Buffer Overflow!");
return false;
}
loraDRBuffTx[startIdxDR].data = *(packet + i);
loraDRBuffTx[startIdxDR].dstAddress = *destMAC;
startIdxDR = (startIdxDR + 1) % DRBUFFSIZE;
DBG("Lora DR Buffer Overflow!");
// We just lost one reading - the oldest reading
BUFFINCSTART(drBuff);
}
DBG2("DR added to LoRa buffer. start: " + String(startIdxDR) + " end: " + String(endIdxDR));
return true;
*(drBuff.dr + drBuff.endIdx) = *(dr + i);
*(drBuff.address + drBuff.endIdx) = *destAddr;
BUFFINCEND(drBuff);
}
else {
// JL - do we internally store the start index, check for space, and then
// adjust the index once the acks are completed???
DBG2("Unable to add DR to LoRa buffer due to pending ACK.");
return false;
// for(int i=drBuff.startIdx; i!=drBuff.endIdx; i = (i + 1) % drBuff.size) {
// printf("id: %d, type: %d data: %f address: %X\n",(drBuff.dr + i)->id, (drBuff.dr + i)->t, (drBuff.dr + i)->d, *(drBuff.address + drBuff.startIdx));
// }
DBG2("DR added to LoRa buffer. start: " + String(drBuff.startIdx) + " end: " + String(drBuff.endIdx));
return true;
}
// write a function to return the number of consecutive DRs in the DR Queue that have the same destination address
uint transmitSameAddrLoRa() {
uint count = 0;
for(int i=drBuff.startIdx; i!=drBuff.endIdx; i = (i + 1) % drBuff.size) {
if(*(drBuff.address + i) == *(drBuff.address + drBuff.startIdx))
count++;
else {
break;
}
}
return count;
}
// Send time to LoRa broadcast and peers
@ -417,43 +426,14 @@ void sendTimeLoRa(uint16_t addr) {
return;
}
// FDRS Sensor pings address and listens for a defined amount of time for a reply
bool pingRequestLoRa(uint16_t address, uint32_t timeout)
{
if(loraPing.status == stReady) {
SystemPacket sys_packet = {.cmd = cmd_ping, .param = ping_request};
loraPing.timeout = timeout;
loraPing.status = stInProcess;
loraPing.address = address;
loraPing.start = millis();
if(loraTxState == stReady) {
transmitLoRa(&address,&sys_packet,1);
DBG1("LoRa ping request sent to address: 0x" + String(address, HEX));
return true;
}
else {
if(transmitLoRaAsync(&address, &sys_packet, 1))
{
DBG1("LoRa ping request queued to address: 0x" + String(address, HEX));
return true;
}
else {
DBG1("Error sending LoRa ping.");
}
}
}
return false;
}
// FDRS sends ping reply
bool pingReplyLoRa(uint16_t address)
{
SystemPacket sys_packet = {.cmd = cmd_ping, .param = ping_reply};
if(loraTxState == stReady) {
transmitLoRa(&address,&sys_packet,1);
DBG1("LoRa ping reply sent to address: 0x" + String(address, HEX));
transmitLoRa(&address,&sys_packet,1);
return true;
}
else {
@ -644,33 +624,6 @@ crcResult receiveLoRa()
return CRC_NULL;
}
// Sends packet to any node that is paired to this gateway
void broadcastLoRa()
{
DBG("Sending to LoRa broadcast buffer");
transmitLoRaAsync(&loraBroadcast,theData,ln);
}
// Sends packet to neighbor gateways
void sendLoRaNbr(uint8_t interface)
{
DBG("Sending to LoRa neighbor buffer");
switch (interface)
{
case 1:
{
transmitLoRaAsync(&LoRa1,theData,ln);
break;
}
case 2:
{
transmitLoRaAsync(&LoRa2,theData,ln);
break;
}
}
}
crcResult LoRaTxRxOperation()
{
crcResult crcReturned = CRC_NULL;
@ -707,8 +660,88 @@ crcResult LoRaTxRxOperation()
return crcReturned;
}
// FDRS Sensor pings address and listens for a defined amount of time for a reply
bool pingRequestLoRa(uint16_t address, uint32_t timeout)
{
if(loraPing.status == stReady) {
SystemPacket sys_packet = {.cmd = cmd_ping, .param = ping_request};
loraPing.timeout = timeout;
loraPing.address = address;
if(loraTxState == stReady) {
loraPing.status = stInProcess;
loraPing.start = millis();
DBG1("LoRa ping request sent to address: 0x" + String(address, HEX));
transmitLoRa(&address,&sys_packet,1);
while(loraPing.status == stInProcess && (millis() - loraPing.start < loraPing.timeout)) {
LoRaTxRxOperation();
}
if(loraPing.status == stCompleted) {
loraPing.response = millis() - loraPing.start;
DBG1("LoRa Ping Returned: " + String(loraPing.response) + "ms.");
if(loraPing.address == timeSource.tmAddress) {
netTimeOffset = loraPing.response/2/1000;
adjTimeforNetDelay(netTimeOffset);
}
}
else {
DBG1("No LoRa ping returned within " + String(loraPing.timeout) + "ms.");
}
loraPing.status = stReady;
loraPing.start = 0;
loraPing.timeout = 0;
loraPing.address = 0;
loraPing.response = UINT32_MAX;
return true;
}
else {
if(transmitLoRaAsync(&address, &sys_packet, 1))
{
DBG1("LoRa ping request queued to address: 0x" + String(address, HEX));
return true;
}
else {
DBG1("Error sending LoRa ping.");
}
}
}
return false;
}
// Sends packet to any node that is paired to this gateway
void broadcastLoRa()
{
DBG("Sending to LoRa broadcast buffer");
transmitLoRaAsync(&loraBroadcast,theData,ln);
}
// Sends packet to neighbor gateways
void sendLoRaNbr(uint8_t interface)
{
DBG("Sending to LoRa neighbor buffer");
switch (interface)
{
case 1:
{
transmitLoRaAsync(&LoRa1,theData,ln);
break;
}
case 2:
{
transmitLoRaAsync(&LoRa2,theData,ln);
break;
}
}
}
void handleLoRa()
{
static uint8_t len = 0;
static DataReading *data;
static uint16_t address;
static unsigned long lastTxtime = 0;
LoRaTxRxOperation();
if(loraPing.status == stCompleted) {
@ -735,82 +768,102 @@ void handleLoRa()
static int retries = FDRS_LORA_RETRIES;
static unsigned long loraAckTimeout = 0;
// Process any DR ACKs in progress
if(loraTxState == stReady && loraAckState != stReady) {
if (loraAckState == stCrcMatch)
{
DBG1("LoRa ACK Received! CRC OK");
msgOkLoRa++;
loraAckState = stReady;
// reset buffer indexes so that buffer is empty
endIdxDR = startIdxDR;
free(data);
data = NULL;
retries = FDRS_LORA_RETRIES;
if(loraTxState == stCompleted) {
loraTxState = stReady;
}
return; // we're done
len = 0;
}
else if(retries == 0) {
DBG2("Retries Exhausted. Data is lost.");
loraAckState = stReady;
// reset buffer indexes so that buffer is empty
endIdxDR = startIdxDR;
else if(retries < 0) {
DBG2("Retries Exhausted.");
retries = FDRS_LORA_RETRIES;
if(loraTxState == stCompleted) {
loraTxState = stReady;
if(ISBUFFFULL(drBuff)) {
len = 0;
free(data);
data = NULL;
}
return;
// do we transmit ourselves to death or just drop the data?
// here we drop the data so we don't keep transmitting to death
len = 0;
free(data);
data = NULL;
}
else if (loraAckState == stCrcMismatch)
{
DBG1("LoRa ACK Received! CRC BAD");
// Resend original packet again if retries are available
DBG2("Retries: " + String(retries) + " DR Index: " + String(endIdxDR) + " Address: 0x" + String(loraDRBuffTx[endIdxDR].dstAddress,HEX));
loraAckTimeout = millis();
loraAckState = stInProcess;
retries--;
transmitLoRa(&loraDRBuffTx[endIdxDR].dstAddress, &loraDRBuffTx[endIdxDR].data, (startIdxDR + DRBUFFSIZE - endIdxDR) % DRBUFFSIZE);
}
else if (TDIFF(loraAckTimeout,FDRS_ACK_TIMEOUT))
{
DBG1("LoRa Timeout waiting for ACK!");
else if (TDIFF(loraAckTimeout,FDRS_ACK_TIMEOUT)) {
DBG1("LoRa Timeout waiting for ACK!");
// resend original packet again if retries are available
DBG2("Retries: " + String(retries) + " DR Index: " + String(endIdxDR) + " Address: 0x" + String(loraDRBuffTx[endIdxDR].dstAddress,HEX));
loraAckTimeout = millis();
loraAckState = stInProcess;
retries--;
transmitLoRa(&loraDRBuffTx[endIdxDR].dstAddress, &loraDRBuffTx[endIdxDR].data, (startIdxDR + DRBUFFSIZE - endIdxDR) % DRBUFFSIZE);
}
if(loraTxState == stCompleted) {
loraTxState = stReady;
}
loraAckState = stReady;
return;
}
static unsigned long txWindow = 0;
// It's polite to Listen more than you talk
if(TDIFF(txWindow,(TXWINDOWMS + random(0,50)))) {
if(TDIFF(lastTxtime,(TXDELAYMS + random(0,50)))) {
// Start Transmit data from the SystemPacket queue
if(!SPQUEUEEMPTY && (loraTxState == stReady)) {
DBG2("SP Index: start: " + String(startIdxSP) + " end: " + String(endIdxSP) + " Address: 0x" + String(loraSPBuffTx[endIdxSP].dstAddress,HEX));
transmitLoRa(&loraSPBuffTx[endIdxSP].dstAddress, &loraSPBuffTx[endIdxSP].data, 1);
endIdxSP = (endIdxSP + 1) % SPBUFFSIZE;
if(!ISBUFFEMPTY(spBuff) && (loraTxState == stReady)) {
DBG2("SP Index: start: " + String(spBuff.startIdx) + " end: " + String(spBuff.endIdx) + " Address: 0x" + String(address,HEX) + " Cmd: " + String(spBuff.sp->cmd));
// Lora ping request stuff here
if((spBuff.sp + spBuff.startIdx)->cmd == cmd_ping && (spBuff.sp + spBuff.startIdx)->param == ping_request) {
loraPing.status = stInProcess;
loraPing.start = millis();
DBG1("LoRa ping request sent to address: 0x" + String(*(spBuff.address + spBuff.startIdx), HEX));
}
transmitLoRa((spBuff.address + spBuff.startIdx), (spBuff.sp + spBuff.startIdx), 1);
BUFFINCSTART(spBuff);
}
// Start Transmit data from the DataReading queue
if(!DRQUEUEEMPTY && loraTxState == stReady && loraAckState == stReady)
if((!ISBUFFEMPTY(drBuff) || (data != NULL)) && loraTxState == stReady && loraAckState == stReady)
{
if(!ack)
{
DBG2("DR Index: start: " + String(startIdxDR) + " end: " + String(endIdxDR) + " Address: 0x" + String(loraDRBuffTx[endIdxDR].dstAddress,HEX));
transmitLoRa(&loraDRBuffTx[endIdxDR].dstAddress, &loraDRBuffTx[endIdxDR].data, (startIdxDR + DRBUFFSIZE - endIdxDR) % DRBUFFSIZE);
endIdxDR = startIdxDR;
// for(int i=drBuff.startIdx; i!=drBuff.endIdx; i = (i + 1) % drBuff.size) {
// printf("id: %d, type: %d data: %f address: %X\n",(drBuff.dr + i)->id, (drBuff.dr + i)->t, (drBuff.dr + i)->d, *(spBuff.address + spBuff.startIdx));
// }
// data memory is not freed when retries are exhausted and DataReading queue is not full
if(data == NULL) {
// Get number of DRs going to same destination address
len = transmitSameAddrLoRa();
// TransmitLoRa cannot handle a circular buffer so need data in one contiguous segment of memory
data = (DataReading *)malloc(len * sizeof(DataReading));
// Transfer data readings from the ring buffer to our local buffer
for(int i=0; i < len; i++) {
*(data + i) = *(drBuff.dr + ((drBuff.startIdx + i) % drBuff.size));
}
address = *(drBuff.address + drBuff.startIdx);
// now we have the data, we can release it from the ring buffer
drBuff.startIdx = (drBuff.startIdx + len) % drBuff.size;
}
else
DBG2("Length: " + String(len) + " Address: 0x" + String(address,HEX) + " Data:");
// for(int i=0; i< len; i++) {
// printf("id: %d, type: %d data: %f\n",(data + i)->id, (data + i)->t, (data + i)->d);
// }
if(!ack && data != NULL)
{
DBG2("Retries: " + String(retries) + " DR Index: " + String(endIdxDR) + " Address: 0x" + String(loraDRBuffTx[endIdxDR].dstAddress,HEX));
transmitLoRa(&address, data, len);
free(data);
data = NULL;
len = 0;
}
else if(data != NULL)
{
retries--;
loraAckState = stInProcess;
loraAckTimeout = millis();
transmitLoRa(&loraDRBuffTx[endIdxDR].dstAddress, &loraDRBuffTx[endIdxDR].data, (startIdxDR + DRBUFFSIZE - endIdxDR) % DRBUFFSIZE);
// Don't reset queue indexes here. We will reset them in the routine that checks for acks
transmitLoRa(&address, data, len);
}
}
@ -824,7 +877,7 @@ void handleLoRa()
lastTimeSourcePing = millis();
}
}
txWindow = millis();
lastTxtime = millis();
}
// Change to ready at the end so only one transmit happens per function call

@ -1,6 +1,6 @@
#include <sys/time.h>
#define MIN_TS 1707000000 // Time in Unit timestamp format should be greater than this number to be valid
#define MIN_TS 1709000000 // Time in Unit timestamp format should be greater than this number to be valid
#define MAX_TS 3318000000 // time in Unit timestamp format should be less than this number to be valid
#define VALID_TS(_unixts) ( (_unixts > MIN_TS && _unixts < MAX_TS) ? true : false )
@ -106,7 +106,7 @@ void begin_rtc() {
DBG1("Using Date and Time from RTC.");
if(setTime(rtc.GetDateTime().Unix32Time())) {
timeSource.tmLastTimeSet = millis();
printTime();
printTime();
}
}
@ -277,7 +277,7 @@ void sendTime() {
DBG1("Sending out time");
#if defined(USE_WIFI) || defined(USE_ETHERNET)
sendTimeSerial();
#endif
#endif
sendTimeLoRa();
sendTimeESPNow();
}
@ -309,10 +309,10 @@ bool setTime(time_t currentTime) {
#ifdef USE_RTC
// Only set the RTC time every 60 minutes in order to prevent flash wear
if(TDIFFMIN(lastRtcTimeSetMin,60)) {
RtcDateTime rtcNow;
rtcNow.InitWithUnix32Time(now);
rtc.SetDateTime(rtcNow);
}
RtcDateTime rtcNow;
rtcNow.InitWithUnix32Time(now);
rtc.SetDateTime(rtcNow);
}
#endif
// Uncomment below to send time and slew rate to the MQTT server
// loadFDRS(now, TIME_T, 111);
@ -354,7 +354,7 @@ void handleTime() {
lastTimeSend = millis();
sendTime();
}
if(timeSource.tmNetIf < TMIF_LOCAL && TDIFFMIN(timeSource.tmLastTimeSet,120)) { // Reset time master to default if not heard anything for two hours
if(timeSource.tmNetIf < TMIF_LOCAL && TDIFFMIN(timeSource.tmLastTimeSet,120)) { // Reset time source to default if not heard anything for two hours
timeSource.tmNetIf = TMIF_NONE;
timeSource.tmAddress = 0x0000;
timeSource.tmLastTimeSet = millis();
@ -364,7 +364,7 @@ void handleTime() {
void adjTimeforNetDelay(time_t newOffset) {
static time_t previousOffset = 0;
// check to see if offset and current time are valid
if(newOffset < UINT32_MAX && validTime()) {
now = now + newOffset - previousOffset;
@ -372,7 +372,7 @@ void adjTimeforNetDelay(time_t newOffset) {
if(newOffset > 2) {
DBG1("Time adj by " + String(newOffset) + " secs");
}
}
}
if(timeSource.tmSource == TMS_NET && newOffset > 10) {
DBG("Time off by more than 10 seconds!");
// loadFDRS();

Loading…
Cancel
Save