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:
localhost
instead of the IP in a desperate try as I thought maybe its not possible to pass an IP directly - no differencewss
to ws
and remove the fingerprint - no differenceIs 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
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.