Search code examples
pythonflaskarduinohttprequestesp8266

Failing to connect an ESP8266 to a Flask Server


I have a flask application that I need to communicate with my ESP8266 and I'm failing miserably to achieve that. It's not supposed to be hard, but I'm clearly missing something, and I wouldn't be surprised since is my first time working with flask. Let me try to explain what I've done so far.

This is my flask code:

from flask import Flask
from flask import request
 
app = Flask(__name__)
 
@app.route('/postjson', methods=['GET', 'POST'])
def postJsonHandler():
    content = request.get_json()
    print (content)
    return 'JSON posted'

As you can see, nothing special.

It runs on the default local http://127.0.0.1:5000/. Using Postman, I can send a JSON with data to http://127.0.0.1:5000/postjson and it works like a charm, the JSON is printed on the terminal as I wanted.

The problem starts when I bring the ESP to the mix. This is my code from the ESP, again, nothing supposed to be special here, all stuff you find googling:

#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
 
void setup() {
 
  Serial.begin(115200);                            //Serial connection
  WiFi.begin("MyInternet", "MyPassword");          //WiFi connection
 
  while (WiFi.status() != WL_CONNECTED) {          //Wait for the WiFI connection completion
 
    delay(500);
    Serial.println("Waiting for connection");
 
  }
 
}
 
void loop() {
 
  if (WiFi.status() == WL_CONNECTED) {             //Check WiFi connection status
 
    DynamicJsonDocument doc(2048);
    doc["hello"] = "world";

    // Serialize JSON document
    String json;
    serializeJson(doc, json);

    WiFiClient client;
    HTTPClient http;                               //Declare object of class HTTPClient
 
    http.begin(client, "http://10.104.2.114:5000/postjson");      //Specify request destination
    http.addHeader("Content-Type", "application/json");           //Specify content-type header
 
    int httpCode = http.POST(json);                               //Send the request
    String payload = http.getString();                            //Get the response payload
 
    Serial.println(httpCode);                                     //Print HTTP return code
    Serial.println(payload);                                      //Print request response payload
 
    http.end();  //Close connection
 
  } else {
 
    Serial.println("Error in WiFi connection");
 
  }
 
  delay(10000);  //Send a request every 10 seconds
 
}

This doesn't work. Nothing happens in my flask terminal, and the httpCode printed is -1, showing that something didn't quite work with the connection. I tried a different code using client.connect(host, port):

if (client.connect(127.0.0.1,5000)) {
  Serial.println("Client Connected");
  } 
else {
    Serial.println("No Connection");
  }

Which also failed. I keep getting "No Connection". So I did some research and I found here at this beautiful website that in order to make your flask application externally visible, you have to use the command:

flask run -h 0.0.0.0

I tried that, and now my flask application runs on my IP http://10.XXX.XX.XXX:5000/, which makes sense. But even doing this I wasn't able to make any of the codes above work. I keep getting no response whatsoever and the http return is either 0 or -1, a big no-no.

Does anyone have a clue on what could be the problem? It's worth mentioning that I tried the ESP codes on different hosts and the code works, so it has to be some sort of IP configuration shenanigans that I'm unaware of.

It's also worth mentioning that I'm running flask on a computer using a portable hotspot from my phone (USB tethering) because my home internet is not working, and my ESP is connected to the same network (portable hotspot wifi), not sure how this could affect anything, but it's the setup.


Solution

  • It's quite likely the IP addresses that you use and possibly your current network setup. If you run Flask locally, by default it will use 127.0.0.1 (localhost) and the application can only be reached from your own computer. Other hosts on the network cannot. So your intuition is correct, you need to run it on 0.0.0.0 so that the application becomes accessible on any interface, not just localhost but also the LAN IP address and WAN IP address (provided you have got one).

    Now the remaining question is, is 10.104.2.114 is the correct address for your PC where the Flask application is running ? Assuming that you use DHCP, the IP address is subject to change. From what you are saying your ESP8266 is on the same network but I think the connection sharing applies some form of isolation between guests (possibly by VLAN). So, for that reason, the guests on that network may not be able to see each other and this is by design. It is normal for wifi hotspots to segregate traffic per client.

    Putting all your devices on the same router/switch could work. Note that you can still use your home router/switch to connect devices, even if Internet access is out of service. This is something you could try, as long as your hardware is in good condition.