├── Meshish.ino ├── MeshishNode.h ├── MeshishNode.cpp └── README.md /Meshish.ino: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Brannon Dorsey 4 | // with support from the SAIC OpenLab 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #include "ESP8266WiFi.h" 25 | #include "ESP8266WebServer.h" 26 | #include "MeshishNode.h" 27 | 28 | MeshishNode node; 29 | 30 | void setup() { 31 | 32 | Serial.begin(9600); 33 | node.debug(&Serial); 34 | node.setup("", false); 35 | } 36 | 37 | void loop() { 38 | // put your main code here, to run repeatedly: 39 | node.loop(); 40 | // Serial.println(node.getStatus()); 41 | } 42 | -------------------------------------------------------------------------------- /MeshishNode.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Brannon Dorsey 4 | // with support from the SAIC OpenLab 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #ifndef __MESHISH_H__ 25 | #define __MESHISH_H__ 26 | 27 | #define MESHISH_HTTP_PORT 80 28 | #define MESHISH_PRIMARY_IP "192.168.4.1" 29 | #define MESHISH_MAX_AP_SCAN 100 30 | 31 | #include "Arduino.h" 32 | #include "ESP8266WiFi.h" 33 | #include "ESP8266WebServer.h" 34 | 35 | class MeshishNode { 36 | 37 | public: 38 | 39 | struct AccessPoint { 40 | String ssid; 41 | long rssi; 42 | byte encrypt; 43 | unsigned int nodeType; 44 | }; 45 | 46 | enum nodeType{ 47 | NODE_NONE, 48 | NODE_PRIMARY, 49 | NODE_SECONDARY 50 | }; 51 | 52 | MeshishNode(); 53 | ~MeshishNode(); 54 | 55 | void setup(String password, bool primary=false); 56 | void loop(); 57 | void makePrimary(bool primary=true); 58 | void debug(HardwareSerial* serial); 59 | bool isPrimary(); 60 | // bool isConnectedToPrimary(); 61 | // bool enableDefaultRoutes(bool b=true); 62 | unsigned int getStatus(); 63 | 64 | protected: 65 | 66 | void _setSSID(); 67 | void _scanAndConnect(); 68 | bool _generateSSID(); 69 | unsigned int _getNodeType(const AccessPoint& ap); 70 | String _ipToString(const IPAddress& ip); 71 | 72 | byte _encrypt; 73 | bool _isPrimary; 74 | bool _debug; 75 | bool _connectingToAP; // true when STA is connecting to AP 76 | bool _creatingAP; // true when AP is being created 77 | unsigned int _numNetworks; 78 | uint32_t _chipId; 79 | String _ssid; 80 | String _ssidPrefix; 81 | String _password; 82 | 83 | ESP8266WebServer _server; 84 | AccessPoint _apList[MESHISH_MAX_AP_SCAN]; 85 | HardwareSerial* _serial; 86 | }; 87 | 88 | #endif /* __MESHISH_H__ */ 89 | 90 | -------------------------------------------------------------------------------- /MeshishNode.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Brannon Dorsey 4 | // with support from the SAIC OpenLab 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #include "MeshishNode.h" 25 | 26 | MeshishNode::MeshishNode(): 27 | _isPrimary(false), 28 | _numNetworks(0), 29 | _ssidPrefix("M"), 30 | _ssid(""), 31 | _chipId(0), 32 | _serial(NULL), 33 | _debug(false), 34 | _connectingToAP(false), 35 | _creatingAP(false), 36 | _password(""), 37 | _server(ESP8266WebServer(80)) 38 | { 39 | 40 | } 41 | 42 | MeshishNode::~MeshishNode() 43 | { 44 | 45 | } 46 | 47 | void MeshishNode::setup(String password, bool primary) 48 | { 49 | 50 | WiFi.mode(WIFI_AP_STA); 51 | 52 | WiFi.disconnect(); 53 | delay(100); 54 | 55 | _isPrimary = primary; 56 | _password = password; 57 | _chipId = ESP.getChipId(); 58 | 59 | bool ssidGenerated = _generateSSID(); 60 | 61 | if (!ssidGenerated && _debug) 62 | { 63 | _serial->println("MeshishNode::setup: _generateSSID() returned false."); 64 | } 65 | 66 | if (_isPrimary && ssidGenerated) 67 | { 68 | if (_debug) 69 | { 70 | _serial->println("MeshishNode::setup: Primary node creating SSID \"" + _ssid + "\""); 71 | } 72 | WiFi.softAP(_ssid.c_str()); 73 | _creatingAP = true; 74 | } 75 | else 76 | { 77 | _scanAndConnect(); 78 | } 79 | 80 | _server.on("/", [this](){ 81 | _server.send(200, "text/plain", "welcome!"); 82 | }); 83 | 84 | _server.onNotFound([this](){ 85 | _server.send(200, "text/plain", "404 file not found"); 86 | }); 87 | 88 | _server.begin(); 89 | } 90 | 91 | void MeshishNode::loop() 92 | { 93 | 94 | if (getStatus() == WL_CONNECTION_LOST) 95 | { 96 | _serial->println("MeshishNode::loop: connection lost"); 97 | } 98 | else if(getStatus() == WL_DISCONNECTED) 99 | { 100 | _serial->println("MeshishNode::loop: disconnected"); 101 | } 102 | 103 | if (_connectingToAP) 104 | { 105 | unsigned int status = getStatus(); 106 | if (_debug) 107 | { 108 | _serial->print("MeshishNode::loop: status "); 109 | _serial->println(status); 110 | } 111 | 112 | // connection established 113 | if (status == WL_CONNECTED) 114 | { 115 | _connectingToAP = false; 116 | 117 | if (_debug) 118 | { 119 | _serial->print("MeshishNode::loop: connection to \""); 120 | _serial->print(WiFi.SSID()); 121 | _serial->println("\" established."); 122 | _serial->print("MeshishNode::loop: recieved IP Address "); 123 | _serial->println(WiFi.localIP()); 124 | } 125 | 126 | // now create a secondary AP 127 | bool ssidGenerated = _generateSSID(); 128 | if (ssidGenerated) 129 | { 130 | // WiFi.softAPConfig(IPAddress(192, 168, 4, 10), 131 | // IPAddress(192, 168, 4, 10), 132 | // IPAddress(255, 255, 255, 0)); 133 | WiFi.softAP(_ssid.c_str()); 134 | _creatingAP = true; 135 | } 136 | 137 | } // connection failed 138 | else if (status == WL_CONNECT_FAILED) 139 | { 140 | _connectingToAP = false; 141 | 142 | if (_debug) 143 | { 144 | _serial->print("MeshishNode::loop: connection to "); 145 | _serial->print(WiFi.SSID()); 146 | _serial->println(" failed."); 147 | } 148 | } // still connecting... 149 | else if (status == WL_IDLE_STATUS) 150 | { 151 | if (_debug) 152 | { 153 | _serial->println("MeshishNode::loop: connection idle..."); 154 | } 155 | } 156 | } 157 | else 158 | { 159 | // not _connectingToAP 160 | } 161 | 162 | if (_creatingAP) 163 | { 164 | unsigned int status = getStatus(); 165 | // connection established 166 | if (status == WL_CONNECTED) 167 | { 168 | _creatingAP = false; 169 | if (_debug) 170 | { 171 | _serial->println("MeshishNode::loop: Access point created."); 172 | WiFi.printDiag(*_serial); 173 | } 174 | } 175 | else if (status == WL_CONNECT_FAILED) 176 | { 177 | _creatingAP = false; 178 | if (_debug) 179 | { 180 | _serial->println("MeshishNode::loop: Failed to create access point."); 181 | } 182 | } 183 | else if (status == WL_IDLE_STATUS) 184 | { 185 | if (_debug) 186 | { 187 | _serial->println("MeshishNode::loop: access point creation idle..."); 188 | } 189 | } 190 | } 191 | 192 | _server.handleClient(); 193 | } 194 | 195 | void MeshishNode::debug(HardwareSerial* serial) 196 | { 197 | _debug = true; 198 | _serial = serial; 199 | } 200 | 201 | void MeshishNode::makePrimary(bool primary) 202 | { 203 | if (_isPrimary != primary) { 204 | 205 | _isPrimary = primary; 206 | WiFi.disconnect(); 207 | 208 | if (_generateSSID() && _isPrimary) 209 | { 210 | WiFi.softAP(_ssid.c_str()); 211 | _creatingAP = true; 212 | } 213 | else if (_debug) 214 | { 215 | _serial->println("MeshishNode::makePrimary: _generateSSID() returned false."); 216 | } 217 | 218 | } 219 | } 220 | 221 | bool MeshishNode::isPrimary() 222 | { 223 | return _isPrimary; 224 | } 225 | 226 | // bool MeshishNode::isConnectedToPrimary() 227 | // { 228 | 229 | // } 230 | 231 | // bool MeshishNode::enableDefaultRoutes(bool enable) 232 | // { 233 | 234 | // } 235 | 236 | unsigned int MeshishNode::getStatus() 237 | { 238 | return WiFi.status(); 239 | } 240 | 241 | 242 | void MeshishNode::_scanAndConnect() 243 | { 244 | if (_debug) 245 | { 246 | _serial->println("scan start..."); 247 | } 248 | 249 | _numNetworks = min(WiFi.scanNetworks(), MESHISH_MAX_AP_SCAN); 250 | 251 | if (_debug) 252 | { 253 | _serial->print(_numNetworks); 254 | _serial->println(" networks found in scan"); 255 | } 256 | 257 | // the index of the node with the highest rssi 258 | int maxDBmPrimary = -1; 259 | 260 | for (int i = 0; i < _numNetworks; i++) 261 | { 262 | _apList[i] = AccessPoint(); 263 | _apList[i].ssid = WiFi.SSID(i); 264 | _apList[i].rssi = WiFi.RSSI(i); 265 | _apList[i].encrypt = WiFi.encryptionType(i); 266 | _apList[i].nodeType = _getNodeType(_apList[i]); 267 | 268 | if (_apList[i].nodeType == NODE_PRIMARY) 269 | { 270 | if (maxDBmPrimary == -1) 271 | { 272 | maxDBmPrimary = i; 273 | } 274 | else 275 | { 276 | if (_apList[i].rssi > _apList[maxDBmPrimary].rssi) 277 | { 278 | maxDBmPrimary = i; 279 | } 280 | } 281 | } 282 | 283 | if (_debug) 284 | { 285 | _serial->print(_apList[i].ssid); 286 | _serial->print("\t"); 287 | _serial->print(_apList[i].rssi); 288 | _serial->print("dBm\t"); 289 | _serial->print("Encryption: "); 290 | _serial->print(_apList[i].encrypt); 291 | _serial->print("\tnodeType: "); 292 | _serial->println(_apList[i].nodeType); 293 | } 294 | } 295 | 296 | if (maxDBmPrimary != -1) 297 | { 298 | if (_debug) 299 | { 300 | _serial->print("MeshishNode::_scanAndConnect: connecting to "); 301 | _serial->println(_apList[maxDBmPrimary].ssid.c_str()); 302 | } 303 | 304 | if (_password.equals("")) WiFi.begin(_apList[maxDBmPrimary].ssid.c_str()); 305 | else WiFi.begin(_apList[maxDBmPrimary].ssid.c_str(), _password.c_str()); 306 | 307 | _connectingToAP = true; 308 | } 309 | } 310 | 311 | bool MeshishNode::_generateSSID() 312 | { 313 | if (_isPrimary) 314 | { 315 | _ssid = String(_ssidPrefix + "_1_" + String(MESHISH_PRIMARY_IP) + "_" + String(_chipId)); 316 | if (_debug) 317 | { 318 | _serial->print("MeshishNode::_generateSSID: _isPrimary, ssid:"); 319 | _serial->println(_ssid); 320 | } 321 | return true; 322 | } 323 | else 324 | { 325 | 326 | if (WiFi.status() == WL_CONNECTED) 327 | { 328 | IPAddress ip = WiFi.localIP(); 329 | _ssid = String(_ssidPrefix + "_0_" + _ipToString(ip) + "_" + String(_chipId)); 330 | if (_debug) 331 | { 332 | _serial->print("MeshishNode::_generateSSID: !_isPrimary, ssid:"); 333 | _serial->println(_ssid); 334 | } 335 | return true; 336 | } 337 | else 338 | { 339 | if (_debug) 340 | { 341 | _serial->println("MeshishNode::_generateSSID: !_isPrimary but status != WL_CONNECTED"); 342 | } 343 | } 344 | 345 | } 346 | 347 | return false; 348 | } 349 | 350 | 351 | unsigned int MeshishNode::_getNodeType(const AccessPoint& ap) 352 | { 353 | String prefix = ap.ssid.substring(0, _ssidPrefix.length()); 354 | 355 | if (prefix.equals(_ssidPrefix)) 356 | { 357 | if (ap.ssid.substring(_ssidPrefix.length(), _ssidPrefix.length() + 3).equals("_1_")) 358 | { 359 | return NODE_PRIMARY; 360 | } 361 | else if (ap.ssid.substring(_ssidPrefix.length(), _ssidPrefix.length() + 3).equals("_0_")) 362 | { 363 | return NODE_SECONDARY; 364 | } 365 | } 366 | 367 | return NODE_NONE; 368 | } 369 | 370 | String MeshishNode::_ipToString(const IPAddress& ip) 371 | { 372 | return String(ip[0]) + "." + 373 | String(ip[1]) + "." + 374 | String(ip[2]) + "." + 375 | String(ip[3]); 376 | } 377 | 378 | 379 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meshish 2 | 3 | Meshish is an experimental Mesh-like library for use with the ESP8266 WiFiSoC. It is built on top of the existing Arduino library for ESP8266. At this time the library __does not work__ as described. In short, this library was created with the incorrect assumption that the ESP8266, acting in AP Mode, has 4 | the ability to route traffic between two or more clients connected to it ([more here](http://www.esp8266.com/viewtopic.php?f=32&t=4686)). This is not the case. This repository now lives as a historical document and proof-of- concept as to one way that cheap WiFi nodes could be configured to communicate in a decentralized mesh-like way. The rest of this document will outline the initial goals and desires of the library design, as conceived before the author came to the disheartening realization that the ESP8266 doesn't have routing/switching capabilities. 5 | 6 | Meshish and [related ESP8266 research](https://github.com/olab-io/ESP8266-Research) was conducted in summer of 2015 by Brannon Dorsey with support from the SAIC OpenLab, SAIC Shapiro Center, and a grant from the Motorola Corporation. 7 | 8 | ## Research Goals 9 | 10 | 1. Provide a general understanding of the ESP8266 hardware/software capabilities and limitations to be leveraged by the School of the Art Institute of Chicago (SAIC) community (and the online community at large), culminating in a one day ESP8266 related workshop at SAIC. 11 | 2. Gain familiarity with a range of ESP8266 supported SDKs and build environments (including [NodeMCU Lua](http://www.electrodragon.com/w/ESP8266_NodeMCU_Lua), [Arduino](https://github.com/esp8266/Arduino), [Open SDK](https://github.com/pfalcon/esp-open-sdk), [AT Commands](http://www.electrodragon.com/w/index.php)), learning and articulating the strengths and weaknesses of each "platform" so as to be able to best choose the appropriate means of development when starting new WiFi related projects. 12 | 3. Outline and construct a prototype __low cost and low power__ mesh network that fulfills the definition as expressed in the [Defining a Mesh Network](https://github.com/olab-io/ESP8266-Research/blob/master/defining_mesh_network_for_esp8266.md) document. 13 | 4. Provide insight into future development and techniques that can be employed by ESP8266 and other WiFi enabled microcontroller chips. 14 | 15 | ## 1. Understanding and Presenting ESP8266 16 | 17 | The allure and popularity of the ESP8266 System on a Chip (SoC) lies primarily in its low cost (~$3 a board) and high-level capabilities to behave as an 802.11 WiFi Access Point/Station. The ESP8266 is the first product of its type to provide these WiFi features at such a low cost ($15+ dollars cheaper than similar featured devices) and on such a small and embeddable platform. 18 | 19 | The ESP8266 is the first SoC I have developed with besides the Arduino platform, and it presents several challenges that make it difficult to use. In understanding and presenting my research I am also challenged by the target audience: creative artists working at the intersection of the arts and technology with varying levels of skill and comfortability when it comes to programming and networking practices. 20 | 21 | ### Technical 22 | 23 | I have outlined some of the challenges I faced when using the ESP8266 chip in [this brief troubleshooting guide](https://github.com/olab-io/ESP8266-Research/blob/master/troubleshooting.md). They can be summarized as follows: 24 | 25 | - Programming Interface: The ESP8266 SoC is made available in many different breakouts ([ESP-01](http://l0l.org.uk/wp-content/uploads/2014/12/ESP01v0.jpg) and [ESP-12](http://esp8266.ru/wp-content/images/esp8266-modules/ESP8266_esp-12.jpg) being perhaps the most common) and development boards ([NodeMCU](http://hackaday.com/2015/01/01/a-dev-board-for-the-esp-lua-interpreter/), [Adafruit HUZZAH](https://www.adafruit.com/products/2471), [SparkFun ESP8266 Thing](https://www.sparkfun.com/products/13231)). Unless you opt to purchase a development board, which significantly raises the cost of each ESP8266, you will have to program the devices using a USB->FTDI programmer attached to the Rx and Tx pins on your SoC. It is also possible to use an Arduino instead of an FTDI programmer. More on that [here](http://www.instructables.com/id/Arduino-Examples-2-Use-an-Arduino-as-a-FTDI-Progr/). 26 | - Power issues: The ESP8266 requires 3.3v and 250mA to behave correctly. However, when flashing new firmware to the device, it may require as much as 350mA of current. See the [Power Issues](https://github.com/olab-io/ESP8266-Research/blob/master/troubleshooting.md#power-issues) section of the troubleshooting document for more info. 27 | - Aggressive Watchdog Timer: A [watchdog timer](https://en.wikipedia.org/wiki/Watchdog_timer) is a common occurrence in SoCs but may be a new concept for people that haven't done much work with them. The watchdog in the ESP8266 is a hardware timer that resets the device if execution of custom code takes longer than ~1 sec without releasing control to the WiFi stack managed by the ESP8266 itself. If you find that your device keeps resetting, you may need to pause your custom code execution, handing off execution to the ESP8266's internal WiFi code. With Arduino, this is done using the `delay(...)` function, however some method for this exists in each SDK/Environment. 28 | 29 | ### Workshop 30 | 31 | In November 2015, the I co-organized _Closer Than Your Skin: A Networked Wearables Workshop_ with Christopher Baker and Sasha De Koninick at the School of the Art Institute of Chicago. The event lasted one day and was attended by 20 students from the school, who formed 4 groups that each developed an project using the ESP8266 throughout the course of workshop. The participants backgrounds ranged from art and technology to fashion and fibers, however most all atendees had no experience with the ESP8266 before the day of the event. In preperation for the workshop we fabricated 16 custom printed circuit boards that provided breakouts to easily add two buttons and two haptic vibration motors to each group's project. My summer research provided a comforatibility with the ESP8266 Arduino library allowing me to help individual groups throughout the day, providing group members an oppertunity to learn about the ESP8266 software development process while also focusing on the presentation and design of their wearable garments. 32 | 33 | Some of the projects built during the workshop include: 34 | 35 | - A bike helmet that uses LEDs to display the rider's heart rate 36 | - A broach that vibrates when it is within the proximity of certain WiFi networks 37 | - Custom embedded hats that augment the traditional roundtable game of "Assassin" 38 | 39 | ## 2. ESP8266 SDKs and Build Environments 40 | 41 | A large part of my ESP8266 related research was devoted to using and familiarizing myself with the various tools and languages that can be used to program the devices. Below include a short list of the strength and weaknesses of some of the most popular SDKs and environments that I experimented with. 42 | 43 | #### [AT Commands](http://www.electrodragon.com/w/index.php?title=Category:ESP8266_Firmware_and_SDK&redirect=no) 44 | The AT Command firmware (aka `Ai-Thinker`) is the default firmware that is developed by ESPRESSIF and shipped with the chips. It uses a [list of commands](http://www.pridopia.co.uk/pi-doc/ESP8266ATCommandsSet.pdf) that are sent serially to the devices to configure different modes and behaviors supported by the chips. 45 | 46 | __Pros:__ Easy to use as a first interface with the chip, as it only requires a serial port. Can provide a good understanding of some of the common uses and capabilities of the ESP8266. 47 | 48 | __Cons:__ Limited programatic control without some sort of "controller" device that is connected to the ESP8266 via serial. 49 | 50 | #### [Open SDK](https://github.com/pfalcon/esp-open-sdk) 51 | The Open SDK is an effort to provide open source (as much as possible) tools to build custom ESP8266 firmware using the official ESPRESSIF SDK. 52 | 53 | __Pros:__ The Open SDK provides the most possible control available with the SDK. New releases of the ESPRESSIF firmware also incorporate features that may not yet be provided in other environments. 54 | 55 | __Cons:__ Documentation is somewhat sparse, and programming in architecture specific C or C++ can be daunting to many people. 56 | 57 | #### [ESP8266 Arduino](https://github.com/esp8266/Arduino) 58 | The Arduino core and IDE is made available for ESP8266 development via the Arduino board manager with Arduino v1.6.5. 59 | 60 | __Pros:__ Arduino is perhaps the most used DIY/Hobbiest microcontroller platform. This environment is by far the most approachable for users already familiar with Arduino or just getting started with working with microcontrollers. It also for easily portable code between traditional Arduino boards and the ESP8266. 61 | 62 | __Cons:__ Because ESP8266 Arduino must be Arduino compatible I've found the library to be somewhat limiting in terms of some of the native capabilities possible with the ESP8266. 63 | 64 | #### [NodeMCU w/ ESPlorer](http://www.electrodragon.com/w/ESP8266_NodeMCU_Lua) 65 | NodeMCU is a Lua binding providing high-level access to the ESPRESSIF SDK via a scripting language. ESPlorer is a full-featured IDE that even provides a small file system on the ESP8266 allowing you to save, run, and include multiple `.lua` files. 66 | 67 | __Pros:__ ESPlorer is hands down the most powerful tool that I have come across to author software that runs on the ESP8266. The benifits provided by a scripting language, not having to compile and flash with each change, also significanly increase development speed. 68 | 69 | __Cons:__ Lua is a somewhat unfamiliar programming language for most people. If you know Lua, this really is the best development environment unless you need the kind of control that the Open SDK provides. 70 | 71 | ## 3. Mesh Network 72 | 73 | My initial interest in the ESP8266 was brought on by a desire to implement a scalable and distributed mesh network using the devices. For my purposes, I define a mesh network, as intended to be implemented entirely with ESP8266s as network nodes/repeaters, to have the following qualities: 74 | 75 | An ESP8266 Mesh Network __is__ a network: 76 | 77 | 1. Where any node in the network can communicate with any other node in the network 78 | 2. Where the range is determined and increased by each node in the network 79 | 80 | An ESP8266 Mesh Network __may__: 81 | 82 | 1. Be a hidden network that pre-programmed ESP8266 devices automatically connect to without SSID advertisement. 83 | 2. Be a visible network that any device may connect to like a traditional wifi Access Point. 84 | 3. Have the functionality to piggy-back off of an existing public wifi network to boost connection availability and speed. 85 | 86 | Once I had outlined these criteria, and had become familiar enough with basic programming of the ESP8266, I made the decision that I wanted to build the mesh network on top of the [Arduino WiFi library](https://www.arduino.cc/en/Reference/WiFi) as it provided enough basic functionality to build an informal network protocol/system so as not to have to implement a custom low-level ESPRESSIF code.If you are familiar with the [OSI Network Model](https://en.wikipedia.org/wiki/OSI_model), my Mesh Network implementation would sit at the highest level, the Application layer. 87 | 88 | ### Meshish 89 | 90 | Meshish was proposed as a solution. The premise of Meshish is that it creates a network using multiple ESP8266 nodes each opperating as both an access point and a station/client simultaneously (or AP/STA Mode). In Meshish, there are two types of nodes, primary and secondary. Primary nodes serve as the main 'routing' nodes that facilitate communication between the multiple ESP8266 secondary clients that may be connected to it. Each primary node then connects to another primary node to act as a gateway between their "subnets", forwarding communications allowing a secondary node attatched to one primary to talk to a secondary node attatched to a different primary. 91 | 92 | #### How it works 93 | 94 | Because the process of [leader election](https://en.wikipedia.org/wiki/Leader_election) can be a somewhat difficult task, and I was hoping to build a proof of concept implementation of library, I chose to predetermine which ESP8266 nodes would be primary and which ones would act as secondary nodes. When any Meshish node powers on, it imediately places itself in STA/AP Mode, and does one of two things, regardless if it's a secondary or primary node: 95 | 96 | - It advertises its network and services by broadcasting an SSID that notifies nearby nodes: 97 | 1. That is itself a Meshish node, remember the world is full of many WiFi networks 98 | 2. Wether it is a primary or secondary Meshish node 99 | 3. Its IP address on the network that it currently belongs 100 | - Attempts to connect to a primary node that it "sees". 101 | 102 | An example SSID of a Meshish node might look like this: 103 | 104 | ``` 105 | Mesh_1_192.168.4.1_28946321 106 | ``` 107 | 108 | Where `Mesh` is the preffix used to indicate this SSID belongs to a Meshish node, `1` indicates the node is primary (`0` if secondary), `192.168.4.1` the node's IP address, and `28946321`, the node's chip id. 109 | 110 | Each primary node will assign itself a `192.168.x.1` IP address with a `255.255.255.0` subnet, allowing the secondary node's broadcast SSID beacons (e.g. `Mesh_0_192.168.5.13_83402919`) to notify to act as an advertisement to other nodes as to which primary node network it belongs to. 111 | 112 | I assumed that the ESP8266 in AP mode had the capability to route TCP/IP traffic between two clients connected in a regular fashion. For instance, given: 113 | 114 | ``` 115 | 192.168.4.1 (AP) 116 | 192.168.4.2 (AP_STA) -> 192.168.4.1 (AP) 117 | 192.168.4.3 (AP_STA) -> 192.168.4.1 (AP) 118 | ``` 119 | 120 | One would think that `192.168.4.2` could exchange data with `192.168.4.3` because they are on the same "network" being served by the `192.168.4.1`, but with the ESP8266 this is not the case. This is where the library fails. It should be noted that the rest of the description of the Meshish library describes what is only hypothetical, as I have not found what I am about to describe to be possible given the current state of ESPRESSIF's SDK. 121 | 122 | After the initial moment of configuration, where the ESP8266 nodes have powered on and are each connected to one primary node that they are within range of (i.e. secondaries connecting to primaries, and primaries connecting to other primaries to act as gateways between networks), then the Meshish "network" behaves as follows. Any node primary or secondary, can communicate with any other node in the "network" by either making a simple connections to another node assosciated with the same primary node (i.e. `255.255.255.0` subnet) (__note: this does not actually work in practice, for reasons described above__), or making connections to the primary node itself in order to be forwarded from primary node to primary node until a connection to a secondary node on another subnet was made. 123 | 124 | Secondary node `192.168.4.10` would communicate with node `192.168.8.30` by connecting to `192.168.4.1:830` where the port number tells the primary node which secondary node on another network to connect to: 125 | 126 | - The first digit, `8`, identifies the 3rd octet of the network the secondary node belongs to 127 | - The remaining digits identify the 4th octet of the secondary node. 128 | 129 | __Note:__ This rudimentary protocol limits the number of primary nodes to 9 (1-9), as the 3rd octet must be one digit only. 130 | 131 | __Note:__ Because this proposed protocol relies heavily on multiple primary nodes to facilitate (forward via proxy) the communications between primary nodes on different networks, there is an implied heirarchy that is problamatic in a mesh network. It is for this reason that I have titled this proof-of-concept mesh-like protocol "Meshish." 132 | --------------------------------------------------------------------------------