mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
- Rework ExpiringTimeTracker to be based on PolledTimeout.
- Ensure espnowDelay and floodingMeshDelay always performs maintenance. - Rework MutexTracker to use shared_ptr. - Change enums to enum class. - Change typedef to using. - Add HeapMonitor class. - Make _messageIDs be a map instead of an unordered_map to reduce heap usage. - Use the possibly broken wifi_country ESP8266 API to check for legal WiFi channels when setting WiFi channels. - Make MessageData, RequestData and ResponseData contain a TimeTracker rather than inherit from TimeTracker. - Add deprecated attribute to TransmissionResult. - Remove superfluous elses. - Reduce cyclomatic complexity. - Change postfix ++ and -- to prefix. - Generalize getEncryptedConnectionIterator method. - Increase code NRVO compatibility. - Change _connectionAttemptTimeoutMs type from int32_t to uint32_t. - Add deprecated attribute to ESP8266WiFiMesh. - Add some constness to TypeConversionFunctions. - Move base36 arrays to PROGMEM in TypeConversionFunctions.cpp. - Add deprecated atttribute to SHA1 and MD5 hashes. - Remove _warningsEnabled in CryptoInterface since this has been replaced by the deprecated attribute. - Prefix all TypeConversion getters with "get". - Improve comments. - Fix merge conflict.
This commit is contained in:
parent
a49f047096
commit
16801f3dac
@ -1,4 +1,4 @@
|
|||||||
#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.
|
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: 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 <ESP8266WiFi.h>
|
||||||
#include <EspnowMeshBackend.h>
|
#include <EspnowMeshBackend.h>
|
||||||
@ -40,7 +40,7 @@ unsigned int responseNumber = 0;
|
|||||||
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
|
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
|
||||||
|
|
||||||
String manageRequest(const String &request, MeshBackendBase &meshInstance);
|
String manageRequest(const String &request, MeshBackendBase &meshInstance);
|
||||||
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance);
|
TransmissionStatusType manageResponse(const String &response, MeshBackendBase &meshInstance);
|
||||||
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||||
bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
||||||
|
|
||||||
@ -55,27 +55,22 @@ EspnowMeshBackend espnowNode = EspnowMeshBackend(manageRequest, manageResponse,
|
|||||||
@return The string to send back to the other node. For ESP-NOW, return an empy string ("") if no response should be sent.
|
@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) {
|
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)
|
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::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.
|
(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 {
|
} else {
|
||||||
Serial.print("UNKNOWN!: ");
|
Serial.print(F("UNKNOWN!: "));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print out received message */
|
/* 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.
|
// 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.
|
// 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.
|
// 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: "));
|
||||||
|
|
||||||
if (request.charAt(0) == 0) {
|
if (request.charAt(0) == 0) {
|
||||||
Serial.println(request); // substring will not work for multiStrings.
|
Serial.println(request); // substring will not work for multiStrings.
|
||||||
@ -84,7 +79,7 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return a string to send back */
|
/* 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('.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,15 +89,15 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
|||||||
@param meshInstance The MeshBackendBase instance that called the function.
|
@param meshInstance The MeshBackendBase instance that called the function.
|
||||||
@return The status code resulting from the response, as an int
|
@return The status code resulting from the response, as an int
|
||||||
*/
|
*/
|
||||||
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance) {
|
TransmissionStatusType manageResponse(const String &response, MeshBackendBase &meshInstance) {
|
||||||
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
|
TransmissionStatusType statusCode = TransmissionStatusType::TRANSMISSION_COMPLETE;
|
||||||
|
|
||||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? ", Encrypted transmission" : ", Unencrypted transmission";
|
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||||
Serial.print("ESP-NOW (" + espnowInstance->getSenderMac() + transmissionEncrypted + "): ");
|
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||||
Serial.print("TCP/IP: ");
|
Serial.print(F("TCP/IP: "));
|
||||||
|
|
||||||
// Getting the sent message like this will work as long as ONLY(!) TCP/IP is used.
|
// 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.
|
// With TCP/IP the response will follow immediately after the request, so the stored message will not have changed.
|
||||||
@ -111,7 +106,7 @@ transmission_status_t manageResponse(const String &response, MeshBackendBase &me
|
|||||||
Serial.print(F("Request sent: "));
|
Serial.print(F("Request sent: "));
|
||||||
Serial.println(tcpIpInstance->getCurrentMessage().substring(0, 100));
|
Serial.println(tcpIpInstance->getCurrentMessage().substring(0, 100));
|
||||||
} else {
|
} else {
|
||||||
Serial.print("UNKNOWN!: ");
|
Serial.print(F("UNKNOWN!: "));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print out received message */
|
/* Print out received message */
|
||||||
@ -146,7 +141,7 @@ void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance) {
|
|||||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||||
tcpIpInstance->connectionQueue().push_back(networkIndex);
|
tcpIpInstance->connectionQueue().push_back(networkIndex);
|
||||||
} else {
|
} else {
|
||||||
Serial.println(String(F("Invalid mesh backend!")));
|
Serial.println(F("Invalid mesh backend!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +172,7 @@ bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance)
|
|||||||
|
|
||||||
String targetMeshName = firstTransmission.substring(0, metadataEndIndex);
|
String targetMeshName = firstTransmission.substring(0, metadataEndIndex);
|
||||||
|
|
||||||
if (targetMeshName != "" && meshInstance.getMeshName() != targetMeshName) {
|
if (!targetMeshName.isEmpty() && meshInstance.getMeshName() != targetMeshName) {
|
||||||
return false; // Broadcast is for another mesh network
|
return false; // Broadcast is for another mesh network
|
||||||
} else {
|
} else {
|
||||||
// Remove metadata from message and mark as accepted broadcast.
|
// Remove metadata from message and mark as accepted broadcast.
|
||||||
@ -274,7 +269,7 @@ void setup() {
|
|||||||
// Storing our message in the EspnowMeshBackend instance is not required, but can be useful for organizing code, especially when using many EspnowMeshBackend instances.
|
// Storing our message in the EspnowMeshBackend instance is not required, but can be useful for organizing code, especially when using many EspnowMeshBackend instances.
|
||||||
// Note that calling the multi-recipient versions of espnowNode.attemptTransmission and espnowNode.attemptAutoEncryptingTransmission will replace the stored message with whatever message is transmitted.
|
// Note that calling the multi-recipient versions of espnowNode.attemptTransmission and espnowNode.attemptAutoEncryptingTransmission will replace the stored message with whatever message is transmitted.
|
||||||
// Also note that the maximum allowed number of ASCII characters in a ESP-NOW message is given by EspnowMeshBackend::getMaxMessageLength().
|
// Also note that the maximum allowed number of ASCII characters in a ESP-NOW message is given by EspnowMeshBackend::getMaxMessageLength().
|
||||||
espnowNode.setMessage(String(F("Hello world request #")) + String(requestNumber) + String(F(" from ")) + espnowNode.getMeshName() + espnowNode.getNodeID() + String(F(".")));
|
espnowNode.setMessage(String(F("Hello world request #")) + String(requestNumber) + F(" from ") + espnowNode.getMeshName() + espnowNode.getNodeID() + String('.'));
|
||||||
|
|
||||||
espnowNode.setTransmissionOutcomesUpdateHook(exampleTransmissionOutcomesUpdateHook);
|
espnowNode.setTransmissionOutcomesUpdateHook(exampleTransmissionOutcomesUpdateHook);
|
||||||
espnowNode.setResponseTransmittedHook(exampleResponseTransmittedHook);
|
espnowNode.setResponseTransmittedHook(exampleResponseTransmittedHook);
|
||||||
@ -290,7 +285,7 @@ void setup() {
|
|||||||
// Uncomment the lines below to use automatic AEAD encryption/decryption of messages sent/received.
|
// Uncomment the lines below to use automatic AEAD encryption/decryption of messages sent/received.
|
||||||
// All nodes this node wishes to communicate with must then also use encrypted messages with the same getEspnowMessageEncryptionKey(), or messages will not be accepted.
|
// All nodes this node wishes to communicate with must then also use encrypted messages with the same getEspnowMessageEncryptionKey(), or messages will not be accepted.
|
||||||
// Note that using AEAD encrypted messages will reduce the number of message bytes that can be transmitted.
|
// Note that using AEAD encrypted messages will reduce the number of message bytes that can be transmitted.
|
||||||
//espnowNode.setEspnowMessageEncryptionKey("ChangeThisKeySeed_TODO"); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
//espnowNode.setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||||
//espnowNode.setUseEncryptedMessages(true);
|
//espnowNode.setUseEncryptedMessages(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,11 +301,11 @@ void loop() {
|
|||||||
EspnowMeshBackend::performEspnowMaintenance();
|
EspnowMeshBackend::performEspnowMaintenance();
|
||||||
|
|
||||||
if (millis() - timeOfLastScan > 10000) { // Give other nodes some time to connect between data transfers.
|
if (millis() - timeOfLastScan > 10000) { // Give other nodes some time to connect between data transfers.
|
||||||
Serial.println("\nPerforming unencrypted ESP-NOW transmissions.");
|
Serial.println(F("\nPerforming unencrypted ESP-NOW transmissions."));
|
||||||
|
|
||||||
uint32_t startTime = millis();
|
uint32_t startTime = millis();
|
||||||
espnowNode.attemptTransmission(espnowNode.getMessage());
|
espnowNode.attemptTransmission(espnowNode.getMessage());
|
||||||
Serial.println("Scan and " + String(espnowNode.latestTransmissionOutcomes().size()) + " transmissions done in " + String(millis() - startTime) + " ms.");
|
Serial.println(String(F("Scan and ")) + String(espnowNode.latestTransmissionOutcomes().size()) + F(" transmissions done in ") + String(millis() - startTime) + F(" ms."));
|
||||||
|
|
||||||
timeOfLastScan = millis();
|
timeOfLastScan = millis();
|
||||||
|
|
||||||
@ -328,19 +323,19 @@ void loop() {
|
|||||||
Serial.println(F("No mesh AP found."));
|
Serial.println(F("No mesh AP found."));
|
||||||
} else {
|
} else {
|
||||||
for (TransmissionOutcome &transmissionOutcome : espnowNode.latestTransmissionOutcomes()) {
|
for (TransmissionOutcome &transmissionOutcome : espnowNode.latestTransmissionOutcomes()) {
|
||||||
if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_FAILED) {
|
if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::TRANSMISSION_FAILED) {
|
||||||
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionOutcome.SSID());
|
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionOutcome.SSID());
|
||||||
} else if (transmissionOutcome.transmissionStatus() == TS_CONNECTION_FAILED) {
|
} else if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::CONNECTION_FAILED) {
|
||||||
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionOutcome.SSID());
|
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionOutcome.SSID());
|
||||||
} else if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
|
} else if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::TRANSMISSION_COMPLETE) {
|
||||||
// No need to do anything, transmission was successful.
|
// No need to do anything, transmission was successful.
|
||||||
} else {
|
} 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);
|
assert(F("Invalid transmission status returned from responseHandler!") && false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("\nPerforming ESP-NOW broadcast.");
|
Serial.println(F("\nPerforming ESP-NOW broadcast."));
|
||||||
|
|
||||||
startTime = millis();
|
startTime = millis();
|
||||||
|
|
||||||
@ -348,9 +343,9 @@ void loop() {
|
|||||||
// Note that data that comes before broadcastMetadataDelimiter should not contain any broadcastMetadataDelimiter characters,
|
// Note that data that comes before broadcastMetadataDelimiter should not contain any broadcastMetadataDelimiter characters,
|
||||||
// otherwise the broadcastFilter function used in this example file will not work.
|
// otherwise the broadcastFilter function used in this example file will not work.
|
||||||
String broadcastMetadata = espnowNode.getMeshName() + String(broadcastMetadataDelimiter);
|
String broadcastMetadata = espnowNode.getMeshName() + String(broadcastMetadataDelimiter);
|
||||||
String broadcastMessage = String(F("Broadcast #")) + String(requestNumber) + String(F(" from ")) + espnowNode.getMeshName() + espnowNode.getNodeID() + String(F("."));
|
String broadcastMessage = String(F("Broadcast #")) + String(requestNumber) + F(" from ") + espnowNode.getMeshName() + espnowNode.getNodeID() + String('.');
|
||||||
espnowNode.broadcast(broadcastMetadata + broadcastMessage);
|
espnowNode.broadcast(broadcastMetadata + broadcastMessage);
|
||||||
Serial.println("Broadcast to all mesh nodes done in " + String(millis() - startTime) + " ms.");
|
Serial.println(String(F("Broadcast to all mesh nodes done in ")) + String(millis() - startTime) + F(" ms."));
|
||||||
|
|
||||||
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
|
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
|
||||||
|
|
||||||
@ -358,25 +353,25 @@ void loop() {
|
|||||||
// You can use String::c_str() or String::begin() to retreive the data array later.
|
// 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.
|
// 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'};
|
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("."));
|
String espnowMessage = TypeCast::uint8ArrayToMultiString(dataArray, sizeof dataArray) + F(" from ") + espnowNode.getMeshName() + espnowNode.getNodeID() + String('.');
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
|
|
||||||
Serial.println("\nPerforming encrypted ESP-NOW transmissions.");
|
Serial.println(F("\nPerforming encrypted ESP-NOW transmissions."));
|
||||||
|
|
||||||
uint8_t targetBSSID[6] {0};
|
uint8_t targetBSSID[6] {0};
|
||||||
|
|
||||||
// We can create encrypted connections to individual nodes so that all ESP-NOW communication with the node will be encrypted.
|
// 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) {
|
if (espnowNode.constConnectionQueue()[0].getBSSID(targetBSSID) && espnowNode.requestEncryptedConnection(targetBSSID) == EncryptedConnectionStatus::CONNECTION_ESTABLISHED) {
|
||||||
// The WiFi scan will detect the AP MAC, but this will automatically be converted to the encrypted STA MAC by the framework.
|
// The WiFi scan will detect the AP MAC, but this will automatically be converted to the encrypted STA MAC by the framework.
|
||||||
String peerMac = TypeCast::macToString(targetBSSID);
|
String peerMac = TypeCast::macToString(targetBSSID);
|
||||||
|
|
||||||
Serial.println("Encrypted ESP-NOW connection with " + peerMac + " established!");
|
Serial.println(String(F("Encrypted ESP-NOW connection with ")) + peerMac + F(" established!"));
|
||||||
|
|
||||||
// Making a transmission now will cause messages to targetBSSID to be encrypted.
|
// Making a transmission now will cause messages to targetBSSID to be encrypted.
|
||||||
String espnowMessage = "This message is encrypted only when received by node " + peerMac;
|
String espnowMessage = String(F("This message is encrypted only when received by node ")) + peerMac;
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
|
|
||||||
@ -389,48 +384,48 @@ void loop() {
|
|||||||
espnowNode.removeEncryptedConnection(targetBSSID);
|
espnowNode.removeEncryptedConnection(targetBSSID);
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
espnowMessage = "This message is no longer encrypted when received by node " + peerMac;
|
espnowMessage = String(F("This message is no longer encrypted when received by node ")) + peerMac;
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
Serial.println("Cannot read the encrypted response...");
|
Serial.println(F("Cannot read the encrypted response..."));
|
||||||
|
|
||||||
// Let's re-add our stored connection so we can communicate properly with targetBSSID again!
|
// Let's re-add our stored connection so we can communicate properly with targetBSSID again!
|
||||||
espnowNode.addEncryptedConnection(serializedEncryptedConnection);
|
espnowNode.addEncryptedConnection(serializedEncryptedConnection);
|
||||||
|
|
||||||
espnowMessage = "This message is once again encrypted when received by node " + peerMac;
|
espnowMessage = String(F("This message is once again encrypted when received by node ")) + peerMac;
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
// If we want to remove the encrypted connection on both nodes, we can do it like this.
|
// If we want to remove the encrypted connection on both nodes, we can do it like this.
|
||||||
encrypted_connection_removal_outcome_t removalOutcome = espnowNode.requestEncryptedConnectionRemoval(targetBSSID);
|
EncryptedConnectionRemovalOutcome removalOutcome = espnowNode.requestEncryptedConnectionRemoval(targetBSSID);
|
||||||
if (removalOutcome == ECRO_REMOVAL_SUCCEEDED) {
|
if (removalOutcome == EncryptedConnectionRemovalOutcome::REMOVAL_SUCCEEDED) {
|
||||||
Serial.println(peerMac + " is no longer encrypted!");
|
Serial.println(peerMac + F(" is no longer encrypted!"));
|
||||||
|
|
||||||
espnowMessage = "This message is only received by node " + peerMac + ". Transmitting in this way will not change the transmission state of the sender.";
|
espnowMessage = String(F("This message is only received by node ")) + peerMac + F(". Transmitting in this way will not change the transmission state of the sender.");
|
||||||
Serial.println("Transmitting: " + espnowMessage);
|
Serial.println(String(F("Transmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, EspnowNetworkInfo(targetBSSID));
|
espnowNode.attemptTransmission(espnowMessage, EspnowNetworkInfo(targetBSSID));
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
// Of course, we can also just create a temporary encrypted connection that will remove itself once its duration has passed.
|
// Of course, we can also just create a temporary encrypted connection that will remove itself once its duration has passed.
|
||||||
if (espnowNode.requestTemporaryEncryptedConnection(targetBSSID, 1000) == ECS_CONNECTION_ESTABLISHED) {
|
if (espnowNode.requestTemporaryEncryptedConnection(targetBSSID, 1000) == EncryptedConnectionStatus::CONNECTION_ESTABLISHED) {
|
||||||
espnowDelay(42);
|
espnowDelay(42);
|
||||||
uint32_t remainingDuration = 0;
|
uint32_t remainingDuration = 0;
|
||||||
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
|
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
|
||||||
|
|
||||||
espnowMessage = "Messages this node sends to " + peerMac + " will be encrypted for " + String(remainingDuration) + " ms more.";
|
espnowMessage = String(F("Messages this node sends to ")) + peerMac + F(" will be encrypted for ") + String(remainingDuration) + F(" ms more.");
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
|
|
||||||
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
|
EspnowMeshBackend::getConnectionInfo(targetBSSID, &remainingDuration);
|
||||||
espnowDelay(remainingDuration + 100);
|
espnowDelay(remainingDuration + 100);
|
||||||
|
|
||||||
espnowMessage = "Due to encrypted connection expiration, this message is no longer encrypted when received by node " + peerMac;
|
espnowMessage = String(F("Due to encrypted connection expiration, this message is no longer encrypted when received by node ")) + peerMac;
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptTransmission(espnowMessage, false);
|
espnowNode.attemptTransmission(espnowMessage, false);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
}
|
}
|
||||||
@ -438,24 +433,24 @@ void loop() {
|
|||||||
// Or if we prefer we can just let the library automatically create brief encrypted connections which are long enough to transmit an encrypted message.
|
// Or if we prefer we can just let the library automatically create brief encrypted connections which are long enough to transmit an encrypted message.
|
||||||
// Note that encrypted responses will not be received, unless there already was an encrypted connection established with the peer before attemptAutoEncryptingTransmission was called.
|
// Note that encrypted responses will not be received, unless there already was an encrypted connection established with the peer before attemptAutoEncryptingTransmission was called.
|
||||||
// This can be remedied via the requestPermanentConnections argument, though it must be noted that the maximum number of encrypted connections supported at a time is 6.
|
// This can be remedied via the requestPermanentConnections argument, though it must be noted that the maximum number of encrypted connections supported at a time is 6.
|
||||||
espnowMessage = "This message is always encrypted, regardless of receiver.";
|
espnowMessage = F("This message is always encrypted, regardless of receiver.");
|
||||||
Serial.println("\nTransmitting: " + espnowMessage);
|
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||||
espnowNode.attemptAutoEncryptingTransmission(espnowMessage);
|
espnowNode.attemptAutoEncryptingTransmission(espnowMessage);
|
||||||
espnowDelay(100); // Wait for response.
|
espnowDelay(100); // Wait for response.
|
||||||
} else {
|
} else {
|
||||||
Serial.println("Ooops! Encrypted connection removal failed. Status: " + String(removalOutcome));
|
Serial.println(String(F("Ooops! Encrypted connection removal failed. Status: ")) + String(static_cast<int>(removalOutcome)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, should you ever want to stop other parties from sending unencrypted messages to the node
|
// Finally, should you ever want to stop other parties from sending unencrypted messages to the node
|
||||||
// setAcceptsUnencryptedRequests(false);
|
// setAcceptsUnencryptedRequests(false);
|
||||||
// can be used for this. It applies to both encrypted connection requests and regular transmissions.
|
// can be used for this. It applies to both encrypted connection requests and regular transmissions.
|
||||||
|
|
||||||
Serial.println("\n##############################################################################################");
|
Serial.println(F("\n##############################################################################################"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Our last request was sent to all nodes found, so time to create a new request.
|
// Our last request was sent to all nodes found, so time to create a new request.
|
||||||
espnowNode.setMessage(String(F("Hello world request #")) + String(++requestNumber) + String(F(" from "))
|
espnowNode.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
||||||
+ espnowNode.getMeshName() + espnowNode.getNodeID() + String(F(".")));
|
+ espnowNode.getMeshName() + espnowNode.getNodeID() + String('.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
That way you will get instant confirmation of the mesh communication without checking the Serial Monitor.
|
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.
|
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: 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 <ESP8266WiFi.h>
|
||||||
#include <TypeConversionFunctions.h>
|
#include <TypeConversionFunctions.h>
|
||||||
@ -175,7 +175,7 @@ void loop() {
|
|||||||
floodingMeshDelay(1);
|
floodingMeshDelay(1);
|
||||||
|
|
||||||
// If you wish to transmit only to a single node, try using one of the following methods (requires the node to be within range and know the MAC of the recipient):
|
// If you wish to transmit only to a single node, try using one of the following methods (requires the node to be within range and know the MAC of the recipient):
|
||||||
// Unencrypted: transmission_status_t floodingMesh.getEspnowMeshBackend().attemptTransmission(message, EspnowNetworkInfo(recipientMac));
|
// Unencrypted: TransmissionStatusType floodingMesh.getEspnowMeshBackend().attemptTransmission(message, EspnowNetworkInfo(recipientMac));
|
||||||
// Encrypted (slow): floodingMesh.getEspnowMeshBackend().attemptAutoEncryptingTransmission(message, EspnowNetworkInfo(recipientMac));
|
// Encrypted (slow): floodingMesh.getEspnowMeshBackend().attemptAutoEncryptingTransmission(message, EspnowNetworkInfo(recipientMac));
|
||||||
|
|
||||||
if (theOne) {
|
if (theOne) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#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.
|
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: 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 <ESP8266WiFi.h>
|
||||||
#include <TcpIpMeshBackend.h>
|
#include <TcpIpMeshBackend.h>
|
||||||
@ -25,7 +25,7 @@ unsigned int requestNumber = 0;
|
|||||||
unsigned int responseNumber = 0;
|
unsigned int responseNumber = 0;
|
||||||
|
|
||||||
String manageRequest(const String &request, MeshBackendBase &meshInstance);
|
String manageRequest(const String &request, MeshBackendBase &meshInstance);
|
||||||
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance);
|
TransmissionStatusType manageResponse(const String &response, MeshBackendBase &meshInstance);
|
||||||
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
void networkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||||
|
|
||||||
/* Create the mesh node object */
|
/* Create the mesh node object */
|
||||||
@ -68,8 +68,8 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
|||||||
@param meshInstance The MeshBackendBase instance that called the function.
|
@param meshInstance The MeshBackendBase instance that called the function.
|
||||||
@return The status code resulting from the response, as an int
|
@return The status code resulting from the response, as an int
|
||||||
*/
|
*/
|
||||||
transmission_status_t manageResponse(const String &response, MeshBackendBase &meshInstance) {
|
TransmissionStatusType manageResponse(const String &response, MeshBackendBase &meshInstance) {
|
||||||
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
|
TransmissionStatusType statusCode = TransmissionStatusType::TRANSMISSION_COMPLETE;
|
||||||
|
|
||||||
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
// To get the actual class of the polymorphic meshInstance, do as follows (meshBackendCast replaces dynamic_cast since RTTI is disabled)
|
||||||
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
if (EspnowMeshBackend *espnowInstance = TypeCast::meshBackendCast<EspnowMeshBackend *>(&meshInstance)) {
|
||||||
@ -142,7 +142,7 @@ bool exampleTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance) {
|
|||||||
// The default hook only returns true and does nothing else.
|
// The default hook only returns true and does nothing else.
|
||||||
|
|
||||||
if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||||
if (tcpIpInstance->latestTransmissionOutcomes().back().transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
|
if (tcpIpInstance->latestTransmissionOutcomes().back().transmissionStatus() == TransmissionStatusType::TRANSMISSION_COMPLETE) {
|
||||||
// Our last request got a response, so time to create a new request.
|
// Our last request got a response, so time to create a new request.
|
||||||
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
||||||
+ meshInstance.getMeshName() + meshInstance.getNodeID() + String('.'));
|
+ meshInstance.getMeshName() + meshInstance.getNodeID() + String('.'));
|
||||||
@ -209,11 +209,11 @@ void loop() {
|
|||||||
Serial.println(F("No mesh AP found."));
|
Serial.println(F("No mesh AP found."));
|
||||||
} else {
|
} else {
|
||||||
for (TransmissionOutcome &transmissionOutcome : tcpIpNode.latestTransmissionOutcomes()) {
|
for (TransmissionOutcome &transmissionOutcome : tcpIpNode.latestTransmissionOutcomes()) {
|
||||||
if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_FAILED) {
|
if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::TRANSMISSION_FAILED) {
|
||||||
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionOutcome.SSID());
|
Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionOutcome.SSID());
|
||||||
} else if (transmissionOutcome.transmissionStatus() == TS_CONNECTION_FAILED) {
|
} else if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::CONNECTION_FAILED) {
|
||||||
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionOutcome.SSID());
|
Serial.println(String(F("Connection failed to mesh AP ")) + transmissionOutcome.SSID());
|
||||||
} else if (transmissionOutcome.transmissionStatus() == TS_TRANSMISSION_COMPLETE) {
|
} else if (transmissionOutcome.transmissionStatus() == TransmissionStatusType::TRANSMISSION_COMPLETE) {
|
||||||
// No need to do anything, transmission was successful.
|
// No need to do anything, transmission was successful.
|
||||||
} else {
|
} else {
|
||||||
Serial.println(String(F("Invalid transmission status for ")) + transmissionOutcome.SSID() + String('!'));
|
Serial.println(String(F("Invalid transmission status for ")) + transmissionOutcome.SSID() + String('!'));
|
||||||
|
@ -12,7 +12,7 @@ ESP8266WiFiMesh KEYWORD3
|
|||||||
# Datatypes (KEYWORD1)
|
# Datatypes (KEYWORD1)
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
transmission_status_t KEYWORD1
|
TransmissionStatusType KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
|
@ -35,8 +35,6 @@ namespace
|
|||||||
size_t _ctMinDataLength = 0;
|
size_t _ctMinDataLength = 0;
|
||||||
size_t _ctMaxDataLength = 1024;
|
size_t _ctMaxDataLength = 1024;
|
||||||
|
|
||||||
bool _warningsEnabled = true;
|
|
||||||
|
|
||||||
br_hkdf_context _storedHkdfContext;
|
br_hkdf_context _storedHkdfContext;
|
||||||
bool _hkdfContextStored = false;
|
bool _hkdfContextStored = false;
|
||||||
|
|
||||||
@ -186,26 +184,44 @@ namespace
|
|||||||
createBearsslHmacCT(hashType, message.c_str(), message.length(), hashKey, hashKeyLength, hmac, hmacLength);
|
createBearsslHmacCT(hashType, message.c_str(), message.length(), hashKey, hashKeyLength, hmac, hmacLength);
|
||||||
return TypeCast::uint8ArrayToHexString(hmac, hmacLength);
|
return TypeCast::uint8ArrayToHexString(hmac, hmacLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function to avoid deprecated warnings.
|
||||||
|
void *md5HashHelper(const void *data, const size_t dataLength, void *resultArray)
|
||||||
|
{
|
||||||
|
br_md5_context context;
|
||||||
|
br_md5_init(&context);
|
||||||
|
br_md5_update(&context, data, dataLength);
|
||||||
|
br_md5_out(&context, resultArray);
|
||||||
|
return resultArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to avoid deprecated warnings.
|
||||||
|
void *sha1HashHelper(const void *data, const size_t dataLength, void *resultArray)
|
||||||
|
{
|
||||||
|
br_sha1_context context;
|
||||||
|
br_sha1_init(&context);
|
||||||
|
br_sha1_update(&context, data, dataLength);
|
||||||
|
br_sha1_out(&context, resultArray);
|
||||||
|
return resultArray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CryptoInterface
|
namespace CryptoInterface
|
||||||
{
|
{
|
||||||
void setCtMinDataLength(const size_t ctMinDataLength)
|
void setCtMinDataLength(const size_t ctMinDataLength)
|
||||||
{
|
{
|
||||||
assert(ctMaxDataLength() - ctMinDataLength <= CT_MAX_DIFF);
|
assert(getCtMaxDataLength() - ctMinDataLength <= CT_MAX_DIFF);
|
||||||
_ctMinDataLength = ctMinDataLength;
|
_ctMinDataLength = ctMinDataLength;
|
||||||
}
|
}
|
||||||
size_t ctMinDataLength() {return _ctMinDataLength;}
|
size_t getCtMinDataLength() {return _ctMinDataLength;}
|
||||||
|
|
||||||
void setCtMaxDataLength(const size_t ctMaxDataLength)
|
void setCtMaxDataLength(const size_t ctMaxDataLength)
|
||||||
{
|
{
|
||||||
assert(ctMaxDataLength - ctMinDataLength() <= CT_MAX_DIFF);
|
assert(ctMaxDataLength - getCtMinDataLength() <= CT_MAX_DIFF);
|
||||||
_ctMaxDataLength = ctMaxDataLength;
|
_ctMaxDataLength = ctMaxDataLength;
|
||||||
}
|
}
|
||||||
size_t ctMaxDataLength() {return _ctMaxDataLength;}
|
size_t getCtMaxDataLength() {return _ctMaxDataLength;}
|
||||||
|
|
||||||
void setWarningsEnabled(bool warningsEnabled) { _warningsEnabled = warningsEnabled; }
|
|
||||||
bool warningsEnabled() { return _warningsEnabled; }
|
|
||||||
|
|
||||||
void setNonceGenerator(nonceGeneratorType nonceGenerator) { _nonceGenerator = nonceGenerator; }
|
void setNonceGenerator(nonceGeneratorType nonceGenerator) { _nonceGenerator = nonceGenerator; }
|
||||||
nonceGeneratorType getNonceGenerator() { return _nonceGenerator; }
|
nonceGeneratorType getNonceGenerator() { return _nonceGenerator; }
|
||||||
@ -216,22 +232,13 @@ namespace CryptoInterface
|
|||||||
// resultArray must have size MD5_NATURAL_LENGTH or greater
|
// resultArray must have size MD5_NATURAL_LENGTH or greater
|
||||||
void *md5Hash(const void *data, const size_t dataLength, void *resultArray)
|
void *md5Hash(const void *data, const size_t dataLength, void *resultArray)
|
||||||
{
|
{
|
||||||
if(warningsEnabled())
|
return md5HashHelper(data, dataLength, resultArray);
|
||||||
Serial.println(F("\nWARNING! The MD5 hash is broken in terms of attacker resistance.\n"
|
|
||||||
"Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.\n"
|
|
||||||
"Use CryptoInterface::setWarningsEnabled(false) to turn off this warning.\n"));
|
|
||||||
|
|
||||||
br_md5_context context;
|
|
||||||
br_md5_init(&context);
|
|
||||||
br_md5_update(&context, data, dataLength);
|
|
||||||
br_md5_out(&context, resultArray);
|
|
||||||
return resultArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String md5Hash(const String &message)
|
String md5Hash(const String &message)
|
||||||
{
|
{
|
||||||
uint8_t hash[MD5_NATURAL_LENGTH];
|
uint8_t hash[MD5_NATURAL_LENGTH];
|
||||||
md5Hash(message.c_str(), message.length(), hash);
|
md5HashHelper(message.c_str(), message.length(), hash);
|
||||||
return TypeCast::uint8ArrayToHexString(hash, MD5_NATURAL_LENGTH);
|
return TypeCast::uint8ArrayToHexString(hash, MD5_NATURAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,22 +268,13 @@ namespace CryptoInterface
|
|||||||
// resultArray must have size SHA1_NATURAL_LENGTH or greater
|
// resultArray must have size SHA1_NATURAL_LENGTH or greater
|
||||||
void *sha1Hash(const void *data, const size_t dataLength, void *resultArray)
|
void *sha1Hash(const void *data, const size_t dataLength, void *resultArray)
|
||||||
{
|
{
|
||||||
if(warningsEnabled())
|
return sha1HashHelper(data, dataLength, resultArray);
|
||||||
Serial.println(F("\nWARNING! The SHA-1 hash is broken in terms of attacker resistance.\n"
|
|
||||||
"Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.\n"
|
|
||||||
"Use CryptoInterface::setWarningsEnabled(false) to turn off this warning.\n"));
|
|
||||||
|
|
||||||
br_sha1_context context;
|
|
||||||
br_sha1_init(&context);
|
|
||||||
br_sha1_update(&context, data, dataLength);
|
|
||||||
br_sha1_out(&context, resultArray);
|
|
||||||
return resultArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String sha1Hash(const String &message)
|
String sha1Hash(const String &message)
|
||||||
{
|
{
|
||||||
uint8_t hash[SHA1_NATURAL_LENGTH];
|
uint8_t hash[SHA1_NATURAL_LENGTH];
|
||||||
sha1Hash(message.c_str(), message.length(), hash);
|
sha1HashHelper(message.c_str(), message.length(), hash);
|
||||||
return TypeCast::uint8ArrayToHexString(hash, SHA1_NATURAL_LENGTH);
|
return TypeCast::uint8ArrayToHexString(hash, SHA1_NATURAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ namespace CryptoInterface
|
|||||||
* naturally yielding constant-time operations. HMAC is naturally as constant-time as the underlying hash function. The size of the MACed data, and the size of the key,
|
* naturally yielding constant-time operations. HMAC is naturally as constant-time as the underlying hash function. The size of the MACed data, and the size of the key,
|
||||||
* may leak, though; only the contents are protected."
|
* may leak, though; only the contents are protected."
|
||||||
*
|
*
|
||||||
* For messages much smaller than ctMaxDataLength(), constant-time processing takes substantially longer time to complete than a normal HMAC,
|
* For messages much smaller than getCtMaxDataLength(), constant-time processing takes substantially longer time to complete than a normal HMAC,
|
||||||
* determined by the size of (ctMaxDataLength() - ctMinDataLength()).
|
* determined by the size of (getCtMaxDataLength() - getCtMinDataLength()).
|
||||||
* Constant-time processing also sets limits on the data length.
|
* Constant-time processing also sets limits on the data length.
|
||||||
*
|
*
|
||||||
* Making the fixed data length limits variable will generally defeat the purpose of using constant-time.
|
* Making the fixed data length limits variable will generally defeat the purpose of using constant-time.
|
||||||
@ -78,34 +78,26 @@ namespace CryptoInterface
|
|||||||
* It should not be changed once a constant time function has been used at least once.
|
* It should not be changed once a constant time function has been used at least once.
|
||||||
* Otherwise the constant time will not be constant for the used functions.
|
* Otherwise the constant time will not be constant for the used functions.
|
||||||
*
|
*
|
||||||
* The difference ctMaxDataLength() - ctMinDataLength() MUST be less than 2^30 (i.e. about one gigabyte).
|
* The difference getCtMaxDataLength() - getCtMinDataLength() MUST be less than 2^30 (i.e. about one gigabyte).
|
||||||
*/
|
*/
|
||||||
void setCtMinDataLength(const size_t ctMinDataLength);
|
void setCtMinDataLength(const size_t ctMinDataLength);
|
||||||
/**
|
/**
|
||||||
* 0 by default.
|
* 0 by default.
|
||||||
*/
|
*/
|
||||||
size_t ctMinDataLength();
|
size_t getCtMinDataLength();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function allows for fine-tuning of the specifications for the constant time calculations.
|
* This function allows for fine-tuning of the specifications for the constant time calculations.
|
||||||
* It should not be changed once a constant time function has been used at least once.
|
* It should not be changed once a constant time function has been used at least once.
|
||||||
* Otherwise the constant time will not be constant for the used functions.
|
* Otherwise the constant time will not be constant for the used functions.
|
||||||
*
|
*
|
||||||
* The difference ctMaxDataLength() - ctMinDataLength() MUST be less than 2^30 (i.e. about one gigabyte).
|
* The difference getCtMaxDataLength() - getCtMinDataLength() MUST be less than 2^30 (i.e. about one gigabyte).
|
||||||
*/
|
*/
|
||||||
void setCtMaxDataLength(const size_t ctMaxDataLength);
|
void setCtMaxDataLength(const size_t ctMaxDataLength);
|
||||||
/**
|
/**
|
||||||
* 1024 by default.
|
* 1024 by default.
|
||||||
*/
|
*/
|
||||||
size_t ctMaxDataLength();
|
size_t getCtMaxDataLength();
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn on or off warning Serial prints from the CryptoInterface functions.
|
|
||||||
*
|
|
||||||
* @param warningsEnabled If true, warnings will be printed to Serial.
|
|
||||||
*/
|
|
||||||
void setWarningsEnabled(bool warningsEnabled);
|
|
||||||
bool warningsEnabled();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the nonce generator used by the CryptoInterface functions.
|
* Set the nonce generator used by the CryptoInterface functions.
|
||||||
@ -119,6 +111,9 @@ namespace CryptoInterface
|
|||||||
// #################### MD5 ####################
|
// #################### MD5 ####################
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WARNING! The MD5 hash is broken in terms of attacker resistance.
|
||||||
|
* Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.
|
||||||
|
*
|
||||||
* Create a MD5 hash of the data. The result will be MD5_NATURAL_LENGTH bytes long and stored in resultArray.
|
* Create a MD5 hash of the data. The result will be MD5_NATURAL_LENGTH bytes long and stored in resultArray.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
@ -128,9 +123,12 @@ namespace CryptoInterface
|
|||||||
*
|
*
|
||||||
* @return A pointer to resultArray.
|
* @return A pointer to resultArray.
|
||||||
*/
|
*/
|
||||||
void *md5Hash(const void *data, const size_t dataLength, void *resultArray);
|
void *md5Hash(const void *data, const size_t dataLength, void *resultArray) __attribute__((deprecated));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WARNING! The MD5 hash is broken in terms of attacker resistance.
|
||||||
|
* Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.
|
||||||
|
*
|
||||||
* Create a MD5 hash of the data. The result will be MD5_NATURAL_LENGTH bytes long and returned as a String in HEX format.
|
* Create a MD5 hash of the data. The result will be MD5_NATURAL_LENGTH bytes long and returned as a String in HEX format.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
@ -138,7 +136,7 @@ namespace CryptoInterface
|
|||||||
*
|
*
|
||||||
* @return A String with the generated hash in HEX format.
|
* @return A String with the generated hash in HEX format.
|
||||||
*/
|
*/
|
||||||
String md5Hash(const String &message);
|
String md5Hash(const String &message) __attribute__((deprecated));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a MD5 HMAC from the data, using the provided hashKey. The result will be up to outputLength bytes long and stored in resultArray.
|
* Create a MD5 HMAC from the data, using the provided hashKey. The result will be up to outputLength bytes long and stored in resultArray.
|
||||||
@ -176,7 +174,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -193,7 +191,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to MD5_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to MD5_NATURAL_LENGTH.
|
||||||
@ -206,6 +204,9 @@ namespace CryptoInterface
|
|||||||
// #################### SHA-1 ####################
|
// #################### SHA-1 ####################
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WARNING! The SHA-1 hash is broken in terms of attacker resistance.
|
||||||
|
* Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.
|
||||||
|
*
|
||||||
* Create a SHA1 hash of the data. The result will be SHA1_NATURAL_LENGTH bytes long and stored in resultArray.
|
* Create a SHA1 hash of the data. The result will be SHA1_NATURAL_LENGTH bytes long and stored in resultArray.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
@ -215,9 +216,12 @@ namespace CryptoInterface
|
|||||||
*
|
*
|
||||||
* @return A pointer to resultArray.
|
* @return A pointer to resultArray.
|
||||||
*/
|
*/
|
||||||
void *sha1Hash(const void *data, const size_t dataLength, void *resultArray);
|
void *sha1Hash(const void *data, const size_t dataLength, void *resultArray) __attribute__((deprecated));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WARNING! The SHA-1 hash is broken in terms of attacker resistance.
|
||||||
|
* Only use it in those cases where attacker resistance is not important. Prefer SHA-256 or higher otherwise.
|
||||||
|
*
|
||||||
* Create a SHA1 hash of the data. The result will be SHA1_NATURAL_LENGTH bytes long and returned as a String in HEX format.
|
* Create a SHA1 hash of the data. The result will be SHA1_NATURAL_LENGTH bytes long and returned as a String in HEX format.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
@ -225,7 +229,7 @@ namespace CryptoInterface
|
|||||||
*
|
*
|
||||||
* @return A String with the generated hash in HEX format.
|
* @return A String with the generated hash in HEX format.
|
||||||
*/
|
*/
|
||||||
String sha1Hash(const String &message);
|
String sha1Hash(const String &message) __attribute__((deprecated));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a SHA1 HMAC from the data, using the provided hashKey. The result will be up to outputLength bytes long and stored in resultArray.
|
* Create a SHA1 HMAC from the data, using the provided hashKey. The result will be up to outputLength bytes long and stored in resultArray.
|
||||||
@ -263,7 +267,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -280,7 +284,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA1_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA1_NATURAL_LENGTH.
|
||||||
@ -350,7 +354,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -367,7 +371,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA224_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA224_NATURAL_LENGTH.
|
||||||
@ -437,7 +441,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -454,7 +458,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA256_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA256_NATURAL_LENGTH.
|
||||||
@ -524,7 +528,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -541,7 +545,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA384_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA384_NATURAL_LENGTH.
|
||||||
@ -611,7 +615,7 @@ namespace CryptoInterface
|
|||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param data The data array from which to create the HMAC.
|
* @param data The data array from which to create the HMAC.
|
||||||
* @param dataLength The length of the data array in bytes. Valid values are in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param dataLength The length of the data array in bytes. Valid values are in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param resultArray The array wherein to store the resulting HMAC.
|
* @param resultArray The array wherein to store the resulting HMAC.
|
||||||
@ -628,7 +632,7 @@ namespace CryptoInterface
|
|||||||
* Constant-time version.
|
* Constant-time version.
|
||||||
* Uses the BearSSL cryptographic library.
|
* Uses the BearSSL cryptographic library.
|
||||||
*
|
*
|
||||||
* @param message The string from which to create the HMAC. Must have a length in the range [ctMinDataLength(), ctMaxDataLength()].
|
* @param message The string from which to create the HMAC. Must have a length in the range [getCtMinDataLength(), getCtMaxDataLength()].
|
||||||
* @param hashKey The hash key to use when creating the HMAC.
|
* @param hashKey The hash key to use when creating the HMAC.
|
||||||
* @param hashKeyLength The length of the hash key in bytes.
|
* @param hashKeyLength The length of the hash key in bytes.
|
||||||
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA512_NATURAL_LENGTH.
|
* @param hmacLength The desired length of the generated HMAC, in bytes. Valid values are 1 to SHA512_NATURAL_LENGTH.
|
||||||
|
@ -54,7 +54,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
|
|||||||
|
|
||||||
const IPAddress ESP8266WiFiMesh::emptyIP = IPAddress();
|
const IPAddress ESP8266WiFiMesh::emptyIP = IPAddress();
|
||||||
|
|
||||||
String ESP8266WiFiMesh::lastSSID = "";
|
String ESP8266WiFiMesh::lastSSID;
|
||||||
bool ESP8266WiFiMesh::staticIPActivated = false;
|
bool ESP8266WiFiMesh::staticIPActivated = false;
|
||||||
|
|
||||||
// IP needs to be at the same subnet as server gateway (192.168.4 in this case). Station gateway ip must match ip for server.
|
// IP needs to be at the same subnet as server gateway (192.168.4 in this case). Station gateway ip must match ip for server.
|
||||||
@ -88,9 +88,9 @@ ESP8266WiFiMesh::ESP8266WiFiMesh(ESP8266WiFiMesh::requestHandlerType requestHand
|
|||||||
|
|
||||||
void ESP8266WiFiMesh::updateNetworkNames(const String &newMeshName, const String &newNodeID)
|
void ESP8266WiFiMesh::updateNetworkNames(const String &newMeshName, const String &newNodeID)
|
||||||
{
|
{
|
||||||
if(newMeshName != "")
|
if(!newMeshName.isEmpty())
|
||||||
_meshName = newMeshName;
|
_meshName = newMeshName;
|
||||||
if(newNodeID != "")
|
if(!newNodeID.isEmpty())
|
||||||
_nodeID = newNodeID;
|
_nodeID = newNodeID;
|
||||||
|
|
||||||
String newSSID = _meshName + _nodeID;
|
String newSSID = _meshName + _nodeID;
|
||||||
@ -469,7 +469,7 @@ void ESP8266WiFiMesh::initiateConnectionToAP(const String &targetSSID, int targe
|
|||||||
*/
|
*/
|
||||||
transmission_status_t ESP8266WiFiMesh::connectToNode(const String &targetSSID, int targetChannel, uint8_t *targetBSSID)
|
transmission_status_t ESP8266WiFiMesh::connectToNode(const String &targetSSID, int targetChannel, uint8_t *targetBSSID)
|
||||||
{
|
{
|
||||||
if(staticIPActivated && lastSSID != "" && lastSSID != targetSSID) // So we only do this once per connection, in case there is a performance impact.
|
if(staticIPActivated && !lastSSID.isEmpty() && lastSSID != targetSSID) // So we only do this once per connection, in case there is a performance impact.
|
||||||
{
|
{
|
||||||
#if LWIP_VERSION_MAJOR >= 2
|
#if LWIP_VERSION_MAJOR >= 2
|
||||||
// Can be used with Arduino core for ESP8266 version 2.4.2 or higher with lwIP2 enabled to keep static IP on even during network switches.
|
// Can be used with Arduino core for ESP8266 version 2.4.2 or higher with lwIP2 enabled to keep static IP on even during network switches.
|
||||||
@ -567,12 +567,12 @@ void ESP8266WiFiMesh::attemptTransmission(const String &message, bool concluding
|
|||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
String currentSSID = "";
|
String currentSSID;
|
||||||
int currentWiFiChannel = NETWORK_INFO_DEFAULT_INT;
|
int currentWiFiChannel = NETWORK_INFO_DEFAULT_INT;
|
||||||
uint8_t *currentBSSID = NULL;
|
uint8_t *currentBSSID = NULL;
|
||||||
|
|
||||||
// If an SSID has been assigned, it is prioritized over an assigned networkIndex since the networkIndex is more likely to change.
|
// If an SSID has been assigned, it is prioritized over an assigned networkIndex since the networkIndex is more likely to change.
|
||||||
if(currentNetwork.SSID != "")
|
if(!currentNetwork.SSID.isEmpty())
|
||||||
{
|
{
|
||||||
currentSSID = currentNetwork.SSID;
|
currentSSID = currentNetwork.SSID;
|
||||||
currentWiFiChannel = currentNetwork.wifiChannel;
|
currentWiFiChannel = currentNetwork.wifiChannel;
|
||||||
|
@ -47,8 +47,9 @@
|
|||||||
#include <WiFiServer.h>
|
#include <WiFiServer.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "NetworkInfo.h"
|
|
||||||
#include "TransmissionResult.h"
|
#include "TransmissionResult.h"
|
||||||
|
#include "NetworkInfo.h"
|
||||||
|
|
||||||
|
|
||||||
const String WIFI_MESH_EMPTY_STRING = "";
|
const String WIFI_MESH_EMPTY_STRING = "";
|
||||||
|
|
||||||
@ -175,7 +176,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
ESP8266WiFiMesh(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter,
|
ESP8266WiFiMesh(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter,
|
||||||
const String &meshPassword, const String &meshName = "MeshNode_", const String &nodeID = WIFI_MESH_EMPTY_STRING, bool verboseMode = false,
|
const String &meshPassword, const String &meshName = "MeshNode_", const String &nodeID = WIFI_MESH_EMPTY_STRING, bool verboseMode = false,
|
||||||
uint8 meshWiFiChannel = 1, uint16_t serverPort = 4011);
|
uint8 meshWiFiChannel = 1, uint16_t serverPort = 4011) __attribute__((deprecated));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vector that contains the NetworkInfo for each WiFi network to connect to.
|
* A vector that contains the NetworkInfo for each WiFi network to connect to.
|
||||||
|
@ -102,10 +102,8 @@ bool EncryptedConnectionData::connectedTo(const uint8_t *peerMac) const
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncryptedConnectionData::setHashKey(const uint8_t hashKey[espnowHashKeyLength])
|
void EncryptedConnectionData::setHashKey(const uint8_t hashKey[espnowHashKeyLength])
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -90,32 +90,34 @@
|
|||||||
#include "EspnowNetworkInfo.h"
|
#include "EspnowNetworkInfo.h"
|
||||||
#include "CryptoInterface.h"
|
#include "CryptoInterface.h"
|
||||||
|
|
||||||
typedef enum
|
namespace Espnow
|
||||||
{
|
{
|
||||||
ECT_NO_CONNECTION = 0,
|
enum class ConnectionType
|
||||||
ECT_TEMPORARY_CONNECTION = 1,
|
{
|
||||||
ECT_PERMANENT_CONNECTION = 2
|
NO_CONNECTION = 0,
|
||||||
} espnow_connection_type_t;
|
TEMPORARY_CONNECTION = 1,
|
||||||
|
PERMANENT_CONNECTION = 2
|
||||||
|
};
|
||||||
|
|
||||||
// A value greater than 0 means that an encrypted connection has been established.
|
// A value greater than 0 means that an encrypted connection has been established.
|
||||||
typedef enum
|
enum class EncryptedConnectionStatus
|
||||||
{
|
{
|
||||||
ECS_MAX_CONNECTIONS_REACHED_SELF = -3,
|
MAX_CONNECTIONS_REACHED_SELF = -3,
|
||||||
ECS_REQUEST_TRANSMISSION_FAILED = -2,
|
REQUEST_TRANSMISSION_FAILED = -2,
|
||||||
ECS_MAX_CONNECTIONS_REACHED_PEER = -1,
|
MAX_CONNECTIONS_REACHED_PEER = -1,
|
||||||
ECS_API_CALL_FAILED = 0,
|
API_CALL_FAILED = 0,
|
||||||
ECS_CONNECTION_ESTABLISHED = 1,
|
CONNECTION_ESTABLISHED = 1,
|
||||||
ECS_SOFT_LIMIT_CONNECTION_ESTABLISHED = 2 // Only used if _encryptedConnectionsSoftLimit is less than 6.
|
SOFT_LIMIT_CONNECTION_ESTABLISHED = 2 // Only used if _encryptedConnectionsSoftLimit is less than 6.
|
||||||
} encrypted_connection_status_t;
|
};
|
||||||
|
|
||||||
typedef enum
|
enum class EncryptedConnectionRemovalOutcome
|
||||||
{
|
{
|
||||||
ECRO_REMOVAL_REQUEST_FAILED = -1,
|
REMOVAL_REQUEST_FAILED = -1,
|
||||||
ECRO_REMOVAL_FAILED = 0,
|
REMOVAL_FAILED = 0,
|
||||||
ECRO_REMOVAL_SUCCEEDED = 1,
|
REMOVAL_SUCCEEDED = 1,
|
||||||
ECRO_REMOVAL_SCHEDULED = 2
|
REMOVAL_SCHEDULED = 2
|
||||||
} encrypted_connection_removal_outcome_t;
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alternative to standard delay(). Will continuously call performEspnowMaintenance() during the waiting time, so that the ESP-NOW node remains responsive.
|
* An alternative to standard delay(). Will continuously call performEspnowMaintenance() during the waiting time, so that the ESP-NOW node remains responsive.
|
||||||
@ -130,12 +132,14 @@ void espnowDelay(uint32_t durationMs);
|
|||||||
|
|
||||||
class RequestData;
|
class RequestData;
|
||||||
|
|
||||||
|
using namespace Espnow; // TODO: Remove
|
||||||
|
|
||||||
class EspnowMeshBackend : public MeshBackendBase {
|
class EspnowMeshBackend : public MeshBackendBase {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::function<bool(String &, EspnowMeshBackend &)> broadcastFilterType;
|
using broadcastFilterType = std::function<bool(String &, EspnowMeshBackend &)>;
|
||||||
typedef std::function<bool(const String &, const uint8_t *, uint32_t, EspnowMeshBackend &)> responseTransmittedHookType;
|
using responseTransmittedHookType = std::function<bool(const String &, const uint8_t *, uint32_t, EspnowMeshBackend &)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -145,7 +149,7 @@ public:
|
|||||||
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
||||||
* is the request string received from another node and returns the string to send back.
|
* is the request string received from another node and returns the string to send back.
|
||||||
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
||||||
* is the response string received from another node. Returns a transmission status code as a transmission_status_t.
|
* is the response string received from another node. Returns a transmission status code as a TransmissionStatusType.
|
||||||
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
||||||
* @param broadcastFilter The callback handler for deciding which ESP-NOW broadcasts to accept.
|
* @param broadcastFilter The callback handler for deciding which ESP-NOW broadcasts to accept.
|
||||||
* @param meshPassword The WiFi password for the mesh network.
|
* @param meshPassword The WiFi password for the mesh network.
|
||||||
@ -155,7 +159,7 @@ public:
|
|||||||
* @param ssidSuffix The suffix (last part) of the node SSID.
|
* @param ssidSuffix The suffix (last part) of the node SSID.
|
||||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
||||||
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
@ -173,7 +177,7 @@ public:
|
|||||||
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
||||||
* is the request string received from another node and returns the string to send back.
|
* is the request string received from another node and returns the string to send back.
|
||||||
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
||||||
* is the response string received from another node. Returns a transmission status code as a transmission_status_t.
|
* is the response string received from another node. Returns a transmission status code as a TransmissionStatusType.
|
||||||
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
||||||
* @param broadcastFilter The callback handler for deciding which ESP-NOW broadcasts to accept.
|
* @param broadcastFilter The callback handler for deciding which ESP-NOW broadcasts to accept.
|
||||||
* @param meshPassword The WiFi password for the mesh network.
|
* @param meshPassword The WiFi password for the mesh network.
|
||||||
@ -183,7 +187,7 @@ public:
|
|||||||
* @param ssidSuffix The suffix (last part) of the node SSID.
|
* @param ssidSuffix The suffix (last part) of the node SSID.
|
||||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
||||||
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
@ -222,7 +226,7 @@ public:
|
|||||||
static std::vector<TransmissionOutcome> & latestTransmissionOutcomes();
|
static std::vector<TransmissionOutcome> & latestTransmissionOutcomes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
|
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TransmissionStatusType::TRANSMISSION_COMPLETE). False otherwise.
|
||||||
* The result is unique for each mesh backend.
|
* The result is unique for each mesh backend.
|
||||||
*/
|
*/
|
||||||
static bool latestTransmissionSuccessful();
|
static bool latestTransmissionSuccessful();
|
||||||
@ -285,7 +289,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param recipientInfo The recipient information.
|
* @param recipientInfo The recipient information.
|
||||||
*/
|
*/
|
||||||
transmission_status_t attemptTransmission(const String &message, const EspnowNetworkInfo &recipientInfo);
|
TransmissionStatusType attemptTransmission(const String &message, const EspnowNetworkInfo &recipientInfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Will ensure that an encrypted connection exists to each target node before sending the message,
|
* Will ensure that an encrypted connection exists to each target node before sending the message,
|
||||||
@ -317,7 +321,7 @@ public:
|
|||||||
* Transmit message to a single recipient without changing the local transmission state (apart from encrypted connections).
|
* Transmit message to a single recipient without changing the local transmission state (apart from encrypted connections).
|
||||||
* Will not change connectionQueue, latestTransmissionOutcomes or stored message.
|
* Will not change connectionQueue, latestTransmissionOutcomes or stored message.
|
||||||
*/
|
*/
|
||||||
transmission_status_t attemptAutoEncryptingTransmission(const String &message, const EspnowNetworkInfo &recipientInfo, bool requestPermanentConnection = false);
|
TransmissionStatusType attemptAutoEncryptingTransmission(const String &message, const EspnowNetworkInfo &recipientInfo, bool requestPermanentConnection = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message simultaneously to all nearby nodes which have ESP-NOW activated.
|
* Send a message simultaneously to all nearby nodes which have ESP-NOW activated.
|
||||||
@ -736,32 +740,32 @@ public:
|
|||||||
|
|
||||||
// Updates connection with current stored encrypted connection key.
|
// Updates connection with current stored encrypted connection key.
|
||||||
// At least one of the leftmost 32 bits in each of the session keys should be 1, since the key otherwise indicates the connection is unencrypted.
|
// At least one of the leftmost 32 bits in each of the session keys should be 1, since the key otherwise indicates the connection is unencrypted.
|
||||||
encrypted_connection_status_t addEncryptedConnection(uint8_t *peerStaMac, uint8_t *peerApMac, uint64_t peerSessionKey, uint64_t ownSessionKey);
|
EncryptedConnectionStatus addEncryptedConnection(uint8_t *peerStaMac, uint8_t *peerApMac, uint64_t peerSessionKey, uint64_t ownSessionKey);
|
||||||
// Note that the espnowEncryptedConnectionKey, espnowEncryptionKok, espnowHashKey and espnowMessageEncryptionKey are not serialized.
|
// Note that the espnowEncryptedConnectionKey, espnowEncryptionKok, espnowHashKey and espnowMessageEncryptionKey are not serialized.
|
||||||
// These will be set to the values of the EspnowMeshBackend instance that is adding the serialized encrypted connection.
|
// These will be set to the values of the EspnowMeshBackend instance that is adding the serialized encrypted connection.
|
||||||
// @param ignoreDuration Ignores any stored duration serializedConnectionState, guaranteeing that the created connection will be permanent. Returns: ECS_REQUEST_TRANSMISSION_FAILED indicates malformed serializedConnectionState.
|
// @param ignoreDuration Ignores any stored duration serializedConnectionState, guaranteeing that the created connection will be permanent. Returns: EncryptedConnectionStatus::REQUEST_TRANSMISSION_FAILED indicates malformed serializedConnectionState.
|
||||||
encrypted_connection_status_t addEncryptedConnection(const String &serializedConnectionState, bool ignoreDuration = false);
|
EncryptedConnectionStatus addEncryptedConnection(const String &serializedConnectionState, bool ignoreDuration = false);
|
||||||
|
|
||||||
// Adds a new temporary encrypted connection, or changes the duration of an existing temporary connection (only updates keys, not duration, for existing permanent connections).
|
// Adds a new temporary encrypted connection, or changes the duration of an existing temporary connection (only updates keys, not duration, for existing permanent connections).
|
||||||
// As with all these methods, changes will only take effect once the requester proves it has the ability to decrypt the session key.
|
// As with all these methods, changes will only take effect once the requester proves it has the ability to decrypt the session key.
|
||||||
// At least one of the leftmost 32 bits in each of the session keys should be 1, since the key otherwise indicates the connection is unencrypted.
|
// At least one of the leftmost 32 bits in each of the session keys should be 1, since the key otherwise indicates the connection is unencrypted.
|
||||||
encrypted_connection_status_t addTemporaryEncryptedConnection(uint8_t *peerStaMac, uint8_t *peerApMac, uint64_t peerSessionKey, uint64_t ownSessionKey, uint32_t duration);
|
EncryptedConnectionStatus addTemporaryEncryptedConnection(uint8_t *peerStaMac, uint8_t *peerApMac, uint64_t peerSessionKey, uint64_t ownSessionKey, uint32_t duration);
|
||||||
// Note that the espnowEncryptedConnectionKey, espnowEncryptionKok, espnowHashKey and espnowMessageEncryptionKey are not serialized.
|
// Note that the espnowEncryptedConnectionKey, espnowEncryptionKok, espnowHashKey and espnowMessageEncryptionKey are not serialized.
|
||||||
// These will be set to the values of the EspnowMeshBackend instance that is adding the serialized encrypted connection.
|
// These will be set to the values of the EspnowMeshBackend instance that is adding the serialized encrypted connection.
|
||||||
// Uses duration argument instead of any stored duration in serializedConnectionState. Returns: ECS_REQUEST_TRANSMISSION_FAILED indicates malformed serializedConnectionState.
|
// Uses duration argument instead of any stored duration in serializedConnectionState. Returns: EncryptedConnectionStatus::REQUEST_TRANSMISSION_FAILED indicates malformed serializedConnectionState.
|
||||||
encrypted_connection_status_t addTemporaryEncryptedConnection(const String &serializedConnectionState, uint32_t duration);
|
EncryptedConnectionStatus addTemporaryEncryptedConnection(const String &serializedConnectionState, uint32_t duration);
|
||||||
|
|
||||||
// If an encrypted connection to peerMac already exists, only connection duration is updated. All other settings are kept as is. Use removeEncryptedConnection/requestEncryptedConnectionRemoval first if encryption keys should be updated.
|
// If an encrypted connection to peerMac already exists, only connection duration is updated. All other settings are kept as is. Use removeEncryptedConnection/requestEncryptedConnectionRemoval first if encryption keys should be updated.
|
||||||
// Makes sure both nodes have an encrypted connection to each other that's permanent.
|
// Makes sure both nodes have an encrypted connection to each other that's permanent.
|
||||||
encrypted_connection_status_t requestEncryptedConnection(uint8_t *peerMac);
|
EncryptedConnectionStatus requestEncryptedConnection(uint8_t *peerMac);
|
||||||
// Makes sure both nodes have an encrypted connection to each other that's either permanent or has the duration specified.
|
// Makes sure both nodes have an encrypted connection to each other that's either permanent or has the duration specified.
|
||||||
encrypted_connection_status_t requestTemporaryEncryptedConnection(uint8_t *peerMac, uint32_t durationMs);
|
EncryptedConnectionStatus requestTemporaryEncryptedConnection(uint8_t *peerMac, uint32_t durationMs);
|
||||||
// Makes sure both nodes have an encrypted connection to each other that's either permanent or has at least the duration specified.
|
// Makes sure both nodes have an encrypted connection to each other that's either permanent or has at least the duration specified.
|
||||||
// Note that if a temporary encrypted connection already exists to a target node, this method will slightly extend the connection duration
|
// Note that if a temporary encrypted connection already exists to a target node, this method will slightly extend the connection duration
|
||||||
// depending on the time it takes to verify the connection to the node.
|
// depending on the time it takes to verify the connection to the node.
|
||||||
encrypted_connection_status_t requestFlexibleTemporaryEncryptedConnection(uint8_t *peerMac, uint32_t minDurationMs);
|
EncryptedConnectionStatus requestFlexibleTemporaryEncryptedConnection(uint8_t *peerMac, uint32_t minDurationMs);
|
||||||
static encrypted_connection_removal_outcome_t removeEncryptedConnection(uint8_t *peerMac);
|
static EncryptedConnectionRemovalOutcome removeEncryptedConnection(uint8_t *peerMac);
|
||||||
encrypted_connection_removal_outcome_t requestEncryptedConnectionRemoval(uint8_t *peerMac);
|
EncryptedConnectionRemovalOutcome requestEncryptedConnectionRemoval(uint8_t *peerMac);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this EspnowMeshBackend instance will accept ESP-NOW requests from unencrypted connections or not, when acting as EspnowRequestManager.
|
* Set whether this EspnowMeshBackend instance will accept ESP-NOW requests from unencrypted connections or not, when acting as EspnowRequestManager.
|
||||||
@ -824,24 +828,24 @@ public:
|
|||||||
* @param peerMac The node MAC for which to get information. Both MAC for AP interface and MAC for STA interface can be used (and will yield the same result).
|
* @param peerMac The node MAC for which to get information. Both MAC for AP interface and MAC for STA interface can be used (and will yield the same result).
|
||||||
* Use the getEncryptedMac method or the indexed based getConnectionInfo if there is a need to find the actual encrypted interface.
|
* Use the getEncryptedMac method or the indexed based getConnectionInfo if there is a need to find the actual encrypted interface.
|
||||||
* @param remainingDuration An optional pointer to a uint32_t variable.
|
* @param remainingDuration An optional pointer to a uint32_t variable.
|
||||||
* If supplied and the connection type is ECT_TEMPORARY_CONNECTION the variable will be set to the remaining duration of the connection.
|
* If supplied and the connection type is ConnectionType::TEMPORARY_CONNECTION the variable will be set to the remaining duration of the connection.
|
||||||
* Otherwise the variable value is not modified.
|
* Otherwise the variable value is not modified.
|
||||||
* @return The espnow_connection_type_t of the connection with peerMac.
|
* @return The ConnectionType of the connection with peerMac.
|
||||||
*/
|
*/
|
||||||
static espnow_connection_type_t getConnectionInfo(uint8_t *peerMac, uint32_t *remainingDuration = nullptr);
|
static ConnectionType getConnectionInfo(uint8_t *peerMac, uint32_t *remainingDuration = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about any current ESP-NOW connection with another node.
|
* Get information about any current ESP-NOW connection with another node.
|
||||||
*
|
*
|
||||||
* @param connectionIndex The connection index of the node for which to get information. Valid values are limited by numberOfEncryptedConnections().
|
* @param connectionIndex The connection index of the node for which to get information. Valid values are limited by numberOfEncryptedConnections().
|
||||||
* @param remainingDuration An optional pointer to a uint32_t variable.
|
* @param remainingDuration An optional pointer to a uint32_t variable.
|
||||||
* If supplied and the connection type is ECT_TEMPORARY_CONNECTION the variable will be set to the remaining duration of the connection.
|
* If supplied and the connection type is ConnectionType::TEMPORARY_CONNECTION the variable will be set to the remaining duration of the connection.
|
||||||
* Otherwise the variable value is not modified.
|
* Otherwise the variable value is not modified.
|
||||||
* @param peerMac An optional pointer to an uint8_t array with at least size 6. It will be filled with the MAC of the encrypted peer interface if an encrypted connection exists.
|
* @param peerMac An optional pointer to an uint8_t array with at least size 6. It will be filled with the MAC of the encrypted peer interface if an encrypted connection exists.
|
||||||
* Otherwise the array is not modified.
|
* Otherwise the array is not modified.
|
||||||
* @return The espnow_connection_type_t of the connection given by connectionIndex.
|
* @return The ConnectionType of the connection given by connectionIndex.
|
||||||
*/
|
*/
|
||||||
static espnow_connection_type_t getConnectionInfo(uint32_t connectionIndex, uint32_t *remainingDuration = nullptr, uint8_t *peerMac = nullptr);
|
static ConnectionType getConnectionInfo(uint32_t connectionIndex, uint32_t *remainingDuration = nullptr, uint8_t *peerMac = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The proportion of ESP-NOW requests made by this node that have failed, since power on or latest reset.
|
* @return The proportion of ESP-NOW requests made by this node that have failed, since power on or latest reset.
|
||||||
@ -858,7 +862,7 @@ protected:
|
|||||||
static std::vector<EspnowNetworkInfo> _connectionQueue;
|
static std::vector<EspnowNetworkInfo> _connectionQueue;
|
||||||
static std::vector<TransmissionOutcome> _latestTransmissionOutcomes;
|
static std::vector<TransmissionOutcome> _latestTransmissionOutcomes;
|
||||||
|
|
||||||
typedef std::vector<EncryptedConnectionLog>::iterator connectionLogIterator;
|
using connectionLogIterator = std::vector<EncryptedConnectionLog>::iterator;
|
||||||
static connectionLogIterator connectionLogEndIterator();
|
static connectionLogIterator connectionLogEndIterator();
|
||||||
|
|
||||||
static const uint8_t broadcastMac[6];
|
static const uint8_t broadcastMac[6];
|
||||||
@ -866,7 +870,7 @@ protected:
|
|||||||
|
|
||||||
bool activateEspnow();
|
bool activateEspnow();
|
||||||
|
|
||||||
static bool encryptedConnectionEstablished(encrypted_connection_status_t connectionStatus);
|
static bool encryptedConnectionEstablished(EncryptedConnectionStatus connectionStatus);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that ESP-NOW is not perfect and in rare cases messages may be dropped.
|
* Note that ESP-NOW is not perfect and in rare cases messages may be dropped.
|
||||||
@ -906,8 +910,8 @@ protected:
|
|||||||
// Consider using getScheduledResponseRecipient and similar methods for this preparation.
|
// Consider using getScheduledResponseRecipient and similar methods for this preparation.
|
||||||
// Should only be used when there is no transmissions in progress. In practice when _espnowTransmissionMutex is free.
|
// Should only be used when there is no transmissions in progress. In practice when _espnowTransmissionMutex is free.
|
||||||
// @param resultingIterator Will be set to the iterator position after the removed element, if an element to remove was found. Otherwise no change will occur.
|
// @param resultingIterator Will be set to the iterator position after the removed element, if an element to remove was found. Otherwise no change will occur.
|
||||||
static encrypted_connection_removal_outcome_t removeEncryptedConnectionUnprotected(const uint8_t *peerMac, std::vector<EncryptedConnectionLog>::iterator *resultingIterator = nullptr);
|
static EncryptedConnectionRemovalOutcome removeEncryptedConnectionUnprotected(const uint8_t *peerMac, std::vector<EncryptedConnectionLog>::iterator *resultingIterator = nullptr);
|
||||||
static encrypted_connection_removal_outcome_t removeEncryptedConnectionUnprotected(connectionLogIterator &connectionIterator, std::vector<EncryptedConnectionLog>::iterator *resultingIterator);
|
static EncryptedConnectionRemovalOutcome removeEncryptedConnectionUnprotected(connectionLogIterator &connectionIterator, std::vector<EncryptedConnectionLog>::iterator *resultingIterator);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the MAC address considered to be the sender of the most recently received ESP-NOW request, response or broadcast.
|
* Set the MAC address considered to be the sender of the most recently received ESP-NOW request, response or broadcast.
|
||||||
@ -935,17 +939,17 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* Will be true if a transmission initiated by a public method is in progress.
|
* Will be true if a transmission initiated by a public method is in progress.
|
||||||
*/
|
*/
|
||||||
static bool _espnowTransmissionMutex;
|
static std::shared_ptr<bool> _espnowTransmissionMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will be true when the connectionQueue should not be modified.
|
* Will be true when the connectionQueue should not be modified.
|
||||||
*/
|
*/
|
||||||
static bool _espnowConnectionQueueMutex;
|
static std::shared_ptr<bool> _espnowConnectionQueueMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will be true when no responsesToSend element should be removed.
|
* Will be true when no responsesToSend element should be removed.
|
||||||
*/
|
*/
|
||||||
static bool _responsesToSendMutex;
|
static std::shared_ptr<bool> _responsesToSendMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if there is an ongoing ESP-NOW transmission in the library. Used to avoid interrupting transmissions.
|
* Check if there is an ongoing ESP-NOW transmission in the library. Used to avoid interrupting transmissions.
|
||||||
@ -955,8 +959,8 @@ protected:
|
|||||||
static bool transmissionInProgress();
|
static bool transmissionInProgress();
|
||||||
|
|
||||||
enum class macAndType_td : uint64_t {};
|
enum class macAndType_td : uint64_t {};
|
||||||
typedef uint64_t messageID_td;
|
using messageID_td = uint64_t;
|
||||||
typedef uint64_t peerMac_td;
|
using peerMac_td = uint64_t;
|
||||||
|
|
||||||
static macAndType_td createMacAndTypeValue(uint64_t uint64Mac, char messageType);
|
static macAndType_td createMacAndTypeValue(uint64_t uint64Mac, char messageType);
|
||||||
static uint64_t macAndTypeToUint64Mac(const macAndType_td &macAndTypeValue);
|
static uint64_t macAndTypeToUint64Mac(const macAndType_td &macAndTypeValue);
|
||||||
@ -985,19 +989,19 @@ protected:
|
|||||||
* @return The transmission status for the transmission.
|
* @return The transmission status for the transmission.
|
||||||
*/
|
*/
|
||||||
// Send a message to the node having targetBSSID as mac, changing targetBSSID to the mac of the encrypted connection if it exists and ensuring such an encrypted connection is synchronized.
|
// Send a message to the node having targetBSSID as mac, changing targetBSSID to the mac of the encrypted connection if it exists and ensuring such an encrypted connection is synchronized.
|
||||||
static transmission_status_t espnowSendToNode(const String &message, const uint8_t *targetBSSID, char messageType, EspnowMeshBackend *espnowInstance = nullptr);
|
static TransmissionStatusType espnowSendToNode(const String &message, const uint8_t *targetBSSID, char messageType, EspnowMeshBackend *espnowInstance = nullptr);
|
||||||
// Send a message using exactly the arguments given, without consideration for any encrypted connections.
|
// Send a message using exactly the arguments given, without consideration for any encrypted connections.
|
||||||
static transmission_status_t espnowSendToNodeUnsynchronized(const String message, const uint8_t *targetBSSID, char messageType, uint64_t messageID, EspnowMeshBackend *espnowInstance = nullptr);
|
static TransmissionStatusType espnowSendToNodeUnsynchronized(const String message, const uint8_t *targetBSSID, char messageType, uint64_t messageID, EspnowMeshBackend *espnowInstance = nullptr);
|
||||||
|
|
||||||
transmission_status_t sendRequest(const String &message, const uint8_t *targetBSSID);
|
TransmissionStatusType sendRequest(const String &message, const uint8_t *targetBSSID);
|
||||||
transmission_status_t sendResponse(const String &message, uint64_t requestID, const uint8_t *targetBSSID);
|
TransmissionStatusType sendResponse(const String &message, uint64_t requestID, const uint8_t *targetBSSID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
EspnowMeshBackend(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, broadcastFilterType broadcastFilter,
|
EspnowMeshBackend(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, broadcastFilterType broadcastFilter,
|
||||||
const String &meshPassword, const String &ssidPrefix, const String &ssidSuffix, bool verboseMode, uint8 meshWiFiChannel);
|
const String &meshPassword, const String &ssidPrefix, const String &ssidSuffix, bool verboseMode, uint8 meshWiFiChannel);
|
||||||
|
|
||||||
typedef std::function<String(const String &, const ExpiringTimeTracker &)> encryptionRequestBuilderType;
|
using encryptionRequestBuilderType = std::function<String(const String &, const ExpiringTimeTracker &)>;
|
||||||
static String defaultEncryptionRequestBuilder(const String &requestHeader, const uint32_t durationMs, const uint8_t *hashKey, const String &requestNonce, const ExpiringTimeTracker &existingTimeTracker);
|
static String defaultEncryptionRequestBuilder(const String &requestHeader, const uint32_t durationMs, const uint8_t *hashKey, const String &requestNonce, const ExpiringTimeTracker &existingTimeTracker);
|
||||||
static String flexibleEncryptionRequestBuilder(const uint32_t minDurationMs, const uint8_t *hashKey, const String &requestNonce, const ExpiringTimeTracker &existingTimeTracker);
|
static String flexibleEncryptionRequestBuilder(const uint32_t minDurationMs, const uint8_t *hashKey, const String &requestNonce, const ExpiringTimeTracker &existingTimeTracker);
|
||||||
|
|
||||||
@ -1055,14 +1059,14 @@ private:
|
|||||||
static EncryptedConnectionLog *getEncryptedConnection(const uint8_t *peerMac);
|
static EncryptedConnectionLog *getEncryptedConnection(const uint8_t *peerMac);
|
||||||
static EncryptedConnectionLog *getTemporaryEncryptedConnection(const uint8_t *peerMac);
|
static EncryptedConnectionLog *getTemporaryEncryptedConnection(const uint8_t *peerMac);
|
||||||
|
|
||||||
//@return iterator to connection in connectionVector, or connectionVector.end() if element not found
|
//@return iterator to connection in connectionContainer, or connectionContainer.end() if element not found
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static typename std::vector<T>::iterator getEncryptedConnectionIterator(const uint8_t *peerMac, typename std::vector<T> &connectionVector);
|
static typename T::iterator getEncryptedConnectionIterator(const uint8_t *peerMac, T &connectionContainer);
|
||||||
static bool getEncryptedConnectionIterator(const uint8_t *peerMac, connectionLogIterator &iterator);
|
static bool getEncryptedConnectionIterator(const uint8_t *peerMac, connectionLogIterator &iterator);
|
||||||
// @return true if an encrypted connection to peerMac is found and the found connection is temporary. Only changes iterator if true is returned.
|
// @return true if an encrypted connection to peerMac is found and the found connection is temporary. Only changes iterator if true is returned.
|
||||||
static bool getTemporaryEncryptedConnectionIterator(const uint8_t *peerMac, connectionLogIterator &iterator);
|
static bool getTemporaryEncryptedConnectionIterator(const uint8_t *peerMac, connectionLogIterator &iterator);
|
||||||
|
|
||||||
static espnow_connection_type_t getConnectionInfoHelper(const EncryptedConnectionLog *encryptedConnection, uint32_t *remainingDuration, uint8_t *peerMac = nullptr);
|
static ConnectionType getConnectionInfoHelper(const EncryptedConnectionLog *encryptedConnection, uint32_t *remainingDuration, uint8_t *peerMac = nullptr);
|
||||||
|
|
||||||
// Should only be used when there is no transmissions in progress, so it is safe to remove encrypted connections. In practice when _espnowTransmissionMutex is free.
|
// Should only be used when there is no transmissions in progress, so it is safe to remove encrypted connections. In practice when _espnowTransmissionMutex is free.
|
||||||
// @param scheduledRemovalOnly If true, only deletes encrypted connections where removalScheduled() is true. This means only connections which have been requested for removal will be deleted,
|
// @param scheduledRemovalOnly If true, only deletes encrypted connections where removalScheduled() is true. This means only connections which have been requested for removal will be deleted,
|
||||||
@ -1072,6 +1076,9 @@ private:
|
|||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static void deleteExpiredLogEntries(std::map<std::pair<U, uint64_t>, T> &logEntries, uint32_t maxEntryLifetimeMs);
|
static void deleteExpiredLogEntries(std::map<std::pair<U, uint64_t>, T> &logEntries, uint32_t maxEntryLifetimeMs);
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static void deleteExpiredLogEntries(std::map<std::pair<U, uint64_t>, TimeTracker> &logEntries, uint32_t maxEntryLifetimeMs);
|
||||||
|
|
||||||
static void deleteExpiredLogEntries(std::map<std::pair<peerMac_td, messageID_td>, RequestData> &logEntries, uint32_t requestLifetimeMs, uint32_t broadcastLifetimeMs);
|
static void deleteExpiredLogEntries(std::map<std::pair<peerMac_td, messageID_td>, RequestData> &logEntries, uint32_t requestLifetimeMs, uint32_t broadcastLifetimeMs);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1082,7 +1089,6 @@ private:
|
|||||||
|
|
||||||
static uint32_t _encryptionRequestTimeoutMs;
|
static uint32_t _encryptionRequestTimeoutMs;
|
||||||
|
|
||||||
static uint32_t _timeOfLastLogClear;
|
|
||||||
static uint32_t _criticalHeapLevel;
|
static uint32_t _criticalHeapLevel;
|
||||||
static uint32_t _criticalHeapLevelBuffer;
|
static uint32_t _criticalHeapLevelBuffer;
|
||||||
|
|
||||||
@ -1096,8 +1102,7 @@ private:
|
|||||||
static String _ongoingPeerRequestNonce;
|
static String _ongoingPeerRequestNonce;
|
||||||
static uint8_t _ongoingPeerRequestMac[6];
|
static uint8_t _ongoingPeerRequestMac[6];
|
||||||
static EspnowMeshBackend *_ongoingPeerRequester;
|
static EspnowMeshBackend *_ongoingPeerRequester;
|
||||||
static encrypted_connection_status_t _ongoingPeerRequestResult;
|
static EncryptedConnectionStatus _ongoingPeerRequestResult;
|
||||||
static uint32_t _ongoingPeerRequestEncryptionStart;
|
|
||||||
static bool _reciprocalPeerRequestConfirmation;
|
static bool _reciprocalPeerRequestConfirmation;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1119,7 +1124,7 @@ private:
|
|||||||
uint8_t _senderAPMac[6] = {0};
|
uint8_t _senderAPMac[6] = {0};
|
||||||
bool _receivedEncryptedTransmission = false;
|
bool _receivedEncryptedTransmission = false;
|
||||||
|
|
||||||
static bool _espnowSendToNodeMutex;
|
static std::shared_ptr<bool> _espnowSendToNodeMutex;
|
||||||
static uint8_t _transmissionTargetBSSID[6];
|
static uint8_t _transmissionTargetBSSID[6];
|
||||||
|
|
||||||
static void storeSentRequest(const uint64_t targetBSSID, const uint64_t messageID, const RequestData &requestData);
|
static void storeSentRequest(const uint64_t targetBSSID, const uint64_t messageID, const RequestData &requestData);
|
||||||
@ -1148,9 +1153,9 @@ private:
|
|||||||
* @param encryptionRequestBuilder A function which is responsible for constructing the request message to send.
|
* @param encryptionRequestBuilder A function which is responsible for constructing the request message to send.
|
||||||
* Called twice when the request is successful. First to build the initial request message and then to build the connection verification message.
|
* Called twice when the request is successful. First to build the initial request message and then to build the connection verification message.
|
||||||
* The request message should typically be of the form: JsonTranslator::createEncryptionRequestIntro() + JsonTranslator::createEncryptionRequestEnding().
|
* The request message should typically be of the form: JsonTranslator::createEncryptionRequestIntro() + JsonTranslator::createEncryptionRequestEnding().
|
||||||
* @return The ultimate status of the requested encrypted connection, as encrypted_connection_status_t.
|
* @return The ultimate status of the requested encrypted connection, as EncryptedConnectionStatus.
|
||||||
*/
|
*/
|
||||||
encrypted_connection_status_t requestEncryptedConnectionKernel(uint8_t *peerMac, const encryptionRequestBuilderType &encryptionRequestBuilder);
|
EncryptedConnectionStatus requestEncryptedConnectionKernel(uint8_t *peerMac, const encryptionRequestBuilderType &encryptionRequestBuilder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new message ID to be used when making a data transmission. The generated ID will be different depending on whether an encrypted connection exists or not.
|
* Generate a new message ID to be used when making a data transmission. The generated ID will be different depending on whether an encrypted connection exists or not.
|
||||||
@ -1170,12 +1175,12 @@ private:
|
|||||||
static uint64_t createSessionKey();
|
static uint64_t createSessionKey();
|
||||||
|
|
||||||
void prepareForTransmission(const String &message, bool scan, bool scanAllWiFiChannels);
|
void prepareForTransmission(const String &message, bool scan, bool scanAllWiFiChannels);
|
||||||
transmission_status_t initiateTransmission(const String &message, const EspnowNetworkInfo &recipientInfo);
|
TransmissionStatusType initiateTransmission(const String &message, const EspnowNetworkInfo &recipientInfo);
|
||||||
transmission_status_t initiateTransmissionKernel(const String &message, const uint8_t *targetBSSID);
|
TransmissionStatusType initiateTransmissionKernel(const String &message, const uint8_t *targetBSSID);
|
||||||
void printTransmissionStatistics();
|
void printTransmissionStatistics();
|
||||||
|
|
||||||
encrypted_connection_status_t initiateAutoEncryptingConnection(const EspnowNetworkInfo &recipientInfo, bool requestPermanentConnection, uint8_t *targetBSSID, EncryptedConnectionLog **existingEncryptedConnection);
|
EncryptedConnectionStatus initiateAutoEncryptingConnection(const EspnowNetworkInfo &recipientInfo, bool requestPermanentConnection, uint8_t *targetBSSID, EncryptedConnectionLog **existingEncryptedConnection);
|
||||||
transmission_status_t initiateAutoEncryptingTransmission(const String &message, const uint8_t *targetBSSID, encrypted_connection_status_t connectionStatus);
|
TransmissionStatusType initiateAutoEncryptingTransmission(const String &message, const uint8_t *targetBSSID, EncryptedConnectionStatus connectionStatus);
|
||||||
void finalizeAutoEncryptingConnection(const uint8_t *targetBSSID, const EncryptedConnectionLog *existingEncryptedConnection, bool requestPermanentConnection);
|
void finalizeAutoEncryptingConnection(const uint8_t *targetBSSID, const EncryptedConnectionLog *existingEncryptedConnection, bool requestPermanentConnection);
|
||||||
|
|
||||||
// Used for verboseMode printing in attemptTransmission, _AT suffix used to reduce namespace clutter
|
// Used for verboseMode printing in attemptTransmission, _AT suffix used to reduce namespace clutter
|
||||||
|
@ -45,7 +45,7 @@ namespace EspnowProtocolInterpreter
|
|||||||
constexpr char basicConnectionInfoHeader[] PROGMEM = "BasicCI:"; // Basic connection info
|
constexpr char basicConnectionInfoHeader[] PROGMEM = "BasicCI:"; // Basic connection info
|
||||||
constexpr char encryptedConnectionInfoHeader[] PROGMEM = "EncryptedCI:"; // Encrypted connection info
|
constexpr char encryptedConnectionInfoHeader[] PROGMEM = "EncryptedCI:"; // Encrypted connection info
|
||||||
constexpr char softLimitEncryptedConnectionInfoHeader[] PROGMEM = "SLEncryptedCI:"; // Soft limit encrypted connection info
|
constexpr char softLimitEncryptedConnectionInfoHeader[] PROGMEM = "SLEncryptedCI:"; // Soft limit encrypted connection info
|
||||||
constexpr char maxConnectionsReachedHeader[] PROGMEM = "ECS_MAX_CONNECTIONS_REACHED_PEER:";
|
constexpr char maxConnectionsReachedHeader[] PROGMEM = "MAX_CONNECTIONS_REACHED_PEER:";
|
||||||
constexpr char encryptedConnectionVerificationHeader[] PROGMEM = "ECVerified:"; // Encrypted connection verified
|
constexpr char encryptedConnectionVerificationHeader[] PROGMEM = "ECVerified:"; // Encrypted connection verified
|
||||||
constexpr char encryptedConnectionRemovalRequestHeader[] PROGMEM = "RemoveEC:"; // Remove encrypted connection
|
constexpr char encryptedConnectionRemovalRequestHeader[] PROGMEM = "RemoveEC:"; // Remove encrypted connection
|
||||||
|
|
||||||
|
@ -24,36 +24,101 @@
|
|||||||
|
|
||||||
#include "ExpiringTimeTracker.h"
|
#include "ExpiringTimeTracker.h"
|
||||||
|
|
||||||
ExpiringTimeTracker::ExpiringTimeTracker(uint32_t duration, uint32_t creationTimeMs) :
|
ExpiringTimeTracker::ExpiringTimeTracker(const uint32_t duration, const uint32_t creationTimeMs) :
|
||||||
TimeTracker(creationTimeMs), _duration(duration)
|
timeoutTemplate(0)
|
||||||
{ }
|
{
|
||||||
|
setDuration(duration);
|
||||||
|
_start = creationTimeMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpiringTimeTracker::ExpiringTimeTracker(const calculatorType durationCalculator, const uint32_t creationTimeMs) :
|
||||||
|
timeoutTemplate(0)
|
||||||
|
{
|
||||||
|
setDuration(durationCalculator);
|
||||||
|
_start = creationTimeMs;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ExpiringTimeTracker::duration() const
|
uint32_t ExpiringTimeTracker::duration() const
|
||||||
{
|
{
|
||||||
return _duration;
|
if(useCalculator)
|
||||||
|
return _durationCalculator();
|
||||||
|
|
||||||
|
return getTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpiringTimeTracker::setRemainingDuration(uint32_t remainingDuration)
|
IRAM_ATTR // called from ISR
|
||||||
|
void ExpiringTimeTracker::setTimeout(const uint32_t newUserTimeout)
|
||||||
{
|
{
|
||||||
_duration = timeSinceCreation() + remainingDuration;
|
_timeout = newUserTimeout;
|
||||||
|
_neverExpires = (newUserTimeout > timeMax()); // newUserTimeout < 0 is always false for uint32_t
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::setDuration(const uint32_t duration)
|
||||||
|
{
|
||||||
|
setTimeout(duration);
|
||||||
|
useCalculator = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::setDuration(const calculatorType durationCalculator)
|
||||||
|
{
|
||||||
|
_durationCalculator = durationCalculator;
|
||||||
|
useCalculator = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::setRemainingDuration(const uint32_t remainingDuration)
|
||||||
|
{
|
||||||
|
setDuration(elapsedTime() + remainingDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::setRemainingDuration(const calculatorType remainingDurationCalculator)
|
||||||
|
{
|
||||||
|
uint32_t currentElapsedTime = elapsedTime();
|
||||||
|
setDuration([remainingDurationCalculator, currentElapsedTime](){ return currentElapsedTime + remainingDurationCalculator(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ExpiringTimeTracker::remainingDuration() const
|
uint32_t ExpiringTimeTracker::remainingDuration() const
|
||||||
{
|
{
|
||||||
uint32_t remainingDuration = duration() - timeSinceCreation();
|
uint32_t remainingDuration = 0;
|
||||||
|
|
||||||
if(expired())
|
if(!expired()) // If expired, overflow will probably occur for remainingDuration calculation.
|
||||||
{
|
{
|
||||||
// Overflow probably occured for remainingDuration calculation.
|
remainingDuration = duration() - elapsedTime();
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return remainingDuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return remainingDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExpiringTimeTracker::elapsedTime() const
|
||||||
|
{
|
||||||
|
return millis() - _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpiringTimeTracker::expired() const
|
bool ExpiringTimeTracker::expired() const
|
||||||
{
|
{
|
||||||
return timeSinceCreation() >= duration();
|
if(useCalculator)
|
||||||
|
return elapsedTime() >= duration();
|
||||||
|
|
||||||
|
return expiredOneShot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::reset()
|
||||||
|
{
|
||||||
|
timeoutTemplate::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::reset(const uint32_t newDuration)
|
||||||
|
{
|
||||||
|
setDuration(newDuration);
|
||||||
|
ExpiringTimeTracker::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpiringTimeTracker::reset(const calculatorType newDurationCalculator)
|
||||||
|
{
|
||||||
|
setDuration(newDurationCalculator);
|
||||||
|
ExpiringTimeTracker::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpiringTimeTracker::operator bool() const
|
||||||
|
{
|
||||||
|
return ExpiringTimeTracker::expired();
|
||||||
}
|
}
|
||||||
|
@ -25,24 +25,54 @@
|
|||||||
#ifndef __EXPIRINGTIMETRACKER_H__
|
#ifndef __EXPIRINGTIMETRACKER_H__
|
||||||
#define __EXPIRINGTIMETRACKER_H__
|
#define __EXPIRINGTIMETRACKER_H__
|
||||||
|
|
||||||
#include "TimeTracker.h"
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <PolledTimeout.h>
|
||||||
|
|
||||||
class ExpiringTimeTracker : public TimeTracker {
|
class ExpiringTimeTracker : private esp8266::polledTimeout::oneShotMs {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~ExpiringTimeTracker() override = default;
|
using calculatorType = std::function<uint32_t()>;
|
||||||
|
|
||||||
|
virtual ~ExpiringTimeTracker() = default;
|
||||||
|
|
||||||
|
ExpiringTimeTracker(const uint32_t duration, const uint32_t creationTimeMs = millis());
|
||||||
|
ExpiringTimeTracker(const calculatorType durationCalculator, const uint32_t creationTimeMs = millis());
|
||||||
|
|
||||||
ExpiringTimeTracker(uint32_t duration, uint32_t creationTimeMs = millis());
|
|
||||||
uint32_t duration() const;
|
uint32_t duration() const;
|
||||||
void setRemainingDuration(uint32_t remainingDuration);
|
void setDuration(const uint32_t duration);
|
||||||
|
void setDuration(const calculatorType durationCalculator);
|
||||||
|
|
||||||
uint32_t remainingDuration() const;
|
uint32_t remainingDuration() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new duration which includes the current elapsedTime(). This means elapsedTime() is not reset.
|
||||||
|
* Note that reset() will use this new duration, including the saved elapsedTime().
|
||||||
|
*/
|
||||||
|
void setRemainingDuration(const uint32_t remainingDuration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new duration which includes the current elapsedTime(). This means elapsedTime() is not reset.
|
||||||
|
* Note that reset() will use this new duration, including the saved elapsedTime().
|
||||||
|
*/
|
||||||
|
void setRemainingDuration(const calculatorType remainingDurationCalculator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time since the ExpiringTimeTracker instance creation or the last reset(), whichever is more recent.
|
||||||
|
*/
|
||||||
|
uint32_t elapsedTime() const;
|
||||||
bool expired() const;
|
bool expired() const;
|
||||||
|
void reset();
|
||||||
|
void reset(const uint32_t newDuration);
|
||||||
|
void reset(const calculatorType newDurationCalculator);
|
||||||
|
explicit operator bool() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32_t _duration;
|
bool useCalculator = false;
|
||||||
|
calculatorType _durationCalculator;
|
||||||
|
|
||||||
|
void setTimeout(const uint32_t newUserTimeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,13 +40,16 @@ char FloodingMesh::_metadataDelimiter = 23;
|
|||||||
|
|
||||||
void floodingMeshDelay(uint32_t durationMs)
|
void floodingMeshDelay(uint32_t durationMs)
|
||||||
{
|
{
|
||||||
uint32_t startingTime = millis();
|
ExpiringTimeTracker timeout(durationMs);
|
||||||
|
|
||||||
while(millis() - startingTime < durationMs)
|
do
|
||||||
{
|
{
|
||||||
|
// We want to delay before performMeshMaintenance() so background tasks can be managed first.
|
||||||
|
// Initial while combined with YieldAndDelayMs polledTimeout::YieldPolicy is not suitable since the delay then occurs before evaluating the condition (meaning durationMs = 1 never executes the loop interior).
|
||||||
delay(1);
|
delay(1);
|
||||||
FloodingMesh::performMeshMaintenance();
|
FloodingMesh::performMeshMaintenance();
|
||||||
}
|
}
|
||||||
|
while(!timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloodingMesh::FloodingMesh(messageHandlerType messageHandler, const String &meshPassword, const uint8_t espnowEncryptedConnectionKey[EspnowProtocolInterpreter::espnowEncryptedConnectionKeyLength],
|
FloodingMesh::FloodingMesh(messageHandlerType messageHandler, const String &meshPassword, const uint8_t espnowEncryptedConnectionKey[EspnowProtocolInterpreter::espnowEncryptedConnectionKeyLength],
|
||||||
@ -428,9 +431,9 @@ String FloodingMesh::_defaultRequestHandler(const String &request, MeshBackendBa
|
|||||||
* @param meshInstance The MeshBackendBase instance that called the function.
|
* @param meshInstance The MeshBackendBase instance that called the function.
|
||||||
* @return The status code resulting from the response, as an int
|
* @return The status code resulting from the response, as an int
|
||||||
*/
|
*/
|
||||||
transmission_status_t FloodingMesh::_defaultResponseHandler(const String &response, MeshBackendBase &meshInstance)
|
TransmissionStatusType FloodingMesh::_defaultResponseHandler(const String &response, MeshBackendBase &meshInstance)
|
||||||
{
|
{
|
||||||
transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
|
TransmissionStatusType statusCode = TransmissionStatusType::TRANSMISSION_COMPLETE;
|
||||||
|
|
||||||
getEspnowMeshBackend().warningPrint(String(F("WARNING! Response to FloodingMesh broadcast received, but none is expected!")));
|
getEspnowMeshBackend().warningPrint(String(F("WARNING! Response to FloodingMesh broadcast received, but none is expected!")));
|
||||||
|
|
||||||
@ -503,26 +506,22 @@ bool FloodingMesh::_defaultBroadcastFilter(String &firstTransmission, EspnowMesh
|
|||||||
{
|
{
|
||||||
return false; // Broadcast is for another mesh network
|
return false; // Broadcast is for another mesh network
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
int32_t messageIDEndIndex = firstTransmission.indexOf(metadataDelimiter(), metadataEndIndex + 1);
|
||||||
|
|
||||||
|
if(messageIDEndIndex == -1)
|
||||||
|
return false; // metadataDelimiter not found
|
||||||
|
|
||||||
|
uint64_t messageID = TypeCast::stringToUint64(firstTransmission.substring(metadataEndIndex + 1, messageIDEndIndex));
|
||||||
|
|
||||||
|
if(insertPreliminaryMessageID(messageID))
|
||||||
{
|
{
|
||||||
int32_t messageIDEndIndex = firstTransmission.indexOf(metadataDelimiter(), metadataEndIndex + 1);
|
// Add broadcast identifier to stored message and mark as accepted broadcast.
|
||||||
|
firstTransmission = String(metadataDelimiter()) + firstTransmission;
|
||||||
if(messageIDEndIndex == -1)
|
return true;
|
||||||
return false; // metadataDelimiter not found
|
|
||||||
|
|
||||||
uint64_t messageID = TypeCast::stringToUint64(firstTransmission.substring(metadataEndIndex + 1, messageIDEndIndex));
|
|
||||||
|
|
||||||
if(insertPreliminaryMessageID(messageID))
|
|
||||||
{
|
|
||||||
// Add broadcast identifier to stored message and mark as accepted broadcast.
|
|
||||||
firstTransmission = String(metadataDelimiter()) + firstTransmission;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false; // Broadcast has already been received the maximum number of times
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false; // Broadcast has already been received the maximum number of times
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include "EspnowMeshBackend.h"
|
#include "EspnowMeshBackend.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,8 +44,8 @@ class FloodingMesh {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::function<bool(String &, FloodingMesh &)> messageHandlerType;
|
using messageHandlerType = std::function<bool(String &, FloodingMesh &)>;
|
||||||
typedef std::unordered_map<uint64_t, uint8_t>::iterator messageQueueElementType;
|
using messageQueueElementType = std::map<uint64_t, uint8_t>::iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ public:
|
|||||||
* @param ssidSuffix The suffix (last part) of the node SSID.
|
* @param ssidSuffix The suffix (last part) of the node SSID.
|
||||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
||||||
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
@ -83,7 +82,7 @@ public:
|
|||||||
* @param ssidSuffix The suffix (last part) of the node SSID.
|
* @param ssidSuffix The suffix (last part) of the node SSID.
|
||||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is shared by all EspnowMeshBackend instances.
|
||||||
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
@ -321,14 +320,14 @@ private:
|
|||||||
|
|
||||||
uint8_t _originMac[6] = {0};
|
uint8_t _originMac[6] = {0};
|
||||||
|
|
||||||
std::unordered_map<uint64_t, uint8_t> _messageIDs = {};
|
std::map<uint64_t, uint8_t> _messageIDs = {};
|
||||||
std::queue<messageQueueElementType> _messageIdOrder = {};
|
std::queue<messageQueueElementType> _messageIdOrder = {};
|
||||||
std::list<std::pair<String, bool>> _forwardingBacklog = {};
|
std::list<std::pair<String, bool>> _forwardingBacklog = {};
|
||||||
|
|
||||||
String _macIgnoreList;
|
String _macIgnoreList;
|
||||||
|
|
||||||
String _defaultRequestHandler(const String &request, MeshBackendBase &meshInstance);
|
String _defaultRequestHandler(const String &request, MeshBackendBase &meshInstance);
|
||||||
transmission_status_t _defaultResponseHandler(const String &response, MeshBackendBase &meshInstance);
|
TransmissionStatusType _defaultResponseHandler(const String &response, MeshBackendBase &meshInstance);
|
||||||
void _defaultNetworkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
void _defaultNetworkFilter(int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||||
bool _defaultBroadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
bool _defaultBroadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
||||||
bool _defaultTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance);
|
bool _defaultTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance);
|
||||||
|
63
libraries/ESP8266WiFiMesh/src/HeapMonitor.cpp
Normal file
63
libraries/ESP8266WiFiMesh/src/HeapMonitor.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Anders Löfgren
|
||||||
|
*
|
||||||
|
* License (MIT license):
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "HeapMonitor.h"
|
||||||
|
|
||||||
|
HeapMonitor::HeapMonitor(const uint32_t criticalHeapLevel, const uint32_t criticalHeapLevelBuffer) :
|
||||||
|
_criticalHeapLevel(criticalHeapLevel), _criticalHeapLevelBuffer(criticalHeapLevelBuffer)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void HeapMonitor::setCriticalHeapLevel(const uint32_t freeHeapInBytes)
|
||||||
|
{
|
||||||
|
_criticalHeapLevel = freeHeapInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HeapMonitor::getCriticalHeapLevel() const
|
||||||
|
{
|
||||||
|
return _criticalHeapLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeapMonitor::setCriticalHeapLevelBuffer(const uint32_t bufferInBytes)
|
||||||
|
{
|
||||||
|
_criticalHeapLevelBuffer = bufferInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HeapMonitor::getCriticalHeapLevelBuffer() const
|
||||||
|
{
|
||||||
|
return _criticalHeapLevelBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapMonitor::HeapStatus HeapMonitor::getHeapStatus() const
|
||||||
|
{
|
||||||
|
HeapStatus heapStatus = HeapStatus::NOMINAL;
|
||||||
|
|
||||||
|
uint32_t freeHeap = ESP.getFreeHeap();
|
||||||
|
|
||||||
|
if(freeHeap <= getCriticalHeapLevel())
|
||||||
|
heapStatus = HeapStatus::CRITICAL;
|
||||||
|
else if(freeHeap <= getCriticalHeapLevel() + getCriticalHeapLevelBuffer())
|
||||||
|
heapStatus = HeapStatus::LIMITED;
|
||||||
|
|
||||||
|
return heapStatus;
|
||||||
|
}
|
66
libraries/ESP8266WiFiMesh/src/HeapMonitor.h
Normal file
66
libraries/ESP8266WiFiMesh/src/HeapMonitor.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Anders Löfgren
|
||||||
|
*
|
||||||
|
* License (MIT license):
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESPHEAPMONITOR_H__
|
||||||
|
#define __ESPHEAPMONITOR_H__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
class HeapMonitor {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class HeapStatus
|
||||||
|
{
|
||||||
|
NOMINAL = 0,
|
||||||
|
LIMITED = 1,
|
||||||
|
CRITICAL = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
HeapMonitor(const uint32_t criticalHeapLevel, const uint32_t criticalHeapLevelBuffer);
|
||||||
|
|
||||||
|
virtual ~HeapMonitor() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum free heap level in bytes within which free heap size is considered critical.
|
||||||
|
*/
|
||||||
|
void setCriticalHeapLevel(const uint32_t freeHeapInBytes);
|
||||||
|
uint32_t getCriticalHeapLevel() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the buffer of the critical heap level, within which free heap size is considered limited.
|
||||||
|
*/
|
||||||
|
void setCriticalHeapLevelBuffer(const uint32_t bufferInBytes);
|
||||||
|
uint32_t getCriticalHeapLevelBuffer() const;
|
||||||
|
|
||||||
|
HeapStatus getHeapStatus() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint32_t _criticalHeapLevel;
|
||||||
|
uint32_t _criticalHeapLevelBuffer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -26,11 +26,11 @@ namespace TypeCast = MeshTypeConversionFunctions;
|
|||||||
|
|
||||||
MeshBackendBase *MeshBackendBase::apController = nullptr;
|
MeshBackendBase *MeshBackendBase::apController = nullptr;
|
||||||
|
|
||||||
bool MeshBackendBase::_scanMutex = false;
|
std::shared_ptr<bool> MeshBackendBase::_scanMutex = std::make_shared<bool>(false);
|
||||||
|
|
||||||
bool MeshBackendBase::_printWarnings = true;
|
bool MeshBackendBase::_printWarnings = true;
|
||||||
|
|
||||||
MeshBackendBase::MeshBackendBase(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, mesh_backend_t classType)
|
MeshBackendBase::MeshBackendBase(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, MeshBackendType classType)
|
||||||
{
|
{
|
||||||
setRequestHandler(requestHandler);
|
setRequestHandler(requestHandler);
|
||||||
setResponseHandler(responseHandler);
|
setResponseHandler(responseHandler);
|
||||||
@ -43,12 +43,12 @@ MeshBackendBase::~MeshBackendBase()
|
|||||||
deactivateControlledAP();
|
deactivateControlledAP();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshBackendBase::setClassType(mesh_backend_t classType)
|
void MeshBackendBase::setClassType(MeshBackendType classType)
|
||||||
{
|
{
|
||||||
_classType = classType;
|
_classType = classType;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh_backend_t MeshBackendBase::getClassType() {return _classType;}
|
MeshBackendType MeshBackendBase::getClassType() {return _classType;}
|
||||||
|
|
||||||
void MeshBackendBase::activateAP()
|
void MeshBackendBase::activateAP()
|
||||||
{
|
{
|
||||||
@ -115,7 +115,9 @@ bool MeshBackendBase::isAPController()
|
|||||||
|
|
||||||
void MeshBackendBase::setWiFiChannel(uint8 newWiFiChannel)
|
void MeshBackendBase::setWiFiChannel(uint8 newWiFiChannel)
|
||||||
{
|
{
|
||||||
assert(1 <= newWiFiChannel && newWiFiChannel <= 13);
|
wifi_country_t wifiCountry;
|
||||||
|
wifi_get_country(&wifiCountry); // Note: Should return 0 on success and -1 on failure, but always seems to return 1. Possibly broken API. Channels 1 to 13 are the default limits.
|
||||||
|
assert(wifiCountry.schan <= newWiFiChannel && newWiFiChannel <= wifiCountry.schan + wifiCountry.nchan - 1);
|
||||||
|
|
||||||
_meshWiFiChannel = newWiFiChannel;
|
_meshWiFiChannel = newWiFiChannel;
|
||||||
|
|
||||||
@ -248,10 +250,10 @@ bool MeshBackendBase::latestTransmissionSuccessfulBase(const std::vector<Transmi
|
|||||||
{
|
{
|
||||||
if(latestTransmissionOutcomes.empty())
|
if(latestTransmissionOutcomes.empty())
|
||||||
return false;
|
return false;
|
||||||
else
|
|
||||||
for(const TransmissionOutcome &transmissionOutcome : latestTransmissionOutcomes)
|
for(const TransmissionOutcome &transmissionOutcome : latestTransmissionOutcomes)
|
||||||
if(transmissionOutcome.transmissionStatus() != TS_TRANSMISSION_COMPLETE)
|
if(transmissionOutcome.transmissionStatus() != TransmissionStatusType::TRANSMISSION_COMPLETE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -23,24 +23,24 @@
|
|||||||
#include "TransmissionOutcome.h"
|
#include "TransmissionOutcome.h"
|
||||||
#include "NetworkInfoBase.h"
|
#include "NetworkInfoBase.h"
|
||||||
|
|
||||||
typedef enum
|
enum class MeshBackendType
|
||||||
{
|
{
|
||||||
MB_TCP_IP = 0,
|
TCP_IP = 0,
|
||||||
MB_ESP_NOW = 1
|
ESP_NOW = 1
|
||||||
} mesh_backend_t;
|
};
|
||||||
|
|
||||||
class MeshBackendBase {
|
class MeshBackendBase {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::function<String(const String &, MeshBackendBase &)> requestHandlerType;
|
using requestHandlerType = std::function<String(const String &, MeshBackendBase &)> ;
|
||||||
typedef std::function<transmission_status_t(const String &, MeshBackendBase &)> responseHandlerType;
|
using responseHandlerType = std::function<TransmissionStatusType(const String &, MeshBackendBase &)>;
|
||||||
typedef std::function<void(int, MeshBackendBase &)> networkFilterType;
|
using networkFilterType = std::function<void(int, MeshBackendBase &)>;
|
||||||
typedef std::function<bool(MeshBackendBase &)> transmissionOutcomesUpdateHookType;
|
using transmissionOutcomesUpdateHookType = std::function<bool(MeshBackendBase &)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MeshBackendBase(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, mesh_backend_t classType);
|
MeshBackendBase(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter, MeshBackendType classType);
|
||||||
|
|
||||||
virtual ~MeshBackendBase();
|
virtual ~MeshBackendBase();
|
||||||
|
|
||||||
@ -109,13 +109,13 @@ public:
|
|||||||
* Will also change the WiFi channel for the active AP (via an AP restart)
|
* Will also change the WiFi channel for the active AP (via an AP restart)
|
||||||
* if this MeshBackendBase instance is the current AP controller and it is possible to change channel.
|
* if this MeshBackendBase instance is the current AP controller and it is possible to change channel.
|
||||||
*
|
*
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several MeshBackendBase instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several MeshBackendBase instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one MeshBackendBase instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one MeshBackendBase instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
* make it impossible for other stations to detect the APs whose WiFi channels have changed.
|
* make it impossible for other stations to detect the APs whose WiFi channels have changed.
|
||||||
*
|
*
|
||||||
* @param newWiFiChannel The WiFi channel to change to. Valid values are integers from 1 to 13.
|
* @param newWiFiChannel The WiFi channel to change to. Valid values are determined by wifi_get_country, usually integers from 1 to 11 or 1 to 13.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setWiFiChannel(uint8 newWiFiChannel);
|
void setWiFiChannel(uint8 newWiFiChannel);
|
||||||
@ -284,14 +284,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void warningPrint(const String &stringToPrint, bool newline = true);
|
static void warningPrint(const String &stringToPrint, bool newline = true);
|
||||||
|
|
||||||
mesh_backend_t getClassType();
|
MeshBackendType getClassType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param latestTransmissionOutcomes The transmission outcomes vector to check.
|
* @param latestTransmissionOutcomes The transmission outcomes vector to check.
|
||||||
*
|
*
|
||||||
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
|
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TransmissionStatusType::TRANSMISSION_COMPLETE). False otherwise.
|
||||||
*/
|
*/
|
||||||
static bool latestTransmissionSuccessfulBase(const std::vector<TransmissionOutcome> &latestTransmissionOutcomes);
|
static bool latestTransmissionSuccessfulBase(const std::vector<TransmissionOutcome> &latestTransmissionOutcomes);
|
||||||
|
|
||||||
@ -310,13 +310,13 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void deactivateAPHook();
|
virtual void deactivateAPHook();
|
||||||
|
|
||||||
void setClassType(mesh_backend_t classType);
|
void setClassType(MeshBackendType classType);
|
||||||
|
|
||||||
static bool _scanMutex;
|
static std::shared_ptr<bool> _scanMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
mesh_backend_t _classType;
|
MeshBackendType _classType;
|
||||||
|
|
||||||
static MeshBackendBase *apController;
|
static MeshBackendBase *apController;
|
||||||
|
|
||||||
|
@ -28,15 +28,15 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MessageData::MessageData(String &message, uint8_t transmissionsRemaining, uint32_t creationTimeMs) :
|
MessageData::MessageData(String &message, uint8_t transmissionsRemaining, uint32_t creationTimeMs) :
|
||||||
TimeTracker(creationTimeMs)
|
_timeTracker(creationTimeMs)
|
||||||
{
|
{
|
||||||
_transmissionsExpected = transmissionsRemaining + 1;
|
_transmissionsExpected = transmissionsRemaining + 1;
|
||||||
_totalMessage += message;
|
_totalMessage += message;
|
||||||
_transmissionsReceived++;
|
++_transmissionsReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageData::MessageData(uint8_t *initialTransmission, uint8_t transmissionLength, uint32_t creationTimeMs) :
|
MessageData::MessageData(uint8_t *initialTransmission, uint8_t transmissionLength, uint32_t creationTimeMs) :
|
||||||
TimeTracker(creationTimeMs)
|
_timeTracker(creationTimeMs)
|
||||||
{
|
{
|
||||||
_transmissionsExpected = EspnowProtocolInterpreter::espnowGetTransmissionsRemaining(initialTransmission) + 1;
|
_transmissionsExpected = EspnowProtocolInterpreter::espnowGetTransmissionsRemaining(initialTransmission) + 1;
|
||||||
addToMessage(initialTransmission, transmissionLength);
|
addToMessage(initialTransmission, transmissionLength);
|
||||||
@ -49,7 +49,7 @@ bool MessageData::addToMessage(uint8_t *transmission, uint8_t transmissionLength
|
|||||||
String message = EspnowProtocolInterpreter::espnowGetMessageContent(transmission, transmissionLength);
|
String message = EspnowProtocolInterpreter::espnowGetMessageContent(transmission, transmissionLength);
|
||||||
assert(message.length() <= EspnowMeshBackend::getMaxMessageBytesPerTransmission()); // Should catch some cases where transmission is not null terminated.
|
assert(message.length() <= EspnowMeshBackend::getMaxMessageBytesPerTransmission()); // Should catch some cases where transmission is not null terminated.
|
||||||
_totalMessage += message;
|
_totalMessage += message;
|
||||||
_transmissionsReceived++;
|
++_transmissionsReceived;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,3 +75,5 @@ String MessageData::getTotalMessage()
|
|||||||
{
|
{
|
||||||
return _totalMessage;
|
return _totalMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TimeTracker &MessageData::getTimeTracker() const { return _timeTracker; }
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include "TimeTracker.h"
|
#include "TimeTracker.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
class MessageData : public TimeTracker {
|
class MessageData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -43,9 +43,11 @@ public:
|
|||||||
uint8_t getTransmissionsExpected();
|
uint8_t getTransmissionsExpected();
|
||||||
uint8_t getTransmissionsRemaining();
|
uint8_t getTransmissionsRemaining();
|
||||||
String getTotalMessage();
|
String getTotalMessage();
|
||||||
|
const TimeTracker &getTimeTracker() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
TimeTracker _timeTracker;
|
||||||
uint8_t _transmissionsReceived = 0;
|
uint8_t _transmissionsReceived = 0;
|
||||||
uint8_t _transmissionsExpected;
|
uint8_t _transmissionsExpected;
|
||||||
String _totalMessage;
|
String _totalMessage;
|
||||||
|
@ -24,19 +24,19 @@
|
|||||||
|
|
||||||
#include "MutexTracker.h"
|
#include "MutexTracker.h"
|
||||||
|
|
||||||
bool MutexTracker::_captureBan = false;
|
std::shared_ptr<bool> MutexTracker::_captureBan = std::make_shared<bool>(false);
|
||||||
|
|
||||||
bool &MutexTracker::captureBan()
|
std::shared_ptr<bool> MutexTracker::captureBan()
|
||||||
{
|
{
|
||||||
return _captureBan;
|
return _captureBan;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexTracker::MutexTracker(bool &mutexToCapture)
|
MutexTracker::MutexTracker(const std::shared_ptr<bool> &mutexToCapture)
|
||||||
{
|
{
|
||||||
attemptMutexCapture(mutexToCapture);
|
attemptMutexCapture(mutexToCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexTracker::MutexTracker(bool &mutexToCapture, std::function<void()> destructorHook) : MutexTracker(mutexToCapture)
|
MutexTracker::MutexTracker(const std::shared_ptr<bool> &mutexToCapture, const std::function<void()> destructorHook) : MutexTracker(mutexToCapture)
|
||||||
{
|
{
|
||||||
_destructorHook = destructorHook;
|
_destructorHook = destructorHook;
|
||||||
}
|
}
|
||||||
@ -47,12 +47,25 @@ MutexTracker::~MutexTracker()
|
|||||||
_destructorHook();
|
_destructorHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MutexTracker::mutexCaptured()
|
bool MutexTracker::mutexFree(const std::shared_ptr<bool> &mutex)
|
||||||
{
|
{
|
||||||
if(_capturedMutex)
|
if(mutex != nullptr && !(*mutex))
|
||||||
return true;
|
return true;
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MutexTracker::mutexCaptured(const std::shared_ptr<bool> &mutex)
|
||||||
|
{
|
||||||
|
if(mutex != nullptr && (*mutex))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MutexTracker::mutexCaptured() const
|
||||||
|
{
|
||||||
|
return mutexCaptured(_capturedMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MutexTracker::releaseMutex()
|
void MutexTracker::releaseMutex()
|
||||||
@ -60,20 +73,18 @@ void MutexTracker::releaseMutex()
|
|||||||
if(mutexCaptured())
|
if(mutexCaptured())
|
||||||
{
|
{
|
||||||
*_capturedMutex = false;
|
*_capturedMutex = false;
|
||||||
_capturedMutex = nullptr;
|
_capturedMutex.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MutexTracker::attemptMutexCapture(bool &mutexToCapture)
|
bool MutexTracker::attemptMutexCapture(const std::shared_ptr<bool> &mutexToCapture)
|
||||||
{
|
{
|
||||||
if(!captureBan() && !mutexToCapture)
|
if(mutexFree(captureBan()) && mutexFree(mutexToCapture))
|
||||||
{
|
{
|
||||||
_capturedMutex = &mutexToCapture;
|
_capturedMutex = mutexToCapture;
|
||||||
*_capturedMutex = true;
|
*_capturedMutex = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define __MUTEXTRACKER_H__
|
#define __MUTEXTRACKER_H__
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SLIM (Scope LImited Manager)/Scope-Bound Resource Management/RAII class to manage the state of a mutex.
|
* A SLIM (Scope LImited Manager)/Scope-Bound Resource Management/RAII class to manage the state of a mutex.
|
||||||
@ -39,23 +40,23 @@ class MutexTracker
|
|||||||
* Set to false by default.
|
* Set to false by default.
|
||||||
* captureBan can be managed by MutexTracker like any other mutex.
|
* captureBan can be managed by MutexTracker like any other mutex.
|
||||||
*/
|
*/
|
||||||
static bool &captureBan();
|
static std::shared_ptr<bool> captureBan();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to capture the mutex. Use the mutexCaptured() method to check success.
|
* Attempts to capture the mutex. Use the mutexCaptured() method to check success.
|
||||||
*/
|
*/
|
||||||
MutexTracker(bool &mutexToCapture);
|
MutexTracker(const std::shared_ptr<bool> &mutexToCapture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to capture the mutex. Use the mutexCaptured() method to check success.
|
* Attempts to capture the mutex. Use the mutexCaptured() method to check success.
|
||||||
*
|
*
|
||||||
* @param destructorHook A function to hook into the MutexTracker destructor. Will be called when the MutexTracker instance is being destroyed, after the mutex has been released.
|
* @param destructorHook A function to hook into the MutexTracker destructor. Will be called when the MutexTracker instance is being destroyed, after the mutex has been released.
|
||||||
*/
|
*/
|
||||||
MutexTracker(bool &mutexToCapture, std::function<void()> destructorHook);
|
MutexTracker(const std::shared_ptr<bool> &mutexToCapture, const std::function<void()> destructorHook);
|
||||||
|
|
||||||
~MutexTracker();
|
~MutexTracker();
|
||||||
|
|
||||||
bool mutexCaptured();
|
bool mutexCaptured() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the mutex free to roam the binary plains, giving new MutexTrackers a chance to capture it.
|
* Set the mutex free to roam the binary plains, giving new MutexTrackers a chance to capture it.
|
||||||
@ -64,17 +65,20 @@ class MutexTracker
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static bool _captureBan;
|
static std::shared_ptr<bool> _captureBan;
|
||||||
|
|
||||||
bool *_capturedMutex = nullptr;
|
std::shared_ptr<bool> _capturedMutex;
|
||||||
std::function<void()> _destructorHook = [](){ };
|
std::function<void()> _destructorHook = [](){ };
|
||||||
|
|
||||||
|
static bool mutexFree(const std::shared_ptr<bool> &mutex);
|
||||||
|
static bool mutexCaptured(const std::shared_ptr<bool> &mutex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to capture the mutex.
|
* Attempt to capture the mutex.
|
||||||
*
|
*
|
||||||
* @return True if mutex was caught (meaning no other instance is holding the mutex). False otherwise.
|
* @return True if mutex was caught (meaning it exists and no other instance is holding the mutex). False otherwise.
|
||||||
*/
|
*/
|
||||||
bool attemptMutexCapture(bool &mutexToCapture);
|
bool attemptMutexCapture(const std::shared_ptr<bool> &mutexToCapture);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,7 +40,7 @@ void NetworkInfoBase::storeBSSID(const uint8_t newBSSID[6])
|
|||||||
_BSSID = _bssidArray;
|
_BSSID = _bssidArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 6; i++)
|
for(int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
_BSSID[i] = newBSSID[i];
|
_BSSID[i] = newBSSID[i];
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
#include "RequestData.h"
|
#include "RequestData.h"
|
||||||
|
|
||||||
RequestData::RequestData(EspnowMeshBackend &meshInstance, uint32_t creationTimeMs) :
|
RequestData::RequestData(EspnowMeshBackend &meshInstance, uint32_t creationTimeMs) :
|
||||||
TimeTracker(creationTimeMs), _meshInstance(meshInstance)
|
_timeTracker(creationTimeMs), _meshInstance(meshInstance)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void RequestData::setMeshInstance(EspnowMeshBackend &meshInstance) { _meshInstance = meshInstance; }
|
void RequestData::setMeshInstance(const EspnowMeshBackend &meshInstance) { _meshInstance = meshInstance; }
|
||||||
EspnowMeshBackend &RequestData::getMeshInstance() { return _meshInstance; }
|
EspnowMeshBackend &RequestData::getMeshInstance() const { return _meshInstance; }
|
||||||
|
const TimeTracker &RequestData::getTimeTracker() const { return _timeTracker; }
|
||||||
|
@ -30,17 +30,19 @@
|
|||||||
|
|
||||||
class EspnowMeshBackend;
|
class EspnowMeshBackend;
|
||||||
|
|
||||||
class RequestData : public TimeTracker {
|
class RequestData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RequestData(EspnowMeshBackend &meshInstance, uint32_t creationTimeMs = millis());
|
RequestData(EspnowMeshBackend &meshInstance, uint32_t creationTimeMs = millis());
|
||||||
|
|
||||||
void setMeshInstance(EspnowMeshBackend &meshInstance);
|
void setMeshInstance(const EspnowMeshBackend &meshInstance);
|
||||||
EspnowMeshBackend &getMeshInstance();
|
EspnowMeshBackend &getMeshInstance() const;
|
||||||
|
const TimeTracker &getTimeTracker() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
TimeTracker _timeTracker;
|
||||||
EspnowMeshBackend &_meshInstance;
|
EspnowMeshBackend &_meshInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,13 +25,13 @@
|
|||||||
#include "ResponseData.h"
|
#include "ResponseData.h"
|
||||||
|
|
||||||
ResponseData::ResponseData(const String &message, const uint8_t recipientMac[6], uint64_t requestID, uint32_t creationTimeMs) :
|
ResponseData::ResponseData(const String &message, const uint8_t recipientMac[6], uint64_t requestID, uint32_t creationTimeMs) :
|
||||||
TimeTracker(creationTimeMs), _message(message), _requestID(requestID)
|
_timeTracker(creationTimeMs), _message(message), _requestID(requestID)
|
||||||
{
|
{
|
||||||
storeRecipientMac(recipientMac);
|
storeRecipientMac(recipientMac);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseData::ResponseData(const ResponseData &other)
|
ResponseData::ResponseData(const ResponseData &other)
|
||||||
: TimeTracker(other), _message(other.getMessage()), _requestID(other.getRequestID())
|
: _timeTracker(other.getTimeTracker()), _message(other.getMessage()), _requestID(other.getRequestID())
|
||||||
{
|
{
|
||||||
storeRecipientMac(other.getRecipientMac());
|
storeRecipientMac(other.getRecipientMac());
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ ResponseData & ResponseData::operator=(const ResponseData &other)
|
|||||||
{
|
{
|
||||||
if(this != &other)
|
if(this != &other)
|
||||||
{
|
{
|
||||||
TimeTracker::operator=(other);
|
_timeTracker = other.getTimeTracker();
|
||||||
_message = other.getMessage();
|
_message = other.getMessage();
|
||||||
_requestID = other.getRequestID();
|
_requestID = other.getRequestID();
|
||||||
storeRecipientMac(other.getRecipientMac());
|
storeRecipientMac(other.getRecipientMac());
|
||||||
@ -51,21 +51,20 @@ ResponseData & ResponseData::operator=(const ResponseData &other)
|
|||||||
|
|
||||||
void ResponseData::storeRecipientMac(const uint8_t newRecipientMac[6])
|
void ResponseData::storeRecipientMac(const uint8_t newRecipientMac[6])
|
||||||
{
|
{
|
||||||
if(newRecipientMac != nullptr)
|
if(newRecipientMac == nullptr)
|
||||||
{
|
|
||||||
if(_recipientMac == nullptr)
|
|
||||||
{
|
|
||||||
_recipientMac = _recipientMacArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
_recipientMac[i] = newRecipientMac[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_recipientMac = nullptr;
|
_recipientMac = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_recipientMac == nullptr)
|
||||||
|
{
|
||||||
|
_recipientMac = _recipientMacArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
_recipientMac[i] = newRecipientMac[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,3 +76,5 @@ String ResponseData::getMessage() const { return _message; }
|
|||||||
|
|
||||||
void ResponseData::setRequestID(uint64_t requestID) { _requestID = requestID; }
|
void ResponseData::setRequestID(uint64_t requestID) { _requestID = requestID; }
|
||||||
uint64_t ResponseData::getRequestID() const { return _requestID; }
|
uint64_t ResponseData::getRequestID() const { return _requestID; }
|
||||||
|
|
||||||
|
const TimeTracker &ResponseData::getTimeTracker() const { return _timeTracker; }
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include "TimeTracker.h"
|
#include "TimeTracker.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
class ResponseData : public TimeTracker {
|
class ResponseData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -46,10 +46,14 @@ public:
|
|||||||
void setRequestID(uint64_t requestID);
|
void setRequestID(uint64_t requestID);
|
||||||
uint64_t getRequestID() const;
|
uint64_t getRequestID() const;
|
||||||
|
|
||||||
|
const TimeTracker &getTimeTracker() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void storeRecipientMac(const uint8_t newRecipientMac[6]);
|
void storeRecipientMac(const uint8_t newRecipientMac[6]);
|
||||||
|
|
||||||
|
TimeTracker _timeTracker;
|
||||||
|
|
||||||
uint8_t _recipientMacArray[6] {0};
|
uint8_t _recipientMacArray[6] {0};
|
||||||
uint8_t *_recipientMac = nullptr;
|
uint8_t *_recipientMac = nullptr;
|
||||||
String _message;
|
String _message;
|
||||||
|
@ -32,8 +32,8 @@ namespace
|
|||||||
|
|
||||||
const IPAddress TcpIpMeshBackend::emptyIP;
|
const IPAddress TcpIpMeshBackend::emptyIP;
|
||||||
|
|
||||||
bool TcpIpMeshBackend::_tcpIpTransmissionMutex = false;
|
std::shared_ptr<bool> TcpIpMeshBackend::_tcpIpTransmissionMutex = std::make_shared<bool>(false);
|
||||||
bool TcpIpMeshBackend::_tcpIpConnectionQueueMutex = false;
|
std::shared_ptr<bool> TcpIpMeshBackend::_tcpIpConnectionQueueMutex = std::make_shared<bool>(false);
|
||||||
|
|
||||||
String TcpIpMeshBackend::lastSSID;
|
String TcpIpMeshBackend::lastSSID;
|
||||||
bool TcpIpMeshBackend::staticIPActivated = false;
|
bool TcpIpMeshBackend::staticIPActivated = false;
|
||||||
@ -51,7 +51,7 @@ std::vector<TransmissionOutcome> TcpIpMeshBackend::_latestTransmissionOutcomes =
|
|||||||
TcpIpMeshBackend::TcpIpMeshBackend(requestHandlerType requestHandler, responseHandlerType responseHandler,
|
TcpIpMeshBackend::TcpIpMeshBackend(requestHandlerType requestHandler, responseHandlerType responseHandler,
|
||||||
networkFilterType networkFilter, const String &meshPassword, const String &ssidPrefix,
|
networkFilterType networkFilter, const String &meshPassword, const String &ssidPrefix,
|
||||||
const String &ssidSuffix, bool verboseMode, uint8 meshWiFiChannel, uint16_t serverPort)
|
const String &ssidSuffix, bool verboseMode, uint8 meshWiFiChannel, uint16_t serverPort)
|
||||||
: MeshBackendBase(requestHandler, responseHandler, networkFilter, MB_TCP_IP), _server(serverPort)
|
: MeshBackendBase(requestHandler, responseHandler, networkFilter, MeshBackendType::TCP_IP), _server(serverPort)
|
||||||
{
|
{
|
||||||
setSSID(ssidPrefix, emptyString, ssidSuffix);
|
setSSID(ssidPrefix, emptyString, ssidSuffix);
|
||||||
setMeshPassword(meshPassword);
|
setMeshPassword(meshPassword);
|
||||||
@ -111,7 +111,7 @@ void TcpIpMeshBackend::deactivateAPHook()
|
|||||||
_server.stop();
|
_server.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TcpIpMeshBackend::transmissionInProgress(){return _tcpIpTransmissionMutex;}
|
bool TcpIpMeshBackend::transmissionInProgress(){return *_tcpIpTransmissionMutex;}
|
||||||
|
|
||||||
void TcpIpMeshBackend::setTemporaryMessage(const String &newTemporaryMessage) {_temporaryMessage = newTemporaryMessage;}
|
void TcpIpMeshBackend::setTemporaryMessage(const String &newTemporaryMessage) {_temporaryMessage = newTemporaryMessage;}
|
||||||
String TcpIpMeshBackend::getTemporaryMessage() {return _temporaryMessage;}
|
String TcpIpMeshBackend::getTemporaryMessage() {return _temporaryMessage;}
|
||||||
@ -180,12 +180,12 @@ void TcpIpMeshBackend::setMaxAPStations(uint8_t maxAPStations)
|
|||||||
|
|
||||||
bool TcpIpMeshBackend::getMaxAPStations() {return _maxAPStations;}
|
bool TcpIpMeshBackend::getMaxAPStations() {return _maxAPStations;}
|
||||||
|
|
||||||
void TcpIpMeshBackend::setConnectionAttemptTimeout(int32_t connectionAttemptTimeoutMs)
|
void TcpIpMeshBackend::setConnectionAttemptTimeout(uint32_t connectionAttemptTimeoutMs)
|
||||||
{
|
{
|
||||||
_connectionAttemptTimeoutMs = connectionAttemptTimeoutMs;
|
_connectionAttemptTimeoutMs = connectionAttemptTimeoutMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t TcpIpMeshBackend::getConnectionAttemptTimeout() {return _connectionAttemptTimeoutMs;}
|
uint32_t TcpIpMeshBackend::getConnectionAttemptTimeout() {return _connectionAttemptTimeoutMs;}
|
||||||
|
|
||||||
void TcpIpMeshBackend::setStationModeTimeout(int stationModeTimeoutMs)
|
void TcpIpMeshBackend::setStationModeTimeout(int stationModeTimeoutMs)
|
||||||
{
|
{
|
||||||
@ -220,12 +220,11 @@ void TcpIpMeshBackend::fullStop(WiFiClient &currClient)
|
|||||||
*/
|
*/
|
||||||
bool TcpIpMeshBackend::waitForClientTransmission(WiFiClient &currClient, uint32_t maxWait)
|
bool TcpIpMeshBackend::waitForClientTransmission(WiFiClient &currClient, uint32_t maxWait)
|
||||||
{
|
{
|
||||||
uint32_t connectionStartTime = millis();
|
ExpiringTimeTracker timeout(maxWait);
|
||||||
uint32_t waitingTime = millis() - connectionStartTime;
|
|
||||||
while(currClient.connected() && !currClient.available() && waitingTime < maxWait)
|
while(currClient.connected() && !currClient.available() && !timeout)
|
||||||
{
|
{
|
||||||
delay(1);
|
delay(1);
|
||||||
waitingTime = millis() - connectionStartTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return false if the client isn't ready to communicate */
|
/* Return false if the client isn't ready to communicate */
|
||||||
@ -246,7 +245,7 @@ bool TcpIpMeshBackend::waitForClientTransmission(WiFiClient &currClient, uint32_
|
|||||||
* @return A status code based on the outcome of the exchange.
|
* @return A status code based on the outcome of the exchange.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
transmission_status_t TcpIpMeshBackend::exchangeInfo(WiFiClient &currClient)
|
TransmissionStatusType TcpIpMeshBackend::exchangeInfo(WiFiClient &currClient)
|
||||||
{
|
{
|
||||||
verboseModePrint(String(F("Transmitting")));
|
verboseModePrint(String(F("Transmitting")));
|
||||||
|
|
||||||
@ -256,13 +255,13 @@ transmission_status_t TcpIpMeshBackend::exchangeInfo(WiFiClient &currClient)
|
|||||||
if (!waitForClientTransmission(currClient, _stationModeTimeoutMs))
|
if (!waitForClientTransmission(currClient, _stationModeTimeoutMs))
|
||||||
{
|
{
|
||||||
fullStop(currClient);
|
fullStop(currClient);
|
||||||
return TS_CONNECTION_FAILED;
|
return TransmissionStatusType::CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currClient.available())
|
if (!currClient.available())
|
||||||
{
|
{
|
||||||
verboseModePrint(F("No response!"));
|
verboseModePrint(F("No response!"));
|
||||||
return TS_TRANSMISSION_FAILED; // WiFi.status() != WL_DISCONNECTED so we do not want to use fullStop(currClient) here since that would force the node to scan for WiFi networks.
|
return TransmissionStatusType::TRANSMISSION_FAILED; // WiFi.status() != WL_DISCONNECTED so we do not want to use fullStop(currClient) here since that would force the node to scan for WiFi networks.
|
||||||
}
|
}
|
||||||
|
|
||||||
String response = currClient.readStringUntil('\r');
|
String response = currClient.readStringUntil('\r');
|
||||||
@ -278,7 +277,7 @@ transmission_status_t TcpIpMeshBackend::exchangeInfo(WiFiClient &currClient)
|
|||||||
*
|
*
|
||||||
* @return A status code based on the outcome of the data transfer attempt.
|
* @return A status code based on the outcome of the data transfer attempt.
|
||||||
*/
|
*/
|
||||||
transmission_status_t TcpIpMeshBackend::attemptDataTransfer()
|
TransmissionStatusType TcpIpMeshBackend::attemptDataTransfer()
|
||||||
{
|
{
|
||||||
// Unlike WiFi.mode(WIFI_AP);, WiFi.mode(WIFI_AP_STA); allows us to stay connected to the AP we connected to in STA mode, at the same time as we can receive connections from other stations.
|
// Unlike WiFi.mode(WIFI_AP);, WiFi.mode(WIFI_AP_STA); allows us to stay connected to the AP we connected to in STA mode, at the same time as we can receive connections from other stations.
|
||||||
// We cannot send data to the AP in STA_AP mode though, that requires STA mode.
|
// We cannot send data to the AP in STA_AP mode though, that requires STA mode.
|
||||||
@ -286,7 +285,7 @@ transmission_status_t TcpIpMeshBackend::attemptDataTransfer()
|
|||||||
WiFiMode_t storedWiFiMode = WiFi.getMode();
|
WiFiMode_t storedWiFiMode = WiFi.getMode();
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
delay(1);
|
delay(1);
|
||||||
transmission_status_t transmissionOutcome = attemptDataTransferKernel();
|
TransmissionStatusType transmissionOutcome = attemptDataTransferKernel();
|
||||||
WiFi.mode(storedWiFiMode);
|
WiFi.mode(storedWiFiMode);
|
||||||
delay(1);
|
delay(1);
|
||||||
|
|
||||||
@ -298,7 +297,7 @@ transmission_status_t TcpIpMeshBackend::attemptDataTransfer()
|
|||||||
*
|
*
|
||||||
* @return A status code based on the outcome of the data transfer attempt.
|
* @return A status code based on the outcome of the data transfer attempt.
|
||||||
*/
|
*/
|
||||||
transmission_status_t TcpIpMeshBackend::attemptDataTransferKernel()
|
TransmissionStatusType TcpIpMeshBackend::attemptDataTransferKernel()
|
||||||
{
|
{
|
||||||
WiFiClient currClient;
|
WiFiClient currClient;
|
||||||
currClient.setTimeout(_stationModeTimeoutMs);
|
currClient.setTimeout(_stationModeTimeoutMs);
|
||||||
@ -308,11 +307,11 @@ transmission_status_t TcpIpMeshBackend::attemptDataTransferKernel()
|
|||||||
{
|
{
|
||||||
fullStop(currClient);
|
fullStop(currClient);
|
||||||
verboseModePrint(F("Server unavailable"));
|
verboseModePrint(F("Server unavailable"));
|
||||||
return TS_CONNECTION_FAILED;
|
return TransmissionStatusType::CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
transmission_status_t transmissionOutcome = exchangeInfo(currClient);
|
TransmissionStatusType transmissionOutcome = exchangeInfo(currClient);
|
||||||
if (transmissionOutcome <= 0)
|
if (static_cast<int>(transmissionOutcome) <= 0)
|
||||||
{
|
{
|
||||||
verboseModePrint(F("Transmission failed during exchangeInfo."));
|
verboseModePrint(F("Transmission failed during exchangeInfo."));
|
||||||
return transmissionOutcome;
|
return transmissionOutcome;
|
||||||
@ -343,7 +342,7 @@ void TcpIpMeshBackend::initiateConnectionToAP(const String &targetSSID, int targ
|
|||||||
* @return A status code based on the outcome of the connection and data transfer process.
|
* @return A status code based on the outcome of the connection and data transfer process.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
transmission_status_t TcpIpMeshBackend::connectToNode(const String &targetSSID, int targetChannel, uint8_t *targetBSSID)
|
TransmissionStatusType TcpIpMeshBackend::connectToNode(const String &targetSSID, int targetChannel, uint8_t *targetBSSID)
|
||||||
{
|
{
|
||||||
if(staticIPActivated && !lastSSID.isEmpty() && lastSSID != targetSSID) // So we only do this once per connection, in case there is a performance impact.
|
if(staticIPActivated && !lastSSID.isEmpty() && lastSSID != targetSSID) // So we only do this once per connection, in case there is a performance impact.
|
||||||
{
|
{
|
||||||
@ -366,37 +365,36 @@ transmission_status_t TcpIpMeshBackend::connectToNode(const String &targetSSID,
|
|||||||
verboseModePrint(F("Connecting... "), false);
|
verboseModePrint(F("Connecting... "), false);
|
||||||
initiateConnectionToAP(targetSSID, targetChannel, targetBSSID);
|
initiateConnectionToAP(targetSSID, targetChannel, targetBSSID);
|
||||||
|
|
||||||
int connectionStartTime = millis();
|
|
||||||
int attemptNumber = 1;
|
int attemptNumber = 1;
|
||||||
|
ExpiringTimeTracker connectionAttemptTimeout([this](){ return _connectionAttemptTimeoutMs; });
|
||||||
|
|
||||||
int waitingTime = millis() - connectionStartTime;
|
while((WiFi.status() == WL_DISCONNECTED) && !connectionAttemptTimeout)
|
||||||
while((WiFi.status() == WL_DISCONNECTED) && waitingTime <= _connectionAttemptTimeoutMs)
|
|
||||||
{
|
{
|
||||||
if(waitingTime > attemptNumber * _connectionAttemptTimeoutMs) // _connectionAttemptTimeoutMs can be replaced (lowered) if you want to limit the time allowed for each connection attempt.
|
if(connectionAttemptTimeout.elapsedTime() > attemptNumber * _connectionAttemptTimeoutMs) // _connectionAttemptTimeoutMs can be replaced (lowered) if you want to limit the time allowed for each connection attempt.
|
||||||
{
|
{
|
||||||
verboseModePrint(F("... "), false);
|
verboseModePrint(F("... "), false);
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
yield();
|
yield();
|
||||||
initiateConnectionToAP(targetSSID, targetChannel, targetBSSID);
|
initiateConnectionToAP(targetSSID, targetChannel, targetBSSID);
|
||||||
attemptNumber++;
|
++attemptNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1);
|
delay(1);
|
||||||
waitingTime = millis() - connectionStartTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verboseModePrint(String(waitingTime));
|
verboseModePrint(String(connectionAttemptTimeout.elapsedTime()));
|
||||||
|
|
||||||
/* If the connection timed out */
|
/* If the connection timed out */
|
||||||
if (WiFi.status() != WL_CONNECTED)
|
if (WiFi.status() != WL_CONNECTED)
|
||||||
{
|
{
|
||||||
verboseModePrint(F("Timeout"));
|
verboseModePrint(F("Timeout"));
|
||||||
return TS_CONNECTION_FAILED;
|
return TransmissionStatusType::CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return attemptDataTransfer();
|
return attemptDataTransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
transmission_status_t TcpIpMeshBackend::initiateTransmission(const TcpIpNetworkInfo &recipientInfo)
|
TransmissionStatusType TcpIpMeshBackend::initiateTransmission(const TcpIpNetworkInfo &recipientInfo)
|
||||||
{
|
{
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
yield();
|
yield();
|
||||||
@ -452,7 +450,7 @@ void TcpIpMeshBackend::attemptTransmission(const String &message, bool scan, boo
|
|||||||
|
|
||||||
if(WiFi.status() == WL_CONNECTED)
|
if(WiFi.status() == WL_CONNECTED)
|
||||||
{
|
{
|
||||||
transmission_status_t transmissionResult = attemptDataTransfer();
|
TransmissionStatusType transmissionResult = attemptDataTransfer();
|
||||||
latestTransmissionOutcomes().push_back(TransmissionOutcome(constConnectionQueue().back(), transmissionResult));
|
latestTransmissionOutcomes().push_back(TransmissionOutcome(constConnectionQueue().back(), transmissionResult));
|
||||||
|
|
||||||
getTransmissionOutcomesUpdateHook()(*this);
|
getTransmissionOutcomesUpdateHook()(*this);
|
||||||
@ -474,7 +472,7 @@ void TcpIpMeshBackend::attemptTransmission(const String &message, bool scan, boo
|
|||||||
{
|
{
|
||||||
for(const TcpIpNetworkInfo ¤tNetwork : constConnectionQueue())
|
for(const TcpIpNetworkInfo ¤tNetwork : constConnectionQueue())
|
||||||
{
|
{
|
||||||
transmission_status_t transmissionResult = initiateTransmission(currentNetwork);
|
TransmissionStatusType transmissionResult = initiateTransmission(currentNetwork);
|
||||||
|
|
||||||
latestTransmissionOutcomes().push_back(TransmissionOutcome{.origin = currentNetwork, .transmissionStatus = transmissionResult});
|
latestTransmissionOutcomes().push_back(TransmissionOutcome{.origin = currentNetwork, .transmissionStatus = transmissionResult});
|
||||||
|
|
||||||
@ -492,16 +490,16 @@ void TcpIpMeshBackend::attemptTransmission(const String &message, bool scan, boo
|
|||||||
attemptTransmission(message, scan, scanAllWiFiChannels, true, false);
|
attemptTransmission(message, scan, scanAllWiFiChannels, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
transmission_status_t TcpIpMeshBackend::attemptTransmission(const String &message, const TcpIpNetworkInfo &recipientInfo, bool concludingDisconnect, bool initialDisconnect)
|
TransmissionStatusType TcpIpMeshBackend::attemptTransmission(const String &message, const TcpIpNetworkInfo &recipientInfo, bool concludingDisconnect, bool initialDisconnect)
|
||||||
{
|
{
|
||||||
MutexTracker mutexTracker(_tcpIpTransmissionMutex);
|
MutexTracker mutexTracker(_tcpIpTransmissionMutex);
|
||||||
if(!mutexTracker.mutexCaptured())
|
if(!mutexTracker.mutexCaptured())
|
||||||
{
|
{
|
||||||
assert(false && String(F("ERROR! TCP/IP transmission in progress. Don't call attemptTransmission from callbacks as this may corrupt program state! Aborting.")));
|
assert(false && String(F("ERROR! TCP/IP transmission in progress. Don't call attemptTransmission from callbacks as this may corrupt program state! Aborting.")));
|
||||||
return TS_CONNECTION_FAILED;
|
return TransmissionStatusType::CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
transmission_status_t transmissionResult = TS_CONNECTION_FAILED;
|
TransmissionStatusType transmissionResult = TransmissionStatusType::CONNECTION_FAILED;
|
||||||
setTemporaryMessage(message);
|
setTemporaryMessage(message);
|
||||||
|
|
||||||
if(initialDisconnect)
|
if(initialDisconnect)
|
||||||
|
@ -43,14 +43,14 @@ public:
|
|||||||
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
* @param requestHandler The callback handler for dealing with received requests. Takes a string as an argument which
|
||||||
* is the request string received from another node and returns the string to send back.
|
* is the request string received from another node and returns the string to send back.
|
||||||
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
* @param responseHandler The callback handler for dealing with received responses. Takes a string as an argument which
|
||||||
* is the response string received from another node. Returns a transmission status code as a transmission_status_t.
|
* is the response string received from another node. Returns a transmission status code as a TransmissionStatusType.
|
||||||
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
||||||
* @param meshPassword The WiFi password for the mesh network.
|
* @param meshPassword The WiFi password for the mesh network.
|
||||||
* @param ssidPrefix The prefix (first part) of the node SSID.
|
* @param ssidPrefix The prefix (first part) of the node SSID.
|
||||||
* @param ssidSuffix The suffix (last part) of the node SSID.
|
* @param ssidSuffix The suffix (last part) of the node SSID.
|
||||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is separate for each TcpIpMeshBackend instance.
|
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default. This setting is separate for each TcpIpMeshBackend instance.
|
||||||
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
* @param meshWiFiChannel The WiFi channel used by the mesh network. Valid values are integers from 1 to 13. Defaults to 1.
|
||||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
* WARNING: The ESP8266 has only one WiFi channel, and the station/client mode is always prioritized for channel selection.
|
||||||
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
* This can cause problems if several mesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||||
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
* In such a case, whenever the station of one mesh instance connects to an AP, it will silently force the
|
||||||
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
* WiFi channel of any active AP on the ESP8266 to match that of the station. This will cause disconnects and possibly
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
static std::vector<TransmissionOutcome> & latestTransmissionOutcomes();
|
static std::vector<TransmissionOutcome> & latestTransmissionOutcomes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
|
* @return True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TransmissionStatusType::TRANSMISSION_COMPLETE). False otherwise.
|
||||||
* The result is unique for each mesh backend.
|
* The result is unique for each mesh backend.
|
||||||
*/
|
*/
|
||||||
static bool latestTransmissionSuccessful();
|
static bool latestTransmissionSuccessful();
|
||||||
@ -124,7 +124,7 @@ public:
|
|||||||
*
|
*
|
||||||
* Note that if wifiChannel and BSSID are missing from recipientInfo, connection time will be longer.
|
* Note that if wifiChannel and BSSID are missing from recipientInfo, connection time will be longer.
|
||||||
*/
|
*/
|
||||||
transmission_status_t attemptTransmission(const String &message, const TcpIpNetworkInfo &recipientInfo, bool concludingDisconnect = true, bool initialDisconnect = false);
|
TransmissionStatusType attemptTransmission(const String &message, const TcpIpNetworkInfo &recipientInfo, bool concludingDisconnect = true, bool initialDisconnect = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If any clients are connected, accept their requests and call the requestHandler function for each one.
|
* If any clients are connected, accept their requests and call the requestHandler function for each one.
|
||||||
@ -183,8 +183,8 @@ public:
|
|||||||
*
|
*
|
||||||
* @param connectionAttemptTimeoutMs The timeout for each connection attempt, in milliseconds.
|
* @param connectionAttemptTimeoutMs The timeout for each connection attempt, in milliseconds.
|
||||||
*/
|
*/
|
||||||
void setConnectionAttemptTimeout(int32_t connectionAttemptTimeoutMs);
|
void setConnectionAttemptTimeout(uint32_t connectionAttemptTimeoutMs);
|
||||||
int32_t getConnectionAttemptTimeout();
|
uint32_t getConnectionAttemptTimeout();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the timeout to use for transmissions when this TcpIpMeshBackend instance acts as a station (i.e. when connected to another AP).
|
* Set the timeout to use for transmissions when this TcpIpMeshBackend instance acts as a station (i.e. when connected to another AP).
|
||||||
@ -228,12 +228,12 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* Will be true if a transmission initiated by a public method is in progress.
|
* Will be true if a transmission initiated by a public method is in progress.
|
||||||
*/
|
*/
|
||||||
static bool _tcpIpTransmissionMutex;
|
static std::shared_ptr<bool> _tcpIpTransmissionMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will be true when the connectionQueue should not be modified.
|
* Will be true when the connectionQueue should not be modified.
|
||||||
*/
|
*/
|
||||||
static bool _tcpIpConnectionQueueMutex;
|
static std::shared_ptr<bool> _tcpIpConnectionQueueMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if there is an ongoing TCP/IP transmission in the library. Used to avoid interrupting transmissions.
|
* Check if there is an ongoing TCP/IP transmission in the library. Used to avoid interrupting transmissions.
|
||||||
@ -257,7 +257,7 @@ private:
|
|||||||
uint16_t _serverPort;
|
uint16_t _serverPort;
|
||||||
WiFiServer _server;
|
WiFiServer _server;
|
||||||
uint8_t _maxAPStations = 4; // Only affects TCP/IP connections, not ESP-NOW connections
|
uint8_t _maxAPStations = 4; // Only affects TCP/IP connections, not ESP-NOW connections
|
||||||
int32_t _connectionAttemptTimeoutMs = 10000;
|
uint32_t _connectionAttemptTimeoutMs = 10000;
|
||||||
int _stationModeTimeoutMs = 5000; // int is the type used in the Arduino core for this particular API, not uint32_t, which is why we use int here.
|
int _stationModeTimeoutMs = 5000; // int is the type used in the Arduino core for this particular API, not uint32_t, which is why we use int here.
|
||||||
uint32_t _apModeTimeoutMs = 4500;
|
uint32_t _apModeTimeoutMs = 4500;
|
||||||
|
|
||||||
@ -271,12 +271,12 @@ private:
|
|||||||
|
|
||||||
void fullStop(WiFiClient &currClient);
|
void fullStop(WiFiClient &currClient);
|
||||||
void initiateConnectionToAP(const String &targetSSID, int targetChannel = NETWORK_INFO_DEFAULT_INT, uint8_t *targetBSSID = NULL);
|
void initiateConnectionToAP(const String &targetSSID, int targetChannel = NETWORK_INFO_DEFAULT_INT, uint8_t *targetBSSID = NULL);
|
||||||
transmission_status_t connectToNode(const String &targetSSID, int targetChannel = NETWORK_INFO_DEFAULT_INT, uint8_t *targetBSSID = NULL);
|
TransmissionStatusType connectToNode(const String &targetSSID, int targetChannel = NETWORK_INFO_DEFAULT_INT, uint8_t *targetBSSID = NULL);
|
||||||
transmission_status_t exchangeInfo(WiFiClient &currClient);
|
TransmissionStatusType exchangeInfo(WiFiClient &currClient);
|
||||||
bool waitForClientTransmission(WiFiClient &currClient, uint32_t maxWait);
|
bool waitForClientTransmission(WiFiClient &currClient, uint32_t maxWait);
|
||||||
transmission_status_t attemptDataTransfer();
|
TransmissionStatusType attemptDataTransfer();
|
||||||
transmission_status_t attemptDataTransferKernel();
|
TransmissionStatusType attemptDataTransferKernel();
|
||||||
transmission_status_t initiateTransmission(const TcpIpNetworkInfo &recipientInfo);
|
TransmissionStatusType initiateTransmission(const TcpIpNetworkInfo &recipientInfo);
|
||||||
void enterPostTransmissionState(bool concludingDisconnect);
|
void enterPostTransmissionState(bool concludingDisconnect);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Minimal time tracking class. Used instead of other classes like ExpiringTimeTracker when small memory footprint is important and other functionality not required.
|
||||||
class TimeTracker {
|
class TimeTracker {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
#include "TransmissionOutcome.h"
|
#include "TransmissionOutcome.h"
|
||||||
|
|
||||||
TransmissionOutcome::TransmissionOutcome(const NetworkInfoBase &origin, transmission_status_t transmissionStatus)
|
TransmissionOutcome::TransmissionOutcome(const NetworkInfoBase &origin, TransmissionStatusType transmissionStatus)
|
||||||
: NetworkInfoBase(origin), _transmissionStatus(transmissionStatus)
|
: NetworkInfoBase(origin), _transmissionStatus(transmissionStatus)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
TransmissionOutcome::TransmissionOutcome(const String &SSID, int32_t wifiChannel, const uint8_t BSSID[6], uint8_t encryptionType, int32_t RSSI, bool isHidden, transmission_status_t transmissionStatus)
|
TransmissionOutcome::TransmissionOutcome(const String &SSID, int32_t wifiChannel, const uint8_t BSSID[6], uint8_t encryptionType, int32_t RSSI, bool isHidden, TransmissionStatusType transmissionStatus)
|
||||||
: NetworkInfoBase(SSID, wifiChannel, BSSID, encryptionType, RSSI, isHidden), _transmissionStatus(transmissionStatus)
|
: NetworkInfoBase(SSID, wifiChannel, BSSID, encryptionType, RSSI, isHidden), _transmissionStatus(transmissionStatus)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void TransmissionOutcome::setTransmissionStatus(transmission_status_t transmissionStatus) { _transmissionStatus = transmissionStatus; }
|
void TransmissionOutcome::setTransmissionStatus(TransmissionStatusType transmissionStatus) { _transmissionStatus = transmissionStatus; }
|
||||||
transmission_status_t TransmissionOutcome::transmissionStatus() const { return _transmissionStatus; }
|
TransmissionStatusType TransmissionOutcome::transmissionStatus() const { return _transmissionStatus; }
|
||||||
|
@ -28,27 +28,27 @@
|
|||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include "NetworkInfoBase.h"
|
#include "NetworkInfoBase.h"
|
||||||
|
|
||||||
typedef enum
|
enum class TransmissionStatusType
|
||||||
{
|
{
|
||||||
TS_CONNECTION_FAILED = -1,
|
CONNECTION_FAILED = -1,
|
||||||
TS_TRANSMISSION_FAILED = 0,
|
TRANSMISSION_FAILED = 0,
|
||||||
TS_TRANSMISSION_COMPLETE = 1
|
TRANSMISSION_COMPLETE = 1
|
||||||
} transmission_status_t;
|
};
|
||||||
|
|
||||||
class TransmissionOutcome : public NetworkInfoBase {
|
class TransmissionOutcome : public NetworkInfoBase {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TransmissionOutcome(const NetworkInfoBase &origin, transmission_status_t transmissionStatus);
|
TransmissionOutcome(const NetworkInfoBase &origin, TransmissionStatusType transmissionStatus);
|
||||||
|
|
||||||
TransmissionOutcome(const String &SSID, int32_t wifiChannel, const uint8_t BSSID[6], uint8_t encryptionType, int32_t RSSI, bool isHidden, transmission_status_t transmissionStatus);
|
TransmissionOutcome(const String &SSID, int32_t wifiChannel, const uint8_t BSSID[6], uint8_t encryptionType, int32_t RSSI, bool isHidden, TransmissionStatusType transmissionStatus);
|
||||||
|
|
||||||
void setTransmissionStatus(transmission_status_t transmissionStatus);
|
void setTransmissionStatus(TransmissionStatusType transmissionStatus);
|
||||||
transmission_status_t transmissionStatus() const;
|
TransmissionStatusType transmissionStatus() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
transmission_status_t _transmissionStatus;
|
TransmissionStatusType _transmissionStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,6 +54,13 @@
|
|||||||
#include "NetworkInfo.h"
|
#include "NetworkInfo.h"
|
||||||
#include "TransmissionOutcome.h"
|
#include "TransmissionOutcome.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TS_CONNECTION_FAILED = -1,
|
||||||
|
TS_TRANSMISSION_FAILED = 0,
|
||||||
|
TS_TRANSMISSION_COMPLETE = 1
|
||||||
|
} transmission_status_t;
|
||||||
|
|
||||||
class TransmissionResult : public NetworkInfo {
|
class TransmissionResult : public NetworkInfo {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -63,11 +70,11 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @param autofill Automatically fill in the rest of the network info using newNetworkIndex and the WiFi scan results.
|
* @param autofill Automatically fill in the rest of the network info using newNetworkIndex and the WiFi scan results.
|
||||||
*/
|
*/
|
||||||
TransmissionResult(int newNetworkIndex, transmission_status_t newTransmissionStatus, bool autofill = true);
|
TransmissionResult(int newNetworkIndex, transmission_status_t newTransmissionStatus, bool autofill = true) __attribute__((deprecated));
|
||||||
|
|
||||||
TransmissionResult(const String &newSSID, int newWiFiChannel, uint8_t newBSSID[6], transmission_status_t newTransmissionStatus);
|
TransmissionResult(const String &newSSID, int newWiFiChannel, uint8_t newBSSID[6], transmission_status_t newTransmissionStatus) __attribute__((deprecated));
|
||||||
|
|
||||||
TransmissionResult(const String &newSSID, int newWiFiChannel, uint8_t newBSSID[6], int newNetworkIndex, transmission_status_t newTransmissionStatus);
|
TransmissionResult(const String &newSSID, int newWiFiChannel, uint8_t newBSSID[6], int newNetworkIndex, transmission_status_t newTransmissionStatus) __attribute__((deprecated));
|
||||||
|
|
||||||
TransmissionResult(const NetworkInfo& origin, transmission_status_t newTransmissionStatus);
|
TransmissionResult(const NetworkInfo& origin, transmission_status_t newTransmissionStatus);
|
||||||
};
|
};
|
||||||
|
@ -27,15 +27,15 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr char chars[36] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
|
constexpr char chars[36] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
|
||||||
constexpr uint8_t charValues[75] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, // 0 to 10
|
constexpr uint8_t charValues[75] PROGMEM {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, // 0 to 9
|
||||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, // Upper case letters
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, // Upper case letters
|
||||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; // Lower case letters
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; // Lower case letters
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MeshTypeConversionFunctions
|
namespace MeshTypeConversionFunctions
|
||||||
{
|
{
|
||||||
String uint64ToString(uint64_t number, byte base)
|
String uint64ToString(uint64_t number, const byte base)
|
||||||
{
|
{
|
||||||
assert(2 <= base && base <= 36);
|
assert(2 <= base && base <= 36);
|
||||||
|
|
||||||
@ -44,14 +44,14 @@ namespace MeshTypeConversionFunctions
|
|||||||
if(base == 16)
|
if(base == 16)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
result += chars[ number % base ];
|
result += (char)pgm_read_byte(chars + number % base);
|
||||||
number >>= 4; // We could write number /= 16; and the compiler would optimize it to a shift, but the explicit shift notation makes it clearer where the speed-up comes from.
|
number >>= 4; // We could write number /= 16; and the compiler would optimize it to a shift, but the explicit shift notation makes it clearer where the speed-up comes from.
|
||||||
} while ( number );
|
} while ( number );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
result += chars[ number % base ];
|
result += (char)pgm_read_byte(chars + number % base);
|
||||||
number /= base;
|
number /= base;
|
||||||
} while ( number );
|
} while ( number );
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t stringToUint64(const String &string, byte base)
|
uint64_t stringToUint64(const String &string, const byte base)
|
||||||
{
|
{
|
||||||
assert(2 <= base && base <= 36);
|
assert(2 <= base && base <= 36);
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
for(uint32_t i = 0; i < string.length(); ++i)
|
for(uint32_t i = 0; i < string.length(); ++i)
|
||||||
{
|
{
|
||||||
result <<= 4; // We could write result *= 16; and the compiler would optimize it to a shift, but the explicit shift notation makes it clearer where the speed-up comes from.
|
result <<= 4; // We could write result *= 16; and the compiler would optimize it to a shift, but the explicit shift notation makes it clearer where the speed-up comes from.
|
||||||
result += charValues[string.charAt(i) - '0'];
|
result += pgm_read_byte(charValues + string.charAt(i) - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -80,14 +80,14 @@ namespace MeshTypeConversionFunctions
|
|||||||
for(uint32_t i = 0; i < string.length(); ++i)
|
for(uint32_t i = 0; i < string.length(); ++i)
|
||||||
{
|
{
|
||||||
result *= base;
|
result *= base;
|
||||||
result += charValues[string.charAt(i) - '0'];
|
result += pgm_read_byte(charValues + string.charAt(i) - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String uint8ArrayToHexString(const uint8_t *uint8Array, uint32_t arrayLength)
|
String uint8ArrayToHexString(const uint8_t *uint8Array, const uint32_t arrayLength)
|
||||||
{
|
{
|
||||||
String hexString;
|
String hexString;
|
||||||
if(!hexString.reserve(2*arrayLength)) // Each uint8_t will become two characters (00 to FF)
|
if(!hexString.reserve(2*arrayLength)) // Each uint8_t will become two characters (00 to FF)
|
||||||
@ -95,26 +95,26 @@ namespace MeshTypeConversionFunctions
|
|||||||
|
|
||||||
for(uint32_t i = 0; i < arrayLength; ++i)
|
for(uint32_t i = 0; i < arrayLength; ++i)
|
||||||
{
|
{
|
||||||
hexString += chars[ uint8Array[i] >> 4 ];
|
hexString += (char)pgm_read_byte(chars + (uint8Array[i] >> 4));
|
||||||
hexString += chars[ uint8Array[i] % 16 ];
|
hexString += (char)pgm_read_byte(chars + uint8Array[i] % 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return hexString;
|
return hexString;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, uint32_t arrayLength)
|
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, const uint32_t arrayLength)
|
||||||
{
|
{
|
||||||
assert(hexString.length() >= arrayLength*2); // Each array element can hold two hexString characters
|
assert(hexString.length() >= arrayLength*2); // Each array element can hold two hexString characters
|
||||||
|
|
||||||
for(uint32_t i = 0; i < arrayLength; ++i)
|
for(uint32_t i = 0; i < arrayLength; ++i)
|
||||||
{
|
{
|
||||||
uint8Array[i] = (charValues[hexString.charAt(i*2) - '0'] << 4) + charValues[hexString.charAt(i*2 + 1) - '0'];
|
uint8Array[i] = (pgm_read_byte(charValues + hexString.charAt(i*2) - '0') << 4) + pgm_read_byte(charValues + hexString.charAt(i*2 + 1) - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint8Array;
|
return uint8Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
String uint8ArrayToMultiString(uint8_t *uint8Array, uint32_t arrayLength)
|
String uint8ArrayToMultiString(uint8_t *uint8Array, const uint32_t arrayLength)
|
||||||
{
|
{
|
||||||
String multiString;
|
String multiString;
|
||||||
if(!multiString.reserve(arrayLength))
|
if(!multiString.reserve(arrayLength))
|
||||||
@ -137,7 +137,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
return multiString;
|
return multiString;
|
||||||
}
|
}
|
||||||
|
|
||||||
String bufferedUint8ArrayToMultiString(const uint8_t *uint8Array, uint32_t arrayLength)
|
String bufferedUint8ArrayToMultiString(const uint8_t *uint8Array, const uint32_t arrayLength)
|
||||||
{
|
{
|
||||||
String multiString;
|
String multiString;
|
||||||
if(!multiString.reserve(arrayLength))
|
if(!multiString.reserve(arrayLength))
|
||||||
@ -174,7 +174,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *uint64ToMac(uint64_t macValue, uint8_t *macArray)
|
uint8_t *uint64ToMac(const uint64_t macValue, uint8_t *macArray)
|
||||||
{
|
{
|
||||||
assert(macValue <= 0xFFFFFFFFFFFF); // Overflow will occur if value can't fit within 6 bytes
|
assert(macValue <= 0xFFFFFFFFFFFF); // Overflow will occur if value can't fit within 6 bytes
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
return macArray;
|
return macArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *uint64ToUint8Array(uint64_t value, uint8_t *resultArray)
|
uint8_t *uint64ToUint8Array(const uint64_t value, uint8_t *resultArray)
|
||||||
{
|
{
|
||||||
resultArray[7] = value;
|
resultArray[7] = value;
|
||||||
resultArray[6] = value >> 8;
|
resultArray[6] = value >> 8;
|
||||||
@ -214,27 +214,25 @@ namespace MeshTypeConversionFunctions
|
|||||||
* Helper function for meshBackendCast.
|
* Helper function for meshBackendCast.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T attemptPointerCast(MeshBackendBase *meshBackendBaseInstance, mesh_backend_t resultClassType)
|
T attemptPointerCast(MeshBackendBase *meshBackendBaseInstance, MeshBackendType resultClassType)
|
||||||
{
|
{
|
||||||
if(meshBackendBaseInstance && meshBackendBaseInstance->getClassType() == resultClassType)
|
if(meshBackendBaseInstance && meshBackendBaseInstance->getClassType() == resultClassType)
|
||||||
{
|
{
|
||||||
return static_cast<T>(meshBackendBaseInstance);
|
return static_cast<T>(meshBackendBaseInstance);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
EspnowMeshBackend *meshBackendCast<EspnowMeshBackend *>(MeshBackendBase *meshBackendBaseInstance)
|
EspnowMeshBackend *meshBackendCast<EspnowMeshBackend *>(MeshBackendBase *meshBackendBaseInstance)
|
||||||
{
|
{
|
||||||
return attemptPointerCast<EspnowMeshBackend *>(meshBackendBaseInstance, MB_ESP_NOW);
|
return attemptPointerCast<EspnowMeshBackend *>(meshBackendBaseInstance, MeshBackendType::ESP_NOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
TcpIpMeshBackend *meshBackendCast<TcpIpMeshBackend *>(MeshBackendBase *meshBackendBaseInstance)
|
TcpIpMeshBackend *meshBackendCast<TcpIpMeshBackend *>(MeshBackendBase *meshBackendBaseInstance)
|
||||||
{
|
{
|
||||||
return attemptPointerCast<TcpIpMeshBackend *>(meshBackendBaseInstance, MB_TCP_IP);
|
return attemptPointerCast<TcpIpMeshBackend *>(meshBackendBaseInstance, MeshBackendType::TCP_IP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param base The radix to convert "number" into. Must be between 2 and 36.
|
* @param base The radix to convert "number" into. Must be between 2 and 36.
|
||||||
* @return A string of "number" encoded in radix "base".
|
* @return A string of "number" encoded in radix "base".
|
||||||
*/
|
*/
|
||||||
String uint64ToString(uint64_t number, byte base = 16);
|
String uint64ToString(uint64_t number, const byte base = 16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that using base 10 instead of 16 increases conversion time by roughly a factor of 2, due to unfavourable 64-bit arithmetic.
|
* Note that using base 10 instead of 16 increases conversion time by roughly a factor of 2, due to unfavourable 64-bit arithmetic.
|
||||||
@ -52,7 +52,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param base The radix of "string". Must be between 2 and 36.
|
* @param base The radix of "string". Must be between 2 and 36.
|
||||||
* @return A uint64_t of the string, using radix "base" during decoding.
|
* @return A uint64_t of the string, using radix "base" during decoding.
|
||||||
*/
|
*/
|
||||||
uint64_t stringToUint64(const String &string, byte base = 16);
|
uint64_t stringToUint64(const String &string, const byte base = 16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the contents of a uint8_t array to a String in HEX format. The resulting String starts from index 0 of the array.
|
* Convert the contents of a uint8_t array to a String in HEX format. The resulting String starts from index 0 of the array.
|
||||||
@ -62,7 +62,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param arrayLength The size of uint8Array, in bytes.
|
* @param arrayLength The size of uint8Array, in bytes.
|
||||||
* @return Normally a String containing the HEX representation of the uint8Array. An empty String if the memory allocation for the String failed.
|
* @return Normally a String containing the HEX representation of the uint8Array. An empty String if the memory allocation for the String failed.
|
||||||
*/
|
*/
|
||||||
String uint8ArrayToHexString(const uint8_t *uint8Array, uint32_t arrayLength);
|
String uint8ArrayToHexString(const uint8_t *uint8Array, const uint32_t arrayLength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the contents of a String in HEX format to a uint8_t array. Index 0 of the array will represent the start of the String.
|
* Convert the contents of a String in HEX format to a uint8_t array. Index 0 of the array will represent the start of the String.
|
||||||
@ -73,7 +73,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param arrayLength The number of bytes to fill in uint8Array.
|
* @param arrayLength The number of bytes to fill in uint8Array.
|
||||||
* @return A pointer to the uint8Array.
|
* @return A pointer to the uint8Array.
|
||||||
*/
|
*/
|
||||||
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, uint32_t arrayLength);
|
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, const uint32_t arrayLength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the exact values of uint8Array in a String, even null values.
|
* Stores the exact values of uint8Array in a String, even null values.
|
||||||
@ -86,7 +86,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param arrayLength The size of uint8Array, in bytes.
|
* @param arrayLength The size of uint8Array, in bytes.
|
||||||
* @return Normally a String containing the same data as the uint8Array. An empty String if the memory allocation for the String failed.
|
* @return Normally a String containing the same data as the uint8Array. An empty String if the memory allocation for the String failed.
|
||||||
*/
|
*/
|
||||||
String uint8ArrayToMultiString(uint8_t *uint8Array, uint32_t arrayLength);
|
String uint8ArrayToMultiString(uint8_t *uint8Array, const uint32_t arrayLength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the exact values of uint8Array in a String, even null values.
|
* Stores the exact values of uint8Array in a String, even null values.
|
||||||
@ -99,7 +99,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param arrayLength The size of uint8Array, in bytes.
|
* @param arrayLength The size of uint8Array, in bytes.
|
||||||
* @return Normally a String containing the same data as the uint8Array. An empty String if the memory allocation for the String failed.
|
* @return Normally a String containing the same data as the uint8Array. An empty String if the memory allocation for the String failed.
|
||||||
*/
|
*/
|
||||||
String bufferedUint8ArrayToMultiString(const uint8_t *uint8Array, uint32_t arrayLength);
|
String bufferedUint8ArrayToMultiString(const uint8_t *uint8Array, const uint32_t arrayLength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a uint8_t array and converts the first 6 bytes to a hexadecimal string.
|
* Takes a uint8_t array and converts the first 6 bytes to a hexadecimal string.
|
||||||
@ -133,7 +133,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param macArray A uint8_t array that will hold the mac address once the function returns. Should have a size of at least 6 bytes.
|
* @param macArray A uint8_t array that will hold the mac address once the function returns. Should have a size of at least 6 bytes.
|
||||||
* @return The macArray.
|
* @return The macArray.
|
||||||
*/
|
*/
|
||||||
uint8_t *uint64ToMac(uint64_t macValue, uint8_t *macArray);
|
uint8_t *uint64ToMac(const uint64_t macValue, uint8_t *macArray);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a uint64_t value and stores the bits in a uint8_t array. Assumes index 0 of the array should contain MSB.
|
* Takes a uint64_t value and stores the bits in a uint8_t array. Assumes index 0 of the array should contain MSB.
|
||||||
@ -142,7 +142,7 @@ namespace MeshTypeConversionFunctions
|
|||||||
* @param resultArray A uint8_t array that will hold the result once the function returns. Should have a size of at least 8 bytes.
|
* @param resultArray A uint8_t array that will hold the result once the function returns. Should have a size of at least 8 bytes.
|
||||||
* @return The resultArray.
|
* @return The resultArray.
|
||||||
*/
|
*/
|
||||||
uint8_t *uint64ToUint8Array(uint64_t value, uint8_t *resultArray);
|
uint8_t *uint64ToUint8Array(const uint64_t value, uint8_t *resultArray);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a uint8_t array and converts the first 8 (lowest index) elements to a uint64_t. Assumes index 0 of the array contains MSB.
|
* Takes a uint8_t array and converts the first 8 (lowest index) elements to a uint64_t. Assumes index 0 of the array contains MSB.
|
||||||
|
@ -30,7 +30,7 @@ namespace MeshUtilityFunctions
|
|||||||
{
|
{
|
||||||
bool macEqual(const uint8_t *macOne, const uint8_t *macTwo)
|
bool macEqual(const uint8_t *macOne, const uint8_t *macTwo)
|
||||||
{
|
{
|
||||||
for(int i = 0; i <= 5; i++)
|
for(int i = 0; i <= 5; ++i)
|
||||||
{
|
{
|
||||||
if(macOne[i] != macTwo[i])
|
if(macOne[i] != macTwo[i])
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user