Skip to content

Commit ee7d55e

Browse files
aerlonTD-er
authored andcommitted
- Make each mesh backend use a unique NetworkInfo class and separate connectionQueue and latestTransmissionOutcomes vectors.
- Deprecate NetworkInfo and TransmissionResult classes. - Add single recipient transmission methods. - Add a getCurrentMessage method to TcpIpMeshBackend to maintain feature parity when using single recipient transmission methods. - Increase code abstraction level in transmission methods. - Remove use of networkIndex except for in constructors, since it can change after each scan. - Make Espnow backend require at least BSSID to connect, and the TcpIp backend require at least SSID. - Make printAPInfo method take NetworkInfo as argument. - Add new TransmissionOutcome class to replace obsolete TransmissionResult. - Add _scanMutex. - Improve code abstraction in HelloEspnow.ino. - Update HelloEspnow.ino example to demonstrate the new features. - Update and improve comments.
1 parent 5d7302e commit ee7d55e

19 files changed

+979
-236
lines changed

libraries/ESP8266WiFiMesh/examples/HelloEspnow/HelloEspnow.ino

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
https://github.com/esp8266/Arduino/issues/1143
1515
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
1616
*/
17-
const char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes during ESP-NOW broadcasts and in the example networkFilter function below.
17+
const char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
1818
const char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
1919

2020
// A custom encryption key is required when using encrypted ESP-NOW transmissions. There is always a default Kok set, but it can be replaced if desired.
@@ -32,6 +32,8 @@ uint8_t espnowHashKey[16] = {0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, //
3232
unsigned int requestNumber = 0;
3333
unsigned int responseNumber = 0;
3434

35+
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
36+
3537
String manageRequest(const String &request, MeshBackendBase &meshInstance);
3638
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance);
3739
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
@@ -96,7 +98,7 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
9698
// With ESP-NOW there is no guarantee when or if a response will show up, it can happen before or after the stored message is changed.
9799
// So for ESP-NOW, adding unique identifiers in the response and request is required to associate a response with a request.
98100
Serial.print(F("Request sent: "));
99-
Serial.println(tcpIpInstance->getMessage().substring(0, 100));
101+
Serial.println(tcpIpInstance->getCurrentMessage().substring(0, 100));
100102
} else {
101103
Serial.print("UNKNOWN!: ");
102104
}
@@ -127,14 +129,18 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
127129
uint64_t targetNodeID = stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
128130

129131
if (targetNodeID < stringToUint64(meshInstance.getNodeID())) {
130-
MeshBackendBase::connectionQueue.push_back(NetworkInfo(networkIndex));
132+
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
133+
espnowInstance->connectionQueue().push_back(networkIndex);
134+
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
135+
tcpIpInstance->connectionQueue().push_back(networkIndex);
136+
} else {
137+
Serial.println(String(F("Invalid mesh backend!")));
138+
}
131139
}
132140
}
133141
}
134142
}
135143

