ESP-RFID与MQTT智能门禁系统:解耦架构与Tasmota/Shelly联动实战
2026/8/20 3:03:45 网站建设 项目流程

1. 项目缘起:当ESP-RFID需要更强的“手”和“脑”

如果你玩过ESP8266/ESP32的RFID门禁,大概率对ESP-RFID这个开源项目不陌生。它把一块小小的开发板变成了一个独立的读卡器+Web服务器,刷一下卡,网页上就能记录,还能控制一个继电器去开门。这很酷,但它的“能力圈”也仅限于此——继电器直接连在ESP的GPIO上,逻辑控制全在ESP内部。一旦你想做点复杂的,比如“刷卡后,不仅要开门,还要点亮走廊灯,同时给手机发个通知,并且记录到云端数据库”,原生ESP-RFID就有点力不从心了。

这就是“ESP-RFID with External Tasmota/Shelly”这个组合诞生的背景。它的核心思想是解耦扩展。我们不再让ESP-RFID亲自去“动手”控制硬件,而是让它专心做好“感知”和“决策”这两件事:感知卡片信息,然后通过一个高效的通信协议(MQTT),把“谁在什么时候刷了卡”这个决策指令,广播出去。至于具体由谁来执行开门、开灯、发通知这些“动手”的活儿,就交给更专业的“执行者”——比如刷了Tasmota固件的智能插座,或者Shelly品牌的智能继电器模块。

简单来说,我们把一个集成的“单片机门禁”,升级成了一个分布式的“智能家居触发中枢”。ESP-RFID是那个敏锐的“哨兵”,而Tasmota/Shelly设备则是听令行事的“士兵”。MQTT协议就是它们之间高效、可靠的“无线电”。这个架构的灵活性是惊人的,你可以在不修改ESP-RFID任何代码的情况下,通过增减或重新配置Tasmota/Shelly设备,来无限扩展门禁系统的功能边界。

2. 核心组件选型与角色定位

要实现这个架构,我们需要三类核心组件,每一类都有其明确的职责和选型考量。

2.1 感知与决策中心:ESP-RFID固件

ESP-RFID在这里扮演大脑和感官的角色。你需要将它刷写到一块ESP8266或ESP32开发板上,并连接RC522或其他兼容的RFID读卡模块。

注意:务必从官方GitHub仓库获取最新稳定版固件。在配置时,除了常规的Wi-Fi设置,最关键的部分在“硬件”和“MQTT”配置页。在硬件页,建议将“继电器控制”设置为“无”。因为我们不再使用ESP板载的GPIO去控制继电器,而是通过MQTT来控制外部设备。这一步是思维转换的关键,意味着ESP-RFID从此“放手”,只做命令的发布者。

2.2 通信骨干:MQTT代理服务器

MQTT是一个基于发布/订阅模式的轻量级消息协议,完美适配物联网设备间通信。它需要一个“中转站”,即MQTT代理服务器。

  • 选型推荐
    • 家用/测试:Mosquitto。这是最流行、最轻量的开源MQTT代理,可以轻松部署在树莓派、NAS甚至一台常年开机的旧电脑上。Docker部署是首选,一条命令即可完成。
    • 云端/省心:EMQX Cloud、阿里云物联网平台、腾讯云IoT Hub。这些云服务提供了免运维的MQTT代理,通常有免费的额度,适合不想自建服务器的用户。它们还额外提供了设备管理、监控看板等增值功能。
  • 关键概念
    • 主题:可以理解为“频道”或“地址”。ESP-RFID和Tasmota/Shelly设备通过订阅和发布到特定的主题来交换信息。例如,ESP-RFID可以将刷卡事件发布到esp-rfid/door/access主题。
    • 消息:在主题中传递的数据内容,通常是JSON或简单字符串格式。

2.3 执行终端:Tasmota与Shelly设备

这是实际执行物理操作的“手”。两者都可以通过MQTT接收指令并控制继电器。

