Skip to content

Commit 5834c54

Browse files
committed
- Add broadcast functionality.
- Add createPermanentConnections argument to attemptAutoEncryptingTransmission method. - Reduce risk of misinterpreting acks by adding check for ack sender MAC. - Reduce _encryptionRequestTimeoutMs from 500 ms to 300 ms since this should give enough (100 %) margin to the level where problems start appearing (150 ms timeout) and also save a lot of time in case of request failure. - Improve comments.
1 parent 26e626d commit 5834c54

17 files changed

+305
-122
lines changed

libraries/ESP8266WiFiMesh/examples/HelloEspnow/HelloEspnow.ino

Lines changed: 61 additions & 8 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 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 during ESP-NOW broadcasts and in the example networkFilter function 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.
@@ -35,16 +35,17 @@ unsigned int responseNumber = 0;
3535
String manageRequest(const String &request, MeshBackendBase &meshInstance);
3636
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance);
3737
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
38+
bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
3839

3940
/* Create the mesh node object */
40-
EspnowMeshBackend espnowNode = EspnowMeshBackend(manageRequest, manageResponse, networkFilter, FPSTR(exampleWiFiPassword), espnowEncryptionKey, espnowHashKey, FPSTR(exampleMeshName), uint64ToString(ESP.getChipId()), true);
41+
EspnowMeshBackend espnowNode = EspnowMeshBackend(manageRequest, manageResponse, networkFilter, broadcastFilter, FPSTR(exampleWiFiPassword), espnowEncryptionKey, espnowHashKey, FPSTR(exampleMeshName), uint64ToString(ESP.getChipId()), true);
4142

4243
/**
4344
Callback for when other nodes send you a request
4445
4546
@param request The request string received from another node in the mesh
4647
@param meshInstance The MeshBackendBase instance that called the function.
47-
@returns The string to send back to the other node. For ESP-NOW, return an empy string ("") if no response should be sent.
48+
@return The string to send back to the other node. For ESP-NOW, return an empy string ("") if no response should be sent.
4849
*/
4950
String manageRequest(const String &request, MeshBackendBase &meshInstance) {
5051
// We do not store strings in flash (via F()) in this function.
@@ -78,7 +79,7 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
7879
7980
@param response The response string received from another node in the mesh
8081
@param meshInstance The MeshBackendBase instance that called the function.
81-
@returns The status code resulting from the response, as an int
82+
@return The status code resulting from the response, as an int
8283
*/
8384
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance) {
8485
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
@@ -132,6 +133,42 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
132133
}
133134
}
134135

