Skip to content
Snippets Groups Projects
Commit f098cfa6 authored by Callum Inglis's avatar Callum Inglis
Browse files

Refactor ESP8266 Transmitter

parent f873cec4
No related branches found
No related tags found
1 merge request!1Reliable polling
...@@ -38,6 +38,16 @@ ...@@ -38,6 +38,16 @@
#include <base64.h> #include <base64.h>
#include "SHTSensor.h" #include "SHTSensor.h"
// Debug / Polling / Transmitting Config
#define DEBUG 1
#define MIN_RAND_DELAY 500 // ms
#define MAX_RAND_DELAY 1250 // ms
#define POLLING_FREQUENCY 2500 // ms Take value every POLLING_FREQUENCY ms
#define MAX_TRANSMISSION_RETRIES 5 // No. Retries before recordings new values then retry
#define TX_AFTER_N_READINGS 10 // No. of samples, after which Transmit Avg Readings
#define TX_RESERVATION_TIME 1 // How long do we require use of TX for sending packets? (Seconds)
int pollEventCount = 0; // Number of times data has been sampled in this recording period
// Lora Config // Lora Config
#define ss 16 // Physical Pin 16 = D0 (Default is Physical Pin 5) #define ss 16 // Physical Pin 16 = D0 (Default is Physical Pin 5)
#define rst 0 #define rst 0
...@@ -61,23 +71,12 @@ byte localAddress = 0xBB; ...@@ -61,23 +71,12 @@ byte localAddress = 0xBB;
byte destination = 0xFF; byte destination = 0xFF;
uint32_t msgCount = 0; uint32_t msgCount = 0;
// Sensor Values - Temp / Humidity double temperature; // Sensor Values - Temp
double temperature; double humidity; // Sensor Values - Humidity
double humidity; double co2; // Sensor Values - Co2
double avgTemperature = 0; uint32_t ppm10; // Sensor Values - Particulate
double avgHumidity = 0; uint32_t ppm25; // Sensor Values - Particulate
uint32_t ppm100; // Sensor Values - Particulate
// Sensor Values - Co2
byte co2;
double avgCo2 = 0;
// Sensor Values - Particles
uint32_t ppm10;
uint32_t ppm25;
uint32_t ppm100;
uint32_t avgPpm10 = 0;
uint32_t avgPpm25 = 0;
uint32_t avgPpm100 = 0;
// Partial Sensor Data // Partial Sensor Data
struct pms5003data { struct pms5003data {
...@@ -91,12 +90,6 @@ struct pms5003data { ...@@ -91,12 +90,6 @@ struct pms5003data {
struct pms5003data data; struct pms5003data data;
// Polling / Transmitting Config
int pollingFrequency = 2500; // Polling Frequency, ms
int pollEventCount = 0; // Number of times data has been sampled in this recording period
int sendAfterPolls = 10; // Sample Period, after which Transmit Reading
int reservationTime = 1; // How long do we require use of TX / RX airways for sending packets?
/** /**
* Setup Humidity / Temperature Sensor * Setup Humidity / Temperature Sensor
*/ */
...@@ -117,10 +110,9 @@ double getTemperature() { ...@@ -117,10 +110,9 @@ double getTemperature() {
if (sht.readSample()) { if (sht.readSample()) {
t = sht.getTemperature(); t = sht.getTemperature();
temperature += t;
} }
return t; // -1 on error TODO Make this better! return t; // -1 on error
} }
double getHumidity() { double getHumidity() {
...@@ -128,12 +120,29 @@ double getHumidity() { ...@@ -128,12 +120,29 @@ double getHumidity() {
if (sht.readSample()) { if (sht.readSample()) {
h = sht.getHumidity(); h = sht.getHumidity();
humidity += h;
} }
return h; // -1 on error return h; // -1 on error
} }
/**
* TODO getCo2()
*/
double getCo2() {
return 0;
}
// TODO DOC
void resetCounters() {
ppm10 = 0;
ppm25 = 0;
ppm100 = 0;
temperature = 0;
humidity = 0;
pollEventCount = 0;
}
bool setupLoRa() { bool setupLoRa() {
LoRa.setPins(ss, rst, dio0); LoRa.setPins(ss, rst, dio0);
if (!LoRa.begin(loraFrequency)) { if (!LoRa.begin(loraFrequency)) {
...@@ -155,15 +164,8 @@ bool setupLoRa() { ...@@ -155,15 +164,8 @@ bool setupLoRa() {
* 2021-11-07 - This method proved unreliable, switched to casting ESP.getChipID() as a string instead * 2021-11-07 - This method proved unreliable, switched to casting ESP.getChipID() as a string instead
*/ */
String getSensorUID() { String getSensorUID() {
// uint64_t chipid = ESP.getChipId(); String sensorID = "EMIEI-"; // [E]nviornmental [M]onitoring [I]ndepenet of [E]xisting [I]nfrastructure
// uint16_t chip = (uint16_t)(chipid >> 32);
//
// char sensorID[23];
// snprintf(sensorID, 23, "EMIEI-%04X%08X", chip, (uint32_t)chipid);
String sensorID = "EMIEI-";
sensorID.concat(String(ESP.getChipId())); sensorID.concat(String(ESP.getChipId()));
return sensorID; return sensorID;
} }
...@@ -218,9 +220,51 @@ boolean readPMSdata(Stream *s) { ...@@ -218,9 +220,51 @@ boolean readPMSdata(Stream *s) {
return true; return true;
} }
/* Turn on Reciever, /**
* listen for messages for [listenDuration] seconds, * Provided sensor data, construct JSON object ready for transmission, Averaged over numSamples
* Return true if no messages recieved *
* @param messageID
* @param numSamples Numer of samples averages
* @param avgPpm10 Average Particuate readings
* @param avgPpm25 Average Particuate readings
* @param avgPpm100 Average Particuate readings
* @param avgTemperature Average Temperature
* @param avgHumidity Average Humidity
* @param avgCo2 Average Co2
*
* @return DynamicJsonDocument sensorData
*/
DynamicJsonDocument prepareSensorData(int messageID, int numSamples, uint32_t avgPpm10, uint32_t avgPpm25, uint32_t avgPpm100, double avgTemperature, double avgHumidity, double avgCo2) {
DynamicJsonDocument doc(2048);
JsonObject metadata = doc.createNestedObject("sensorMetadata");
metadata["uid"] = getSensorUID();
metadata["messageID"] = messageID;
metadata["samplePeriod"] = numSamples;
JsonObject data = doc.createNestedObject("data");
JsonObject ppm = data.createNestedObject("ppm"); // Particulates
ppm["p10"] = avgPpm10;
ppm["p25"] = avgPpm25;
ppm["p100"] = avgPpm100;
JsonObject sht = data.createNestedObject("sht"); // Temp, Humidity
sht["temperature"] = avgTemperature;
sht["humidity"] = avgHumidity;
JsonObject co2 = data.createNestedObject("co2"); // TODO Co2
co2["tmp"] = avgCo2;
return doc;
}
/**
* Listen on Lora for other messages, returns true if no messages detected within [listenDuration] seconds
* Use prior to transmissions to avoid interruption of other messages
*
* @param int listenDuration How long to listen on Lora RX in Seconds
* @returns boolean If messages detected within listenDuration
*/ */
boolean clearToSend(int listenDuration) { boolean clearToSend(int listenDuration) {
int listenUntil = now() + listenDuration; int listenUntil = now() + listenDuration;
...@@ -230,7 +274,8 @@ boolean clearToSend(int listenDuration) { ...@@ -230,7 +274,8 @@ boolean clearToSend(int listenDuration) {
int packetSize = LoRa.parsePacket(); int packetSize = LoRa.parsePacket();
if (packetSize) { if (packetSize) {
return false; // Other message heard on Rx, we can not transmit just now. Serial.println("[-] TX Busy - Not Clear To Send");
return false; // Other message heard on Rx, infer that we can not transmit just now.
} }
delay(5); delay(5);
...@@ -239,193 +284,223 @@ boolean clearToSend(int listenDuration) { ...@@ -239,193 +284,223 @@ boolean clearToSend(int listenDuration) {
return true; // We didn't hear anything, so continue return true; // We didn't hear anything, so continue
} }
// Listen of listenDuration seconds // Introduce random delay to avoid another collision
// If we see a response to our txHello packet, and txHello.okToTransmit is True, we can send our packet void waitRandomDelay(int minSeconds = 0) {
boolean listenTxHelloAccept(int listenDuration, int messageID) { int randDelay = (minSeconds * 1000) + random(MIN_RAND_DELAY, MAX_RAND_DELAY);
int time_now = now() + listenDuration; if (DEBUG){
Serial.println("[i] Delay for " + String(randDelay) + "ms");
}
delay(randDelay);
}
/**
* Send short "clear to send?" packet
* Tx - "I've got data to send!" + UID
* @param messageID ID of this message / sample period
*/
void sendTxHello(int messageID) {
Serial.println("[+] Transmit - \"Hello\"");
DynamicJsonDocument txHello(2048);
txHello["uid"] = getSensorUID();
txHello["reservationTime"] = TX_RESERVATION_TIME;
txHello["messageID"] = messageID;
sendJsonPayloadWithLoRa(txHello);
}
/**
* Send Payload
* Tx - Sensor Payload
* @param payload JSON Payload to be sent
*/
void sendTxPayload(DynamicJsonDocument payload) {
Serial.println("[+] Transmit - Payload");
sendJsonPayloadWithLoRa(payload);
}
/**
* Listen for messages on TX, expecting JSON
*
* @param listenDuration How long to listen on Lora RX in Seconds
* @return StaticJsonDocument|null RX Payload in JSON, null on timeout reached or error
*/
StaticJsonDocument<1024> listenForAndConsumeMessage(int listenDuration) {
int listenUntil = now() + listenDuration;
StaticJsonDocument<1024> json;
// Listen until timeout expires // Listen until timeout expires
Serial.println("[+] Transmit - \"Hello\" - Listening for ack & clear to send"); while (listenUntil >= now()) {
while (time_now >= now()) {
int packetSize = LoRa.parsePacket(); int packetSize = LoRa.parsePacket();
if (!packetSize) {
delay(3);
continue;
}
// Read in packet, ensure we only bring in anything after { and before } inclusive
String incoming = "";
char temp;
if (packetSize) { while (LoRa.available()) {
String incoming = ""; temp = (char)LoRa.read();
char temp;
while (LoRa.available()) {
// TODO - Tidy this up, ensure we only read in valid JSON
temp = (char)LoRa.read();
// Opening {
if (incoming.length() == 0 && temp == '{') {
incoming = "{";
// Closing }
} else if (temp == '}') {
incoming.concat("}");
break;
// Anything else that's valid
} else if (incoming.length() > 0) {
incoming.concat(temp);
}
}
// DEBUG if (incoming.length() == 0 && temp == '{') { // Opening {
// Serial.print("in listenTxHelloAccept() Recieved: \n"); incoming = "{";
// Serial.println(incoming);
} else if (temp == '}') { // Closing }
// Verify its OK to transmit incoming.concat("}");
StaticJsonDocument<200> doc; break;
deserializeJson(doc, incoming);
} else if (incoming.length() > 0) { // Anything else that's valid
const bool okToTransmit = doc["okTransmit"]; incoming.concat(temp);
const String authIsForUid = doc["uid"]; }
const int authIsForMessageID = doc["messageID"];
const String gatewayUid = doc["gatewayUid"];
// Verify txHello.okToTransmit is True & UID Match & Message IDs Match
if (authIsForUid == getSensorUID()) { Serial.println("[+] Transmit - \"Hello\" - Sensor UID Match!"); } else { Serial.println("[-] Transmit - \"Hello\" - Sensor UID Mis-Match! " + String(authIsForUid) + " vs " + String(getSensorUID())); }
if (authIsForMessageID == messageID) { Serial.println("[+] Transmit - \"Hello\" - Message ID Match!"); } else { Serial.println("[-] Transmit - \"Hello\" - MessageID Mis-Match!"); }
return (okToTransmit
&& authIsForUid == getSensorUID()
&& authIsForMessageID == messageID);
} }
delay(3); // Deserialize - TODO Error Handling https://arduinojson.org/v6/api/json/deserializejson/
deserializeJson(json, incoming);
break;
} }
Serial.println("[-] Transmit - \"Hello\" - Timeout while waiting for Clear to Send\n\n"); return json;
return false; // We didn't hear anything, conside this as meaning "Can't Send"
} }
void sendJsonPayloadWithLoRa(DynamicJsonDocument payload) { /**
LoRa.beginPacket(); * Listen for response to TxHello for [listenDuration] seconds, check Sensor UID & Message ID match and return true if we have clear to transmit payload.
serializeJson(payload, LoRa); * @param listenDuration How long to listen on Lora RX in Seconds
LoRa.endPacket(); * @param messageID ID of message we are expecting to receive
} * @return boolean Clear to Transmit
*/
boolean listenForTxHelloAccept(int listenDuration, int messageID) {
Serial.println("[+] Transmit - \"Hello\" - Listening for \"Hello\" Ack & Clear to Send");
// TODO - Finish Acks & Naks StaticJsonDocument<1024> json = listenForAndConsumeMessage(listenDuration);
boolean transmitData(DynamicJsonDocument payload) {
// Listen for other communication // Timeout, likely TX Hello was not recieved or ack got lost
// Rx - Listen for other messages, if no messages heard then continue if (json.isNull()) {
if (!clearToSend(0.5)) { Serial.println("[-] Transmit - \"Hello\" - Timeout while waiting for Clear to Send\n\n");
Serial.println("[-] Airways busy, could not send"); return false;
delay(random(500, 1250)); // Introduce random delay to avoid another collision }
// TODO Refactor const bool okToTransmit = json["okTransmit"];
while (!clearToSend(0.5)) { const String authIsForUid = json["uid"];
Serial.println("[-] Airways busy, could not send"); const int authIsForMessageID = json["messageID"];
delay(random(500, 1250)); // Introduce random delay to avoid another collision const String gatewayUid = json["gatewayUid"];
// Verify txHello.okTransmit is True and Sensor UID & Message IDs Match
if (DEBUG) {
if (authIsForUid == getSensorUID()) {
Serial.println("[+] Transmit - \"Hello\" - Sensor UID Match!");
} else {
Serial.println("[-] Transmit - \"Hello\" - Sensor UID Mis-Match! " + String(authIsForUid) + " vs " + String(getSensorUID()));
}
if (authIsForMessageID == messageID) {
Serial.println("[+] Transmit - \"Hello\" - Message ID Match!");
} else {
Serial.println("[-] Transmit - \"Hello\" - MessageID Mis-Match!");
} }
//return false;
} }
Serial.println("[+] Transmit - \"Hello\""); // Ok To Trasmit, Sensor UID Match & Message ID Match
// Send short "clear to send?" packet bool clearToSend = (okToTransmit
// Tx - "I've got data to send!" + UID && authIsForUid == getSensorUID()
// RX - Continue upon recieving "OK" + UID + TX_Auth_ID && authIsForMessageID == messageID);
DynamicJsonDocument txHello(2048);
txHello["uid"] = sensorID;
txHello["reservationTime"] = reservationTime; // How long do we require reservation of radio?
txHello["messageID"] = msgCount;
sendJsonPayloadWithLoRa(txHello);
if (!listenTxHelloAccept(reservationTime * 1.5, msgCount)) { // Can't transmit just now if (DEBUG) {
Serial.println("[-] Transmit - \"Hello\" - Can Not Transmit At This Time\n"); if (clearToSend) {
return false; Serial.println("[+] Transmit - \"Hello\" - Recieved \"Clear to Transmit\" Payload");
} else {
Serial.println("[-] Transmit - \"Hello\" - Can Not Transmit At This Time");
}
} }
Serial.println("[+] Recieved - Clear to Transmit Payload"); // Else we have clear to send return clearToSend;
}
// TODO DOC
boolean listenForTxPayloadAccept(int listenDuration, int messageID) {
Serial.println("[.] Transmit - Payload - Listening for Ack");
// Transmit Payload StaticJsonDocument<1024> json = listenForAndConsumeMessage(listenDuration);
// Tx - Send payload + UID + TX_Auth_ID
// Rx - Listen for Ack/Nack
Serial.println("[+] Transmit - Payload");
sendJsonPayloadWithLoRa(payload);
// Timeout, likely TX Payload was not recieved or ack got lost.
if (json.isNull()) {
Serial.println("[-] Transmit - Payload - Ack Timeout Reached - Assuming Message Was Not Delivered\n\n");
return false;
}
// TODO Await Response Ack/Nak const bool ackStatus = json["ackStatus"];
int ackTimeout = 2; // Seconds const String authIsForUid = json["uid"];
int time_now = now() + ackTimeout; const int authIsForMessageID = json["replyMsgID"];
const String gatewayUid = json["gatewayUid"];
// Listen until timeout expires // Verify Sensor UID Match
Serial.println("[.] Transmit - Payload - Listening for Ack"); if (authIsForUid == getSensorUID()
while (time_now >= now()) { && authIsForMessageID == messageID) {
int packetSize = LoRa.parsePacket();
Serial.println("[+] Transmit - Payload - Ack Recieved: " + String(ackStatus) + "\n");
if (packetSize) { if (ackStatus) { return true; } // It all worked :)
String incoming = "";
char temp; // TODO Retransmit, recover, etc
Serial.println("[-] Transmit - Payload - Ack Failed - TODO Setup Retransmission");
while (LoRa.available()) { return false;
// TODO - Tidy this up, ensure we only read in valid JSON }
temp = (char)LoRa.read();
// TODO Else UID Mis-Match so we wait for next message
// Opening { Serial.println("[-] Transmit - Payload - Ack Message ID or Sensor ID Mis-Match");
if (incoming.length() == 0 && temp == '{') { return false;
incoming = "{"; }
// Closing } /**
} else if (temp == '}') { * Send JSON Payload over LoRa
incoming.concat("}"); * @param payload JSON Payload to be send
break; */
void sendJsonPayloadWithLoRa(DynamicJsonDocument payload) {
// Anything else that's valid LoRa.beginPacket();
} else if (incoming.length() > 0) { serializeJson(payload, LoRa);
incoming.concat(temp); LoRa.endPacket();
} }
}
// DEBUG // TODO - Finish Acks & Naks
// Serial.print("\nin listedForAck() Recieved: \n"); boolean transmitData(DynamicJsonDocument payload) {
// Serial.println(incoming);
StaticJsonDocument<200> doc; // TODO MAX_RETRIES
deserializeJson(doc, incoming);
const bool ackStatus = doc["ackStatus"]; // Listen for other communication
const String authIsForUid = doc["uid"]; // Rx - Listen for other messages, if no messages heard then continue
const String gatewayUid = doc["gatewayUid"]; if (!clearToSend(0.5)) {
waitRandomDelay(); // Wait for short time before retrying
while (!clearToSend(0.5)) { waitRandomDelay(); } // TODO MAX_TIMEOUT
}
// Verify txHello.okToTransmit is True & UID Match // Send TX Hello
if (authIsForUid == getSensorUID()) { sendTxHello(msgCount);
Serial.println("[+] Transmit - Payload - Ack Recieved: " + String(ackStatus) + "\n");
if (ackStatus) { return true; } // It all worked :)
// TODO Retransmit, recover, etc // Await TX Hello Auth - Expect: Timeout | Not Auth | Accept + Clear To Transmit
return false; if (!listenForTxHelloAccept(TX_RESERVATION_TIME * 1.5, msgCount)) {
} return false; // Can't transmit just now, we will retry
}
// Else UID Mis-Match so we wait for next message // Send TX Payload
} sendTxPayload(payload);
delay(5); // Await TX Payload Ack - Expect: Timeout | Nack | Accept + Data Match
if (!listenForTxPayloadAccept(2, msgCount)) {
return false; // TODO Ack Failed Setup a retry here!
} }
// TODO After Timeout we need to deal with! // TODO Update Sensor Config
Serial.println("[-] Transmit - Payload - Ack Timeout Reached - Assuming Message Was Not Delivered");
// TODO Listen for ack/nak // TODO Clear values & Continue
resetCounters();
// T+2 Rx OFF Serial.println("Packet Sent Succesfully\n");
// Handle Ack + UID + Next_Send_Interval Serial.println("---------------+++++-------------------");
// Handle Nak + UID: GoTo T-3 msgCount++;
// Handle No Response: GoTo T-3
// T+3 Tx/Rx Window Expires
return true;
//LoRa.write(localAddress);
// LoRa.write(msgCount);
//LoRa.write(outgoing.length());
//LoRa.print(outgoing);
return true;
} }
void setup() { void setup() {
...@@ -434,17 +509,14 @@ void setup() { ...@@ -434,17 +509,14 @@ void setup() {
Serial.begin(115200); // Console Debug Serial.begin(115200); // Console Debug
Serial.println("\n\n[+] Transmitter Node"); Serial.println("\n\n[+] Transmitter Node");
sensorID = getSensorUID();
pmsSerial.begin(9600); // Partical Sensor pmsSerial.begin(9600); // Partical Sensor
// Setup Sensors // Setup Hardware
if (!setupSHT()) { while(1); } // Temp/Humidity - Die on Error if (!setupSHT()) { while(1); } // Temp/Humidity - Die on Error
// Setup LoRa
if (!setupLoRa()) { while(1); } // Die on error if (!setupLoRa()) { while(1); } // Die on error
} }
// Main
void loop() { void loop() {
// TODO Gather Sensor Data // TODO Gather Sensor Data
...@@ -457,93 +529,74 @@ void loop() { ...@@ -457,93 +529,74 @@ void loop() {
pollEventCount++; pollEventCount++;
Serial.println(); if (DEBUG) {
Serial.print(String(pollEventCount) + ") "); Serial.println();
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard); Serial.print(String(pollEventCount) + ") ");
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard); Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 10: "); Serial.print(data.pm100_standard); Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tTemp: "); Serial.print(getTemperature()); Serial.print("\t\tPM 10: "); Serial.print(data.pm100_standard);
Serial.print("\t\tHumidity: "); Serial.print(getHumidity()); Serial.print("\t\tTemp: "); Serial.print(getTemperature());
Serial.print("\t\tHumidity: "); Serial.print(getHumidity());
Serial.print("\t\tCo2: "); Serial.print(getCo2());
}
// Add to Average // Add to Average
// Standard (_standard) or Environmental (_env) temperature += getTemperature();
ppm10 = ppm10 + data.pm10_standard; humidity += getHumidity();
co2 += getCo2();
ppm10 = ppm10 + data.pm10_standard; // Standard (_standard) or Environmental (_env) readings for Particulate Data
ppm25 = ppm25 + data.pm25_standard; ppm25 = ppm25 + data.pm25_standard;
ppm100 = ppm100 + data.pm100_standard; ppm100 = ppm100 + data.pm100_standard;
if (pollEventCount == sendAfterPolls) { // If we should now transmit
// Average Values over recording period if (pollEventCount >= TX_AFTER_N_READINGS) {
avgPpm10 = ppm10 / sendAfterPolls;
avgPpm25 = ppm25 / sendAfterPolls;
avgPpm100 = ppm100 / sendAfterPolls;
avgTemperature = temperature / sendAfterPolls;
avgHumidity = humidity / sendAfterPolls;
// TODO Transmit Sensor Data
Serial.println("");
Serial.print("Avg ppm10: "); Serial.print(avgPpm10);
Serial.print("\t\tAvg ppm25: "); Serial.print(avgPpm25);
Serial.print("\t\tAvg ppm100: "); Serial.print(avgPpm100);
Serial.print("\t\tAvg Temp: "); Serial.print(avgTemperature);
Serial.print("\t\tAvg Humidity: "); Serial.print(avgHumidity);
Serial.print("\t\tChip ID: "); Serial.println(sensorID);
Serial.println("");
// LORA SEND
DynamicJsonDocument doc(2048);
JsonObject metadata = doc.createNestedObject("sensorMetadata");
metadata["uid"] = sensorID;
metadata["messageID"] = msgCount;
metadata["samplePeriod"] = sendAfterPolls; // TODO: Multiply by poll duration!
JsonObject data = doc.createNestedObject("data");
JsonObject ppm = data.createNestedObject("ppm"); // Particulates
ppm["p10"] = avgPpm10;
ppm["p25"] = avgPpm25;
ppm["p100"] = avgPpm100;
JsonObject sht = data.createNestedObject("sht"); // Temp, Humidity
sht["temperature"] = avgTemperature;
sht["humidity"] = avgHumidity;
JsonObject co2 = data.createNestedObject("co2"); // Co2
co2["tmp"] = 0;
if (transmitData(doc)) {
Serial.println("Packet Sent\n");
} else {
int maxRetries = 10; // TODO Move to Config
int numRetries = 1;
while (!transmitData(doc) && numRetries < maxRetries){
numRetries++;
Serial.println("[-] Failed to send packet, retrying. Attempt " + String(numRetries) + " of " + String(maxRetries) + "\n");
delay(reservationTime + random(1250, 5250)); // Introduce random delay to avoid another collision
}
if (numRetries >= maxRetries) {
Serial.println("[-] Failed to send packet, max retries reached. Aborting");
// TODO Don't Clear Counters, record more values then try to retransmit // Average Values over recording period
} double avgTemperature = temperature / pollEventCount;
double avgHumidity = humidity / pollEventCount;
double avgCo2 = co2 / pollEventCount;
uint32_t avgPpm10 = ppm10 / pollEventCount;
uint32_t avgPpm25 = ppm25 / pollEventCount;
uint32_t avgPpm100 = ppm100 / pollEventCount;
if (DEBUG) {
Serial.println("");
Serial.print("Avg ppm10: "); Serial.print(avgPpm10);
Serial.print("\t\tAvg ppm25: "); Serial.print(avgPpm25);
Serial.print("\t\tAvg ppm100: "); Serial.print(avgPpm100);
Serial.print("\t\tAvg Temp: "); Serial.print(avgTemperature);
Serial.print("\t\tAvg Humidity: "); Serial.print(avgHumidity);
Serial.print("\t\tAvg Co2: "); Serial.print(avgCo2);
Serial.print("\t\tChip ID: "); Serial.println(getSensorUID());
Serial.println("");
} }
// Prepare Data For Send
DynamicJsonDocument sensorData = prepareSensorData(msgCount, pollEventCount, avgPpm10, avgPpm25, avgPpm100, avgTemperature, avgHumidity, avgCo2);
// Reset Loop Values // Transmit
ppm10 = 0; if (transmitData(sensorData)) {
ppm25 = 0; return; // It all worked, values reset, now record new values
ppm100 = 0; }
temperature = 0;
humidity = 0; // Transmission failed, handle re-tries
int numRetries = 1;
pollEventCount = 0; while (!transmitData(sensorData) && numRetries < MAX_TRANSMISSION_RETRIES){
Serial.println("---------------+++++-------------------"); numRetries++;
Serial.println("[-] Failed to send packet, retrying. Attempt " + String(numRetries) + " of " + String(MAX_TRANSMISSION_RETRIES) + "\n");
waitRandomDelay(TX_RESERVATION_TIME); // Introduce random delay to avoid another collision
}
// We were able to transmit after retries, values reset, now record new values
if (numRetries < MAX_TRANSMISSION_RETRIES) {
return;
}
msgCount++; // Failed to transmit - Don't Clear Counters, record more values then try to retransmit on next send
Serial.println("[-] Failed to send packet, max retries reached. Aborting");
return;
} }
delay(pollingFrequency); delay(POLLING_FREQUENCY);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment