websocketesp8266platformioesp8266wifi

Connect websocket on esp8266 to local server using IP


I started working a small "smart home" project to learn about embedded development and Rust. I have

The "production" version of the server is hosted and has a domain name which I can use to connect to it. The microcontroller and FE can connect using wss and https respectively using the domain name.

I also want a setup that I can use locally to debug. Meaning, the server is running on 127.0.0.1 and the microcontroller can connect to it. In the end I want to have a build flag that I can set to define what is being built. Ideally the local setup would also have SSL encryption to better approximate the "production" setup. I already have a locally created certificate that I could use but as a first step a simple connection is enough.

My problem is that I can't get the microcontroller to connect to the local server running on 127.0.0.1

I'm using PlatformIO with the following libraries:

Here is the code of the microcontroller:

#include <Arduino.h>
#include <DHT.h>
#include <DHT_U.h>
#include <ESP8266WiFi.h>
#include <ArduinoWebsockets.h>

#define DHTTYPE    DHT11
#define DHTPIN 2

DHT_Unified dht(DHTPIN, DHTTYPE);

const char* const public_address = "wss://mydomain.com/sensor/";
const char public_fingerprint[] PROGMEM = "<fingerprint>";

const char* const local_address = "wss://127.0.0.1:9231/sensor/";
const char local_fingerprint[] PROGMEM = "<fingerprint>";

const bool IS_LOCAL_SETUP = true; // for now simple bool switch

bool connected = false;

using namespace websockets;
WebsocketsClient client;

void onMessageCallback(WebsocketsMessage message) {
  // ...
}

void onEventsCallback(WebsocketsEvent event, String data) {
  // ...
}

void setup() {
  Serial.begin(115200);

  while (!Serial) {
    ; // Wait for serial
  }

  WiFi.mode(WIFI_STA);
  int count = WiFi.scanNetworks(false, true, 0, NULL);
  Serial.printf("Number of wifi networks: %d\n", count);

  String ssid = "<ssid>";

  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, "<password>");

  while (WiFi.status() != WL_CONNECTED && WiFi.status() != WL_CONNECT_FAILED)
  {
    delay(750);
    Serial.print('*');
  }

  Serial.println();

  if (WiFi.status() == WL_CONNECT_FAILED)
  {
    Serial.println("Error when connecting to wifi");
    return;
  }

  Serial.println("WiFi connection successful");
  Serial.println(WiFi.localIP());

  // run callback when messages are received
  client.onMessage(onMessageCallback);
  
  // run callback when events are occuring
  client.onEvent(onEventsCallback);

  if (IS_LOCAL_SETUP) {
    client.setFingerprint(local_fingerprint);
  } else {
    client.setFingerprint(public_fingerprint);
  }

  bool res;
  // Connect to server
  if (IS_LOCAL_SETUP) {
    res = client.connect(local_address);
  } else {
    res = client.connect(public_address);
  }
  if (!res) {
    Serial.println("Failed to connect");
    return;
  }

  connected = true;

  dht.begin();
  // printing sensor info
}

void loop() {
  delay(2000);

  if (!connected) {
    return;
  }

  client.poll();

  // Get temperature event and print its value.
  // ...

  // Send a message
  std::string msg = "...";
  bool res = client.send(msg.c_str());
  if (!res) {
    Serial.println("Failed to send message");
    return;  
  }
}

I set the defines DEBUG_ESP_SSL and DEBUG_ESP_PORT to get more logs from the WSP8266WiFi library but can't see anything useful:

SDK:2.2.2-dev(38a443e)/Core:3.1.2=30102000/lwIP:STABLE-2_1_3_RELEASE/glue:1.2-65-g06164fb/BearSSL:b024386
fpm close 1
mode : sta(c4:5b:be:55:92:4d)
add if0
scandone

**scandone
state: 0 -> 2 (b0)
*state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 17
cnt

connected with <SSID>, channel 6
dhcp client start...
ip:<ip>,mask:255.255.255.0,gw:<>

Setting fingerprint
Creating client
BSSL:connect: Unable to connect TCP socket

pm open,type:2 0

No matter what, the client.connect call returns 0. From the logs I can see that the connection fails when calling WiFiClient::connect, though I don't know why.

What I have tried:

Is there something obvious I'm missing? I read that firewall might be an issue but since I can access the FE and the FE can create a websocket connection to the local server I doubt that is the issue.

Please let me know if you need the code for the server.

Thanks a lot for any help and tips


Solution

  • You can't connect to 127.0.0.1 because 127.0.0.1 is the "loopback" interface; it's shorthand that means "the same device". It's not accessible from anywhere outside of the device that the server is running on. "localhost" is the exact same thing.

    You need to use the IP address of one of the network interfaces of the device your server is running on. And you need to configure the server to bind to that IP address when it starts up, not just to 127.0.0.1. How you find that IP address depends on the OS your server is running on.