随着物联网设备的普及,越来越多的智能场景开始从本地局域网扩展到广域网。对于一些需要远程触发的物理设备,例如按键机器人、舵机驱动机构等,完全依赖商业云平台并非唯一选择。通过自建基础设施,可以获得更高的隐私性、稳定性与可控性。
本文提供一套完整的、可在任意 VPS 上部署的广域网远程控制方案,实现:
- ESP8266/ESP32 持续连接 VPS
- 使用 MQTT(TLS 加密)进行指令下发与状态回传
- 舵机执行按压动作
- 远程客户端可通过命令行或 HTTP API 触发指令
- 全程无需使用任何商业云服务
该方案适用于智能按键器、远程机械执行器、低成本自动化场景等。
方案整体架构
系统由三个核心部分组成:
控制客户端(电脑/脚本/小程序)
↓ MQTT 指令
VPS(Mosquitto Broker)
↓ 加密连接
ESP8266/ESP32(驱动舵机)
远程控制流程如下:
- ESP 自动连接家庭 Wi-Fi
- ESP 主动连接 VPS 上的 MQTT Broker
- 控制端发布指令至 MQTT
- ESP 收到指令 → 驱动舵机执行按键动作
- ESP 上报“状态/心跳”等信息
整个过程安全、轻量且易扩展。
一、VPS 部署 MQTT Broker(Mosquitto)
以下示例基于 Debian / Ubuntu 服务器,可根据实际环境调整。
1. 安装 Mosquitto
apt update
apt install mosquitto mosquitto-clients
systemctl enable mosquitto
2. 使用 TLS 证书
如果服务器已有 ACME/Certbot 证书,可直接复用:
/etc/letsencrypt/live/<domain>/fullchain.pem/etc/letsencrypt/live/<domain>/privkey.pem
3. 创建 MQTT 用户
mosquitto_passwd -c /etc/mosquitto/passwd iotuser
4. 编写配置文件
文件:/etc/mosquitto/conf.d/iot.conf
listener 8883
protocol mqtt
cafile /etc/letsencrypt/live/<domain>/fullchain.pem
certfile /etc/letsencrypt/live/<domain>/fullchain.pem
keyfile /etc/letsencrypt/live/<domain>/privkey.pem
allow_anonymous false
password_file /etc/mosquitto/passwd
log_dest syslog
log_type error
log_type warning
log_type notice
5. 重启服务
systemctl restart mosquitto
systemctl status mosquitto
6. 防火墙放行端口
ufw allow 8883/tcp
二、客户端验证 MQTT 服务
订阅监控全部消息
mosquitto_sub \
-h <domain> \
-p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-u iotuser \
-P 'password' \
-t 'iot/#' -v
发布测试消息
mosquitto_pub \
-h <domain> \
-p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-u iotuser \
-P 'password' \
-t 'iot/button1/cmd' \
-m 'TEST'
若能在订阅端收到消息,则服务器配置成功。
三、硬件接线(ESP + 舵机)
以 SG90 舵机为例:
- 舵机红线 → 5V 电源
- 舵机黑/棕线 → GND
- 舵机橙线(信号)→ ESP GPIO14(D5)
建议使用单独稳压电源为舵机供电,ESP 与舵机 共地。
四、ESP 端 MQTT 控制代码
适用于 Arduino / PlatformIO(ESP8266 示例)。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h>
const char* ssid = "WiFi";
const char* password = "password";
const char* mqtt_server = "<domain>";
const int mqtt_port = 8883;
const char* mqtt_user = "iotuser";
const char* mqtt_pass = "password";
WiFiClientSecure espClient;
PubSubClient client(espClient);
Servo servo;
const int SERVO_PIN = 14;
void pressButton() {
servo.write(0);
delay(200);
servo.write(40);
delay(300);
servo.write(0);
delay(200);
}
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
if (String(topic) == "iot/button1/cmd") {
if (msg == "PRESS") {
client.publish("iot/button1/status", "RUN");
pressButton();
client.publish("iot/button1/status", "DONE");
}
}
}
void setup_wifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void reconnect() {
while (!client.connected()) {
if (client.connect("button1", mqtt_user, mqtt_pass)) {
client.subscribe("iot/button1/cmd");
client.publish("iot/button1/status", "ONLINE");
} else {
delay(5000);
}
}
}
unsigned long lastHeartbeat = 0;
void setup() {
servo.attach(SERVO_PIN);
servo.write(0);
setup_wifi();
espClient.setInsecure(); // 使用 TLS 通道但不验证证书
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
if (millis() - lastHeartbeat > 30000) {
lastHeartbeat = millis();
client.publish("iot/button1/heartbeat", "alive");
}
}
ESP 启动后即会注册:
- 指令主题:
iot/button1/cmd - 状态主题:
iot/button1/status - 心跳主题:
iot/button1/heartbeat
五、远程控制方式
1. 命令行触发动作
mosquitto_pub \
-h <domain> \
-p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-u iotuser \
-P 'password' \
-t 'iot/button1/cmd' \
-m 'PRESS'
2. 监控状态
mosquitto_sub \
-h <domain> \
-p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-u iotuser \
-P 'password' \
-t 'iot/button1/#' \
-v
六、可选:HTTP → MQTT 网关
如需通过浏览器或外部程序直接触发控制,可在 VPS 上部署轻量 Web 网关。示例(Flask + paho-mqtt):
from flask import Flask, request, jsonify
import paho.mqtt.publish as publish
app = Flask(__name__)
@app.route("/press")
def press():
publish.single(
"iot/button1/cmd",
payload="PRESS",
hostname="<domain>",
port=8883,
auth={"username": "iotuser", "password": "password"},
tls={"ca_certs": "/etc/ssl/certs/ca-certificates.crt"}
)
return jsonify({"status": "ok"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5001)
结合反向代理或认证后,即可安全开放给外界使用。
七、安全设计建议
为了在广域网上安全运行,建议:
- 使用强密码与独立账号
- 强制启用 TLS 加密
- 限制 MQTT 端口的访问来源(可选)
- 监控心跳与系统日志
- 完善指令权限与可恢复机制
可进一步使用 WireGuard/Tailscale 将所有节点拉入虚拟内网,仅在内网中暴露 MQTT 服务。
总结
该方案通过 VPS + MQTT 构建稳定的广域网远程控制体系,适合智能按键器、机械执行器、家庭自动化、远程实验装置等场景。具备以下特点:
- 完全自托管
- 不依赖商业云
- 具备良好的安全性与可扩展性
- 支持全球范围远程控制
- 极低成本即可部署
通过适当扩展,还可以接入多设备、脚本化自动化、定时任务、Web 控制面板等更多功能,构建完整的 DIY 物联网环境。