ESP32 DIY温湿度传感器接入米家全流程:从平台配置到代码实现

发布时间:2026/9/2 19:07:01
ESP32 DIY温湿度传感器接入米家全流程:从平台配置到代码实现 在实际智能家居项目中我们常常会遇到一些非米家原生的、自己动手制作DIY的智能设备比如用ESP8266/ESP32开发板制作的温湿度传感器、智能开关或自定义控制器。这些设备功能正常但无法直接与庞大的米家生态联动无法通过米家App统一控制也无法参与米家自动化场景这大大限制了其价值。将DIY设备接入米家本质上是一个设备“入云”和“协议对接”的过程它能让你的自制硬件获得与商业产品同等的智能体验。本文将以一个典型的ESP32温湿度传感器为例带你走通从零开始将DIY设备接入米家的完整路径。整个过程不涉及任何复杂的逆向工程而是基于小米面向开发者的官方与开源方案重点在于理解其背后的认证、通信和控制逻辑。你将学习到如何为设备配置Wi-Fi、如何与小米IoT平台建立安全连接、如何上报数据以及如何接收来自米家App的指令。完成本文的实践后你将掌握一套方法论可以举一反三地将各类基于ESP8266/ESP32或其他支持MQTT的微控制器接入米家。1. 理解米家设备接入的核心机制与准备工作在动手写代码之前必须厘清几个核心概念否则后续的配置和调试会困难重重。米家设备的接入并非一个简单的“配对”动作其背后是一套完整的云-端认证与控制体系。1.1 米家IoT平台与设备三元组小米为开发者提供了“小米IoT开发者平台”。DIY设备想要接入首先需要在这个平台上进行产品创建和设备注册。平台会为每一个设备实例分配一组唯一的凭证通常被称为“设备三元组”Product ID (PID)产品ID代表你创建的某一类产品。Device ID (DID)设备ID代表这个产品下的一个具体设备。Device Secret设备密钥用于设备与云端建立连接时的身份认证和通信加密。这组三元组是设备在小米IoT云中的“身份证”任何通信都必须携带这些信息。对于DIY设备我们需要在固件中妥善保管并使用这些凭证。1.2 通信协议MQTT与MiOT米家生态主要使用两种协议进行通信MQTT一种轻量级的发布/订阅消息传输协议是小米IoT平台与设备间数据通信的骨干。设备通过MQTT客户端连接至小米的MQTT Broker订阅特定的主题Topic以接收指令并向特定主题发布消息以上报状态或属性。MiOT协议小米自定义的物联网协议定义了设备功能、属性、事件和动作的标准模型。它通常以JSON格式的数据在MQTT通道中传输。简单理解MQTT是“高速公路”而MiOT协议是公路上跑的“标准化货车”及其“货物格式”。我们的DIY设备需要实现一个MQTT客户端并按照MiOT协议格式组装和解析数据。1.3 开源库的选择miio vs. miot-codeless对于嵌入式开发我们不必从零实现所有协议。社区和官方提供了开源库来简化开发miio早期用于与小米Wi-Fi设备如净化器、网关通信的库部分协议已公开。但对于接入米家App的新设备直接使用它较为复杂。miot-codeless这是目前更推荐的方式。它并非完全“无代码”而是小米提供的一套面向嵌入式设备特别是乐鑫ESP系列的SDK和示例代码封装了连接、认证、数据上报等复杂流程。我们将主要依托此方案进行开发。1.4 环境与物料准备在开始前请确保准备好以下软硬件环境硬件清单ESP32开发板一块如NodeMCU-32S、ESP32-DevKitC。DHT11或DHT22温湿度传感器模块一个。杜邦线若干。微型USB数据线用于供电和烧录程序。软件与环境清单Arduino IDE或PlatformIO推荐。本文将使用Arduino IDE进行演示因其受众更广。在Arduino IDE中安装ESP32开发板支持。可通过“文件”-“首选项”-“附加开发板管理器网址”中添加https://espressif.github.io/arduino-esp32/package_esp32_index.json然后在“工具”-“开发板”-“开发板管理器”中搜索安装“esp32”。注册小米IoT开发者平台账号 https://iot.mi.com 。一个可用的2.4GHz Wi-Fi网络ESP32通常不支持5GHz。2. 在小米IoT平台创建产品与设备这是将虚拟产品与实体设备关联的关键一步所有后续代码中的配置都源于此。2.1 创建新产品登录小米IoT开发者平台。进入“产品”页面点击“创建产品”。选择产品类别例如“传感器”-“温湿度传感器”。产品名称可自定义如“DIY温湿度计”。在“联网方式”中选择“Wi-Fi”。在“技术方案”选择上对于DIY设备我们通常选择“自定义方案”如果你使用ESP32也可以留意是否有“MCU方案”的选项但自定义方案自由度更高。完成创建后进入产品详情页记录下你的Product ID (PID)。2.2 定义设备功能属性与事件MiOT协议的核心是数据模型。我们需要定义设备能做什么属性和能报告什么事件。在产品详情页找到“功能定义”或“物模型”相关选项。我们需要添加两个属性温度属性名可设为temperature数据类型为浮点数float单位摄氏度℃访问模式为“可读”设备上报App读取。湿度属性名可设为humidity数据类型为浮点数float单位百分比%RH访问模式为“可读”。保存功能定义。平台会为每个属性生成一个唯一的SIID服务ID、PIID属性ID。请务必记录下温度、湿度属性对应的SIID和PIID后续代码中需要用到。例如温度SIID2, PIID1湿度SIID2, PIID2 具体数值以平台实际生成为准2.3 添加测试设备并获取三元组在产品详情页找到“设备管理”或“测试设备”选项。点击“添加设备”你可以为设备命名如“客厅传感器”。添加成功后平台会生成该设备的Device ID (DID)和Device Secret。请立即妥善保存这三元组PID, DID, Device SecretDevice Secret通常只显示一次。至此云端的产品和设备信息已配置完成。接下来我们将重心转移到设备端固件开发。3. 设备端固件开发与代码详解我们将编写一个Arduino程序让ESP32读取DHT传感器数据并通过Wi-Fi连接到小米IoT平台上报数据。3.1 硬件连接与库安装首先进行硬件连接以DHT11为例DHT11 VCC 接 ESP32 3.3VDHT11 GND 接 ESP32 GNDDHT11 DATA 接 ESP32 某个GPIO引脚例如 GPIO4在Arduino IDE中我们需要安装必要的库点击“项目”-“加载库”-“管理库”。搜索并安装DHT sensor library作者Adafruit。搜索并安装PubSubClient作者Nick O‘Leary。这是一个通用的MQTT客户端库我们将用它进行通信。由于小米的认证流程需要一些加密算法我们可能还需要ArduinoJson库来处理JSON数据。3.2 核心代码实现以下是完整的Arduino草图Sketch代码请将中的内容替换为你自己的信息。#include WiFi.h #include PubSubClient.h #include DHT.h // 1. Wi-Fi 配置 const char* ssid 你的Wi-Fi名称; const char* password 你的Wi-Fi密码; // 2. 小米IoT平台设备三元组 (从平台获取) const char* productID 你的PID; const char* deviceID 你的DID; const char* deviceSecret 你的DeviceSecret; // 3. 小米IoT MQTT 服务器地址 const char* mqtt_server cn.iot.mi.com; // 国内服务器 // 4. DHT传感器配置 #define DHTPIN 4 // DHT数据引脚连接的GPIO #define DHTTYPE DHT11 // DHT 11 DHT dht(DHTPIN, DHTTYPE); // 全局对象 WiFiClient espClient; PubSubClient client(espClient); unsigned long lastMsgTime 0; const long reportInterval 30000; // 每30秒上报一次数据 // 生成MQTT客户端ID和用户名密码基于小米规范 String generateClientId() { return String() deviceID; } String generateUsername() { return String() deviceID; } // 生成密码这是一个简化示例。实际生产中密码生成更复杂涉及签名算法。 // 对于学习和测试有时平台会提供固定的密码生成规则或直接提供密码。 // 此处我们先使用一个占位符后续需要根据平台文档实现签名。 String generatePassword() { // 警告此处仅为示例并非真实可用的密码生成算法。 // 真实密码通常需要将 deviceSecret 与其它参数进行HMAC-SHA256签名。 // 请务必参考小米IoT平台最新的设备端接入文档实现。 return String(token) deviceSecret clientId deviceID; } // 连接Wi-Fi void setupWiFi() { delay(10); Serial.println(); Serial.print(正在连接到: ); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(); Serial.println(WiFi连接成功); Serial.print(IP地址: ); Serial.println(WiFi.localIP()); } // MQTT回调函数用于接收云端指令 void callback(char* topic, byte* payload, unsigned int length) { Serial.print(收到消息 [); Serial.print(topic); Serial.print(]: ); for (int i 0; i length; i) { Serial.print((char)payload[i]); } Serial.println(); // 此处可以解析payloadJSON格式根据指令控制设备如开关 } // 连接/重连MQTT Broker void reconnectMQTT() { while (!client.connected()) { Serial.print(尝试MQTT连接...); String clientId generateClientId(); String username generateUsername(); String password generatePassword(); if (client.connect(clientId.c_str(), username.c_str(), password.c_str())) { Serial.println(MQTT连接成功); // 订阅设备控制主题格式通常为 /{PID}/{DID}/cmd String subscribeTopic String(/) productID / deviceID /cmd; client.subscribe(subscribeTopic.c_str()); Serial.print(已订阅主题: ); Serial.println(subscribeTopic); } else { Serial.print(连接失败 rc); Serial.print(client.state()); Serial.println( 5秒后重试...); delay(5000); } } } // 按照MiOT协议格式上报属性数据 void reportProperties(float temp, float humi) { // 构建一个简化的属性上报JSON消息 // 实际格式需严格参照小米MiOT协议文档 String payload {; payload \id\:12345,; // 消息ID可自增 payload \method\:\properties_changed\,; payload \params\:{; // 假设温度属性 SIID2, PIID1 payload \2.1\: String(temp) ,; // 假设湿度属性 SIID2, PIID2 payload \2.2\: String(humi); payload }; payload }; String publishTopic String(/) productID / deviceID /properties; client.publish(publishTopic.c_str(), payload.c_str()); Serial.println(数据已上报: payload); } void setup() { Serial.begin(115200); dht.begin(); setupWiFi(); client.setServer(mqtt_server, 1883); // MQTT默认端口1883 client.setCallback(callback); } void loop() { if (!client.connected()) { reconnectMQTT(); } client.loop(); // 维持MQTT连接并处理接收到的消息 unsigned long now millis(); if (now - lastMsgTime reportInterval) { lastMsgTime now; // 读取传感器数据 float humidity dht.readHumidity(); float temperature dht.readTemperature(); // 检查读取是否成功 if (isnan(humidity) || isnan(temperature)) { Serial.println(读取DHT传感器失败!); return; } Serial.print(温度: ); Serial.print(temperature); Serial.print( °C, 湿度: ); Serial.print(humidity); Serial.println( %); // 上报数据到云端 reportProperties(temperature, humidity); } }3.3 关键代码段解释设备三元组productID,deviceID,deviceSecret是代码与云端设备绑定的核心必须准确无误。MQTT连接认证generatePassword()函数是最大的难点和关键点。示例中的生成方式仅为示意。小米IoT平台对MQTT连接的密码有严格的签名算法要求通常需要用到deviceSecret对特定字符串进行HMAC-SHA256运算。你必须查阅小米IoT平台最新的设备端开发文档找到正确的密码生成算法并实现它。连接失败client.state()返回4或5大多源于此。MiOT协议数据格式reportProperties函数中构建的JSON字符串是上报数据的载体。属性键“2.1”对应SIID.PIID。这个格式必须与你在平台定义的功能模型完全匹配。更复杂的设备可能涉及事件上报、动作响应等需要参考官方协议文档。主题Topic订阅主题 (/PID/DID/cmd) 用于接收控制指令发布主题 (/PID/DID/properties) 用于上报属性。这是小米IoT平台约定的主题格式。4. 编译、烧录与运行验证4.1 编译与烧录在Arduino IDE中选择正确的开发板如“ESP32 Dev Module”和端口。点击“上传”按钮编译并烧录程序到ESP32。4.2 串口监视器调试打开串口监视器波特率115200观察输出日志。正常流程如下连接Wi-Fi成功打印IP地址。尝试MQTT连接。如果密码算法正确会打印“MQTT连接成功”和“已订阅主题”。每30秒读取一次传感器数据并打印同时尝试上报。如果上报成功可能在日志中看到更详细的信息取决于库和服务器响应。4.3 在米家App中绑定设备这是验证接入是否成功的最终步骤。打开米家App点击右上角“”添加设备。由于我们的产品是“未发布”的测试产品它不会出现在品类列表中。你需要使用“手动添加”功能。在手动添加页面你需要输入设备的蓝牙MAC地址或二维码。对于Wi-Fi设备平台通常会在设备详情页为测试设备生成一个绑定二维码。回到小米IoT开发者平台找到你添加的测试设备查看其信息应该能找到“绑定二维码”或一串用于绑定的数字ID。在米家App中扫描此二维码或输入ID按照提示完成绑定通常需要设备进入配网模式我们的代码是自动连接Wi-Fi的所以确保设备已通电并运行。绑定成功后设备应该出现在米家App的“我的设备”列表中。点击进入设备页面你应该能看到实时更新的温度和湿度数据。5. 常见问题排查与解决方案将DIY设备接入米家的过程可能遇到各种问题下表列出了常见现象、原因及排查方向问题现象可能原因排查步骤与解决方案Wi-Fi连接失败SSID/密码错误路由器仅支持5GHz信号太弱。1. 检查代码中SSID/密码。2. 确认路由器开启2.4GHz网络。3. 查看串口日志确认连接过程。MQTT连接失败(state4, 5)设备三元组错误MQTT密码生成算法错误网络无法访问IoT服务器。1. 核对PID、DID、DeviceSecret。2.重点检查generatePassword()函数确保其算法与平台最新文档一致。3. 尝试Pingcn.iot.mi.com测试网络连通性。设备无法在米家App中找到/绑定产品未发布未使用手动添加绑定二维码错误设备未进入配网状态对于需要按键配网的型号。1. 使用米家App的“手动添加”或“扫码”功能。2. 使用IoT平台提供的该测试设备专属的绑定二维码而非产品二维码。3. 有些方案需要设备先进入配网模式如快闪确保代码逻辑正确。App中显示设备离线MQTT连接已断开设备断电或网络异常设备端代码存在BUG导致重启。1. 查看串口日志确认MQTT是否保持连接。2. 检查设备供电和Wi-Fi稳定性。3. 检查代码是否存在内存泄漏或看门狗复位。数据上报但App不显示属性上报的JSON格式错误SIID/PIID与平台定义不匹配数据类型不匹配。1. 在串口打印出准备上报的JSON字符串与MiOT协议示例对比。2. 核对平台功能定义中属性的SIID和PIID。3. 确保上报的数值类型如float与定义一致。设备频繁重启代码存在内存访问错误看门狗超时电源不稳定。1. 检查数组越界、空指针等。2. 在长时间循环操作中适当加入delay()或调用yield()。3. 使用稳定的5V/1A以上电源适配器供电。6. 生产环境考量与最佳实践本文示例旨在跑通流程。若想用于更稳定、可靠的环境还需考虑以下方面6.1 安全增强密钥管理切勿将设备三元组硬编码在源码中。对于量产应考虑在首次配网时通过安全通道如蓝牙配网从手机App下发或使用芯片的安全存储区域。固件签名与升级实现OTA升级功能并对升级固件进行签名验证防止恶意固件刷入。通信加密确保MQTT连接使用TLS加密端口8883示例中未启用生产环境必须启用。6.2 可靠性提升健壮的Wi-Fi连接实现Wi-Fi断开自动重连并处理多种网络异常情况。MQTT持久化与遗嘱设置MQTT的cleanSession为false并设置遗嘱消息以便设备异常离线时云端能及时知晓。数据缓存与重发在网络不稳定时将待上报数据缓存在非易失性存储器中待网络恢复后重发。功耗优化对于电池供电设备采用深度睡眠、定时唤醒上报的策略大幅延长续航。6.3 功能完善实现设备控制在callback函数中完整解析云端下发的控制指令如开关命令并执行相应操作。上报事件除了属性还可以上报事件如“检测到漏水”。支持本地自动化如果设备是传感器可以考虑与米家多模网关等本地中枢配合实现更快的本地自动化触发。通过以上步骤你不仅成功将一个具体的DIY传感器接入了米家更重要的是掌握了接入流程的通用框架平台创建设备、获取凭证、设备端实现MQTT连接与MiOT协议数据封装。这套方法可以扩展到智能开关、灯光控制器、环境监测仪等各种DIY设备上。下一步你可以尝试为设备添加更多的可控属性或者探索如何通过米家自动化场景让你自制的设备与其他智能设备联动真正释放智能家居的潜力。