mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-13 13:01:55 +03:00
- Make most type definitions public instead of protected, to facilitate use in composition.
- Call ResponseTransmittedHook after every response transmission attempt, instead of after every successful response transmission attempt. - Improve documentation. - Finalize README.md. - Update keywords.txt.
This commit is contained in:
@ -106,11 +106,9 @@ void espnowDelay(const uint32_t durationMs);
|
||||
|
||||
class EspnowMeshBackend : public MeshBackendBase {
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
using broadcastFilterType = std::function<bool(String &, EspnowMeshBackend &)>;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* ESP-NOW constructor method. Creates an ESP-NOW node, ready to be initialised.
|
||||
@ -299,6 +297,8 @@ public:
|
||||
* This also means that the broadcaster can receive duplicate responses from the same node if transmission conditions are poor and an ack is lost.
|
||||
* A broadcast can never be sent encrypted.
|
||||
*
|
||||
* Note that the node needs to have its AP active to be able to receive broadcasts. Nodes can send broadcasts even if their AP is off.
|
||||
*
|
||||
* @param message The message to send to the other nodes. Unlike the attemptTransmission method, the message will not be stored in the class instance, since there is no certain way to change the message during an ongoing broadcast.
|
||||
*/
|
||||
void broadcast(const String &message);
|
||||
@ -639,13 +639,13 @@ public:
|
||||
broadcastFilterType getBroadcastFilter() const;
|
||||
|
||||
/**
|
||||
* Set a function that should be called after each successful ESP-NOW response transmission, just before the response is removed from the waiting list.
|
||||
* If a particular response is not sent, there will be no function call for it.
|
||||
* Set a function that should be called after each attempted ESP-NOW response transmission.
|
||||
* In case of a successful response transmission, the call happens just before the response is removed from the waiting list.
|
||||
* Only the hook of the EspnowMeshBackend instance that is getEspnowRequestManager() will be called.
|
||||
*
|
||||
* The hook should return a bool.
|
||||
* If this return value is true, the response transmission process will continue with the next response in the waiting list.
|
||||
* If it is false, the response transmission process will stop after removing the just sent response from the waiting list.
|
||||
* If it is false, the response transmission process will stop once processing of the just sent response is complete.
|
||||
* The default responseTransmittedHook always returns true.
|
||||
*/
|
||||
void setResponseTransmittedHook(const EspnowTransmitter::responseTransmittedHookType responseTransmittedHook);
|
||||
@ -714,6 +714,8 @@ public:
|
||||
*
|
||||
* When called, the method will update an existing encrypted ESP-NOW connection with the current stored encrypted connection key. (in case it has changed since the connection was established)
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* @param peerStaMac The station MAC of the other node.
|
||||
* @param peerApMac The AP MAC of the other node.
|
||||
* @param peerSessionKey The session key of the other node. At least one of the leftmost 32 bits should be 1, since the key otherwise indicates the connection is unencrypted.
|
||||
@ -730,6 +732,8 @@ public:
|
||||
*
|
||||
* When called, the method will update an existing encrypted ESP-NOW connection with the current stored encrypted connection key. (in case it has changed since the connection was established)
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@ -747,6 +751,8 @@ public:
|
||||
*
|
||||
* When called, the method will update an existing encrypted ESP-NOW connection with the current stored encrypted connection key. (in case it has changed since the connection was established)
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* As with all these methods, changes will only take effect once the requester proves it has the ability to decrypt the session key.
|
||||
*
|
||||
* @param peerStaMac The station MAC of the other node.
|
||||
@ -766,6 +772,8 @@ public:
|
||||
*
|
||||
* When called, the method will update an existing encrypted ESP-NOW connection with the current stored encrypted connection key. (in case it has changed since the connection was established)
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@ -782,6 +790,8 @@ public:
|
||||
* 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.
|
||||
* The method makes sure both nodes have an encrypted connection to each other that's permanent.
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* @param peerMac The MAC of the other node to which the request should be sent.
|
||||
*
|
||||
* @return EncryptedConnectionStatus::CONNECTION_ESTABLISHED if the permanent connection was created. EncryptedConnectionStatus::SOFT_LIMIT_CONNECTION_ESTABLISHED if only a temporary soft limit connection could be established (see the setEncryptedConnectionsSoftLimit method documentation for details). Otherwise another status code based on the outcome.
|
||||
@ -793,6 +803,8 @@ public:
|
||||
* If a temporary encrypted connection to peerMac already exists, only connection duration is updated. All other settings are kept as is. Permanent connections are not modified. Use removeEncryptedConnection/requestEncryptedConnectionRemoval first if encryption keys should be updated.
|
||||
* The method makes sure both nodes have an encrypted connection to each other that's either permanent or has exactly the duration specified.
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* @param peerMac The MAC of the other node to which the request should be sent.
|
||||
* @param durationMs The desired duration of the connection.
|
||||
*
|
||||
@ -805,6 +817,8 @@ public:
|
||||
* If a temporary encrypted connection to peerMac with a shorter duration already exists, connection duration is updated. All other settings are kept as is. Permanent connections are not modified. Use removeEncryptedConnection/requestEncryptedConnectionRemoval first if encryption keys should be updated.
|
||||
* The method makes sure both nodes have an encrypted connection to each other that's either permanent or has at least the duration specified.
|
||||
*
|
||||
* The maximum number of simultaneous encrypted connections is restricted by the ESP-NOW API and is EspnowProtocolInterpreter::maxEncryptedConnections (6 by default).
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
@ -162,15 +162,17 @@ void EspnowTransmitter::sendEspnowResponses(const ExpiringTimeTracker *estimated
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hookOutcome = true;
|
||||
// Note that callbacks can be called during delay time, so it is possible to receive a transmission during espnowSendToNode
|
||||
// (which may add an element to the responsesToSend list).
|
||||
if(espnowSendToNodeUnsynchronized(responseIterator->getMessage(), responseIterator->getRecipientMac(), 'A', responseIterator->getRequestID())
|
||||
== TransmissionStatusType::TRANSMISSION_COMPLETE)
|
||||
bool transmissionSuccessful = espnowSendToNodeUnsynchronized(responseIterator->getMessage(), responseIterator->getRecipientMac(), 'A', responseIterator->getRequestID())
|
||||
== TransmissionStatusType::TRANSMISSION_COMPLETE;
|
||||
|
||||
bool hookOutcome = true;
|
||||
if(EspnowMeshBackend *currentEspnowRequestManager = EspnowMeshBackend::getEspnowRequestManager())
|
||||
hookOutcome = currentEspnowRequestManager->getResponseTransmittedHook()(transmissionSuccessful, responseIterator->getMessage(), responseIterator->getRecipientMac(), responseIndex, *currentEspnowRequestManager);
|
||||
|
||||
if(transmissionSuccessful)
|
||||
{
|
||||
if(EspnowMeshBackend *currentEspnowRequestManager = EspnowMeshBackend::getEspnowRequestManager())
|
||||
hookOutcome = currentEspnowRequestManager->getResponseTransmittedHook()(responseIterator->getMessage(), responseIterator->getRecipientMac(), responseIndex, *currentEspnowRequestManager);
|
||||
|
||||
responseIterator = EspnowDatabase::responsesToSend().erase(responseIterator);
|
||||
--responseIndex;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class EspnowTransmitter
|
||||
|
||||
public:
|
||||
|
||||
using responseTransmittedHookType = std::function<bool(const String &, const uint8_t *, uint32_t, EspnowMeshBackend &)>;
|
||||
using responseTransmittedHookType = std::function<bool(bool, const String &, const uint8_t *, uint32_t, EspnowMeshBackend &)>;
|
||||
|
||||
EspnowTransmitter(ConditionalPrinter &conditionalPrinterInstance, EspnowDatabase &databaseInstance, EspnowConnectionManager &connectionManagerInstance);
|
||||
|
||||
@ -101,7 +101,7 @@ private:
|
||||
EspnowDatabase & _database;
|
||||
EspnowConnectionManager & _connectionManager;
|
||||
|
||||
responseTransmittedHookType _responseTransmittedHook = [](const String &, const uint8_t *, uint32_t, EspnowMeshBackend &){ return true; };
|
||||
responseTransmittedHookType _responseTransmittedHook = [](bool, const String &, const uint8_t *, uint32_t, EspnowMeshBackend &){ return true; };
|
||||
|
||||
uint8_t _broadcastTransmissionRedundancy = 1;
|
||||
};
|
||||
|
@ -272,6 +272,9 @@ void FloodingMesh::setMetadataDelimiter(const char metadataDelimiter)
|
||||
assert(metadataDelimiter < '0' || '9' < metadataDelimiter);
|
||||
assert(metadataDelimiter < 'A' || 'F' < metadataDelimiter);
|
||||
assert(metadataDelimiter < 'a' || 'f' < metadataDelimiter);
|
||||
|
||||
// Reserved for encryptedBroadcast for now
|
||||
assert(metadataDelimiter != ',');
|
||||
|
||||
_metadataDelimiter = metadataDelimiter;
|
||||
}
|
||||
@ -370,8 +373,8 @@ void FloodingMesh::restoreDefaultTransmissionOutcomesUpdateHook()
|
||||
|
||||
void FloodingMesh::restoreDefaultResponseTransmittedHook()
|
||||
{
|
||||
getEspnowMeshBackend().setResponseTransmittedHook([this](const String &response, const uint8_t *recipientMac, uint32_t responseIndex, EspnowMeshBackend &meshInstance)
|
||||
{ return _defaultResponseTransmittedHook(response, recipientMac, responseIndex, meshInstance); });
|
||||
getEspnowMeshBackend().setResponseTransmittedHook([this](bool transmissionSuccessful, const String &response, const uint8_t *recipientMac, uint32_t responseIndex, EspnowMeshBackend &meshInstance)
|
||||
{ return _defaultResponseTransmittedHook(transmissionSuccessful, response, recipientMac, responseIndex, meshInstance); });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -543,21 +546,23 @@ bool FloodingMesh::_defaultTransmissionOutcomesUpdateHook(MeshBackendBase &meshI
|
||||
|
||||
/**
|
||||
* Once passed to the setResponseTransmittedHook method of the ESP-NOW backend,
|
||||
* this function will be called after each successful ESP-NOW response transmission, just before the response is removed from the waiting list.
|
||||
* If a particular response is not sent, there will be no function call for it.
|
||||
* this function will be called after each attempted ESP-NOW response transmission.
|
||||
* In case of a successful response transmission, this happens just before the response is removed from the waiting list.
|
||||
* Only the hook of the EspnowMeshBackend instance that is getEspnowRequestManager() will be called.
|
||||
*
|
||||
* @param transmissionSuccessful True if the response was transmitted successfully. False otherwise.
|
||||
* @param response The sent response.
|
||||
* @param recipientMac The MAC address the response was sent to.
|
||||
* @param responseIndex The index of the response in the waiting list.
|
||||
* @param meshInstance The EspnowMeshBackend instance that called the function.
|
||||
*
|
||||
* @return True if the response transmission process should continue with the next response in the waiting list.
|
||||
* False if the response transmission process should stop after removing the just sent response from the waiting list.
|
||||
* False if the response transmission process should stop after processing of the just sent response is complete.
|
||||
*/
|
||||
bool FloodingMesh::_defaultResponseTransmittedHook(const String &response, const uint8_t *recipientMac, const uint32_t responseIndex, EspnowMeshBackend &meshInstance)
|
||||
bool FloodingMesh::_defaultResponseTransmittedHook(bool transmissionSuccessful, const String &response, const uint8_t *recipientMac, const uint32_t responseIndex, EspnowMeshBackend &meshInstance)
|
||||
{
|
||||
(void)response; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)transmissionSuccessful; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)response;
|
||||
(void)recipientMac;
|
||||
(void)responseIndex;
|
||||
(void)meshInstance;
|
||||
|
@ -41,14 +41,11 @@
|
||||
void floodingMeshDelay(const uint32_t durationMs);
|
||||
|
||||
class FloodingMesh {
|
||||
|
||||
protected:
|
||||
|
||||
using messageHandlerType = std::function<bool(String &, FloodingMesh &)>;
|
||||
using messageQueueElementType = std::map<uint64_t, uint8_t>::iterator;
|
||||
|
||||
public:
|
||||
|
||||
using messageHandlerType = std::function<bool(String &, FloodingMesh &)>;
|
||||
|
||||
/**
|
||||
* FloodingMesh constructor method. Creates a FloodingMesh node, ready to be initialised.
|
||||
*
|
||||
@ -160,6 +157,8 @@ public:
|
||||
/**
|
||||
* Make an unencrypted broadcast to the entire mesh network.
|
||||
*
|
||||
* activateAP() must have been called for nodes to be able to receive broadcasts. Nodes can however send broadcasts even if their AP is off.
|
||||
*
|
||||
* It is recommended that there is at most one new message transmitted in the mesh every 10, 20, 30 ms for messages up to length maxUnencryptedMessageLength()*n,
|
||||
* where n is (roughly, depending on mesh name length) 1/4, 3/5 and 1 respectively. If transmissions are more frequent than this, message loss will increase.
|
||||
*
|
||||
@ -179,6 +178,8 @@ public:
|
||||
/**
|
||||
* Make an encrypted broadcast to the entire mesh network.
|
||||
*
|
||||
* activateAP() must have been called for encryptedBroadcast to work.
|
||||
*
|
||||
* ########## WARNING! This an experimental feature. API may change at any time. Only use if you like it when things break. ##########
|
||||
* Will be very slow compared to unencrypted broadcasts. Probably works OK in a small mesh with a maximum of 2-3 new messages transmitted in the mesh every second.
|
||||
* Because of the throughput difference, mixing encypted and unencrypted broadcasts is not recommended if there are frequent mesh broadcasts (multiple per second),
|
||||
@ -285,6 +286,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
using messageQueueElementType = std::map<uint64_t, uint8_t>::iterator;
|
||||
|
||||
static std::set<FloodingMesh *> availableFloodingMeshes;
|
||||
|
||||
String generateMessageID();
|
||||
@ -323,7 +326,7 @@ private:
|
||||
void _defaultNetworkFilter(const int numberOfNetworks, MeshBackendBase &meshInstance);
|
||||
bool _defaultBroadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance);
|
||||
bool _defaultTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance);
|
||||
bool _defaultResponseTransmittedHook(const String &response, const uint8_t *recipientMac, const uint32_t responseIndex, EspnowMeshBackend &meshInstance);
|
||||
bool _defaultResponseTransmittedHook(bool transmissionSuccessful, const String &response, const uint8_t *recipientMac, const uint32_t responseIndex, EspnowMeshBackend &meshInstance);
|
||||
|
||||
uint8_t _originMac[6] = {0};
|
||||
|
||||
|
@ -32,15 +32,13 @@ enum class MeshBackendType
|
||||
|
||||
class MeshBackendBase {
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
using requestHandlerType = std::function<String(const String &, MeshBackendBase &)> ;
|
||||
using responseHandlerType = std::function<TransmissionStatusType(const String &, MeshBackendBase &)>;
|
||||
using networkFilterType = std::function<void(int, MeshBackendBase &)>;
|
||||
using transmissionOutcomesUpdateHookType = std::function<bool(MeshBackendBase &)>;
|
||||
|
||||
public:
|
||||
|
||||
MeshBackendBase(const requestHandlerType requestHandler, const responseHandlerType responseHandler, const networkFilterType networkFilter, const MeshBackendType classType);
|
||||
|
||||
virtual ~MeshBackendBase();
|
||||
|
@ -280,7 +280,7 @@ TransmissionStatusType TcpIpMeshBackend::exchangeInfo(WiFiClient &currClient)
|
||||
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.
|
||||
// We cannot send data to the AP in STA_AP mode though, that requires STA mode.
|
||||
// We cannot send data to the AP in AP_STA mode though, that requires STA mode.
|
||||
// Switching to STA mode will disconnect all stations connected to the node AP (though they can request a reconnect even while we are in STA mode).
|
||||
WiFiMode_t storedWiFiMode = WiFi.getMode();
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
Reference in New Issue
Block a user