├── README.md ├── WiFiManager.h ├── websocketserver.ino └── websocketserver.ino.ino └── wifibridge.gif /README.md: -------------------------------------------------------------------------------- 1 | # LW3 is obsolete. Please refer to https://github.com/LaserWeb/LaserWeb4 2 | 3 | 4 | (note instructions written for Windows, but may equally well be used for other O/S) 5 | 6 | 7 | `1.` Download and install Arduino IDE 1.6.x from https://www.arduino.cc/en/Main/Software 8 | 9 | `2.` Install ESP8266 Arduino support https://github.com/esp8266/Arduino#installing-with-boards-manager 10 | 11 | `3.` Install the following libraries: 12 | 13 | `3.1:` WifiManager: https://github.com/tzapu/WiFiManager#install-through-library-manager 14 | 15 | `3.2:` arduinoWebSockets: https://github.com/Links2004/arduinoWebSockets 16 | 17 | `4.` Replace the provided WifiManager.h file from the WifiManager library, with the new template from https://github.com/openhardwarecoza/LaserWeb3/blob/master/ESP8266%20Wifi%20Bridge/WiFiManager.h (For Emblaser/Darklylabs theme) 18 | 19 | `5.` Configure your ESP8266 for sketch upload (GIPOs pulled up and down accordingly, USB to serial connected, reset and ready for upload) 20 | 21 | `6.` Upload the Sketch https://github.com/openhardwarecoza/LaserWeb3/blob/master/ESP8266%20Wifi%20Bridge/websocketserver.ino/websocketserver.ino.ino 22 | 23 | `7.` Connect the TX of the ESP8266 to RX of the Smoothie, and RX of the ESP8266 to TX of the Smoothie. Power up the ESP and Smoothie 24 | 25 | `8.` Connect to the Emblaser2 AP to connect the ESP to your local Wifi, then switch back to your local wifi (Animation below shows the details) 26 | 27 | `9.` Update LaserWeb to the version released on 12 October 2016 or newer 28 | 29 | `10.` In LaserWeb, set it to ESP8266, and connect to the IP of the ESP (Note, I will add an IP scanner soon. For now, check on your DHCP server which IP was dished out) 30 | 31 | ![Setting Up Wifi](wifibridge.gif) 32 | 33 | 34 | NOTE: To reset the Wifi settings you can: 35 | - Connect GPIO0 of the ESP8266 to GND (for 1-2s) or 36 | - If WiFi is still connected: Send `resetWiFi` via websocket 37 | -------------------------------------------------------------------------------- /WiFiManager.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | WiFiManager is a library for the ESP8266/Arduino platform 3 | (https://github.com/esp8266/Arduino) to enable easy 4 | configuration and reconfiguration of WiFi credentials using a Captive Portal 5 | inspired by: 6 | http://www.esp8266.com/viewtopic.php?f=29&t=2520 7 | https://github.com/chriscook8/esp-arduino-apboot 8 | https://github.com/esp8266/Arduino/tree/esp8266/hardware/esp8266com/esp8266/libraries/DNSServer/examples/CaptivePortalAdvanced 9 | Built by AlexT https://github.com/tzapu 10 | Licensed under MIT license 11 | **************************************************************/ 12 | 13 | #ifndef WiFiManager_h 14 | #define WiFiManager_h 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | extern "C" { 22 | #include "user_interface.h" 23 | } 24 | 25 | const char HTTP_HEAD[] PROGMEM = "{v}"; 26 | const char HTTP_STYLE[] PROGMEM = ""; 27 | const char HTTP_SCRIPT[] PROGMEM = ""; 28 | const char HTTP_HEAD_END[] PROGMEM = "
"; 29 | const char HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; 30 | const char HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; 31 | const char HTTP_FORM_START[] PROGMEM = "


"; 32 | const char HTTP_FORM_PARAM[] PROGMEM = "
"; 33 | const char HTTP_FORM_END[] PROGMEM = "
"; 34 | const char HTTP_SCAN_LINK[] PROGMEM = "
"; 35 | const char HTTP_SAVED[] PROGMEM = "
Credentials Saved