136-
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
137-
138144
/**
139145
Callback used to decide which broadcast messages to accept. Only called for the first transmission in each broadcast.
140146
If true is returned from this callback, the first broadcast transmission is saved until the entire broadcast message has been received.
@@ -147,10 +153,8 @@ const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (E
147153
@return True if the broadcast should be accepted. False otherwise.
148154
*/
149155
bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance) {
150-
/**
151-
This example broadcastFilter will accept a transmission if it contains the broadcastMetadataDelimiter
152-
and as metaData either no targetMeshName or a targetMeshName that matches the MeshName of meshInstance.
153-
*/
156+
// This example broadcastFilter will accept a transmission if it contains the broadcastMetadataDelimiter
157+
// and as metaData either no targetMeshName or a targetMeshName that matches the MeshName of meshInstance.
154158

155159
int32_t metadataEndIndex = firstTransmission.indexOf(broadcastMetadataDelimiter);
156160

@@ -230,7 +234,7 @@ void loop() {
230234

231235
uint32_t startTime = millis();
232236
espnowNode.attemptTransmission(espnowNode.getMessage());
233-
Serial.println("Scan and " + String(MeshBackendBase::latestTransmissionOutcomes.size()) + " transmissions done in " + String(millis() - startTime) + " ms.");
237+
Serial.println("Scan and " + String(espnowNode.latestTransmissionOutcomes().size()) + " transmissions done in " + String(millis() - startTime) + " ms.");
234238

235239
timeOfLastScan = millis();
236240

@@ -239,23 +243,23 @@ void loop() {
239243
espnowDelay(100);
240244

241245
// One way to check how attemptTransmission worked out
242-
if (MeshBackendBase::latestTransmissionSuccessful()) {
246+
if (espnowNode.latestTransmissionSuccessful()) {
243247
Serial.println(F("Transmission successful."));
244248
}
245249

246250
// Another way to check how attemptTransmission worked out
247-
if (MeshBackendBase::latestTransmissionOutcomes.empty()) {
251+
if (espnowNode.latestTransmissionOutcomes().empty()) {
248252
Serial.println(F("No mesh AP found."));
249253
} else {
250-
for (TransmissionResult &transmissionResult : MeshBackendBase::latestTransmissionOutcomes) {
251-
if (transmissionResult.transmissionStatus == TS_TRANSMISSION_FAILED) {
252-
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionResult.SSID);
253-
} else if (transmissionResult.transmissionStatus == TS_CONNECTION_FAILED) {
254-
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionResult.SSID);
255-
} else if (transmissionResult.transmissionStatus == TS_TRANSMISSION_COMPLETE) {
254+
for (TransmissionOutcome &transmissionOutcome : espnowNode.latestTransmissionOutcomes()) {
255+
if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_FAILED) {
256+
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionOutcome.SSID());
257+
} else if (transmissionOutcome.transmissionStatus() == TS_CONNECTION_FAILED) {
258+
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionOutcome.SSID());
259+
} else if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
256260
// No need to do anything, transmission was successful.
257261
} else {
258-
Serial.println(String(F("Invalid transmission status for ")) + transmissionResult.SSID + String(F("!")));
262+
Serial.println(String(F("Invalid transmission status for ")) + transmissionOutcome.SSID() + String(F("!")));
259263
assert(F("Invalid transmission status returned from responseHandler!") && false);
260264
}
261265
}
@@ -276,26 +280,28 @@ void loop() {
276280

277281
Serial.println("\nPerforming encrypted ESP-NOW transmissions.");
278282

283+
uint8_t targetBSSID[6] {0};
284+
279285
// We can create encrypted connections to individual nodes so that all ESP-NOW communication with the node will be encrypted.
280-
if (espnowNode.requestEncryptedConnection(MeshBackendBase::connectionQueue[0].BSSID) == ECS_CONNECTION_ESTABLISHED) {
286+
if (espnowNode.connectionQueue()[0].getBSSID(targetBSSID) && espnowNode.requestEncryptedConnection(targetBSSID) == ECS_CONNECTION_ESTABLISHED) {
281287
// The WiFi scan will detect the AP MAC, but this will automatically be converted to the encrypted STA MAC by the framework.
282-
String peerMac = macToString(MeshBackendBase::connectionQueue[0].BSSID);
288+
String peerMac = macToString(targetBSSID);
283289

284290
Serial.println("Encrypted ESP-NOW connection with " + peerMac + " established!");
285291

286-
// Making a transmission now will cause messages to MeshBackendBase::connectionQueue[0].BSSID to be encrypted.
292+
// Making a transmission now will cause messages to targetBSSID to be encrypted.
287293
String espnowMessage = "This message is encrypted only when received by node " + peerMac;
288294
Serial.println("\nTransmitting: " + espnowMessage);
289295
espnowNode.attemptTransmission(espnowMessage, false);
290296
espnowDelay(100); // Wait for response.
291297

292298
// A connection can be serialized and stored for later use.
293299
// Note that this saves the current state only, so if encrypted communication between the nodes happen after this, the stored state is invalid.
294-
String serializedEncryptedConnection = EspnowMeshBackend::serializeEncryptedConnection(MeshBackendBase::connectionQueue[0].BSSID);
300+
String serializedEncryptedConnection = EspnowMeshBackend::serializeEncryptedConnection(targetBSSID);
295301

296302
Serial.println();
297303
// We can remove an encrypted connection like so.
298-
espnowNode.removeEncryptedConnection(MeshBackendBase::connectionQueue[0].BSSID);
304+
espnowNode.removeEncryptedConnection(targetBSSID);
299305

300306
// Note that the peer will still be encrypted, so although we can send unencrypted messages to the peer, we cannot read the encrypted responses it sends back.
301307
espnowMessage = "This message is no longer encrypted when received by node " + peerMac;
@@ -304,7 +310,7 @@ void loop() {
304310
espnowDelay(100); // Wait for response.
305311
Serial.println("Cannot read the encrypted response...");
306312

307-
// Let's re-add our stored connection so we can communicate properly with MeshBackendBase::connectionQueue[0].BSSID again!
313+
// Let's re-add our stored connection so we can communicate properly with targetBSSID again!
308314
espnowNode.addEncryptedConnection(serializedEncryptedConnection);
309315

310316
espnowMessage = "This message is once again encrypted when received by node " + peerMac;
@@ -314,21 +320,28 @@ void loop() {
314320

315321
Serial.println();
316322
// If we want to remove the encrypted connection on both nodes, we can do it like this.
317-
encrypted_connection_removal_outcome_t removalOutcome = espnowNode.requestEncryptedConnectionRemoval(MeshBackendBase::connectionQueue[0].BSSID);
323+
encrypted_connection_removal_outcome_t removalOutcome = espnowNode.requestEncryptedConnectionRemoval(targetBSSID);
318324
if (removalOutcome == ECRO_REMOVAL_SUCCEEDED) {
319-
Serial.println(peerMac + " is no longer encrypted!\n");
325+
Serial.println(peerMac + " is no longer encrypted!");
326+
327+
espnowMessage = "This message is only received by node " + peerMac + ". Transmitting in this way will not change the transmission state of the sender.";
328+
Serial.println("Transmitting: " + espnowMessage);
329+
espnowNode.attemptTransmission(espnowMessage, EspnowNetworkInfo(targetBSSID));
330+
espnowDelay(100); // Wait for response.
331+
332+
Serial.println();
320333

321334
// Of course, we can also just create a temporary encrypted connection that will remove itself once its duration has passed.
322-
if (espnowNode.requestTemporaryEncryptedConnection(MeshBackendBase::connectionQueue[0].BSSID, 1000) == ECS_CONNECTION_ESTABLISHED) {
335+
if (espnowNode.requestTemporaryEncryptedConnection(targetBSSID, 1000) == ECS_CONNECTION_ESTABLISHED) {
323336
espnowDelay(42);
324337
uint32_t remainingDuration = 0;
325-
EspnowMeshBackend::getConnectionInfo(MeshBackendBase::connectionQueue[0].BSSID, &remainingDuration);
338+
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
326339

327340
espnowMessage = "Messages this node sends to " + peerMac + " will be encrypted for " + String(remainingDuration) + " ms more.";
328341
Serial.println("\nTransmitting: " + espnowMessage);
329342
espnowNode.attemptTransmission(espnowMessage, false);
330343

331-
EspnowMeshBackend::getConnectionInfo(MeshBackendBase::connectionQueue[0].BSSID, &remainingDuration);
344+
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
332345
espnowDelay(remainingDuration + 100);
333346

334347
espnowMessage = "Due to encrypted connection expiration, this message is no longer encrypted when received by node " + peerMac;

0 commit comments

Comments
 (0)