特性Tasmota (固件)Shelly (硬件产品)
本质一个开源固件,需要刷入支持的硬件(如Sonoff、Shelly等)一个集成了硬件和官方固件的商业产品
灵活性极高。可刷入大量廉价Wi-Fi模块,完全开源,功能可深度定制。中等。开箱即用,官方固件功能稳定但相对固定,部分型号支持自定义脚本。
上手难度较高。需要寻找兼容硬件、刷机、配置模板。极低。插电、配网、设置MQTT即可使用。
稳定性依赖社区和硬件质量,配置得当后非常稳定。商业产品,稳定性通常有保障。
成本通常更低(硬件成本低)。稍高,为便利性和稳定性付费。

如何选择?

  • 如果你是极客,享受折腾过程,手头有闲置的Sonoff Basic等模块,Tasmota是不二之选,它能给你最大的控制权和性价比。
  • 如果你追求快速部署、稳定可靠,希望用最少的时间让系统跑起来,Shelly系列产品(如Shelly 1, Shelly Plus 1)是你的最佳伙伴。它的官方固件已经原生支持MQTT,配置过程非常直观。

在本方案中,我们将一个Shelly 1作为执行开门动作的继电器。它的角色非常纯粹:订阅ESP-RFID发出的特定MQTT主题,当收到“开”指令时,闭合继电器1秒钟,模拟开门动作。

3. 实战部署:从零搭建完整链路

现在,我们假设在一个典型的家庭实验室环境,使用Mosquitto作为本地MQTT服务器,Shelly 1作为执行器,来搭建整个系统。

3.1 第一步:部署MQTT服务器

如果你使用树莓派,安装Mosquitto非常简单:

sudo apt update sudo apt install mosquitto mosquitto-clients sudo systemctl enable mosquitto sudo systemctl start mosquitto

安装后,Mosquitto默认就在1883端口运行了。为了测试,我们可以用mosquitto_submosquitto_pub命令进行本地订阅和发布测试,确保服务正常。

对于生产环境,强烈建议配置用户名密码认证。编辑/etc/mosquitto/mosquitto.conf文件,取消相关注释并设置密码文件:

allow_anonymous false password_file /etc/mosquitto/passwd

然后创建密码文件:

sudo mosquitto_passwd -c /etc/mosquitto/passwd your_username

输入密码后,重启Mosquitto服务。

3.2 第二步:配置ESP-RFID连接MQTT

在ESP-RFID的Web配置界面(通常通过IP地址访问),找到MQTT设置页面。

  • MQTT服务器:填入你的Mosquitto服务器IP地址,例如192.168.1.100
  • 端口:默认1883,如果用了TLS加密则是8883
  • 用户名/密码:填写上一步在Mosquitto中创建的凭据。
  • 客户端ID:起一个唯一的名字,如ESP-RFID_Garage
  • 主题配置:这是核心!
    • 主主题:设定一个基础主题,如home/access。所有相关消息都会以此为基础。
    • 门禁主题:ESP-RFID会在检测到刷卡后,向一个特定的主题发布消息。通常格式是[主主题]/[门禁点名称]。例如,我们设置为home/access/door1
    • 消息格式:选择JSON。这会发布一个结构化的消息,例如{"tag":"A1B2C3D4", "granted":true},其中包含卡号tag和是否授权granted。这比简单的“ON/OFF”字符串包含更多信息,为后续复杂逻辑处理留有余地。

保存配置后,ESP-RFID会重启并尝试连接MQTT服务器。你可以在Mosquitto服务器上用命令行工具订阅home/access/##是通配符)来监听所有相关消息,刷卡测试是否能看到JSON数据。

3.3 第三步:配置Shelly 1执行动作