Trying to connect your Emblaser2 to network...

If it fails, please reconnect to the 'Emblaser2' access point to try again

If the connection is successful, then a few moments from now, you can try connecting from LaserWeb

"; 36 | const char HTTP_END[] PROGMEM = "
"; 37 | 38 | 39 | 40 | #define WIFI_MANAGER_MAX_PARAMS 10 41 | 42 | class WiFiManagerParameter { 43 | public: 44 | WiFiManagerParameter(const char *custom); 45 | WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length); 46 | WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); 47 | 48 | const char *getID(); 49 | const char *getValue(); 50 | const char *getPlaceholder(); 51 | int getValueLength(); 52 | const char *getCustomHTML(); 53 | private: 54 | const char *_id; 55 | const char *_placeholder; 56 | char *_value; 57 | int _length; 58 | const char *_customHTML; 59 | 60 | void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); 61 | 62 | friend class WiFiManager; 63 | }; 64 | 65 | 66 | class WiFiManager 67 | { 68 | public: 69 | WiFiManager(); 70 | 71 | boolean autoConnect(); 72 | boolean autoConnect(char const *apName, char const *apPassword = NULL); 73 | 74 | //if you want to always start the config portal, without trying to connect first 75 | boolean startConfigPortal(char const *apName, char const *apPassword = NULL); 76 | 77 | // get the AP name of the config portal, so it can be used in the callback 78 | String getConfigPortalSSID(); 79 | 80 | void resetSettings(); 81 | 82 | //sets timeout before webserver loop ends and exits even if there has been no setup. 83 | //usefully for devices that failed to connect at some point and got stuck in a webserver loop 84 | //in seconds setConfigPortalTimeout is a new name for setTimeout 85 | void setConfigPortalTimeout(unsigned long seconds); 86 | void setTimeout(unsigned long seconds); 87 | 88 | //sets timeout for which to attempt connecting, usefull if you get a lot of failed connects 89 | void setConnectTimeout(unsigned long seconds); 90 | 91 | 92 | void setDebugOutput(boolean debug); 93 | //defaults to not showing anything under 8% signal quality if called 94 | void setMinimumSignalQuality(int quality = 8); 95 | //sets a custom ip /gateway /subnet configuration 96 | void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); 97 | //sets config for a static IP 98 | void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); 99 | //called when AP mode and config portal is started 100 | void setAPCallback( void (*func)(WiFiManager*) ); 101 | //called when settings have been changed and connection was successful 102 | void setSaveConfigCallback( void (*func)(void) ); 103 | //adds a custom parameter 104 | void addParameter(WiFiManagerParameter *p); 105 | //if this is set, it will exit after config, even if connection is unsucessful. 106 | void setBreakAfterConfig(boolean shouldBreak); 107 | //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) 108 | //TODO 109 | //if this is set, customise style 110 | void setCustomHeadElement(const char* element); 111 | //if this is true, remove duplicated Access Points - defaut true 112 | void setRemoveDuplicateAPs(boolean removeDuplicates); 113 | 114 | private: 115 | std::unique_ptr dnsServer; 116 | std::unique_ptr server; 117 | 118 | //const int WM_DONE = 0; 119 | //const int WM_WAIT = 10; 120 | 121 | //const String HTTP_HEAD = "{v}"; 122 | 123 | void setupConfigPortal(); 124 | void startWPS(); 125 | 126 | const char* _apName = "no-net"; 127 | const char* _apPassword = NULL; 128 | String _ssid = ""; 129 | String _pass = ""; 130 | unsigned long _configPortalTimeout = 0; 131 | unsigned long _connectTimeout = 0; 132 | unsigned long _configPortalStart = 0; 133 | 134 | IPAddress _ap_static_ip; 135 | IPAddress _ap_static_gw; 136 | IPAddress _ap_static_sn; 137 | IPAddress _sta_static_ip; 138 | IPAddress _sta_static_gw; 139 | IPAddress _sta_static_sn; 140 | 141 | int _paramsCount = 0; 142 | int _minimumQuality = -1; 143 | boolean _removeDuplicateAPs = true; 144 | boolean _shouldBreakAfterConfig = false; 145 | boolean _tryWPS = false; 146 | 147 | const char* _customHeadElement = ""; 148 | 149 | //String getEEPROMString(int start, int len); 150 | //void setEEPROMString(int start, int len, String string); 151 | 152 | int status = WL_IDLE_STATUS; 153 | int connectWifi(String ssid, String pass); 154 | uint8_t waitForConnectResult(); 155 | 156 | void handleRoot(); 157 | void handleWifi(boolean scan); 158 | void handleWifiSave(); 159 | void handleInfo(); 160 | void handleReset(); 161 | void handleNotFound(); 162 | void handle204(); 163 | boolean captivePortal(); 164 | 165 | // DNS server 166 | const byte DNS_PORT = 53; 167 | 168 | //helpers 169 | int getRSSIasQuality(int RSSI); 170 | boolean isIp(String str); 171 | String toStringIp(IPAddress ip); 172 | 173 | boolean connect; 174 | boolean _debug = true; 175 | 176 | void (*_apcallback)(WiFiManager*) = NULL; 177 | void (*_savecallback)(void) = NULL; 178 | 179 | WiFiManagerParameter* _params[WIFI_MANAGER_MAX_PARAMS]; 180 | 181 | template 182 | void DEBUG_WM(Generic text); 183 | 184 | template 185 | auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) { 186 | return obj->fromString(s); 187 | } 188 | auto optionalIPFromString(...) -> bool { 189 | DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); 190 | return false; 191 | } 192 | }; 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /websocketserver.ino/websocketserver.ino.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //https://github.com/Links2004/arduinoWebSockets/issues/61 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include //https://github.com/tzapu/WiFiManager 9 | 10 | 11 | // Transparent Serial Bridge code from Marcus https://github.com/Links2004/arduinoWebSockets/issues/61 12 | 13 | ESP8266WebServer httpServer(80); 14 | ESP8266HTTPUpdateServer httpUpdater; 15 | const char* host = "webupdate"; 16 | const char* update_path = "/firmware"; 17 | const char* update_username = "admin"; 18 | const char* update_password = "admin"; 19 | 20 | 21 | WebSocketsServer webSocket = WebSocketsServer(81); 22 | 23 | 24 | WiFiManager wifiManager; 25 | int loopCount = 0; 26 | int resetCount = 0; 27 | int RESET_PIN = 0; // = GPIO0 on nodeMCU 28 | bool socketConnected = false; 29 | 30 | #define SEND_SERIAL_TIME (50) 31 | 32 | class SerialTerminal { 33 | public: 34 | void setup() { 35 | _lastRX = 0; 36 | resetBuffer(); 37 | Serial.begin(115200); 38 | } 39 | 40 | void loop() { 41 | unsigned long t = millis(); 42 | bool forceSend = false; 43 | 44 | size_t len = (_bufferWritePtr - &_buffer[0]); 45 | int free = (sizeof(_buffer) - len); 46 | 47 | int available = Serial.available(); 48 | if(available > 0 && free > 0) { 49 | int readBytes = available; 50 | if(readBytes > free) { 51 | readBytes = free; 52 | } 53 | readBytes = Serial.readBytes(_bufferWritePtr, readBytes); 54 | _bufferWritePtr += readBytes; 55 | _lastRX = t; 56 | } 57 | 58 | // check for data in buffer 59 | len = (_bufferWritePtr - &_buffer[0]); 60 | if(len >= sizeof(_buffer)) { 61 | forceSend = true; 62 | } 63 | if(len > (WEBSOCKETS_MAX_HEADER_SIZE + 1)) { 64 | if(((t - _lastRX) > SEND_SERIAL_TIME) || forceSend) { 65 | //Serial1.printf("broadcastBIN forceSend: %d\n", forceSend); 66 | webSocket.broadcastTXT(&_buffer[0], (len - WEBSOCKETS_MAX_HEADER_SIZE), true); 67 | resetBuffer(); 68 | } 69 | } 70 | } 71 | 72 | 73 | protected: 74 | uint8_t _buffer[1460]; 75 | uint8_t * _bufferWritePtr; 76 | unsigned long _lastRX; 77 | 78 | void resetBuffer() { 79 | // offset for adding Websocket header 80 | _bufferWritePtr = &_buffer[WEBSOCKETS_MAX_HEADER_SIZE]; 81 | // addChar('T'); 82 | } 83 | 84 | inline void addChar(char c) { 85 | *_bufferWritePtr = (uint8_t) c; // message type for Webinterface 86 | _bufferWritePtr++; 87 | } 88 | }; 89 | 90 | SerialTerminal term; 91 | 92 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) { 93 | switch(type) { 94 | case WStype_DISCONNECTED: 95 | socketConnected = false; 96 | // Serial1.printf("[%u] Disconnected!\n", num); 97 | break; 98 | case WStype_CONNECTED: { 99 | IPAddress ip = webSocket.remoteIP(num); 100 | socketConnected = true; 101 | // Serial1.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 102 | // send message to client 103 | webSocket.sendTXT(num, "Connected"); 104 | } 105 | break; 106 | case WStype_TEXT: 107 | // Serial1.printf("[%u] get Text: %s\n", num, payload); 108 | if(lenght > 0) { 109 | String command = String((const char *)payload); 110 | if (command.indexOf("resetWiFi") != -1){ 111 | webSocket.sendTXT(num, "Resetting WiFi settings..."); 112 | delay(500); 113 | //wifiManager.resetSettings(); 114 | delay(100); 115 | //ESP.restart(); 116 | } 117 | Serial.write((const char *) (payload), (lenght)); 118 | } 119 | break; 120 | } 121 | } 122 | 123 | void setup() 124 | { 125 | // use Serial 1 for debug out 126 | // Serial1.begin(921600); 127 | // Serial1.setDebugOutput(true); 128 | 129 | // Serial1.println(); 130 | // Serial1.println(); 131 | // Serial1.println(); 132 | 133 | for(uint8_t t = 4; t > 0; t--) { 134 | // Serial1.printf("[SETUP] BOOT WAIT %d...\n", t); 135 | delay(1000); 136 | } 137 | 138 | // Serial1.printf("[SETUP] HEAP: %d\n", ESP.getFreeHeap()); 139 | 140 | pinMode(RESET_PIN, INPUT_PULLUP); 141 | 142 | //WiFiManager wifiManager; 143 | //wifiManager.resetSettings(); 144 | 145 | wifiManager.autoConnect("Emblaser2"); 146 | 147 | webSocket.begin(); 148 | webSocket.onEvent(webSocketEvent); 149 | 150 | httpUpdater.setup(&httpServer, update_path, update_username, update_password); 151 | httpServer.begin(); 152 | 153 | term.setup(); 154 | 155 | // disable WiFi sleep for more performance 156 | WiFi.setSleepMode(WIFI_NONE_SLEEP); 157 | } 158 | 159 | 160 | void loop() 161 | { 162 | term.loop(); 163 | webSocket.loop(); 164 | httpServer.handleClient(); 165 | 166 | if (socketConnected == false){ 167 | //check every 10 loops 168 | if (loopCount > 100){ 169 | loopCount = 0; 170 | // if GPIO0 is LOW for 10 times -> reset settings 171 | if (resetCount > 10){ 172 | resetCount = 0; 173 | //wifiManager.resetSettings(); 174 | delay(100); 175 | //ESP.restart(); 176 | } else { 177 | if (digitalRead(RESET_PIN) == LOW) { 178 | resetCount++; 179 | } else { 180 | resetCount = 0; 181 | } 182 | } 183 | } else { 184 | loopCount++; 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /wifibridge.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaserWeb/LaserWeb3-ESP8266/7d63887c725072255d59cb1a5f5768229369cfa1/wifibridge.gif --------------------------------------------------------------------------------