diff --git a/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino b/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino new file mode 100644 index 000000000..0423c20cf --- /dev/null +++ b/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino @@ -0,0 +1,44 @@ +#include +#include + +/* Create the mesh node object */ +ESP8266WiFiMesh mesh_node = ESP8266WiFiMesh(ESP.getChipId(), manageRequest); + +/** + * Callback for when other nodes send you data + * + * @request The string received from another node in the mesh + * @returns The string to send back to the other node + */ +String manageRequest(String request) +{ + /* Print out received message */ + Serial.print("received: "); + Serial.println(request); + + /* return a string to send back */ + return String("Hello world response."); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.println(); + Serial.println(); + Serial.println("Setting up mesh node..."); + + /* Initialise the mesh node */ + mesh_node.begin(); +} + +void loop() +{ + /* Accept any incoming connections */ + mesh_node.acceptRequest(); + + /* Scan for other nodes and send them a message */ + mesh_node.attemptScan("Hello world request."); + delay(1000); +} diff --git a/libraries/ESP8266WiFiMesh/keywords.txt b/libraries/ESP8266WiFiMesh/keywords.txt new file mode 100644 index 000000000..14657d805 --- /dev/null +++ b/libraries/ESP8266WiFiMesh/keywords.txt @@ -0,0 +1,23 @@ +####################################### +# Syntax Coloring Map For ESP8266WiFiMesh +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +ESP8266WiFiMesh KEYWORD3 + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ESP8266WiFiMesh KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +attemptScan KEYWORD2 +acceptRequest KEYWORD2 diff --git a/libraries/ESP8266WiFiMesh/library.properties b/libraries/ESP8266WiFiMesh/library.properties new file mode 100644 index 000000000..dc6ba9a4d --- /dev/null +++ b/libraries/ESP8266WiFiMesh/library.properties @@ -0,0 +1,9 @@ +name=ESP8266WiFiMesh +version=1.0 +author=Julian Fell +maintainer= +sentence=Mesh network library +paragraph=The library sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. +category=Communication +url= +architectures=esp8266 diff --git a/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp new file mode 100644 index 000000000..97ec0954b --- /dev/null +++ b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp @@ -0,0 +1,168 @@ +/* + ESP8266WiFiMesh.cpp - 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. + + Copyright (c) 2015 Julian Fell. All rights reserved. + + 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 +*/ + +#include +#include +#include +#include + +#include "ESP8266WiFiMesh.h" + +#define SSID_PREFIX "Mesh_Node" +#define SERVER_IP_ADDR "192.168.4.1" +#define SERVER_PORT 4011 + +ESP8266WiFiMesh::ESP8266WiFiMesh(uint32_t chip_id, std::function handler) +: _server(SERVER_PORT) +{ + _chip_id = chip_id; + _ssid = String( String( SSID_PREFIX ) + String( _chip_id ) ); + _ssid_prefix = String( SSID_PREFIX ); + _handler = handler; +} + +void ESP8266WiFiMesh::begin() +{ + WiFi.mode(WIFI_AP_STA); + WiFi.softAP( _ssid.c_str() ); + _server.begin(); +} + +/** + * Wait for a WiFiClient to connect + * + * @returns: True if the client is ready, false otherwise. + * + */ +bool ESP8266WiFiMesh::waitForClient(WiFiClient curr_client, int max_wait) +{ + int wait = max_wait; + while(curr_client.connected() && !curr_client.available() && wait--) + delay(3); + + /* Return false if the client isn't ready to communicate */ + if (WiFi.status() == WL_DISCONNECTED || !curr_client.connected()) + return false; + + return true; +} + +/** + * Send the supplied message then read back the other node's response + * and pass that to the user-supplied handler. + * + * @target_ssid The name of the AP the other node has set up. + * @message The string to send to the node. + * @returns: True if the exchange was a succes, false otherwise. + * + */ +bool ESP8266WiFiMesh::exchangeInfo(String message, WiFiClient curr_client) +{ + curr_client.println( message.c_str() ); + + if (!waitForClient(curr_client, 1000)) + return false; + + String response = curr_client.readStringUntil('\r'); + curr_client.readStringUntil('\n'); + + if (response.length() <= 2) + return false; + + /* Pass data to user callback */ + _handler(response); + return true; +} + +/** + * Connect to the AP at ssid, send them a message then disconnect. + * + * @target_ssid The name of the AP the other node has set up. + * @message The string to send to the node. + * + */ +void WiFiMesh::connectToNode(String target_ssid, String message) +{ + WiFiClient curr_client; + WiFi.begin( target_ssid.c_str() ); + + int wait = 1500; + while((WiFi.status() == WL_DISCONNECTED) && wait--) + delay(3); + + /* If the connection timed out */ + if (WiFi.status() != 3) + return; + + /* Connect to the node's server */ + if (!curr_client.connect(SERVER_IP_ADDR, SERVER_PORT)) + return; + + if (!exchangeInfo(message, curr_client)) + return; + + curr_client.stop(); + WiFi.disconnect(); +} + +void ESP8266WiFiMesh::attemptScan(String message) +{ + /* Scan for APs */ + int n = WiFi.scanNetworks(); + + for (int i = 0; i < n; ++i) { + String current_ssid = WiFi.SSID(i); + int index = current_ssid.indexOf( _ssid_prefix ); + uint32_t target_chip_id = (current_ssid.substring(index + _ssid_prefix.length())).toInt(); + + /* Connect to any _suitable_ APs which contain _ssid_prefix */ + if (index >= 0 && (target_chip_id < _chip_id)) { + + WiFi.mode(WIFI_STA); + delay(100); + connectToNode(current_ssid, message); + WiFi.mode(WIFI_AP_STA); + delay(100); + } + } +} + +void ESP8266WiFiMesh::acceptRequest() +{ + while (true) { + _client = _server.available(); + if (!_client) + break; + + if (!waitForClient(_client, 1500)) { + continue; + } + + /* Read in request and pass it to the supplied handler */ + String request = _client.readStringUntil('\r'); + _client.readStringUntil('\n'); + + String response = _handler(request); + + /* Send the response back to the client */ + if (_client.connected()) + _client.println(response); + } +} \ No newline at end of file diff --git a/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h new file mode 100644 index 000000000..dd959731b --- /dev/null +++ b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h @@ -0,0 +1,75 @@ +/* + 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. + + Copyright (c) 2015 Julian Fell. All rights reserved. + + 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 +#include +#include + +class ESP8266WiFiMesh { + +private: + String _ssid; + String _ssid_prefix; + uint32_t _chip_id; + + std::function _handler; + + WiFiServer _server; + WiFiClient _client; + + void connectToNode(String target_ssid, String message); + bool exchangeInfo(String message, WiFiClient curr_client); + bool waitForClient(WiFiClient curr_client, int max_wait); + +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 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(String message); + + /** + * If any clients are connected, accept their requests and call the hander function for each one. + */ + void acceptRequest(); +}; + +#endif