将Shelly 1接上电源和你要控制的电锁(注意安全,操作强电请断电进行)。通过手机App或网页(Shelly设备会创建一个Wi-Fi热点)将其连接到你的家庭Wi-Fi。

  1. 启用MQTT:在Shelly的Web界面(通过IP访问),找到Internet & Security -> Advanced - Developer Settings
  2. 启用MQTT:勾选启用,填写MQTT服务器地址、端口、用户名、密码(与ESP-RFID使用的相同)。
  3. 配置动作:这是最关键的一步。我们需要让Shelly订阅ESP-RFID发布的主题,并在收到授权成功的消息时触发继电器。
    • 在Shelly的Web界面,找到ScriptsActions页面(不同固件版本位置可能不同)。
    • 创建一个新的脚本。脚本语言通常是JavaScript(Shelly Script)。
    • 脚本逻辑
      // 订阅ESP-RFID发布的主题 MQTT.subscribe("home/access/door1", function(topic, message, retained) { // 解析收到的JSON消息 let msg = JSON.parse(message); // 判断是否是授权通过的刷卡事件 if (msg.granted === true) { // 控制继电器0(Shelly 1的第一个继电器)打开1秒 Shelly.call("Switch.Set", { id:0, on:true }); // 设置一个1秒后关闭的定时器 Timer.set(1000, false, function() { Shelly.call("Switch.Set", { id:0, on:false }); }); } });
    这个脚本做了几件事:订阅特定主题、解析消息、判断条件、执行动作。Shelly.call是调用设备内部API的方法,Switch.Set用于控制继电器开关。
  4. 保存并启用脚本。现在,当你用授权的卡在ESP-RFID上刷卡时,Shelly 1的继电器就会“咔哒”一声闭合一秒再断开,完美模拟了开门动作。

3.4 第四步:功能扩展与联动思路

至此,基础的门禁功能已经实现。但这个架构的魅力在于其扩展性。以下是一些进阶玩法:

  • 多门禁点联动:你可以部署多个ESP-RFID读卡器(厨房门、车库门),每个发布到类似home/access/kitchen,home/access/garage的主题。然后配置一个Shelly 2.5(双路继电器)分别订阅这两个主题,控制不同的门锁。
  • 灯光与通知联动:在Node-RED(一个图形化的低代码物联网集成工具)中,订阅home/access/#主题。当收到刷卡消息时,Node-RED可以同时执行多个动作:通过MQTT命令打开Tasmota控制的走廊灯;通过HTTP请求调用手机推送服务(如Pushover、Bark)发送通知;甚至将刷卡记录写入Google Sheets或本地数据库。
  • 条件化执行:在Shelly脚本或Node-RED中增加逻辑判断。例如,只在晚上8点到早上7点之间,刷卡时才联动打开灯光;或者当刷特定管理员卡片时,触发一个5秒的长开信号用于维护。
  • 状态反馈:让Shelly在动作执行后,发布一个状态消息到如home/access/door1/status主题,内容为{"relay":"on"}{"relay":"off"}。ESP-RFID或其他设备可以订阅此主题,实现状态同步,甚至在Web界面上显示“门已开启”的提示。

4. 深度排错:从理论到信号的完整链路检查

系统不工作?别慌。物联网项目的调试就是逐层验证通信链路。请按照以下顺序排查,这能帮你系统地定位问题。

4.1 第一层:网络连通性

这是所有问题的基础。确保ESP-RFID、Shelly设备和运行Mosquitto的服务器(或电脑)都在同一个局域网段(如192.168.1.x),并且可以互相ping通。防火墙需要放行MQTT端口(默认1883)。一个常见的坑是,电脑的防火墙阻止了入站连接,导致设备无法连接到电脑上运行的Mosquitto。

4.2 第二层:MQTT服务器与认证

在服务器上,使用sudo systemctl status mosquitto检查服务是否运行。查看Mosquitto的日志sudo tail -f /var/log/mosquitto/mosquitto.log,当设备尝试连接时,日志会显示连接成功或失败的原因,如“认证失败”、“错误的协议版本”等。

使用MQTT客户端工具(如MQTT Explorer、Desktop)进行手动测试。用正确的服务器地址、端口、用户名密码连接,然后手动向home/access/door1主题发布一个JSON消息{"tag":"test", "granted":true}。同时订阅#主题,看能否收到Shelly设备上线或下线的状态消息(通常Shelly会发布shellies/[device-id]/online消息)。这个步骤能彻底分离“服务器问题”和“设备配置问题”。

4.3 第三层:ESP-RFID配置与发布

进入ESP-RFID的Web界面,查看状态页,确认MQTT显示为“已连接”。如果显示断开,检查配置的IP、端口、用户名密码是否正确。ESP-RFID的日志功能有限,但你可以通过监听它的串口输出(如果方便接线)来查看启动和连接时的详细信息。

