add custom SPI definitions for ESP32

compiled but untested on hardware
pull/136/head
Timm Bogner 1 year ago
parent dbf87a711f
commit 780881d0e7

@ -24,9 +24,6 @@
#define LORA1_ACT sendSerial();
#define LORA2_ACT
//
//
//
// Neighboring gateway addresses
#define ESPNOW_NEIGHBOR_1 0x00 // ESPNOW1 Address
@ -44,6 +41,11 @@
#define LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define LORA_ACK // Request LoRa acknowledgment.
//#define CUSTOM_SPI
#define LORA_SPI_SCK 5
#define LORA_SPI_MISO 19
#define LORA_SPI_MOSI 27
//Pins for UART data interface (ESP32 only)
#define RXD2 14
#define TXD2 15

@ -23,3 +23,7 @@
#define LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define LORA_ACK // Request LoRa acknowledgment.
//#define CUSTOM_SPI
#define LORA_SPI_SCK 5
#define LORA_SPI_MISO 19
#define LORA_SPI_MOSI 27

@ -75,7 +75,15 @@
const uint8_t lora_size = 256 / sizeof(DataReading);
#ifdef CUSTOM_SPI
#ifdef ESP32
SPIClass LORA_SPI(HSPI);
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, -1, LORA_SPI);
#endif // ESP32
#else
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, -1);
#endif // CUSTOM_SPI
bool transmitFlag = false; // flag to indicate transmission or reception state
volatile bool enableInterrupt = true; // disable interrupt when it's not needed
volatile bool operationDone = false; // flag to indicate that a packet was sent or received
@ -241,6 +249,13 @@ void printLoraPacket(uint8_t *p, int size)
#ifdef USE_LORA
void begin_lora()
{
#ifdef CUSTOM_SPI
#ifdef ESP32
LORA_SPI.begin(LORA_SPI_SCK, LORA_SPI_MISO, LORA_SPI_MOSI);
#endif // ESP32
#else
#endif // CUSTOM_SPI
int state = radio.begin(FDRS_LORA_FREQUENCY, FDRS_LORA_BANDWIDTH, FDRS_LORA_SF, FDRS_LORA_CR, FDRS_LORA_SYNCWORD, FDRS_LORA_TXPWR, 8, 0);
if (state == RADIOLIB_ERR_NONE)
{

@ -23,9 +23,9 @@
// Internal Globals
// Default values that are assigned if none are present in config
#define GLOBAL_ACK_TIMEOUT 400 // LoRa ACK timeout in ms. (Minimum = 200)
#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 GLOBAL_ACK_TIMEOUT 400 // LoRa ACK timeout in ms. (Minimum = 200)
#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))
#ifdef USE_LORA
// select LoRa band configuration
@ -33,64 +33,63 @@
#define FDRS_LORA_FREQUENCY LORA_FREQUENCY
#else
#define FDRS_LORA_FREQUENCY GLOBAL_LORA_FREQUENCY
#endif //LORA_FREQUENCY
#endif // LORA_FREQUENCY
// select LoRa SF configuration
#if defined(LORA_SF)
#define FDRS_LORA_SF LORA_SF
#else
#define FDRS_LORA_SF GLOBAL_LORA_SF
#endif //LORA_SF
#endif // LORA_SF
// select LoRa ACK configuration
#if defined(LORA_ACK) || defined(GLOBAL_LORA_ACK)
#define FDRS_LORA_ACK
#endif //LORA_ACK
#endif // LORA_ACK
// select LoRa ACK Timeout configuration
#if defined(LORA_ACK_TIMEOUT)
#define FDRS_ACK_TIMEOUT LORA_ACK_TIMEOUT
#else
#define FDRS_ACK_TIMEOUT GLOBAL_ACK_TIMEOUT
#endif //LORA_ACK_TIMEOUT
#endif // LORA_ACK_TIMEOUT
// select LoRa Retry configuration
#if defined(LORA_RETRIES)
#define FDRS_LORA_RETRIES LORA_RETRIES
#else
#define FDRS_LORA_RETRIES GLOBAL_LORA_RETRIES
#endif //LORA_RETRIES
#endif // LORA_RETRIES
// select LoRa Tx Power configuration
#if defined(LORA_TXPWR)
#define FDRS_LORA_TXPWR LORA_TXPWR
#else
#define FDRS_LORA_TXPWR GLOBAL_LORA_TXPWR
#endif //LORA_TXPWR
#endif // LORA_TXPWR
// select LoRa BANDWIDTH configuration
#if defined(LORA_BANDWIDTH)
#define FDRS_LORA_BANDWIDTH LORA_BANDWIDTH
#else
#define FDRS_LORA_BANDWIDTH GLOBAL_LORA_BANDWIDTH
#endif //LORA_BANDWIDTH
#endif // LORA_BANDWIDTH
// select LoRa Coding Rate configuration
#if defined(LORA_CR)
#define FDRS_LORA_CR LORA_CR
#else
#define FDRS_LORA_CR GLOBAL_LORA_CR
#endif //LORA_CR
#endif // LORA_CR
// select LoRa SyncWord configuration
#if defined(LORA_SYNCWORD)
#define FDRS_LORA_SYNCWORD LORA_SYNCWORD
#else
#define FDRS_LORA_SYNCWORD GLOBAL_LORA_SYNCWORD
#endif //LORA_SYNCWORD
#endif // LORA_SYNCWORD
#endif //USE_LORA
#endif // USE_LORA
#ifdef FDRS_DEBUG
#define DBG(a) (Serial.println(a))
@ -98,28 +97,31 @@
#define DBG(a)
#endif
#ifdef DEBUG_CONFIG
//#include "fdrs_checkConfig.h"
// #include "fdrs_checkConfig.h"
#endif
const uint16_t espnow_size = 250 / sizeof(DataReading);
uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
uint16_t gtwyAddress = ((gatewayAddress[4] << 8) | GTWY_MAC);
#ifdef USE_LORA
#ifdef CUSTOM_SPI
#ifdef ESP32
SPIClass LORA_SPI(HSPI);
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, -1, LORA_SPI);
#endif // ESP32
#else
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO, LORA_RST, -1);
bool transmitFlag = false;// flag to indicate transmission or reception state
volatile bool enableInterrupt = true;// disable interrupt when it's not needed
volatile bool operationDone = false;// flag to indicate that a packet was sent or received
#endif // CUSTOM_SPI
bool transmitFlag = false; // flag to indicate transmission or reception state
volatile bool enableInterrupt = true; // disable interrupt when it's not needed
volatile bool operationDone = false; // flag to indicate that a packet was sent or received
uint16_t LoRaAddress = ((UniqueID8[6] << 8) | UniqueID8[7]);
unsigned long transmitLoRaMsgwAck = 0; // Number of total LoRa packets destined for us and of valid size
unsigned long msgOkLoRa = 0; // Number of total LoRa packets with valid CRC
#endif
unsigned long transmitLoRaMsgwAck = 0; // Number of total LoRa packets destined for us and of valid size
unsigned long msgOkLoRa = 0; // Number of total LoRa packets with valid CRC
#endif
uint32_t gtwy_timeout = 0;
uint8_t incMAC[6];
uint32_t wait_time = 0;
@ -140,47 +142,65 @@ bool active_subs[256] = {};
#ifdef USE_ESPNOW
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
if(sendStatus == 0){
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus)
{
if (sendStatus == 0)
{
esp_now_ack_flag = CRC_OK;
} else {
}
else
{
esp_now_ack_flag = CRC_BAD;
}
}
void OnDataRecv(uint8_t* mac, uint8_t *incomingData, uint8_t len) {
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) {
if(status == ESP_NOW_SEND_SUCCESS){
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
if (status == ESP_NOW_SEND_SUCCESS)
{
esp_now_ack_flag = CRC_OK;
} else {
}
else
{
esp_now_ack_flag = CRC_BAD;
}
}
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len)
{
#endif
memcpy(&incMAC, mac, sizeof(incMAC));
if (len < sizeof(DataReading)) {
if (len < sizeof(DataReading))
{
SystemPacket command;
memcpy(&command, incomingData, sizeof(command));
switch (command.cmd) {
case cmd_ping:
is_ping = true;
break;
case cmd_add:
is_added = true;
gtwy_timeout = command.param;
break;
switch (command.cmd)
{
case cmd_ping:
is_ping = true;
break;
case cmd_add:
is_added = true;
gtwy_timeout = command.param;
break;
}
} else{
}
else
{
memcpy(&incData, incomingData, len);
int pkt_readings = len / sizeof(DataReading);
for (int i = 0; i <= pkt_readings; i++) { //Cycle through array of incoming DataReadings for any addressed to this device
for (int j = 0; j < 255; j++){ //Cycle through subscriptions for active entries
if (active_subs[j]){
if (incData[i].id == subscription_list[j]){
(*callback_ptr)(incData[i]);
int pkt_readings = len / sizeof(DataReading);
for (int i = 0; i <= pkt_readings; i++)
{ // Cycle through array of incoming DataReadings for any addressed to this device
for (int j = 0; j < 255; j++)
{ // Cycle through subscriptions for active entries
if (active_subs[j])
{
if (incData[i].id == subscription_list[j])
{
(*callback_ptr)(incData[i]);
}
}
}
@ -191,58 +211,80 @@ void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
#ifdef USE_LORA
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
if(!enableInterrupt) { // check if the interrupt is enabled
void setFlag(void)
{
if (!enableInterrupt)
{ // check if the interrupt is enabled
return;
}
operationDone = true; // we sent or received packet, set the flag
operationDone = true; // we sent or received packet, set the flag
}
#endif
void handleLoRa(){
#ifdef USE_LORA
if(operationDone) { // the interrupt was triggered
void handleLoRa()
{
#ifdef USE_LORA
if (operationDone)
{ // the interrupt was triggered
enableInterrupt = false;
operationDone = false;
if(transmitFlag) { // the previous operation was transmission,
radio.startReceive(); // return to listen mode
if (transmitFlag)
{ // the previous operation was transmission,
radio.startReceive(); // return to listen mode
enableInterrupt = true;
transmitFlag = false;
} else { // the previous operation was reception
}
else
{ // the previous operation was reception
returnCRC = getLoRa();
radio.startReceive(); // fixes the problem?
radio.startReceive(); // fixes the problem?
enableInterrupt = true;
}
}
#endif //USE_LORA
}
}
#endif // USE_LORA
}
void begin_lora()
{
#ifdef USE_LORA
#ifdef CUSTOM_SPI
#ifdef ESP32
LORA_SPI.begin(LORA_SPI_SCK, LORA_SPI_MISO, LORA_SPI_MOSI);
#endif // ESP32
#else
#endif // CUSTOM_SPI
void begin_lora() {
// #ifdef ESP32
// SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// #endif
#ifdef USE_LORA
int state = radio.begin(FDRS_LORA_FREQUENCY, FDRS_LORA_BANDWIDTH, FDRS_LORA_SF, FDRS_LORA_CR, FDRS_LORA_SYNCWORD, FDRS_LORA_TXPWR, 8, 0);
if (state == RADIOLIB_ERR_NONE) {
if (state == RADIOLIB_ERR_NONE)
{
DBG("RadioLib initialization successful!");
} else {
}
else
{
DBG("RadioLib initialization failed, code " + String(state));
while (true);
while (true)
;
}
DBG("LoRa Initialized. Frequency: " + String(FDRS_LORA_FREQUENCY) + " Bandwidth: " + String(FDRS_LORA_BANDWIDTH) + " SF: " + String(FDRS_LORA_SF) + " CR: " + String(FDRS_LORA_CR) + " SyncWord: " + String(FDRS_LORA_SYNCWORD) + " Tx Power: " + String(FDRS_LORA_TXPWR) + "dBm");
radio.setDio0Action(setFlag);
radio.setCRC(false);
state = radio.startReceive(); // start listening for LoRa packets
if (state == RADIOLIB_ERR_NONE) {
} else {
if (state == RADIOLIB_ERR_NONE)
{
}
else
{
DBG(" failed, code " + String(state));
while (true);
while (true)
;
}
#endif // USE_LORA
}
void beginFDRS() {
void beginFDRS()
{
#ifdef FDRS_DEBUG
Serial.begin(115200);
// // find out the reset reason
@ -251,7 +293,7 @@ void beginFDRS() {
#endif
DBG("FDRS User Node initializing...");
DBG(" Reading ID " + String(READING_ID));
DBG(" Gateway: " + String (GTWY_MAC, HEX));
DBG(" Gateway: " + String(GTWY_MAC, HEX));
#ifdef POWER_CTRL
DBG("Powering up the sensor array!");
pinMode(POWER_CTRL, OUTPUT);
@ -264,7 +306,8 @@ void beginFDRS() {
WiFi.mode(WIFI_STA);
WiFi.disconnect();
#if defined(ESP8266)
if (esp_now_init() != 0) {
if (esp_now_init() != 0)
{
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
@ -275,7 +318,8 @@ void beginFDRS() {
esp_now_add_peer(gatewayAddress, ESP_NOW_ROLE_COMBO, 0, NULL, 0);
#elif defined(ESP32)
if (esp_now_init() != ESP_OK) {
if (esp_now_init() != ESP_OK)
{
DBG("Error initializing ESP-NOW");
return;
}
@ -287,25 +331,26 @@ void beginFDRS() {
peerInfo.channel = 0;
peerInfo.encrypt = false;
memcpy(peerInfo.peer_addr, broadcast_mac, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
DBG("Failed to add peer bcast");
return;
}
memcpy(peerInfo.peer_addr, gatewayAddress, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
DBG("Failed to add peer");
return;
}
#endif
DBG(" ESP-NOW Initialized.");
#endif //USE_ESPNOW
#endif // USE_ESPNOW
begin_lora();
#ifdef DEBUG_CONFIG
// if (resetReason != ESP_RST_DEEPSLEEP) {
//checkConfig();
// checkConfig();
// }
#endif //DEBUG_CONFIG
#endif // DEBUG_CONFIG
}
// CRC16 from https://github.com/4-20ma/ModbusMaster/blob/3a05ff87677a9bdd8e027d6906dc05ca15ca8ade/src/util/crc16.h#L71
@ -320,7 +365,8 @@ void beginFDRS() {
@return calculated CRC (0x0000..0xFFFF)
*/
static uint16_t crc16_update(uint16_t crc, uint8_t a) {
static uint16_t crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
@ -335,7 +381,8 @@ static uint16_t crc16_update(uint16_t crc, uint8_t a) {
return crc;
}
void transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) {
void transmitLoRa(uint16_t *destMAC, DataReading *packet, uint8_t len)
{
#ifdef USE_LORA
uint8_t pkt[6 + (len * sizeof(DataReading))];
uint16_t calcCRC = 0x0000;
@ -345,68 +392,83 @@ void transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) {
pkt[2] = (LoRaAddress >> 8);
pkt[3] = (LoRaAddress & 0x00FF);
memcpy(&pkt[4], packet, len * sizeof(DataReading));
for(int i = 0; i < (sizeof(pkt) - 2); i++) { // Last 2 bytes are CRC so do not include them in the calculation itself
//printf("CRC: %02X : %d\n",calcCRC, i);
for (int i = 0; i < (sizeof(pkt) - 2); i++)
{ // Last 2 bytes are CRC so do not include them in the calculation itself
// printf("CRC: %02X : %d\n",calcCRC, i);
calcCRC = crc16_update(calcCRC, pkt[i]);
}
#ifndef LORA_ACK
calcCRC = crc16_update(calcCRC, 0xA1); // Recalculate CRC for No ACK
#endif // LORA_ACK
#endif // LORA_ACK
pkt[len * sizeof(DataReading) + 4] = (calcCRC >> 8);
pkt[len * sizeof(DataReading) + 5] = (calcCRC & 0x00FF);
#ifdef LORA_ACK // Wait for ACK
#ifdef LORA_ACK // Wait for ACK
int retries = FDRS_LORA_RETRIES + 1;
while(retries != 0) {
if(transmitLoRaMsgwAck != 0)
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX) + ". Retries remaining: " + String(retries - 1) + ", Ack Ok " + String((float)msgOkLoRa/transmitLoRaMsgwAck*100) + "%");
else
while (retries != 0)
{
if (transmitLoRaMsgwAck != 0)
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX) + ". Retries remaining: " + String(retries - 1) + ", Ack Ok " + String((float)msgOkLoRa / transmitLoRaMsgwAck * 100) + "%");
else
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX) + ". Retries remaining: " + String(retries - 1));
//printLoraPacket(pkt,sizeof(pkt));
int state = radio.transmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
// printLoraPacket(pkt,sizeof(pkt));
int state = radio.transmit(pkt, sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE)
{
}
else
{
DBG(" failed, code " + String(state));
while (true)
;
}
transmitLoRaMsgwAck++;
unsigned long loraAckTimeout = millis() + FDRS_ACK_TIMEOUT;
unsigned long loraAckTimeout = millis() + FDRS_ACK_TIMEOUT;
retries--;
delay(10);
while(returnCRC == CRC_NULL && (millis() < loraAckTimeout)) {
while (returnCRC == CRC_NULL && (millis() < loraAckTimeout))
{
handleLoRa();
}
if(returnCRC == CRC_OK) {
//DBG("LoRa ACK Received! CRC OK");
if (returnCRC == CRC_OK)
{
// DBG("LoRa ACK Received! CRC OK");
msgOkLoRa++;
return; // we're done
return; // we're done
}
else if(returnCRC == CRC_BAD) {
//DBG("LoRa ACK Received! CRC BAD");
// Resend original packet again if retries are available
else if (returnCRC == CRC_BAD)
{
// DBG("LoRa ACK Received! CRC BAD");
// Resend original packet again if retries are available
}
else {
else
{
DBG("LoRa Timeout waiting for ACK!");
// resend original packet again if retries are available
}
}
#else // Send and do not wait for ACK reply
#else // Send and do not wait for ACK reply
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX));
//printLoraPacket(pkt,sizeof(pkt));
int state = radio.transmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
// printLoraPacket(pkt,sizeof(pkt));
int state = radio.transmit(pkt, sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE)
{
}
else
{
DBG(" failed, code " + String(state));
while (true);
while (true)
;
}
transmitLoRaMsgwAck++;
#endif // LORA_ACK
#endif // USE_LORA
#endif // LORA_ACK
#endif // USE_LORA
}
// For now SystemPackets will not use ACK but will calculate CRC
void transmitLoRa(uint16_t* destMAC, SystemPacket* packet, uint8_t len) {
void transmitLoRa(uint16_t *destMAC, SystemPacket *packet, uint8_t len)
{
#ifdef USE_LORA
uint8_t pkt[6 + (len * sizeof(SystemPacket))];
uint16_t calcCRC = 0x0000;
@ -416,38 +478,45 @@ void transmitLoRa(uint16_t* destMAC, SystemPacket* packet, uint8_t len) {
pkt[2] = (LoRaAddress >> 8);
pkt[3] = (LoRaAddress & 0x00FF);
memcpy(&pkt[4], packet, len * sizeof(SystemPacket));
for(int i = 0; i < (sizeof(pkt) - 2); i++) { // Last 2 bytes are CRC so do not include them in the calculation itself
//printf("CRC: %02X : %d\n",calcCRC, i);
for (int i = 0; i < (sizeof(pkt) - 2); i++)
{ // Last 2 bytes are CRC so do not include them in the calculation itself
// printf("CRC: %02X : %d\n",calcCRC, i);
calcCRC = crc16_update(calcCRC, pkt[i]);
}
calcCRC = crc16_update(calcCRC, 0xA1); // Recalculate CRC for No ACK
pkt[len * sizeof(SystemPacket) + 4] = (calcCRC >> 8);
pkt[len * sizeof(SystemPacket) + 5] = (calcCRC & 0x00FF);
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to destination 0x" + String(*destMAC, HEX));
//printLoraPacket(pkt,sizeof(pkt));
int state = radio.startTransmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
// printLoraPacket(pkt,sizeof(pkt));
int state = radio.startTransmit(pkt, sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE)
{
}
else
{
DBG(" failed, code " + String(state));
while (true);
while (true)
;
}
#endif // USE_LORA
#endif // USE_LORA
}
// getLoRa for Sensors
// USED to get ACKs (SystemPacket type) from LoRa gateway at this point. May be used in the future to get other data
// Return type is crcResult struct - CRC_OK, CRC_BAD, CRC_NULL. CRC_NULL used for non-ack data
crcResult getLoRa() {
crcResult getLoRa()
{
#ifdef USE_LORA
int packetSize = radio.getPacketLength();
if((packetSize - 6) % sizeof(SystemPacket) == 0 && packetSize > 0) { // packet size should be 6 bytes plus multiple of size of SystemPacket
if ((packetSize - 6) % sizeof(SystemPacket) == 0 && packetSize > 0)
{ // packet size should be 6 bytes plus multiple of size of SystemPacket
uint8_t packet[packetSize];
uint16_t packetCRC = 0x0000; // CRC Extracted from received LoRa packet
uint16_t calcCRC = 0x0000; // CRC calculated from received LoRa packet
uint16_t calcCRC = 0x0000; // CRC calculated from received LoRa packet
uint16_t sourceMAC = 0x0000;
uint16_t destMAC = 0x0000;
unsigned int ln = (packetSize - 6) / sizeof(SystemPacket);
SystemPacket receiveData[ln];
@ -457,104 +526,131 @@ crcResult getLoRa() {
sourceMAC = (packet[2] << 8) | packet[3];
packetCRC = ((packet[packetSize - 2] << 8) | packet[packetSize - 1]);
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(radio.getRSSI()) + "dBm, SNR: " + String(radio.getSNR()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX));
if (destMAC == LoRaAddress) { // The packet is for us so let's process it
//printLoraPacket(packet,sizeof(packet));
for(int i = 0; i < (packetSize - 2); i++) { // Last 2 bytes of packet are the CRC so do not include them in calculation
//printf("CRC: %02X : %d\n",calcCRC, i);
calcCRC = crc16_update(calcCRC, packet[i]);
if (destMAC == LoRaAddress)
{ // The packet is for us so let's process it
// printLoraPacket(packet,sizeof(packet));
for (int i = 0; i < (packetSize - 2); i++)
{ // Last 2 bytes of packet are the CRC so do not include them in calculation
// printf("CRC: %02X : %d\n",calcCRC, i);
calcCRC = crc16_update(calcCRC, packet[i]);
}
if(calcCRC == packetCRC) {
memcpy(receiveData, &packet[4], packetSize - 6); //Split off data portion of packet (N bytes)
if(ln == 1 && receiveData[0].cmd == cmd_ack) {
if (calcCRC == packetCRC)
{
memcpy(receiveData, &packet[4], packetSize - 6); // Split off data portion of packet (N bytes)
if (ln == 1 && receiveData[0].cmd == cmd_ack)
{
DBG("ACK Received - CRC Match");
}
else if(ln == 1 && receiveData[0].cmd == cmd_ping) { // We have received a ping request or reply??
if(receiveData[0].param == 1) { // This is a reply to our ping request
else if (ln == 1 && receiveData[0].cmd == cmd_ping)
{ // We have received a ping request or reply??
if (receiveData[0].param == 1)
{ // This is a reply to our ping request
is_ping = true;
DBG("We have received a ping reply via LoRa from address 0x" + String(sourceMAC, HEX));
}
else if(receiveData[0].param == 0) {
else if (receiveData[0].param == 0)
{
DBG("We have received a ping request from 0x" + String(sourceMAC, HEX) + ", Replying.");
SystemPacket pingReply = { .cmd = cmd_ping, .param = 1 };
SystemPacket pingReply = {.cmd = cmd_ping, .param = 1};
transmitLoRa(&sourceMAC, &pingReply, 1);
}
}
else { // data we have received is not yet programmed. How we handle is future enhancement.
else
{ // data we have received is not yet programmed. How we handle is future enhancement.
DBG("Received some LoRa SystemPacket data that is not yet handled. To be handled in future enhancement.");
DBG("ln: " + String(ln) + "data type: " + String(receiveData[0].cmd));
}
return CRC_OK;
}
else if(packetCRC == crc16_update(calcCRC,0xA1)) { // Sender does not want ACK and CRC is valid
memcpy(receiveData, &packet[4], packetSize - 6); //Split off data portion of packet (N bytes)
if(ln == 1 && receiveData[0].cmd == cmd_ack) {
else if (packetCRC == crc16_update(calcCRC, 0xA1))
{ // Sender does not want ACK and CRC is valid
memcpy(receiveData, &packet[4], packetSize - 6); // Split off data portion of packet (N bytes)
if (ln == 1 && receiveData[0].cmd == cmd_ack)
{
DBG("ACK Received - CRC Match");
}
else if(ln == 1 && receiveData[0].cmd == cmd_ping) { // We have received a ping request or reply??
if(receiveData[0].param == 1) { // This is a reply to our ping request
else if (ln == 1 && receiveData[0].cmd == cmd_ping)
{ // We have received a ping request or reply??
if (receiveData[0].param == 1)
{ // This is a reply to our ping request
is_ping = true;
DBG("We have received a ping reply via LoRa from address 0x" + String(sourceMAC, HEX));
}
else if(receiveData[0].param == 0) {
else if (receiveData[0].param == 0)
{
DBG("We have received a ping request from 0x" + String(sourceMAC, HEX) + ", Replying.");
SystemPacket pingReply = { .cmd = cmd_ping, .param = 1 };
SystemPacket pingReply = {.cmd = cmd_ping, .param = 1};
transmitLoRa(&sourceMAC, &pingReply, 1);
}
}
else { // data we have received is not yet programmed. How we handle is future enhancement.
else
{ // data we have received is not yet programmed. How we handle is future enhancement.
DBG("Received some LoRa SystemPacket data that is not yet handled. To be handled in future enhancement.");
DBG("ln: " + String(ln) + "data type: " + String(receiveData[0].cmd));
}
return CRC_OK;
}
else {
else
{
DBG("ACK Received CRC Mismatch! Packet CRC is 0x" + String(packetCRC, HEX) + ", Calculated CRC is 0x" + String(calcCRC, HEX));
return CRC_BAD;
}
}
else if((packetSize - 6) % sizeof(DataReading) == 0 && packetSize > 0) { // packet size should be 6 bytes plus multiple of size of DataReading)
else if ((packetSize - 6) % sizeof(DataReading) == 0 && packetSize > 0)
{ // packet size should be 6 bytes plus multiple of size of DataReading)
DBG("Incoming LoRa packet of " + String(packetSize) + " bytes received, with DataReading data to be processed.");
return CRC_NULL;
}
else {
else
{
DBG("Incoming LoRa packet of " + String(packetSize) + " bytes received, not destined to our address.");
return CRC_NULL;
}
}
else {
if(packetSize != 0) {
else
{
if (packetSize != 0)
{
DBG("Incoming LoRa packet of " + String(packetSize) + " bytes received");
return CRC_NULL;
}
}
return CRC_NULL;
return CRC_NULL;
#endif
}
void printLoraPacket(uint8_t* p, int size) {
void printLoraPacket(uint8_t *p, int size)
{
printf("Printing packet of size %d.", size);
for (int i = 0; i < size; i++ ) {
if (i % 2 == 0) printf("\n%02d: ", i);
for (int i = 0; i < size; i++)
{
if (i % 2 == 0)
printf("\n%02d: ", i);
printf("%02X ", p[i]);
}
printf("\n");
}
bool sendFDRS() {
bool sendFDRS()
{
DBG("Sending FDRS Packet!");
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
esp_now_ack_flag = CRC_NULL;
while(esp_now_ack_flag == CRC_NULL){
esp_now_send(gatewayAddress, (uint8_t *)&fdrsData, data_count * sizeof(DataReading));
esp_now_ack_flag = CRC_NULL;
while (esp_now_ack_flag == CRC_NULL)
{
delay(0);
}
if (esp_now_ack_flag == CRC_OK){
data_count = 0;
return true;
} else {
data_count = 0;
return false;
}
if (esp_now_ack_flag == CRC_OK)
{
data_count = 0;
return true;
}
else
{
data_count = 0;
return false;
}
#endif
#ifdef USE_LORA
transmitLoRa(&gtwyAddress, fdrsData, data_count);
@ -562,12 +658,14 @@ bool sendFDRS() {
data_count = 0;
returnCRC = CRC_NULL;
#endif
return true;
return true;
}
void loadFDRS(float d, uint8_t t) {
void loadFDRS(float d, uint8_t t)
{
DBG("Id: " + String(READING_ID) + " - Type: " + String(t) + " - Data loaded: " + String(d));
if (data_count > espnow_size) sendFDRS();
if (data_count > espnow_size)
sendFDRS();
DataReading dr;
dr.id = READING_ID;
dr.t = t;
@ -575,9 +673,11 @@ void loadFDRS(float d, uint8_t t) {
fdrsData[data_count] = dr;
data_count++;
}
void loadFDRS(float d, uint8_t t, uint16_t id) {
void loadFDRS(float d, uint8_t t, uint16_t id)
{
DBG("Id: " + String(id) + " - Type: " + String(t) + " - Data loaded: " + String(d));
if (data_count > espnow_size) sendFDRS();
if (data_count > espnow_size)
sendFDRS();
DataReading dr;
dr.id = id;
dr.t = t;
@ -585,7 +685,8 @@ void loadFDRS(float d, uint8_t t, uint16_t id) {
fdrsData[data_count] = dr;
data_count++;
}
void sleepFDRS(int sleep_time) {
void sleepFDRS(int sleep_time)
{
DBG("Sleepytime!");
#ifdef DEEP_SLEEP
DBG(" Deep sleeping.");
@ -601,24 +702,30 @@ void sleepFDRS(int sleep_time) {
delay(sleep_time * 1000);
}
void loopFDRS() {
if (is_added) {
if ((millis() - last_refresh) >= gtwy_timeout) {
last_refresh = millis();
void loopFDRS()
{
if (is_added)
{
if ((millis() - last_refresh) >= gtwy_timeout)
{
last_refresh = millis();
}
}
}
bool seekFDRS(int timeout) {
SystemPacket sys_packet = { .cmd = cmd_ping, .param = 0 };
bool seekFDRS(int timeout)
{
SystemPacket sys_packet = {.cmd = cmd_ping, .param = 0};
#ifdef USE_ESPNOW
esp_now_send(broadcast_mac, (uint8_t *) &sys_packet, sizeof(SystemPacket));
esp_now_send(broadcast_mac, (uint8_t *)&sys_packet, sizeof(SystemPacket));
DBG("Seeking nearby gateways");
uint32_t ping_start = millis();
is_ping = false;
while ((millis() - ping_start) <= timeout) {
yield(); //do I need to yield or does it automatically?
if (is_ping) {
while ((millis() - ping_start) <= timeout)
{
yield(); // do I need to yield or does it automatically?
if (is_ping)
{
DBG("Responded:" + String(incMAC[5]));
return true;
}
@ -627,70 +734,82 @@ bool seekFDRS(int timeout) {
#endif
}
bool addFDRS(int timeout, void (*new_cb_ptr)(DataReading)) {
callback_ptr = new_cb_ptr;
SystemPacket sys_packet = { .cmd = cmd_add, .param = 0 };
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &sys_packet, sizeof(SystemPacket));
DBG("ESP-NOW peer registration request submitted to " + String(gatewayAddress[5]));
uint32_t add_start = millis();
is_added = false;
while ((millis() - add_start) <= timeout) {
yield();
if (is_added) {
DBG("Registration accepted. Timeout: " + String(gtwy_timeout));
last_refresh = millis();
return true;
}
bool addFDRS(int timeout, void (*new_cb_ptr)(DataReading))
{
callback_ptr = new_cb_ptr;
SystemPacket sys_packet = {.cmd = cmd_add, .param = 0};
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *)&sys_packet, sizeof(SystemPacket));
DBG("ESP-NOW peer registration request submitted to " + String(gatewayAddress[5]));
uint32_t add_start = millis();
is_added = false;
while ((millis() - add_start) <= timeout)
{
yield();
if (is_added)
{
DBG("Registration accepted. Timeout: " + String(gtwy_timeout));
last_refresh = millis();
return true;
}
DBG("No gateways accepted the request");
return false;
#endif
}
DBG("No gateways accepted the request");
return false;
#endif
}
uint32_t pingFDRS(int timeout) {
SystemPacket sys_packet = { .cmd = cmd_ping, .param = 0 };
uint32_t pingFDRS(int timeout)
{
SystemPacket sys_packet = {.cmd = cmd_ping, .param = 0};
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &sys_packet, sizeof(SystemPacket));
esp_now_send(gatewayAddress, (uint8_t *)&sys_packet, sizeof(SystemPacket));
DBG(" ESP-NOW ping sent.");
uint32_t ping_start = millis();
is_ping = false;
while ((millis() - ping_start) <= timeout) {
yield(); //do I need to yield or does it automatically?
if (is_ping) {
while ((millis() - ping_start) <= timeout)
{
yield(); // do I need to yield or does it automatically?
if (is_ping)
{
DBG("Ping Returned:" + String(millis() - ping_start) + " from " + String(incMAC[5]));
return millis() - ping_start;
}
}
#endif
#ifdef USE_LORA
//transmitLoRa(gtwyAddress, sys_packet, data_count); // TODO: Make this congruent to esp_now_send()
// transmitLoRa(gtwyAddress, sys_packet, data_count); // TODO: Make this congruent to esp_now_send()
DBG(" LoRa ping not sent because it isn't implemented.");
#endif
}
bool subscribeFDRS(uint16_t sub_id){
for(int i = 0; i < 255; i++){
if ((subscription_list[i] == sub_id) && (active_subs[i])){
bool subscribeFDRS(uint16_t sub_id)
{
for (int i = 0; i < 255; i++)
{
if ((subscription_list[i] == sub_id) && (active_subs[i]))
{
DBG("You're already subscribed to that!");
return true;
}
}
for(int i = 0; i < 255; i++){
if (!active_subs[i]){
for (int i = 0; i < 255; i++)
{
if (!active_subs[i])
{
DBG("Adding subscription at position " + String(i));
subscription_list[i] = sub_id;
active_subs[i] = true;
return true;
subscription_list[i] = sub_id;
active_subs[i] = true;
return true;
}
}
DBG("No subscription could be established!");
return false;
}
bool unsubscribeFDRS(uint16_t sub_id){
for(int i = 0; i < 255; i++){
if ((subscription_list[i] == sub_id) && (active_subs[i])){
bool unsubscribeFDRS(uint16_t sub_id)
{
for (int i = 0; i < 255; i++)
{
if ((subscription_list[i] == sub_id) && (active_subs[i]))
{
DBG("Removing subscription.");
active_subs[i] = false;
return true;
@ -698,5 +817,4 @@ bool unsubscribeFDRS(uint16_t sub_id){
}
DBG("No subscription to remove");
return false;
}

Loading…
Cancel
Save