136+
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
137+
138+
/**
139+
Callback used to decide which broadcast messages to accept. Only called for the first transmission in each broadcast.
140+
If true is returned from this callback, the first broadcast transmission is saved until the entire broadcast message has been received.
141+
The complete broadcast message will then be sent to the requestHandler (manageRequest in this example).
142+
If false is returned from this callback, the broadcast message is discarded.
143+
144+
@param firstTransmission The first transmission of the broadcast.
145+
@param meshInstance The EspnowMeshBackend instance that called the function.
146+
147+
@return True if the broadcast should be accepted. False otherwise.
148+
*/
149+
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+
*/
154+
155+
int32_t metadataEndIndex = firstTransmission.indexOf(broadcastMetadataDelimiter);
156+
157+
if (metadataEndIndex == -1) {
158+
return false; // broadcastMetadataDelimiter not found
159+
}
160+
161+
String targetMeshName = firstTransmission.substring(0, metadataEndIndex);
162+
163+
if (targetMeshName != "" && meshInstance.getMeshName() != targetMeshName) {
164+
return false; // Broadcast is for another mesh network
165+
} else {
166+
// Remove metadata from message and mark as accepted broadcast.
167+
firstTransmission = firstTransmission.substring(metadataEndIndex + 1);
168+
return true;
169+
}
170+
}
171+
135172
void setup() {
136173
// Prevents the flash memory from being worn out, see: https://github.com/esp8266/Arduino/issues/1054 .
137174
// This will however delay node WiFi start-up by about 700 ms. The delay is 900 ms if we otherwise would have stored the WiFi network we want to connect to.
@@ -173,6 +210,7 @@ void setup() {
173210

174211
// Storing our message in the EspnowMeshBackend instance is not required, but can be useful for organizing code, especially when using many EspnowMeshBackend instances.
175212
// Note that calling espnowNode.attemptTransmission will replace the stored message with whatever message is transmitted.
213+
// Also note that the maximum allowed number of ASCII characters in a ESP-NOW message is given by EspnowMeshBackend::getMaxMessageLength().
176214
espnowNode.setMessage(String(F("Hello world request #")) + String(requestNumber) + String(F(" from ")) + espnowNode.getMeshName() + espnowNode.getNodeID() + String(F(".")));
177215
}
178216

@@ -188,18 +226,18 @@ void loop() {
188226
EspnowMeshBackend::performEspnowMaintainance();
189227

190228
if (millis() - timeOfLastScan > 10000) { // Give other nodes some time to connect between data transfers.
191-
uint32_t startTime = millis();
192-
193229
Serial.println("\nPerforming unencrypted ESP-NOW transmissions.");
230+
231+
uint32_t startTime = millis();
194232
espnowNode.attemptTransmission(espnowNode.getMessage());
195233
Serial.println("Scan and " + String(MeshBackendBase::latestTransmissionOutcomes.size()) + " transmissions done in " + String(millis() - startTime) + " ms.");
196234

235+
timeOfLastScan = millis();
236+
197237
// Wait for response. espnowDelay continuously calls performEspnowMaintainance() so we will respond to ESP-NOW request while waiting.
198238
// Should not be used inside responseHandler, requestHandler or networkFilter callbacks since performEspnowMaintainance() can alter the ESP-NOW state.
199239
espnowDelay(100);
200240

201-
timeOfLastScan = millis();
202-
203241
// One way to check how attemptTransmission worked out
204242
if (MeshBackendBase::latestTransmissionSuccessful()) {
205243
Serial.println(F("Transmission successful."));
@@ -222,6 +260,20 @@ void loop() {
222260
}
223261
}
224262

263+
Serial.println("\nPerforming ESP-NOW broadcast.");
264+
265+
startTime = millis();
266+
267+
// Remove espnowNode.getMeshName() from the broadcastMetadata below to broadcast to all ESP-NOW nodes regardless of MeshName.
268+
// Note that data that comes before broadcastMetadataDelimiter should not contain any broadcastMetadataDelimiter characters,
269+
// otherwise the broadcastFilter function used in this example file will not work.
270+
String broadcastMetadata = espnowNode.getMeshName() + String(broadcastMetadataDelimiter);
271+
String broadcastMessage = String(F("Broadcast #")) + String(requestNumber) + String(F(" from ")) + espnowNode.getMeshName() + espnowNode.getNodeID() + String(F("."));
272+
espnowNode.broadcast(broadcastMetadata + broadcastMessage);
273+
Serial.println("Broadcast to all mesh nodes done in " + String(millis() - startTime) + " ms.");
274+
275+
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
276+
225277
Serial.println("\nPerforming encrypted ESP-NOW transmissions.");
226278

227279
// We can create encrypted connections to individual nodes so that all ESP-NOW communication with the node will be encrypted.
@@ -287,6 +339,7 @@ void loop() {
287339

288340
// Or if we prefer we can just let the library automatically create brief encrypted connections which are long enough to transmit an encrypted message.
289341
// Note that encrypted responses will not be received, unless there already was an encrypted connection established with the peer before attemptAutoEncryptingTransmission was called.
342+
// This can be remedied via the createPermanentConnections argument, though it must be noted that the maximum number of encrypted connections supported at a time is 6.
290343
espnowMessage = "This message is always encrypted, regardless of receiver.";
291344
Serial.println("\nTransmitting: " + espnowMessage);
292345
espnowNode.attemptAutoEncryptingTransmission(espnowMessage);

libraries/ESP8266WiFiMesh/src/CompatibilityLayer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
/********************************************************************************************
2828
* NOTE!
2929
*
30-
* All method signatures in this file are deprecated and will be removed in core version 2.5.0.
30+
* All method signatures in this file are deprecated and will be removed in core version 3.0.0.
3131
* If you are still using these methods, please consider migrating to the new API shown in
32-
* the ESP8266WiFiMesh.h source file.
32+
* the EspnowMeshBackend.h or TcpIpMeshBackend.h source files.
3333
*
3434
* TODO: delete this file.
3535
********************************************************************************************/

libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ void ESP8266WiFiMesh::fullStop(WiFiClient &currClient)
337337
/**
338338
* Wait for a WiFiClient to transmit
339339
*
340-
* @returns: True if the client is ready, false otherwise.
340+
* @return: True if the client is ready, false otherwise.
341341
*
342342
*/
343343
bool ESP8266WiFiMesh::waitForClientTransmission(WiFiClient &currClient, uint32_t maxWait)
@@ -365,7 +365,7 @@ bool ESP8266WiFiMesh::waitForClientTransmission(WiFiClient &currClient, uint32_t
365365
* and pass that to the user-supplied responseHandler.
366366
*
367367
* @param currClient The client to which the message should be transmitted.
368-
* @returns: A status code based on the outcome of the exchange.
368+
* @return: A status code based on the outcome of the exchange.
369369
*
370370
*/
371371
transmission_status_t ESP8266WiFiMesh::exchangeInfo(WiFiClient &currClient)
@@ -398,7 +398,7 @@ transmission_status_t ESP8266WiFiMesh::exchangeInfo(WiFiClient &currClient)
398398
/**
399399
* Handle data transfer process with a connected AP.
400400
*
401-
* @returns: A status code based on the outcome of the data transfer attempt.
401+
* @return: A status code based on the outcome of the data transfer attempt.
402402
*/
403403
transmission_status_t ESP8266WiFiMesh::attemptDataTransfer()
404404
{
@@ -418,7 +418,7 @@ transmission_status_t ESP8266WiFiMesh::attemptDataTransfer()
418418
/**
419419
* Helper function that contains the core functionality for the data transfer process with a connected AP.
420420
*
421-
* @returns: A status code based on the outcome of the data transfer attempt.
421+
* @return: A status code based on the outcome of the data transfer attempt.
422422
*/
423423
transmission_status_t ESP8266WiFiMesh::attemptDataTransferKernel()
424424
{
@@ -462,7 +462,7 @@ void ESP8266WiFiMesh::initiateConnectionToAP(const String &targetSSID, int targe
462462
* @param targetSSID The name of the AP the other node has set up.
463463
* @param targetChannel The WiFI channel of the AP the other node has set up.
464464
* @param targetBSSID The mac address of the AP the other node has set up.
465-
* @returns: A status code based on the outcome of the connection and data transfer process.
465+
* @return: A status code based on the outcome of the connection and data transfer process.
466466
*
467467
*/
468468
transmission_status_t ESP8266WiFiMesh::connectToNode(const String &targetSSID, int targetChannel, uint8_t *targetBSSID)

libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class ESP8266WiFiMesh {
194194
static std::vector<TransmissionResult> latestTransmissionOutcomes;
195195

196196
/**
197-
* @returns True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
197+
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
198198
*/
199199
static bool latestTransmissionSuccessful();
200200

@@ -217,15 +217,15 @@ class ESP8266WiFiMesh {
217217
* If another instance takes control over the AP after the pointer is created,
218218
* the created pointer will still point to the old AP instance.
219219
*
220-
* @returns A pointer to the ESP8266WiFiMesh instance currently in control of the ESP8266 AP,
220+
* @return A pointer to the ESP8266WiFiMesh instance currently in control of the ESP8266 AP,
221221
* or nullptr if there is no active AP controller.
222222
*/
223223
static ESP8266WiFiMesh * getAPController();
224224

225225
/**
226226
* Check if this ESP8266WiFiMesh instance is in control of the ESP8266 AP.
227227
*
228-
* @returns True if this ESP8266WiFiMesh instance is in control of the ESP8266 AP. False otherwise.
228+
* @return True if this ESP8266WiFiMesh instance is in control of the ESP8266 AP. False otherwise.
229229
*/
230230
bool isAPController();
231231

libraries/ESP8266WiFiMesh/src/EncryptedConnectionData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class EncryptedConnectionData {
4848
/**
4949
* @param resultArray An uint8_t array with at least size 6.
5050
*
51-
* @returns The interface MAC used for communicating with the peer.
51+
* @return The interface MAC used for communicating with the peer.
5252
*/
5353
uint8_t *getEncryptedPeerMac(uint8_t *resultArray) const;
5454
uint8_t *getUnencryptedPeerMac(uint8_t *resultArray) const;

0 commit comments

Comments
 (0)