I started working a small "smart home" project to learn about embedded development and Rust. I have
- an ESP8266 with a DHT to measure humidity and temperature, written in C++
- a server written in Rust that has a route with a very small FE (see next point) and routes for websockets to send and receive data
- a small FE which is currently a few lines of HTML and JS that connects to above mentioned server and reads the data sent by the sensor
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:
- adafruit/DHT sensor library@^1.4.6
- adafruit/Adafruit Unified Sensor@^1.1.14
- gilmaimon/ArduinoWebsockets@^0.5.3
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:
- Use
localhostinstead of the IP in a desperate try as I thought maybe its not possible to pass an IP directly - no difference - Convert
wsstowsand remove the fingerprint - no difference
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