diff --git a/src/fdrs_node.h b/src/fdrs_node.h index 957277f..aeca8ae 100644 --- a/src/fdrs_node.h +++ b/src/fdrs_node.h @@ -88,7 +88,7 @@ uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC}; uint16_t gtwyAddress = ((gatewayAddress[4] << 8) | GTWY_MAC); #ifdef USE_LORA uint16_t LoRaAddress = ((UniqueID8[6] << 8) | UniqueID8[7]); -unsigned long transmitLoRaMsg = 0; // Number of total LoRa packets destined for us and of valid size +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; @@ -265,56 +265,84 @@ static uint16_t crc16_update(uint16_t crc, uint8_t a) { return crc; } -// USED to get ACKs from LoRa gateway at this point. May be used in the future to get other data +// 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() { #ifdef USE_LORA int packetSize = LoRa.parsePacket(); - 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 sourceMAC = 0x0000; - uint16_t destMAC = 0x0000; uint16_t packetCRC = 0x0000; // CRC Extracted from received LoRa packet uint16_t calcCRC = 0x0000; // CRC calculated from received LoRa packet + uint16_t sourceMAC = 0x0000; + uint16_t destMAC = 0x0000; + uint ln = (packetSize - 6) / sizeof(SystemPacket); SystemPacket receiveData[ln]; - + LoRa.readBytes((uint8_t *)&packet, packetSize); - + destMAC = (packet[0] << 8) | packet[1]; sourceMAC = (packet[2] << 8) | packet[3]; packetCRC = ((packet[packetSize - 2] << 8) | packet[packetSize - 1]); - DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(LoRa.packetRssi()) + "dBi, SNR: " + String(LoRa.packetSnr()) + "dB, PacketCRC: 0x" + String(packetCRC, 16)); - if (destMAC == LoRaAddress) { + DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(LoRa.packetRssi()) + "dBm, SNR: " + String(LoRa.packetSnr()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX)); + if (destMAC == LoRaAddress) { // The packet is for us so let's process it //printLoraPacket(packet,sizeof(packet)); - memcpy(receiveData, &packet[4], packetSize - 6); //Split off data portion of packet (N bytes) - if (ln == 1 && receiveData[0].cmd == cmd_ack) { // We have received an ACK packet - if (packetCRC == 0xFFFF) { - DBG("ACK Received - address 0x" + String(sourceMAC, 16) + "(hex) does not want ACKs"); - return CRC_OK; - } - else { - 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) { - DBG("ACK Received - CRC Match"); - return CRC_OK; - } - else { - DBG("ACK Received CRC Mismatch! Packet CRC is 0x" + String(packetCRC, 16) + ", Calculated CRC is 0x" + String(calcCRC, 16)); - return CRC_BAD; - } - } + 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]); } - else { // data we have received is not of type ACK_T. How we handle is future enhancement. - DBG("Received some LoRa SystemPacket data that is not of type ACK. To be handled in future enhancement."); - DBG("ln: " + String(ln) + "data type: " + String(receiveData[0].cmd)); - return CRC_NULL; + 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 + is_ping = true; + DBG("We have received a ping reply via LoRa from address 0x" + String(sourceMAC, HEX)); + } + 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 }; + transmitLoRa(&sourceMAC, &pingReply, 1); + } + } + 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) { + 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 + is_ping = true; + DBG("We have received a ping reply via LoRa from address 0x" + String(sourceMAC, HEX)); + } + 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 }; + transmitLoRa(&sourceMAC, &pingReply, 1); + } + } + 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 { + 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) { // 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; } @@ -323,25 +351,17 @@ crcResult getLoRa() { 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) { - printf("Printing packet of size %d.", size); - for (int i = 0; i < size; i++ ) { - if (i % 2 == 0) printf("\n%02d: ", i); - printf("%02X ", p[i]); - } - printf("\n"); -} - -bool 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; @@ -351,7 +371,7 @@ bool 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 + 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]); } @@ -362,50 +382,83 @@ bool transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) { pkt[len * sizeof(DataReading) + 5] = (calcCRC & 0x00FF); #ifdef LORA_ACK // Wait for ACK int retries = LORA_RETRIES + 1; - while (retries != 0) { - if (transmitLoRaMsg != 0){ - DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, 16) + " to gateway 0x" + String(*destMAC, 16) + ". Retries remaining: " + String(retries - 1) + ", CRC OK " + String((float)msgOkLoRa / transmitLoRaMsg * 100) + "%"); - }else{ - DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, 16) + " to gateway 0x" + String(*destMAC, 16) + ". Retries remaining: " + String(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 + 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)); LoRa.beginPacket(); LoRa.write((uint8_t*)&pkt, sizeof(pkt)); LoRa.endPacket(); - transmitLoRaMsg++; - unsigned long loraAckTimeout = millis() + LORA_ACK_TIMEOUT; + transmitLoRaMsgwAck++; + unsigned long loraAckTimeout = millis() + LORA_ACK_TIMEOUT; retries--; delay(10); - while (returnCRC == CRC_NULL && (millis() < loraAckTimeout)) { + while(returnCRC == CRC_NULL && (millis() < loraAckTimeout)) { returnCRC = getLoRa(); } - if (returnCRC == CRC_OK) { + if(returnCRC == CRC_OK) { //DBG("LoRa ACK Received! CRC OK"); msgOkLoRa++; - return true; // we're done + return; // we're done } - else if (returnCRC == CRC_BAD) { + else if(returnCRC == CRC_BAD) { //DBG("LoRa ACK Received! CRC BAD"); // Resend original packet again if retries are available } else { DBG("LoRa Timeout waiting for ACK!"); // resend original packet again if retries are available - } + } } - return false; #else // Send and do not wait for ACK reply - DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, 16) + " to gateway 0x" + String(*destMAC, 16)); + 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)); LoRa.beginPacket(); LoRa.write((uint8_t*)&pkt, sizeof(pkt)); LoRa.endPacket(); - transmitLoRaMsg++; - return true; + transmitLoRaMsgwAck++; #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) { +#ifdef USE_LORA + uint8_t pkt[6 + (len * sizeof(SystemPacket))]; + uint16_t calcCRC = 0x0000; + + pkt[0] = (*destMAC >> 8); + pkt[1] = (*destMAC & 0x00FF); + 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); + 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)); + LoRa.beginPacket(); + LoRa.write((uint8_t*)&pkt, sizeof(pkt)); + LoRa.endPacket(); +#endif // USE_LORA +} + + +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); + printf("%02X ", p[i]); + } + printf("\n"); +} + bool sendFDRS() { DBG("Sending FDRS Packet!"); #ifdef USE_ESPNOW @@ -425,17 +478,12 @@ bool sendFDRS() { #endif #ifdef USE_LORA - if(transmitLoRa(>wyAddress, fdrsData, data_count)){ - data_count = 0; - returnCRC = CRC_NULL; - return true; - } else { - data_count = 0; - returnCRC = CRC_NULL; - return false; - } + transmitLoRa(>wyAddress, fdrsData, data_count); + DBG(" LoRa sent."); + data_count = 0; + returnCRC = CRC_NULL; #endif -return false; +return true; } void loadFDRS(float d, uint8_t t) {