我开始从事一个小型“智能家居”项目,以了解嵌入式开发和 Rust。我有
服务器的“生产”版本是托管的,并且有一个域名,我可以用它来连接到它。单片机和FE可以使用域名分别使用wss和https连接。
我还想要一个可以在本地使用来调试的设置。这意味着服务器在 127.0.0.1 上运行,并且微控制器可以连接到它。最后,我想要一个构建标志,我可以设置它来定义正在构建的内容。 理想情况下,本地设置还应具有 SSL 加密,以更好地接近“生产”设置。我已经有一个可以使用的本地创建的证书,但作为第一步,简单的连接就足够了。
我的问题是我无法让微控制器连接到在 127.0.0.1 上运行的本地服务器
我将 PlatformIO 与以下库一起使用:
这是微控制器的代码:
#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;
}
}
我设置了定义
DEBUG_ESP_SSL
和 DEBUG_ESP_PORT
以从 WSP8266WiFi 库获取更多日志,但看不到任何有用的内容:
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
无论如何,
client.connect
调用都会返回0
。从日志中我可以看到调用 WiFiClient::connect
时连接失败,尽管我不知道为什么。
我尝试过的:
localhost
代替IP,因为我认为也许不可能直接传递IP - 没有区别wss
转换为 ws
并删除指纹 - 没有区别我是否遗漏了一些明显的东西?我读到防火墙可能是一个问题,但由于我可以访问 FE 并且 FE 可以创建到本地服务器的 Websocket 连接,我怀疑这就是问题所在。
如果您需要服务器代码,请告诉我。
非常感谢您的帮助和提示
无法连接到127.0.0.1,因为127.0.0.1是“环回”接口;它是“同一设备”的缩写。无法从运行服务器的设备之外的任何地方访问它。 “localhost”是完全相同的东西。
您需要使用运行服务器的设备的网络接口之一的 IP 地址。您需要将服务器配置为在启动时绑定到该 IP 地址,而不仅仅是 127.0.0.1。如何找到 IP 地址取决于您的服务器运行的操作系统。