/* Rev 1 of Wifi Bridge for BLE Load this sketch to the Adafruit HAZZAH ESP8266 module (Other ESP8266 modules can also be used, this code drives GPIO0 to indicate when connected) This code uses Arduino ESP8266 is V2.3.0. Other versions may not work as expected The ESP8266 can only handle sending one TCP packet (of 1460 bytes of data) at a time. This code and the associated pfodESP8266WiFi non-blocking library allows incoming Serial data to be read and buffered while the ESP is handling the previous packet, waiting for it to be ACKed. This allows data to be streamed at higher baud rates. Window's OS takes about 200mS to ACK a single TCP packet. Since the ESP8266 blocks handling more outgoing data until the last packet is ACKed, so, even with this non-blocking code and library, for continual data transmission you should limit the Serial baud rate to <= 57600 baud to avoid loss of data. For linux and Android, the ACKs come back much faster, 10-40mS, so when connecting from these OS's you can send data continually at 115200 baud. If the WiFi connection is poor and there are re-transmissions of lost packets, it takes longer for the ESP to successfully send the packed and you will need to set a lower baud rate to avoid lost data. 19200 is the maximum practical baud rate for communicating with Arduino UNO and Arduino Mega boards This code also has a connection idle timeout. If there is no incoming data from the connected client, this code will close the connection after the connection timeout time (default 15 secs). The prevents half-closed connections from locking out new connections. If you set connection timeout to 0 the connection will never time out, not recommended. This code also batches outgoing data by delaying sending of the buffered data until either the buffer is full, a full TCP packet, or no data has been received from the Serial port for SEND_DELAY_TIME (10mS). This improves through put and allows higher baud rates without data loss. */ /** Wifi to BLE Bridge http://www.forward.com.au/pfod/HomeAutomation/Wifi2BLE/index.html (c)2015 Forward Computing and Control Pty. Ltd. This code may be freely used for both private and commerical use. Provide this copyright is maintained. */ // On Adafruit HUZZAH ESP8266 module the RED led is constant when connection to the router is established // and blinks when there is a data connection running. #include #include #include #include char ssid[] = "**** ***"; char password[] = "**** *****"; char staticIP[] = "10.1.1.180"; int portNo = 23; uint32_t connectionTimeout = 60000; // 60sec connection time out void closeConnection(); // normally DEBUG is commented out //#define DEBUG // uncomment this to connect / disconnect messages on Serial out. // normally not used check the red led which blinks when connected. //#define CONNECTION_MESSAGES WiFiServer server(portNo); WiFiClient client; // just one client reused pfodESP8266BufferedClient bufferedClient; void setup ( void ) { Serial.begin(9600); delay(10); // Don't add any more delays here as the ESP8266 V2.3.0 library does not like it #ifdef DEBUG Serial.println(); Serial.println(F("Starting Setup")); // bufferedClient.setDebugStream(&Serial); // add this line if using DEBUG in pfodESP8266BufferedClient library code #endif // Initialise wifi module #ifdef DEBUG Serial.println(); Serial.println(F("Connecting to AP")); Serial.print("ssid '"); Serial.print(ssid); Serial.println("'"); Serial.print("password '"); Serial.print(password); Serial.println("'"); #endif // config static IP IPAddress ip(pfodESP8266Utils::ipStrToNum(staticIP)); IPAddress gateway(ip[0], ip[1], ip[2], 1); // set gatway to ... 1 #ifdef DEBUG Serial.print(F("Setting gateway to: ")); Serial.println(gateway); #endif IPAddress subnet(255, 255, 255, 0); WiFi.config(ip, gateway, subnet); // setup GPIO0 to flash Led on Adafruit Huzzah-ESP8266 // On Adafruit HUZZAH ESP8266 module the RED led is constant when connection to the router is established // and blinks when there is a data connection running. pinMode(0, OUTPUT); digitalWrite(0, HIGH); // OFF WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); #ifdef DEBUG Serial.print("."); #endif } #ifdef DEBUG Serial.println(); Serial.println(F("Connected!")); #endif digitalWrite(0, LOW); // ON // Start listening for connections #ifdef DEBUG Serial.println(F("Start Server")); #endif server.begin(); server.setNoDelay(true); // does not do much if anything #ifdef DEBUG Serial.println(F("Server Started")); // Print the IP address Serial.print(WiFi.localIP()); Serial.print(':'); Serial.println(portNo); Serial.println(F("Listening for connections...")); #endif } unsigned long timeoutTimerStart = 0; unsigned long flasherTimer = 0; const unsigned long FLASH_TIME = 1000; // 1sec bool ledOn = true; // after connection bool alreadyConnected = false; // the loop routine runs over and over again forever: void loop() { if (server.hasClient()) { // avoid creating WiFiClient object if no connection, ESP8266 specific WiFiClient anotherClient = server.available(); if (!client) { client = anotherClient; // take this connection } else { #ifdef DEBUG Serial.println("Stop extra connection"); #endif anotherClient.stop(); // stop this extra connection } } // anotherClient is disposed here at end of its block if (client) { // have client if (!client.connected()) { if (alreadyConnected) { // client closed so clean up closeConnection(); } } else { // have connected client if (!alreadyConnected) { #if defined(CONNECTION_MESSAGES) || defined(DEBUG) Serial.println("ConnectionOpened"); #endif client.setNoDelay(true); // does not do much if anything bufferedClient.connect(&client); // buffer this client alreadyConnected = true; // start timer timeoutTimerStart = millis(); flasherTimer = millis(); // reset flasher digitalWrite(0, HIGH); // off ledOn = false; } } } //check UART for data if (Serial.available()) { size_t len = Serial.available(); if (len > 0) { // size_t is an unsigned type so >0 is actually redundent for (size_t i = 0; i < len; i++) { bufferedClient.write(Serial.read()); } } } // NOTE: MUST call some bufferedClient method each loop to push out buffered data on delayed send timeout if (bufferedClient.connected()) { while ((bufferedClient.available() > 0) && (Serial.availableForWrite() > 0)) { // use Serial.availableForWrite to prevent loosing incoming data timeoutTimerStart = millis(); // reset timer if we have incoming data Serial.write(bufferedClient.read()); } } // see if we should drop the connection if (alreadyConnected && (connectionTimeout > 0) && ((millis() - timeoutTimerStart) > connectionTimeout)) { closeConnection(); } // Flash GPIO0 if have connection if (!alreadyConnected) { digitalWrite(0, LOW); // back to solid ledOn = true; } else { if ((millis() - flasherTimer) > FLASH_TIME) { flasherTimer += FLASH_TIME; ledOn = !ledOn; if (ledOn) { digitalWrite(0, LOW); } else { digitalWrite(0, HIGH); } } } } void closeConnection() { #if defined(CONNECTION_MESSAGES) || defined(DEBUG) Serial.println("ConnectionClosed"); #endif alreadyConnected = false; bufferedClient.stop(); // clears client reference client.stop(); // stop client and tcp buffer. if (server.hasClient()) { // avoid creating WiFiClient object if no connection, ESP8266 specific client = server.available(); } // else just keep client that was just stopped will evaluate to false digitalWrite(0, LOW); // back to solid ledOn = true; }