mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
375 lines
18 KiB
C++
375 lines
18 KiB
C++
/*
|
|
ESP8266WiFiMesh.h - Mesh network node
|
|
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
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef __WIFIMESH_H__
|
|
#define __WIFIMESH_H__
|
|
|
|
#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 _meshName;
|
|
String _nodeID;
|
|
uint16_t _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;
|
|
bool _scanHidden = false;
|
|
bool _apHidden = false;
|
|
uint8_t _maxAPStations = 4;
|
|
int32_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.
|
|
uint32_t _apModeTimeoutMs = 4500;
|
|
|
|
static String lastSSID;
|
|
static bool staticIPActivated;
|
|
static IPAddress staticIP;
|
|
static IPAddress gateway;
|
|
static IPAddress subnetMask;
|
|
static ESP8266WiFiMesh *apController;
|
|
|
|
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, uint32_t 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:
|
|
|
|
////////////////////////////<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);
|
|
|
|
/**
|
|
* 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////////////////////////////
|
|
|
|
~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, uint16_t 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;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/**
|
|
* @returns True if latest transmission was successful (i.e. latestTransmissionOutcomes is not empty and all entries have transmissionStatus TS_TRANSMISSION_COMPLETE). False otherwise.
|
|
*/
|
|
static bool latestTransmissionSuccessful();
|
|
|
|
/**
|
|
* 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();
|
|
|
|
/**
|
|
* Change the WiFi channel used by this ESP8266WiFiMesh instance.
|
|
* Will also change the WiFi channel for the active AP if this ESP8266WiFiMesh 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.
|
|
* 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);
|
|
uint8 getWiFiChannel();
|
|
|
|
/**
|
|
* Change the mesh name used by this ESP8266WiFiMesh instance.
|
|
* Will also change the mesh name (SSID prefix) for the active AP if this ESP8266WiFiMesh instance is the current AP controller.
|
|
*
|
|
* @param newMeshName The mesh name to change to.
|
|
*/
|
|
void setMeshName(const String &newMeshName);
|
|
String getMeshName();
|
|
|
|
/**
|
|
* Change the node id used by this ESP8266WiFiMesh instance.
|
|
* Will also change the node id (SSID suffix) for the active AP if this ESP8266WiFiMesh instance is the current AP controller.
|
|
*
|
|
* @param newNodeID The node id to change to.
|
|
*/
|
|
void setNodeID(const String &newNodeID);
|
|
String getNodeID();
|
|
|
|
/**
|
|
* Change the SSID (mesh name + node id) used by this ESP8266WiFiMesh instance.
|
|
* Will also change the SSID for the active AP 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 getSSID();
|
|
|
|
/**
|
|
* Set the message that will be sent to other nodes when calling attemptTransmission.
|
|
*
|
|
* @param newMessage The message to send.
|
|
*/
|
|
void setMessage(const String &newMessage);
|
|
String getMessage();
|
|
|
|
/**
|
|
* 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;
|
|
|
|
void setRequestHandler(requestHandlerType requestHandler);
|
|
requestHandlerType getRequestHandler();
|
|
|
|
void setResponseHandler(responseHandlerType responseHandler);
|
|
responseHandlerType getResponseHandler();
|
|
|
|
void setNetworkFilter(networkFilterType networkFilter);
|
|
networkFilterType getNetworkFilter();
|
|
|
|
/**
|
|
* Set whether scan results from this ESP8266WiFiMesh instance will include WiFi networks with hidden SSIDs.
|
|
* This is false by default.
|
|
* The SSID field of a found hidden network will be blank in the scan results.
|
|
* WiFi.isHidden(networkIndex) can be used to verify that a found network is hidden.
|
|
*
|
|
* @param scanHidden If true, WiFi networks with hidden SSIDs will be included in scan results.
|
|
*/
|
|
void setScanHidden(bool scanHidden);
|
|
bool getScanHidden();
|
|
|
|
/**
|
|
* Set whether the AP controlled by this ESP8266WiFiMesh instance will have a WiFi network with hidden SSID.
|
|
* This is false by default.
|
|
* Will also change the setting for the active AP if this ESP8266WiFiMesh instance is the current AP controller.
|
|
*
|
|
* @param apHidden If true, the WiFi network created will have a hidden SSID.
|
|
*/
|
|
void setAPHidden(bool apHidden);
|
|
bool getAPHidden();
|
|
|
|
/**
|
|
* Set the maximum number of stations that can simultaneously be connected to the AP controlled by this ESP8266WiFiMesh instance.
|
|
* This number is 4 by default.
|
|
* Once the max number has been reached, any other station that wants to connect will be forced to wait until an already connected station disconnects.
|
|
* The more stations that are connected, the more memory is required.
|
|
* Will also change the setting for the active AP if this ESP8266WiFiMesh instance is the current AP controller.
|
|
*
|
|
* @param maxAPStations The maximum number of simultaneous station connections allowed. Valid values are 0 to 8.
|
|
*/
|
|
void setMaxAPStations(uint8_t maxAPStations);
|
|
bool getMaxAPStations();
|
|
|
|
/**
|
|
* Set the timeout for each attempt to connect to another AP that occurs through the attemptTransmission method by this ESP8266WiFiMesh instance.
|
|
* The timeout is 10 000 ms by default.
|
|
*
|
|
* @param connectionAttemptTimeoutMs The timeout for each connection attempt, in milliseconds.
|
|
*/
|
|
void setConnectionAttemptTimeout(int32_t connectionAttemptTimeoutMs);
|
|
int32_t getConnectionAttemptTimeout();
|
|
|
|
/**
|
|
* Set the timeout to use for transmissions when this ESP8266WiFiMesh instance acts as a station (i.e. when connected to another AP).
|
|
* This will affect the timeout of the attemptTransmission method once a connection to an AP has been established.
|
|
* The timeout is 5 000 ms by default.
|
|
*
|
|
* @param stationModeTimeoutMs The timeout to use, in milliseconds.
|
|
*/
|
|
void setStationModeTimeout(int stationModeTimeoutMs);
|
|
int getStationModeTimeout();
|
|
|
|
/**
|
|
* Set the timeout to use for transmissions when this ESP8266WiFiMesh instance acts as an AP (i.e. when receiving connections from other stations).
|
|
* This will affect the timeout of the acceptRequest method.
|
|
* The timeout is 4 500 ms by default.
|
|
* Will also change the setting for the active AP if this ESP8266WiFiMesh instance is the current AP controller.
|
|
*
|
|
* @param apModeTimeoutMs The timeout to use, in milliseconds.
|
|
*/
|
|
void setAPModeTimeout(uint32_t apModeTimeoutMs);
|
|
uint32_t getAPModeTimeout();
|
|
};
|
|
|
|
#endif
|