mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-23 19:21:59 +03:00
Update of mesh network library. (#4718)
* Make mesh network actually usable. Make mesh network use static IP during initial connection to speed up connection time. Add separate handlers for requests and responses. Add network password. Provide more detailed code example. Add optional verbose mode. Improve comments. Add readme file. * Fix compiler warnings. Fix code style of HelloMesh.ino to avoid upsetting Travis. * Remove stray spaces. * Make mesh network WiFi password settable via the ESP8266WiFiMesh constructor. Make use of static IP optional by moving static IP initialization code to setStaticIP method. Increase scanning interval from one to two seconds in the HelloMesh.ino example to increase chances of successful connections. Update comments. Update README.rst. * Increase specificity in the conditions of the waitForClientTransmission method (renamed from waitForClient) to avoid issues related to #4626 , #4728 and #4754 in the future. * Improve most parts of the library to achieve better performance and greatly increase flexibility. Changes: * Make WiFi-connection related variables static to allow for the use of multiple ESP8266WiFiMesh instances on a single node (useful e.g. when communicating with several different mesh networks). * Make it possible to choose AP port, which is helpful when using multiple ESP8266WiFiMesh AP:s on a single node. * Add user-customizable network filter. * Make activation of own AP optional for each mesh node. * Add ways to change mesh network name and node id for existing ESP8266WiFiMesh instances. * Add verboseModePrint method to clean up the code. * Add reactivation of static IP after successful data transfers to speed up re-connection attempts. * Add empty_IP constant which can be used to check if static IP is disabled for a ESP8266WiFiMesh instance. * Remove the WiFiClient _client class variable in ESP8266WiFiMesh since there is no need to save _client in the class instance. * Add transmission status as a return value from attemptTransmission. * Pass calling ESP8266WiFiMesh instance pointer to callback functions to allow for greater range of actions in callbacks. * Make transmission message a class variable to allow it to be stored in the class and accessed from callbacks. * Add getters for mesh name and node id to ESP8266WiFiMesh. * Add getter and setter for networkFilter to ESP8266WiFiMesh. * Increase range of available node_id:s by changing the type to String and adding functions to convert between String and uint64_t using a customizable radix between 2 and 36. * Make it possible to connect to several nodes during each attemptTransmission call. * Add static connection_queue and latest_transmission_outcomes vectors to the ESP8266WiFiMesh class, a NetworkInfo class and a TransmissionResult class to aid in bookkeeping when connecting to several AP:s during one attemptTransmission call. * Make wifi_channel and BSSID optional when connecting to an AP (though excluding them will slow down the connection process). * Add optional scan and static ip optimizations available in Arduino core for ESP8266 version 2.4.2. * Add functions to check lwIP version in order to enable WiFi optimizations only available with lwIP2. * Add concluding_disconnect, initial_disconnect and no_scan options to the attemptTransmission method. * Update documentation. * Improve README.rst formatting. * Further improve README.rst. * Even further improve README.rst. * Make source code comments Doxygen compatible. Improve README file and change its file format to .md. * Add temporary compatibility layer to ensure backwards compatibility with the old mesh network library API until the next major core release (2.5.0). * Polish documentation slightly. * Add scan_all_wifi_channels option to attemptTransmission method. * - Add getter and setter for the WiFi channel of a ESP8266WiFiMesh instance. - Separate methods for changing mesh name and node id from AP control methods. - Add methods getAPController and isAPController to better handle situations when multiple ESP8266WiFiMesh instances take turns to be in control of the AP. - Create separate UtilityMethods.cpp file for utility methods. - Improve code efficiency and robustness, e.g. by passing arguments by reference instead of by value for non-POD types and employing typedefs. - Update README.md. * Make the code more stylish. * Update README.md with the new ESP8266WiFiMesh constructor documentation. * Make attemptScan method in CompatibilityLayer use reference as argument. * Make it possible to use const String as argument to attemptScan. * - Make code use camelCase instead of snake_case. - Improve documentation. * Rename Uint64ToString to uint64ToString and StringToUint64 to stringToUint64, since they are methods.
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
/*
|
||||
ESP8266WiFiMesh.h - Mesh network node
|
||||
Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
|
||||
is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
|
||||
Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes.
|
||||
|
||||
Copyright (c) 2015 Julian Fell. All rights reserved.
|
||||
Updated 2018 by Anders Löfgren.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -24,52 +24,278 @@
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiServer.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include "NetworkInfo.h"
|
||||
#include "TransmissionResult.h"
|
||||
|
||||
#define ENABLE_STATIC_IP_OPTIMIZATION // Requires Arduino core for ESP8266 version 2.4.2 or higher and lwIP2 (lwIP can be changed in "Tools" menu of Arduino IDE).
|
||||
#define ENABLE_WIFI_SCAN_OPTIMIZATION // Requires Arduino core for ESP8266 version 2.4.2 or higher. Scan time should go from about 2100 ms to around 60 ms if channel 1 (standard) is used.
|
||||
|
||||
const String WIFI_MESH_EMPTY_STRING = "";
|
||||
|
||||
class ESP8266WiFiMesh {
|
||||
|
||||
private:
|
||||
String _ssid;
|
||||
String _ssid_prefix;
|
||||
uint32_t _chip_id;
|
||||
String _SSID;
|
||||
String _meshName;
|
||||
String _nodeID;
|
||||
int _serverPort;
|
||||
String _meshPassword;
|
||||
uint8 _meshWiFiChannel;
|
||||
bool _verboseMode;
|
||||
WiFiServer _server;
|
||||
uint32_t _lwipVersion[3];
|
||||
static const uint32_t lwipVersion203Signature[3];
|
||||
String _message = WIFI_MESH_EMPTY_STRING;
|
||||
|
||||
std::function<String(String)> _handler;
|
||||
|
||||
WiFiServer _server;
|
||||
WiFiClient _client;
|
||||
static String lastSSID;
|
||||
static bool staticIPActivated;
|
||||
static IPAddress staticIP;
|
||||
static IPAddress gateway;
|
||||
static IPAddress subnetMask;
|
||||
static ESP8266WiFiMesh *apController;
|
||||
|
||||
void connectToNode(String target_ssid, String message);
|
||||
bool exchangeInfo(String message, WiFiClient curr_client);
|
||||
bool waitForClient(WiFiClient curr_client, int max_wait);
|
||||
typedef std::function<String(const String &, ESP8266WiFiMesh &)> requestHandlerType;
|
||||
typedef std::function<transmission_status_t(const String &, ESP8266WiFiMesh &)> responseHandlerType;
|
||||
typedef std::function<void(int, ESP8266WiFiMesh &)> networkFilterType;
|
||||
|
||||
requestHandlerType _requestHandler;
|
||||
responseHandlerType _responseHandler;
|
||||
networkFilterType _networkFilter;
|
||||
|
||||
void updateNetworkNames(const String &newMeshName = WIFI_MESH_EMPTY_STRING, const String &newNodeID = WIFI_MESH_EMPTY_STRING);
|
||||
void verboseModePrint(const String &stringToPrint, bool newline = true);
|
||||
void fullStop(WiFiClient &currClient);
|
||||
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);
|
||||
transmission_status_t exchangeInfo(WiFiClient &currClient);
|
||||
bool waitForClientTransmission(WiFiClient &currClient, int maxWait);
|
||||
transmission_status_t attemptDataTransfer();
|
||||
transmission_status_t attemptDataTransferKernel();
|
||||
void storeLwipVersion();
|
||||
bool atLeastLwipVersion(const uint32_t minLwipVersion[3]);
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////<DEPRECATED> TODO: REMOVE IN 2.5.0////////////////////////////
|
||||
|
||||
typedef std::function<String(String)> compatibilityLayerHandlerType;
|
||||
|
||||
String _ssidPrefix;
|
||||
uint32_t _chipID;
|
||||
|
||||
compatibilityLayerHandlerType _handler = NULL;
|
||||
|
||||
WiFiClient _client;
|
||||
|
||||
void connectToNode(const String &targetSSID, const char *message);
|
||||
bool exchangeInfo(const char *message, WiFiClient &currClient);
|
||||
bool waitForClient(WiFiClient &currClient, int maxWait);
|
||||
void attemptScanKernel(const char *message);
|
||||
|
||||
////////////////////////////</DEPRECATED> TODO: REMOVE IN 2.5.0////////////////////////////
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised.
|
||||
*
|
||||
* @chip_id A unique identifier number for the node.
|
||||
* @handler The callback handler for dealing with received messages. Takes a string as an argument which
|
||||
* is the string received from another node and returns the string to send back.
|
||||
*
|
||||
*/
|
||||
ESP8266WiFiMesh(uint32_t chip_id, std::function<String(String)> handler);
|
||||
////////////////////////////<DEPRECATED> TODO: REMOVE IN 2.5.0////////////////////////////
|
||||
|
||||
/**
|
||||
* WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised.
|
||||
*
|
||||
* @chipID A unique identifier number for the node.
|
||||
* @handler The callback handler for dealing with received messages. Takes a string as an argument which
|
||||
* is the string received from another node and returns the string to send back.
|
||||
*
|
||||
*/
|
||||
ESP8266WiFiMesh(uint32_t chipID, compatibilityLayerHandlerType handler);
|
||||
|
||||
/**
|
||||
* Initialises the node.
|
||||
*/
|
||||
void begin();
|
||||
/**
|
||||
* Scan for other nodes, and exchange the chosen message with any that are found.
|
||||
*
|
||||
* @message The message to send to all other nodes.
|
||||
*
|
||||
*/
|
||||
void attemptScan(const String &message);
|
||||
void attemptScan(char *message);
|
||||
|
||||
template<size_t Size>
|
||||
void attemptScan(char (&message)[Size]);
|
||||
|
||||
////////////////////////////</DEPRECATED> TODO: REMOVE IN 2.5.0////////////////////////////
|
||||
|
||||
/**
|
||||
* Scan for other nodes, and exchange the chosen message with any that are found.
|
||||
*
|
||||
* @message The message to send to all other nodes.
|
||||
*
|
||||
*/
|
||||
void attemptScan(String message);
|
||||
~ESP8266WiFiMesh();
|
||||
|
||||
/**
|
||||
* WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised.
|
||||
*
|
||||
* @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.
|
||||
* @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.
|
||||
* @param networkFilter The callback handler for deciding which WiFi networks to connect to.
|
||||
* @param meshPassword The WiFi password for the mesh network.
|
||||
* @param meshName The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example network filter function.
|
||||
* @param nodeID The id for this mesh node. Used as suffix for the node SSID. If set to "", the id will default to ESP.getChipId().
|
||||
* @param verboseMode Determines if we should print the events occurring in the library to Serial. Off by default.
|
||||
* @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.
|
||||
* This can cause problems if several ESP8266WiFiMesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||
* In such a case, whenever the station of one ESP8266WiFiMesh 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
|
||||
* make it impossible for other stations to detect the APs whose WiFi channels have changed.
|
||||
* @param serverPort The server port used by the AP of the ESP8266WiFiMesh instance. If multiple APs exist on a single ESP8266, each requires a separate server port.
|
||||
* If two AP:s on the same ESP8266 are using the same server port, they will not be able to have both server instances active at the same time.
|
||||
* This is managed automatically by the activateAP method.
|
||||
*
|
||||
*/
|
||||
ESP8266WiFiMesh(requestHandlerType requestHandler, responseHandlerType responseHandler, networkFilterType networkFilter,
|
||||
const String &meshPassword, const String &meshName = "MeshNode_", const String &nodeID = WIFI_MESH_EMPTY_STRING, bool verboseMode = false,
|
||||
uint8 meshWiFiChannel = 1, int serverPort = 4011);
|
||||
|
||||
/**
|
||||
* A vector that contains the NetworkInfo for each WiFi network to connect to.
|
||||
* The connectionQueue vector is cleared before each new scan and filled via the networkFilter callback function once the scan completes.
|
||||
* WiFi connections will start with connectionQueue[0] and then incrementally proceed to higher vector positions.
|
||||
* Note that old network indicies often are invalidated whenever a new WiFi network scan occurs.
|
||||
*/
|
||||
static std::vector<NetworkInfo> connectionQueue;
|
||||
|
||||
/**
|
||||
* If any clients are connected, accept their requests and call the hander function for each one.
|
||||
*/
|
||||
void acceptRequest();
|
||||
/**
|
||||
* A vector with the TransmissionResult for each AP to which a transmission was attempted during the latest attemptTransmission call.
|
||||
* The latestTransmissionOutcomes vector is cleared before each new transmission attempt.
|
||||
* Connection attempts are indexed in the same order they were attempted.
|
||||
* Note that old network indicies often are invalidated whenever a new WiFi network scan occurs.
|
||||
*/
|
||||
static std::vector<TransmissionResult> latestTransmissionOutcomes;
|
||||
|
||||
/**
|
||||
* Initialises the node.
|
||||
*/
|
||||
void begin();
|
||||
|
||||
/**
|
||||
* Each AP requires a separate server port. If two AP:s are using the same server port, they will not be able to have both server instances active at the same time.
|
||||
* This is managed automatically by the activateAP method.
|
||||
*/
|
||||
void activateAP();
|
||||
void deactivateAP();
|
||||
void restartAP();
|
||||
|
||||
/**
|
||||
* Get the ESP8266WiFiMesh instance currently in control of the ESP8266 AP.
|
||||
* Note that the result will be nullptr when there is no active AP controller.
|
||||
* If another instance takes control over the AP after the pointer is created,
|
||||
* the created pointer will still point to the old AP instance.
|
||||
*
|
||||
* @returns A pointer to the ESP8266WiFiMesh instance currently in control of the ESP8266 AP,
|
||||
* or nullptr if there is no active AP controller.
|
||||
*/
|
||||
static ESP8266WiFiMesh * getAPController();
|
||||
|
||||
/**
|
||||
* Check if this ESP8266WiFiMesh instance is in control of the ESP8266 AP.
|
||||
*
|
||||
* @returns True if this ESP8266WiFiMesh instance is in control of the ESP8266 AP. False otherwise.
|
||||
*/
|
||||
bool isAPController();
|
||||
|
||||
uint8 getWiFiChannel();
|
||||
|
||||
/**
|
||||
* Change the WiFi channel used by this ESP8266WiFiMesh instance.
|
||||
* Will also change the AP WiFi channel if this ESP8266WiFiMesh instance is the current AP controller.
|
||||
*
|
||||
* WARNING: The ESP8266 has only one WiFi channel, and the the station/client mode is always prioritized for channel selection.
|
||||
* This can cause problems if several ESP8266WiFiMesh instances exist on the same ESP8266 and use different WiFi channels.
|
||||
* In such a case, whenever the station of one ESP8266WiFiMesh 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
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
void setWiFiChannel(uint8 newWiFiChannel);
|
||||
|
||||
String getMeshName();
|
||||
|
||||
/**
|
||||
* Change the mesh name used by this ESP8266WiFiMesh instance.
|
||||
* Will also change the AP mesh name (SSID prefix) if this ESP8266WiFiMesh instance is the current AP controller.
|
||||
*
|
||||
* @param newMeshName The mesh name to change to.
|
||||
*/
|
||||
void setMeshName(const String &newMeshName);
|
||||
|
||||
String getNodeID();
|
||||
|
||||
/**
|
||||
* Change the node id used by this ESP8266WiFiMesh instance.
|
||||
* Will also change the AP node id (SSID suffix) if this ESP8266WiFiMesh instance is the current AP controller.
|
||||
*
|
||||
* @param newNodeID The node id to change to.
|
||||
*/
|
||||
void setNodeID(const String &newNodeID);
|
||||
|
||||
/**
|
||||
* Change the SSID (mesh name + node id) used by this ESP8266WiFiMesh instance.
|
||||
* Will also change the AP SSID if this ESP8266WiFiMesh instance is the current AP controller.
|
||||
*
|
||||
* @param newMeshName The mesh name to change to. Will be the SSID prefix.
|
||||
* @param newNodeID The node id to change to. Will be the SSID suffix.
|
||||
*/
|
||||
void setSSID(const String &newMeshName, const String &newNodeID);
|
||||
|
||||
String getMessage();
|
||||
|
||||
/**
|
||||
* Set the message that will be sent to other nodes when calling attemptTransmission.
|
||||
*
|
||||
* @param newMessage The message to send.
|
||||
*/
|
||||
void setMessage(const String &newMessage);
|
||||
|
||||
/**
|
||||
* If AP connection already exists, and the initialDisconnect argument is set to false, send message only to the already connected AP.
|
||||
* Otherwise, scan for other networks, send the scan result to networkFilter and then transmit the message to the networks found in connectionQueue.
|
||||
*
|
||||
* @param message The message to send to other nodes. It will be stored in the class instance until replaced via attemptTransmission or setMessage.
|
||||
* @param concludingDisconnect Disconnect from AP once transmission is complete.
|
||||
* @param initialDisconnect Disconnect from any currently connected AP before attempting transmission.
|
||||
* @param noScan Do not scan for new networks and do not call networkFilter function. Will only use the data already in connectionQueue for the transmission.
|
||||
* @param scanAllWiFiChannels Scan all WiFi channels during a WiFi scan, instead of just the channel the ESP8266WiFiMesh instance is using.
|
||||
* Scanning all WiFi channels takes about 2100 ms, compared to just 60 ms if only channel 1 (standard) is scanned.
|
||||
* Note that if the ESP8266 has an active AP, that AP will switch WiFi channel to match that of any other AP the ESP8266 connects to.
|
||||
* This can make it impossible for other nodes to detect the AP if they are scanning the wrong WiFi channel.
|
||||
*/
|
||||
void attemptTransmission(const String &message, bool concludingDisconnect = true, bool initialDisconnect = false, bool noScan = false, bool scanAllWiFiChannels = false);
|
||||
|
||||
/**
|
||||
* If any clients are connected, accept their requests and call the requestHandler function for each one.
|
||||
*/
|
||||
void acceptRequest();
|
||||
|
||||
/**
|
||||
* Set a static IP address for the ESP8266 and activate use of static IP.
|
||||
* The static IP needs to be at the same subnet as the server's gateway.
|
||||
*/
|
||||
void setStaticIP(const IPAddress &newIP);
|
||||
|
||||
IPAddress getStaticIP();
|
||||
void disableStaticIP();
|
||||
|
||||
/**
|
||||
* An empty IPAddress. Used as default when no IP is set.
|
||||
*/
|
||||
static const IPAddress emptyIP;
|
||||
|
||||
static String uint64ToString(uint64_t number, byte base = 16);
|
||||
static uint64_t stringToUint64(const String &string, byte base = 16);
|
||||
|
||||
networkFilterType getNetworkFilter();
|
||||
void setNetworkFilter(networkFilterType networkFilter);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user