mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-27 18:02:17 +03:00
- Move all Strings to flash and optimize String usage, saving 4-5 kB of RAM.
- Replace const with constexpr where possible. - Use default constructor instead of copy constructor for IPAddress variable initialization. - Add MeshTypeConversionFunctions namespace around TypeConversionFunctions. - Add MeshUtilityFunctions namespace around UtilityFunctions. - Add ESP8266WIFIMESH_DISABLE_COMPATIBILITY preprocessor flag to retain compatibility with old code despite new namespaces. - Add setLogEntryLifetimeMs and setBroadcastResponseTimeoutMs methods to EspnowMeshBackend. - Move FloodingMesh constant definitions from header to .cpp file to reduce the risk of extra RAM consumption. - Add deactivateAP method to FloodingMesh. - Make deactivateAP static and add new non-static deactivateControlledAP method to MeshBackendBase. - Add example of how to transfer null values using multiStrings to HelloEspnow.ino. - Improve documentation. - Improve comments.
This commit is contained in:
@ -1,8 +1,12 @@
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <EspnowMeshBackend.h>
|
||||
#include <TypeConversionFunctions.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace TypeCast = MeshTypeConversionFunctions;
|
||||
|
||||
/**
|
||||
NOTE: Although we could define the strings below as normal String variables,
|
||||
here we are using PROGMEM combined with the FPSTR() macro (and also just the F() macro further down in the file).
|
||||
@ -14,8 +18,8 @@
|
||||
https://github.com/esp8266/Arduino/issues/1143
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
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.
|
||||
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.
|
||||
constexpr 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.
|
||||
constexpr 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.
|
||||
|
||||
// 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.
|
||||
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
|
||||
@ -41,7 +45,7 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||
bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
||||
|
||||
/* Create the mesh node object */
|
||||
EspnowMeshBackend espnowNode = EspnowMeshBackend(manageRequest, manageResponse, networkFilter, broadcastFilter, FPSTR(exampleWiFiPassword), espnowEncryptedConnectionKey, espnowHashKey, FPSTR(exampleMeshName), uint64ToString(ESP.getChipId()), true);
|
||||
EspnowMeshBackend espnowNode = EspnowMeshBackend(manageRequest, manageResponse, networkFilter, broadcastFilter, FPSTR(exampleWiFiPassword), espnowEncryptedConnectionKey, espnowHashKey, FPSTR(exampleMeshName), TypeCast::uint64ToString(ESP.getChipId()), true);
|
||||
|
||||
/**
|
||||
Callback for when other nodes send you a request
|
||||
@ -57,10 +61,10 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
||||
// Of course, it is advised to adjust this approach based on RAM requirements.
|
||||
|
||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
Serial.print("TCP/IP: ");
|
||||
} else {
|
||||
@ -72,7 +76,12 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
||||
// If you need to print the whole String it is better to store it and print it in the loop() later.
|
||||
// Note that request.substring will not work as expected if the String contains null values as data.
|
||||
Serial.print("Request received: ");
|
||||
Serial.println(request.substring(0, 100));
|
||||
|
||||
if (request.charAt(0) == 0) {
|
||||
Serial.println(request); // substring will not work for multiStrings.
|
||||
} else {
|
||||
Serial.println(request.substring(0, 100));
|
||||
}
|
||||
|
||||
/* return a string to send back */
|
||||
return ("Hello world response #" + String(responseNumber++) + " from " + meshInstance.getMeshName() + meshInstance.getNodeID() + " with AP MAC " + WiFi.softAPmacAddress() + ".");
|
||||
@ -89,10 +98,10 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
|
||||
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
|
||||
|
||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
Serial.print("TCP/IP: ");
|
||||
|
||||
// Getting the sent message like this will work as long as ONLY(!) TCP/IP is used.
|
||||
@ -129,12 +138,12 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
|
||||
|
||||
/* Connect to any _suitable_ APs which contain meshInstance.getMeshName() */
|
||||
if (meshNameIndex >= 0) {
|
||||
uint64_t targetNodeID = stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
|
||||
uint64_t targetNodeID = TypeCast::stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
|
||||
|
||||
if (targetNodeID < stringToUint64(meshInstance.getNodeID())) {
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
if (targetNodeID < TypeCast::stringToUint64(meshInstance.getNodeID())) {
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
espnowInstance->connectionQueue().push_back(networkIndex);
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
tcpIpInstance->connectionQueue().push_back(networkIndex);
|
||||
} else {
|
||||
Serial.println(String(F("Invalid mesh backend!")));
|
||||
@ -345,6 +354,15 @@ void loop() {
|
||||
|
||||
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
|
||||
|
||||
// If you have a data array containing null values it is possible to transmit the raw data by making the array into a multiString as shown below.
|
||||
// You can use String::c_str() or String::begin() to retreive the data array later.
|
||||
// Note that certain String methods such as String::substring use null values to determine String length, which means they will not work as normal with multiStrings.
|
||||
uint8_t dataArray[] = {0, '\'', 0, '\'', ' ', '(', 'n', 'u', 'l', 'l', ')', ' ', 'v', 'a', 'l', 'u', 'e'};
|
||||
String espnowMessage = TypeCast::uint8ArrayToMultiString(dataArray, sizeof dataArray) + String(F(" from ")) + espnowNode.getMeshName() + espnowNode.getNodeID() + String(F("."));
|
||||
Serial.println("\nTransmitting: " + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
|
||||
Serial.println("\nPerforming encrypted ESP-NOW transmissions.");
|
||||
|
||||
uint8_t targetBSSID[6] {0};
|
||||
@ -352,7 +370,7 @@ void loop() {
|
||||
// We can create encrypted connections to individual nodes so that all ESP-NOW communication with the node will be encrypted.
|
||||
if (espnowNode.constConnectionQueue()[0].getBSSID(targetBSSID) && espnowNode.requestEncryptedConnection(targetBSSID) == ECS_CONNECTION_ESTABLISHED) {
|
||||
// The WiFi scan will detect the AP MAC, but this will automatically be converted to the encrypted STA MAC by the framework.
|
||||
String peerMac = macToString(targetBSSID);
|
||||
String peerMac = TypeCast::macToString(targetBSSID);
|
||||
|
||||
Serial.println("Encrypted ESP-NOW connection with " + peerMac + " established!");
|
||||
|
||||
|
@ -5,11 +5,15 @@
|
||||
That way you will get instant confirmation of the mesh communication without checking the Serial Monitor.
|
||||
*/
|
||||
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <TypeConversionFunctions.h>
|
||||
#include <assert.h>
|
||||
#include <FloodingMesh.h>
|
||||
|
||||
namespace TypeCast = MeshTypeConversionFunctions;
|
||||
|
||||
/**
|
||||
NOTE: Although we could define the strings below as normal String variables,
|
||||
here we are using PROGMEM combined with the FPSTR() macro (and also just the F() macro further down in the file).
|
||||
@ -21,8 +25,8 @@
|
||||
https://github.com/esp8266/Arduino/issues/1143
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
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.
|
||||
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.
|
||||
constexpr 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.
|
||||
constexpr 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.
|
||||
|
||||
// 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.
|
||||
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
|
||||
@ -37,10 +41,10 @@ uint8_t espnowHashKey[16] = {0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, //
|
||||
bool meshMessageHandler(String &message, FloodingMesh &meshInstance);
|
||||
|
||||
/* Create the mesh node object */
|
||||
FloodingMesh floodingMesh = FloodingMesh(meshMessageHandler, FPSTR(exampleWiFiPassword), espnowEncryptedConnectionKey, espnowHashKey, FPSTR(exampleMeshName), uint64ToString(ESP.getChipId()), true);
|
||||
FloodingMesh floodingMesh = FloodingMesh(meshMessageHandler, FPSTR(exampleWiFiPassword), espnowEncryptedConnectionKey, espnowHashKey, FPSTR(exampleMeshName), TypeCast::uint64ToString(ESP.getChipId()), true);
|
||||
|
||||
bool theOne = true;
|
||||
String theOneMac = "";
|
||||
String theOneMac;
|
||||
|
||||
bool useLED = false; // Change this to true if you wish the onboard LED to mark The One.
|
||||
|
||||
@ -58,7 +62,7 @@ bool useLED = false; // Change this to true if you wish the onboard LED to mark
|
||||
bool meshMessageHandler(String &message, FloodingMesh &meshInstance) {
|
||||
int32_t delimiterIndex = message.indexOf(meshInstance.metadataDelimiter());
|
||||
if (delimiterIndex == 0) {
|
||||
Serial.print("Message received from STA MAC " + meshInstance.getEspnowMeshBackend().getSenderMac() + ": ");
|
||||
Serial.print(String(F("Message received from STA MAC ")) + meshInstance.getEspnowMeshBackend().getSenderMac() + F(": "));
|
||||
Serial.println(message.substring(2, 102));
|
||||
|
||||
String potentialMac = message.substring(2, 14);
|
||||
@ -95,17 +99,17 @@ bool meshMessageHandler(String &message, FloodingMesh &meshInstance) {
|
||||
previousTotalBroadcasts = totalBroadcasts;
|
||||
|
||||
if (totalReceivedBroadcasts % 50 == 0) {
|
||||
Serial.println("missed/total: " + String(missedBroadcasts) + '/' + String(totalReceivedBroadcasts));
|
||||
Serial.println(String(F("missed/total: ")) + String(missedBroadcasts) + '/' + String(totalReceivedBroadcasts));
|
||||
}
|
||||
if (totalReceivedBroadcasts % 500 == 0) {
|
||||
Serial.println("Benchmark message: " + message.substring(0, 100));
|
||||
Serial.println(String(F("Benchmark message: ")) + message.substring(0, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Only show first 100 characters because printing a large String takes a lot of time, which is a bad thing for a callback function.
|
||||
// If you need to print the whole String it is better to store it and print it in the loop() later.
|
||||
Serial.print("Message with origin " + meshInstance.getOriginMac() + " received: ");
|
||||
Serial.print(String(F("Message with origin ")) + meshInstance.getOriginMac() + F(" received: "));
|
||||
Serial.println(message.substring(0, 100));
|
||||
}
|
||||
|
||||
@ -139,7 +143,7 @@ void setup() {
|
||||
floodingMesh.activateAP();
|
||||
|
||||
uint8_t apMacArray[6] {0};
|
||||
theOneMac = macToString(WiFi.softAPmacAddress(apMacArray));
|
||||
theOneMac = TypeCast::macToString(WiFi.softAPmacAddress(apMacArray));
|
||||
|
||||
if (useLED) {
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||
@ -150,7 +154,7 @@ void setup() {
|
||||
// The main benefit of AEAD encryption is that it can be used with normal broadcasts (which are substantially faster than encryptedBroadcasts).
|
||||
// The main drawbacks are that AEAD only encrypts the message data (not transmission metadata), transfers less data per message and lacks replay attack protection.
|
||||
// When using AEAD, potential replay attacks must thus be handled manually.
|
||||
//floodingMesh.getEspnowMeshBackend().setEspnowMessageEncryptionKey("ChangeThisKeySeed_TODO"); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
//floodingMesh.getEspnowMeshBackend().setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
//floodingMesh.getEspnowMeshBackend().setUseEncryptedMessages(true);
|
||||
|
||||
floodingMeshDelay(5000); // Give some time for user to start the nodes
|
||||
@ -180,8 +184,8 @@ void loop() {
|
||||
ledState = ledState ^ bool(benchmarkCount); // Make other nodes' LEDs alternate between on and off once benchmarking begins.
|
||||
|
||||
// Note: The maximum length of an unencrypted broadcast message is given by floodingMesh.maxUnencryptedMessageLength(). It is around 670 bytes by default.
|
||||
floodingMesh.broadcast(String(floodingMesh.metadataDelimiter()) + String(ledState) + theOneMac + " is The One.");
|
||||
Serial.println("Proclamation broadcast done in " + String(millis() - startTime) + " ms.");
|
||||
floodingMesh.broadcast(String(floodingMesh.metadataDelimiter()) + String(ledState) + theOneMac + F(" is The One."));
|
||||
Serial.println(String(F("Proclamation broadcast done in ")) + String(millis() - startTime) + F(" ms."));
|
||||
|
||||
timeOfLastProclamation = millis();
|
||||
floodingMeshDelay(20);
|
||||
@ -189,8 +193,8 @@ void loop() {
|
||||
|
||||
if (millis() - loopStart > 23000) { // Start benchmarking the mesh once three proclamations have been made
|
||||
uint32_t startTime = millis();
|
||||
floodingMesh.broadcast(String(benchmarkCount++) + String(floodingMesh.metadataDelimiter()) + ": Not a spoon in sight.");
|
||||
Serial.println("Benchmark broadcast done in " + String(millis() - startTime) + " ms.");
|
||||
floodingMesh.broadcast(String(benchmarkCount++) + String(floodingMesh.metadataDelimiter()) + F(": Not a spoon in sight."));
|
||||
Serial.println(String(F("Benchmark broadcast done in ")) + String(millis() - startTime) + F(" ms."));
|
||||
floodingMeshDelay(20);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <TcpIpMeshBackend.h>
|
||||
#include <TypeConversionFunctions.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace TypeCast = MeshTypeConversionFunctions;
|
||||
|
||||
/**
|
||||
NOTE: Although we could define the strings below as normal String variables,
|
||||
here we are using PROGMEM combined with the FPSTR() macro (and also just the F() macro further down in the file).
|
||||
@ -14,8 +18,8 @@
|
||||
https://github.com/esp8266/Arduino/issues/1143
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
const char exampleMeshName[] PROGMEM = "MeshNode_";
|
||||
const char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO";
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_";
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO";
|
||||
|
||||
unsigned int requestNumber = 0;
|
||||
unsigned int responseNumber = 0;
|
||||
@ -25,7 +29,7 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
|
||||
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||
|
||||
/* Create the mesh node object */
|
||||
TcpIpMeshBackend tcpIpNode = TcpIpMeshBackend(manageRequest, manageResponse, networkFilter, FPSTR(exampleWiFiPassword), FPSTR(exampleMeshName), uint64ToString(ESP.getChipId()), true);
|
||||
TcpIpMeshBackend tcpIpNode = TcpIpMeshBackend(manageRequest, manageResponse, networkFilter, FPSTR(exampleWiFiPassword), FPSTR(exampleMeshName), TypeCast::uint64ToString(ESP.getChipId()), true);
|
||||
|
||||
/**
|
||||
Callback for when other nodes send you a request
|
||||
@ -35,31 +39,26 @@ TcpIpMeshBackend tcpIpNode = TcpIpMeshBackend(manageRequest, manageResponse, net
|
||||
@return The string to send back to the other node. For ESP-NOW, return an empy string ("") if no response should be sent.
|
||||
*/
|
||||
String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
||||
// We do not store strings in flash (via F()) in this function.
|
||||
// The reason is that the other node will be waiting for our response,
|
||||
// so keeping the strings in RAM will give a (small) improvement in response time.
|
||||
// Of course, it is advised to adjust this approach based on RAM requirements.
|
||||
|
||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
Serial.print("TCP/IP: ");
|
||||
Serial.print(F("TCP/IP: "));
|
||||
} else {
|
||||
Serial.print("UNKNOWN!: ");
|
||||
Serial.print(F("UNKNOWN!: "));
|
||||
}
|
||||
|
||||
/* Print out received message */
|
||||
// Only show first 100 characters because printing a large String takes a lot of time, which is a bad thing for a callback function.
|
||||
// If you need to print the whole String it is better to store it and print it in the loop() later.
|
||||
// Note that request.substring will not work as expected if the String contains null values as data.
|
||||
Serial.print("Request received: ");
|
||||
Serial.print(F("Request received: "));
|
||||
Serial.println(request.substring(0, 100));
|
||||
|
||||
/* return a string to send back */
|
||||
return ("Hello world response #" + String(responseNumber++) + " from " + meshInstance.getMeshName() + meshInstance.getNodeID() + " with AP MAC " + WiFi.softAPmacAddress() + ".");
|
||||
return (String(F("Hello world response #")) + String(responseNumber++) + F(" from ") + meshInstance.getMeshName() + meshInstance.getNodeID() + F(" with AP MAC ") + WiFi.softAPmacAddress() + String('.'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,11 +72,11 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
|
||||
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
|
||||
|
||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
Serial.print("TCP/IP: ");
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
Serial.print(F("TCP/IP: "));
|
||||
|
||||
// Getting the sent message like this will work as long as ONLY(!) TCP/IP is used.
|
||||
// With TCP/IP the response will follow immediately after the request, so the stored message will not have changed.
|
||||
@ -86,7 +85,7 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
|
||||
Serial.print(F("Request sent: "));
|
||||
Serial.println(tcpIpInstance->getCurrentMessage().substring(0, 100));
|
||||
} else {
|
||||
Serial.print("UNKNOWN!: ");
|
||||
Serial.print(F("UNKNOWN!: "));
|
||||
}
|
||||
|
||||
/* Print out received message */
|
||||
@ -113,15 +112,15 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
|
||||
|
||||
/* Connect to any _suitable_ APs which contain meshInstance.getMeshName() */
|
||||
if (meshNameIndex >= 0) {
|
||||
uint64_t targetNodeID = stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
|
||||
uint64_t targetNodeID = TypeCast::stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
|
||||
|
||||
if (targetNodeID < stringToUint64(meshInstance.getNodeID())) {
|
||||
if (EspnowMeshBackend *espnowInstance = meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
if (targetNodeID < TypeCast::stringToUint64(meshInstance.getNodeID())) {
|
||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||
espnowInstance->connectionQueue().push_back(networkIndex);
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
tcpIpInstance->connectionQueue().push_back(networkIndex);
|
||||
} else {
|
||||
Serial.println(String(F("Invalid mesh backend!")));
|
||||
Serial.println(F("Invalid mesh backend!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,14 +141,14 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
|
||||
bool exampleTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance) {
|
||||
// The default hook only returns true and does nothing else.
|
||||
|
||||
if (TcpIpMeshBackend *tcpIpInstance = meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
if (tcpIpInstance->latestTransmissionOutcomes().back().transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
|
||||
// Our last request got a response, so time to create a new request.
|
||||
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + String(F(" from "))
|
||||
+ meshInstance.getMeshName() + meshInstance.getNodeID() + String(F(".")));
|
||||
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
||||
+ meshInstance.getMeshName() + meshInstance.getNodeID() + String('.'));
|
||||
}
|
||||
} else {
|
||||
Serial.println(String(F("Invalid mesh backend!")));
|
||||
Serial.println(F("Invalid mesh backend!"));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -186,7 +185,7 @@ void setup() {
|
||||
|
||||
// Storing our message in the TcpIpMeshBackend instance is not required, but can be useful for organizing code, especially when using many TcpIpMeshBackend instances.
|
||||
// Note that calling the multi-recipient tcpIpNode.attemptTransmission will replace the stored message with whatever message is transmitted.
|
||||
tcpIpNode.setMessage(String(F("Hello world request #")) + String(requestNumber) + String(F(" from ")) + tcpIpNode.getMeshName() + tcpIpNode.getNodeID() + String(F(".")));
|
||||
tcpIpNode.setMessage(String(F("Hello world request #")) + String(requestNumber) + F(" from ") + tcpIpNode.getMeshName() + tcpIpNode.getNodeID() + String('.'));
|
||||
|
||||
tcpIpNode.setTransmissionOutcomesUpdateHook(exampleTransmissionOutcomesUpdateHook);
|
||||
}
|
||||
@ -217,7 +216,7 @@ void loop() {
|
||||
} else if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
|
||||
// No need to do anything, transmission was successful.
|
||||
} else {
|
||||
Serial.println(String(F("Invalid transmission status for ")) + transmissionOutcome.SSID() + String(F("!")));
|
||||
Serial.println(String(F("Invalid transmission status for ")) + transmissionOutcome.SSID() + String('!'));
|
||||
assert(F("Invalid transmission status returned from responseHandler!") && false);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user