# 智能宠物喂食器 - MQTT 通信协议 ## 概述 本文档描述智能宠物喂食器微信小程序与 STM32 单片机之间的 MQTT 通信协议。 ## MQTT 连接配置 - **Broker 地址**: 根据实际情况配置 - **Broker 端口**: 根据实际情况配置(通常为 1883 或 8883) - **连接方式**: TLS 加密连接(推荐) - **客户端 ID**: 自动生成 ## 主题列表 | 主题 | 方向 | 说明 | |------|------|------| | `petfeeder/sensor` | STM32 → 小程序 | 传感器数据上报 | | `petfeeder/status` | STM32 → 小程序 | 设备状态上报 | | `petfeeder/control` | 小程序 → STM32 | 控制指令下发 | | `petfeeder/config` | 小程序 → STM32 | 配置参数下发 | --- ## 一、传感器数据上报 **Topic**: `petfeeder/sensor` **方向**: STM32 → 小程序 **频率**: 建议每 30 秒上报一次,或数据变化时立即上报 ### 数据格式 ```json { "temperature": 25.5, "humidity": 60, "foodWeight": 500, "waterLevel": 1 } ``` ### 字段说明 | 字段 | 类型 | 范围/值 | 说明 | |------|------|---------|------| | `temperature` | Float | -20~100 | 温度,单位:°C | | `humidity` | Integer | 0~100 | 湿度,单位:% | | `foodWeight` | Integer | 0~5000 | 食物重量,单位:克 | | `waterLevel` | Integer | 0 或 1 | 水位状态:0=缺水,1=满水 | ### 示例代码(STM32 C) ```c // 构造传感器数据 JSON void send_sensor_data(float temp, int hum, int weight, int water) { char payload[128]; snprintf(payload, sizeof(payload), "{\"temperature\":%.1f,\"humidity\":%d,\"foodWeight\":%d,\"waterLevel\":%d}", temp, hum, weight, water); // 发布到 MQTT broker mqtt_publish("petfeeder/sensor", payload); } ``` --- ## 二、设备状态上报 **Topic**: `petfeeder/status` **方向**: STM32 → 小程序 **触发**: 设备状态变化时上报,或小程序主动查询时上报 ### 数据格式 ```json { "mode": "auto" } ``` ### 字段说明 | 字段 | 类型 | 可选值 | 说明 | |------|------|--------|------| | `mode` | String | `auto` \| `manual` | 运行模式:auto=自动模式,manual=手动模式 | ### 示例代码(STM32 C) ```c // 发送状态数据 void send_device_status(const char* mode) { char payload[64]; snprintf(payload, sizeof(payload), "{\"mode\":\"%s\"}", mode); mqtt_publish("petfeeder/status", payload); } ``` --- ## 三、控制指令下发 **Topic**: `petfeeder/control` **方向**: 小程序 → STM32 ### 3.1 手动喂食指令 ```json { "action": "feed", "amount": 50, "timestamp": "2024-01-01T12:00:00.000Z" } ``` | 字段 | 类型 | 说明 | |------|------|------| | `action` | String | 固定值 `"feed"` | | `amount` | Integer | 喂食重量,单位:克 | | `timestamp` | String | ISO 8601 时间戳(可选) | **STM32 处理逻辑**: 控制舵机或电机转动,投放指定重量的食物 --- ### 3.2 手动补水指令 ```json { "action": "addWater", "timestamp": "2024-01-01T12:00:00.000Z" } ``` | 字段 | 类型 | 说明 | |------|------|------| | `action` | String | 固定值 `"addWater"` | | `timestamp` | String | ISO 8601 时间戳(可选) | **STM32 处理逻辑**: 控制水泵工作,向水箱注水 --- ### 3.3 设置运行模式 ```json { "action": "setMode", "mode": "auto", "timestamp": "2024-01-01T12:00:00.000Z" } ``` | 字段 | 类型 | 可选值 | 说明 | |------|------|--------|------| | `action` | String | 固定值 `"setMode"` | | `mode` | String | `auto` \| `manual` | 要设置的模式 | | `timestamp` | String | ISO 8601 时间戳(可选) | **STM32 处理逻辑**: 更新设备的运行模式状态 --- ### 3.4 查询设备状态 ```json { "action": "getStatus", "timestamp": "2024-01-01T12:00:00.000Z" } ``` | 字段 | 类型 | 说明 | |------|------|------| | `action` | String | 固定值 `"getStatus"` | | `timestamp` | String | ISO 8601 时间戳(可选) | **STM32 处理逻辑**: 立即发送当前状态到 `petfeeder/status` 主题 --- ## 四、配置参数下发 **Topic**: `petfeeder/config` **方向**: 小程序 → STM32 ### 数据格式 ```json { "feedTimes": ["08:00", "18:00"], "singleFeedWeight": 50 } ``` ### 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `feedTimes` | Array\ | 喂食时间点数组,格式 `HH:MM`,最多2个时间点 | | `singleFeedWeight` | Integer | 单次喂食重量,单位:克 | ### STM32 处理逻辑 1. 解析 `feedTimes` 数组,提取时间点 2. 存储到 RTC 或内部 Flash 3. 设置 RTC 闹钟,在指定时间触发自动喂食 4. 根据 `singleFeedWeight` 控制喂食量 ### 示例代码(STM32 C) ```c // 解析配置数据 void handle_config(const char* payload) { // 使用 JSON 解析库(如 cJSON)解析 payload // 提取 feedTimes 和 singleFeedWeight // 示例:存储喂食时间 char time1[8] = {0}; char time2[8] = {0}; int weight = 50; // 解析 JSON(使用 cJSON) cJSON* root = cJSON_Parse(payload); cJSON* feedTimes = cJSON_GetObjectItem(root, "feedTimes"); if (feedTimes && cJSON_IsArray(feedTimes)) { if (cJSON_GetArraySize(feedTimes) >= 1) { strcpy(time1, cJSON_GetArrayItem(feedTimes, 0)->valuestring); } if (cJSON_GetArraySize(feedTimes) >= 2) { strcpy(time2, cJSON_GetArrayItem(feedTimes, 1)->valuestring); } } cJSON* weightItem = cJSON_GetObjectItem(root, "singleFeedWeight"); if (weightItem) { weight = weightItem->valueint; } // 设置 RTC 闹钟 set_alarm(time1, weight); if (strlen(time2) > 0) { set_alarm(time2, weight); } cJSON_Delete(root); } ``` --- ## 五、STM32 MQTT 订阅列表 STM32 需要订阅以下主题以接收小程序指令: | 主题 | 说明 | |------|------| | `petfeeder/control` | 接收控制指令 | | `petfeeder/config` | 接收配置参数 | --- ## 六、通信流程示例 ### 6.1 自动喂食流程 ``` 1. STM32 启动后连接 MQTT Broker 2. STM32 订阅 petfeeder/control 和 petfeeder/config 3. STM32 定时上报传感器数据到 petfeeder/sensor 4. RTC 闹钟触发时间到 5. STM32 自动喂食(投放 singleFeedWeight 克食物) 6. STM32 上报新的 foodWeight 到 petfeeder/sensor ``` ### 6.2 手动喂食流程 ``` 1. 用户在小程序点击"喂食"按钮 2. 小程序发送控制指令到 petfeeder/control 3. STM32 收到 feed 指令 4. STM32 控制舵机投放指定重量的食物 5. STM32 更新 foodWeight 并上报到 petfeeder/sensor ``` ### 6.3 模式切换流程 ``` 1. 用户在小程序切换模式开关 2. 小程序发送 setMode 指令到 petfeeder/control 3. STM32 收到指令,更新运行模式 4. STM32 发送新的 mode 状态到 petfeeder/status 5. 小程序更新界面显示 ``` --- ## 七、STM32 建议实现 ### 7.1 定时任务 - **传感器上报**: 每 30 秒上报一次传感器数据 - **心跳保持**: 每 60 秒发送一次 MQTT PING - **状态检查**: RTC 中断检查是否到达喂食时间 ### 7.2 硬件接口 | 功能 | 硬件接口 | 说明 | |------|----------|------| | 温度传感器 | ADC/DHT22 | 温度采集 | | 湿度传感器 | ADC/DHT22 | 湿度采集 | | 食物重量 | ADC/称重模块 | 称重传感器 | | 水位检测 | GPIO/ADC | 水位开关或浮子传感器 | | 喂食执行 | PWM/GPIO | 舵机或步进电机 | | 补水执行 | GPIO | 水泵控制 | | RTC | 内部RTC/DS3231 | 实时时钟,用于定时喂食 | ### 7.3 JSON 解析库推荐 STM32 可使用以下 JSON 库: - **cJSON**: 轻量级,资源占用小 - **Jansson**: 功能完整,稍大 - **ArduinoJson**: 如果使用 Arduino 框架 --- ## 八、调试建议 ### 8.1 MQTT 测试工具 使用以下工具测试通信协议: - **MQTTX**: 跨平台 MQTT 客户端 - **mosquitto_pub/sub**: 命令行工具 ### 8.2 测试步骤 1. STM32 上电后,用 MQTTX 订阅 `petfeeder/sensor` 2. 检查传感器数据是否正确上报 3. 用 MQTTX 发布测试消息到 `petfeeder/control` 4. 验证 STM32 是否正确响应指令 5. 打开小程序,测试完整功能 --- ## 九、注意事项 1. **JSON 格式**: 所有 MQTT 消息必须是有效的 JSON 格式 2. **时间格式**: timestamp 使用 ISO 8601 标准格式 3. **错误处理**: STM32 应校验接收到的 JSON 格式,避免解析错误 4. **断线重连**: MQTT 断线后自动重连,重连后重新上报状态 5. **数据范围**: 传感器数据应在合理范围内,避免异常值 6. **喂食保护**: 避免短时间内重复喂食,设置最小间隔(如 10 分钟) --- ## 十、版本历史 | 版本 | 日期 | 说明 | |------|------|------| | v1.0 | 2024-02-10 | 初始版本 | --- ## 联系与反馈 如有问题或建议,请通过以下方式联系: - 项目地址: [项目 GitHub 链接] - Issue: [GitHub Issues]