在MQTT客户端工具中,订阅home/access/#主题。用一张已知的授权卡刷卡,观察是否能收到消息。如果收不到,问题出在ESP-RFID的MQTT配置或网络连接上。如果收到了,但格式不对(比如不是JSON),检查ESP-RFID中MQTT设置的消息格式选项。

4.4 第四层:Shelly订阅与脚本逻辑

这是最复杂的一环。首先,在Shelly的Web界面,检查MQTT连接状态是否正常。然后,验证脚本是否正确保存和启用。Shelly Script的调试比较麻烦,但你可以通过增加日志输出来辅助:

MQTT.subscribe("home/access/door1", function(topic, message, retained) { console.log("Received:", topic, message); // 打印接收到的消息 let msg = JSON.parse(message); console.log("Parsed granted:", msg.granted); if (msg.granted === true) { console.log("Access granted, triggering relay."); Shelly.call("Switch.Set", { id:0, on:true }); Timer.set(1000, false, function() { Shelly.call("Switch.Set", { id:0, on:false }); console.log("Relay turned off."); }); } });

在Shelly的Web界面的“日志”或“事件”查看器中,观察是否有这些console.log的输出。如果没有输出,说明脚本没有触发,可能是主题名拼写错误,或者MQTT消息没有成功送达Shelly。如果有输出但继电器没动作,检查Shelly.call的语法,特别是继电器id是否正确(Shelly 1通常是0)。

4.5 第五层:电源与硬件

不要忽略最简单的硬件问题。确保Shelly 1的供电稳定。测量一下继电器的输出端,在脚本触发时是否有电压变化。如果控制的是12V电锁,确保Shelly的继电器输出端正确连接到电锁的电源回路中。有时候,问题仅仅是接线松动或电源功率不足。

5. 安全加固与生产环境考量

家庭实验室可以玩得随意些,但如果你打算将其用于真正的门禁,安全必须放在首位。

  1. 网络隔离:将物联网设备(ESP-RFID, Shelly)放在一个独立的VLAN或访客网络中,与你的主用电脑、手机网络隔离。防止某个设备被攻破后危及整个内网。
  2. MQTT加密
    • 端口加密:使用MQTT over TLS(端口8883)。这需要在Mosquitto服务器上配置SSL证书(可以使用Let‘s Encrypt的免费证书,或自签名证书)。然后在ESP-RFID和Shelly的MQTT配置中启用TLS,并上传或信任证书。
    • 传输加密:如果觉得配置TLS麻烦,至少要在MQTT连接中使用用户名和强密码,并禁用匿名访问。
  3. 主题权限:在Mosquitto中,可以使用ACL(访问控制列表)文件精细控制每个客户端能订阅和发布哪些主题。例如,只允许ESP-RFID客户端发布到home/access/door1,只允许Shelly客户端订阅这个主题和自己的状态主题。
  4. 设备认证:为每个物联网设备使用独特的客户端ID和密码,避免使用通用密码。
  5. 逻辑防呆:在Shelly脚本中增加防误触发逻辑。例如,收到“开”指令后,设置一个3秒的“冷却期”,在此期间忽略所有同类指令,防止因网络波动导致消息重发造成的继电器快速通断。
  6. 后备电源:考虑为ESP-RFID、网络交换机和Mosquitto服务器(如果是小型设备如树莓派)配置UPS,避免停电导致门禁系统完全失效。对于Shelly控制的电锁,需了解其断电时的状态(是开还是关),并选择符合安全要求的锁具。

将ESP-RFID与外部Tasmota/Shelly通过MQTT整合,远不止是换了一种控制继电器的方式。它代表了一种架构思维的升级:从单体固件走向分布式系统,从硬编码逻辑走向可编程的、事件驱动的自动化。这个方案给了你一个坚实的、可扩展的基础框架。一旦跑通,你会发现,给这个系统增加一个新功能,往往不再是去修改复杂的嵌入式代码,而只是在Node-RED里拖拽几个节点,或者在Shelly里写几行简单的脚本。这种灵活性和效率的提升,才是这个项目带来的最大价值。我自己的车库门和室内几个智能灯联动,就是基于这个架构,稳定运行了超过一年,期间增减设备、修改逻辑都无比顺畅。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询