1+ /*
2+ ESP8266WiFiMesh.cpp - Mesh network node
3+ Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
4+ is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
5+
6+ Copyright (c) 2015 Julian Fell. All rights reserved.
7+
8+ This library is free software; you can redistribute it and/or
9+ modify it under the terms of the GNU Lesser General Public
10+ License as published by the Free Software Foundation; either
11+ version 2.1 of the License, or (at your option) any later version.
12+ This library is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ Lesser General Public License for more details.
16+ You should have received a copy of the GNU Lesser General Public
17+ License along with this library; if not, write to the Free Software
18+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+ #include < Arduino.h>
22+ #include < ESP8266WiFi.h>
23+ #include < WiFiClient.h>
24+ #include < WiFiServer.h>
25+
26+ #include " ESP8266WiFiMesh.h"
27+
28+ #define SSID_PREFIX " Mesh_Node"
29+ #define SERVER_IP_ADDR " 192.168.4.1"
30+ #define SERVER_PORT 4011
31+
32+ ESP8266WiFiMesh::ESP8266WiFiMesh (uint32_t chip_id, std::function<String(String)> handler)
33+ : _server(SERVER_PORT)
34+ {
35+ _chip_id = chip_id;
36+ _ssid = String ( String ( SSID_PREFIX ) + String ( _chip_id ) );
37+ _ssid_prefix = String ( SSID_PREFIX );
38+ _handler = handler;
39+ }
40+
41+ void ESP8266WiFiMesh::begin ()
42+ {
43+ WiFi.mode (WIFI_AP_STA);
44+ WiFi.softAP ( _ssid.c_str () );
45+ _server.begin ();
46+ }
47+
48+ /* *
49+ * Wait for a WiFiClient to connect
50+ *
51+ * @returns: True if the client is ready, false otherwise.
52+ *
53+ */
54+ bool ESP8266WiFiMesh::waitForClient (WiFiClient curr_client, int max_wait)
55+ {
56+ int wait = max_wait;
57+ while (curr_client.connected () && !curr_client.available () && wait--)
58+ delay (3 );
59+
60+ /* Return false if the client isn't ready to communicate */
61+ if (WiFi.status () == WL_DISCONNECTED || !curr_client.connected ())
62+ return false ;
63+
64+ return true ;
65+ }
66+
67+ /* *
68+ * Send the supplied message then read back the other node's response
69+ * and pass that to the user-supplied handler.
70+ *
71+ * @target_ssid The name of the AP the other node has set up.
72+ * @message The string to send to the node.
73+ * @returns: True if the exchange was a succes, false otherwise.
74+ *
75+ */
76+ bool ESP8266WiFiMesh::exchangeInfo (String message, WiFiClient curr_client)
77+ {
78+ curr_client.println ( message.c_str () );
79+
80+ if (!waitForClient (curr_client, 1000 ))
81+ return false ;
82+
83+ String response = curr_client.readStringUntil (' \r ' );
84+ curr_client.readStringUntil (' \n ' );
85+
86+ if (response.length () <= 2 )
87+ return false ;
88+
89+ /* Pass data to user callback */
90+ _handler (response);
91+ return true ;
92+ }
93+
94+ /* *
95+ * Connect to the AP at ssid, send them a message then disconnect.
96+ *
97+ * @target_ssid The name of the AP the other node has set up.
98+ * @message The string to send to the node.
99+ *
100+ */
101+ void WiFiMesh::connectToNode (String target_ssid, String message)
102+ {
103+ WiFiClient curr_client;
104+ WiFi.begin ( target_ssid.c_str () );
105+
106+ int wait = 1500 ;
107+ while ((WiFi.status () == WL_DISCONNECTED) && wait--)
108+ delay (3 );
109+
110+ /* If the connection timed out */
111+ if (WiFi.status () != 3 )
112+ return ;
113+
114+ /* Connect to the node's server */
115+ if (!curr_client.connect (SERVER_IP_ADDR, SERVER_PORT))
116+ return ;
117+
118+ if (!exchangeInfo (message, curr_client))
119+ return ;
120+
121+ curr_client.stop ();
122+ WiFi.disconnect ();
123+ }
124+
125+ void ESP8266WiFiMesh::attemptScan (String message)
126+ {
127+ /* Scan for APs */
128+ int n = WiFi.scanNetworks ();
129+
130+ for (int i = 0 ; i < n; ++i) {
131+ String current_ssid = WiFi.SSID (i);
132+ int index = current_ssid.indexOf ( _ssid_prefix );
133+ uint32_t target_chip_id = (current_ssid.substring (index + _ssid_prefix.length ())).toInt ();
134+
135+ /* Connect to any _suitable_ APs which contain _ssid_prefix */
136+ if (index >= 0 && (target_chip_id < _chip_id)) {
137+
138+ WiFi.mode (WIFI_STA);
139+ delay (100 );
140+ connectToNode (current_ssid, message);
141+ WiFi.mode (WIFI_AP_STA);
142+ delay (100 );
143+ }
144+ }
145+ }
146+
147+ void ESP8266WiFiMesh::acceptRequest ()
148+ {
149+ while (true ) {
150+ _client = _server.available ();
151+ if (!_client)
152+ break ;
153+
154+ if (!waitForClient (_client, 1500 )) {
155+ continue ;
156+ }
157+
158+ /* Read in request and pass it to the supplied handler */
159+ String request = _client.readStringUntil (' \r ' );
160+ _client.readStringUntil (' \n ' );
161+
162+ String response = _handler (request);
163+
164+ /* Send the response back to the client */
165+ if (_client.connected ())
166+ _client.println (response);
167+ }
168+ }
0 commit comments