Files
DistributedCollectorGateway/README.md

442 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Distributed Collector Gateway - 使用说明
## 功能概述
本设备是一个分布式采集网关,支持通过 MQTT 远程控制 MODBUS RTU 轮询参数,并定期上报设备状态信息。
## SNTP 时间同步
设备内置 SNTPSimple Network Time Protocol时间同步功能在网络连接成功后会自动同步系统时间。
### 时间同步特性
- **自动同步**:获取 IP 地址后自动启动 SNTP 客户端
- **多服务器支持**:配置了中国地区多个 NTP 服务器
- `cn.pool.ntp.org` - 中国 NTP 服务器
- `ntp1.aliyun.com` - 阿里云 NTP 服务器
- `ntp.tencent.com` - 腾讯云 NTP 服务器
- **时区设置**自动设置为北京时间CST-8
- **超时保护**:等待时间同步最长 10 秒,超时后使用本地时间继续运行
### 时间同步状态
设备会在启动日志中显示时间同步状态:
```
I (xxxx) SNTP_ESP: 初始化SNTP服务
I (xxxx) SNTP_ESP: 时区设置为北京时间 (CST-8)
I (xxxx) SNTP_ESP: 当前时间: 1970-01-01 08:00:00 Thursday (同步前)
I (xxxx) SNTP_ESP: 时间同步成功: 2026-02-01 15:30:45 (同步后)
I (xxxx) SNTP_ESP: 时间同步完成
```
### 时间在系统中的应用
同步后的时间会在以下场景中使用:
1. **设备状态上报** - `update_time` 字段显示精确的同步时间
2. **数据采集记录** - 可扩展用于记录数据采集时间戳
3. **日志时间戳** - 方便调试和问题追踪
### 注意事项
- 需要网络连接正常才能进行时间同步
- 首次启动时,时间同步可能需要几秒钟
- 如果网络连接异常,设备会使用本地时间继续工作
- 时间同步完成后,系统时间会持续由 SNTP 守护进程维护
## 设备状态上报
### 上报主题
`CONFIG_MQTT_PUB_TOPIC` (在 `sdkconfig` 中配置)
### 上报类型
设备会定期上报以下类型的数据:
1. **设备状态**`message_type: "device_status"`
2. **MODBUS 采集数据**`function_code: 3`
### 设备状态上报格式
```json
{
"message_type": "device_status",
"mac_address": "D0:CF:13:1B:C3:94",
"ip_address": "192.168.1.100",
"chip_model": "ESP32-S3",
"idf_version": "v5.5.2-dirty",
"uptime": 16,
"uptime_desc": "16秒",
"free_heap": 312996,
"status": "online",
"status_desc": "在线",
"update_time": "2026-02-01 15:30:45",
"led1_state": 1,
"led1_desc": "常亮",
"led1_function": "网络状态灯",
"led2_state": 4,
"led2_desc": "心跳",
"led2_function": "通信状态灯",
"modbus_enabled": 1,
"modbus_enabled_desc": "启用",
"modbus_channel": 0,
"modbus_channel_desc": "通道0 (UART0)",
"modbus_slave_addr": 1,
"modbus_interval": 1000,
"heap_status": "充足"
}
```
### 字段说明
#### 基本信息
| 字段 | 类型 | 说明 |
|------|------|------|
| `message_type` | string | 消息类型:`"device_status"` |
| `mac_address` | string | 设备 WiFi MAC 地址(唯一标识) |
| `ip_address` | string | 设备 IP 地址 |
| `chip_model` | string | 芯片型号 |
| `idf_version` | string | ESP-IDF 版本 |
#### 运行状态
| 字段 | 类型 | 说明 |
|------|------|------|
| `uptime` | number | 设备运行时间(秒) |
| `uptime_desc` | string | 运行时间中文描述(如:"1天5小时30分" |
| `free_heap` | number | 剩余堆内存(字节) |
| `heap_status` | string | 内存状态:`"充足"` / `"一般"` / `"紧张"` |
| `status` | string | 设备状态:`"online"` |
| `status_desc` | string | 设备状态中文描述:`"在线"` |
| `update_time` | string | 状态更新时间YYYY-MM-DD HH:MM:SS通过 SNTP 同步) |
#### LED 状态
| 字段 | 类型 | 说明 |
|------|------|------|
| `led1_state` | number | LED1 状态0=关闭, 1=常亮, 2=慢闪, 3=快闪, 4=心跳 |
| `led1_desc` | string | LED1 状态中文描述 |
| `led1_function` | string | LED1 功能:`"网络状态灯"` |
| `led2_state` | number | LED2 状态:同 LED1 |
| `led2_desc` | string | LED2 状态中文描述 |
| `led2_function` | string | LED2 功能:`"通信状态灯"` |
#### MODBUS 轮询状态
| 字段 | 类型 | 说明 |
|------|------|------|
| `modbus_enabled` | number | MODBUS 轮询是否启用0=禁用, 1=启用) |
| `modbus_enabled_desc` | string | 轮询状态中文描述:`"启用"` / `"禁用"` / `"未配置"` |
| `modbus_channel` | number | 当前使用的 RS485 通道0 或 1 |
| `modbus_channel_desc` | string | 通道中文描述 |
| `modbus_slave_addr` | number | 当前轮询的从机地址 |
| `modbus_interval` | number | 当前轮询间隔(毫秒) |
### 中文提示字段说明
带有 `_desc` 后缀的字段是中文提示字段,设计用于:
- **直接显示在 Web 页面上**,无需额外转换
- **不会被程序解析**,仅用于展示
- **提升用户体验**,让状态更直观
Web 页面可以选择显示:
- 程序解析字段(如 `led1_state`)用于逻辑判断
- 中文描述字段(如 `led1_desc`)用于界面显示
### 上报时机
- MQTT 订阅成功后立即上报一次
- 之后每隔 10 秒上报一次(可在 main.c 中修改 `mqtt_start_device_status_task(10000)` 的参数)
---
## MODBUS 控制说明
本设备是一个分布式采集网关,支持通过 MQTT 远程控制 MODBUS RTU 轮询参数。
## MQTT 控制指令
### 控制主题
发布控制指令到订阅主题:`CONFIG_MQTT_SUB_TOPIC` (在 `sdkconfig` 中配置)
### 指令格式 (JSON)
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000,
"enabled": true
}
```
### 参数说明
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `command` | string | 是 | 固定为 `"modbus_poll"` |
| `channel` | number | 是 | RS485 通道号 (0 或 1) |
| `slave_addr` | number | 是 | 从机地址 (1-247) |
| `start_addr` | number | 是 | 起始寄存器地址 (0-65535) |
| `reg_count` | number | 是 | 读取寄存器数量 (1-125) |
| `interval` | number | 是 | 轮询间隔(毫秒),最小 100ms |
| `enabled` | boolean | 否 | 是否启用轮询,默认 `true` |
## 使用示例
### 示例 1读取设备地址 1 的寄存器
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000
}
```
设备会每 1 秒读取一次从机地址 1从寄存器 0 开始的 2 个寄存器。
### 示例 2读取设备地址 10 的寄存器
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 10,
"start_addr": 0,
"reg_count": 5,
"interval": 2000
}
```
设备会每 2 秒读取一次从机地址 10从寄存器 0 开始的 5 个寄存器。
### 示例 3读取指定范围的寄存器
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 10,
"reg_count": 4,
"interval": 500
}
```
设备会每 500ms 读取一次从机地址 1从寄存器 10 开始的 4 个寄存器(地址 10, 11, 12, 13
### 示例 4停止轮询
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000,
"enabled": false
}
```
设置 `"enabled": false` 可以暂停轮询任务。
### 示例 5使用 RS485 通道 1
```json
{
"command": "modbus_poll",
"channel": 1,
"slave_addr": 5,
"start_addr": 0,
"reg_count": 10,
"interval": 1000
}
```
使用 RS485 通道 1 进行轮询。
## 数据上报
### 上报主题
`CONFIG_MQTT_PUB_TOPIC` (在 `sdkconfig` 中配置)
### 上报数据格式 (JSON)
```json
{
"channel": "RS485-1",
"slave_addr": 1,
"function_code": 3,
"status": "success",
"byte_count": 4,
"register_count": 2,
"registers": [
556,
998
]
}
```
### 字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `channel` | string | RS485 通道名称 |
| `slave_addr` | number | 从机地址 |
| `function_code` | number | MODBUS 功能码(始终为 3 |
| `status` | string | 状态:`"success"``"exception"` |
| `byte_count` | number | 数据字节数 |
| `register_count` | number | 寄存器数量 |
| `registers` | array | 寄存器值数组 |
### 异常响应格式
```json
{
"channel": "RS485-1",
"slave_addr": 1,
"function_code": 131,
"status": "exception",
"exception_code": 2
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `exception_code` | number | 异常码:<br>1 - 非法功能<br>2 - 非法数据地址<br>3 - 非法数据值<br>4 - 服务器设备故障 |
## 动态更新
每次发送 MQTT 控制指令都会立即更新轮询参数,无需重启设备。
### 更新流程
1. 发送新的控制指令
2. 设备接收并解析 JSON
3. 立即更新轮询配置
4. 下一次轮询使用新参数
## MQTT 控制指令
### 控制主题
发布控制指令到订阅主题:`CONFIG_MQTT_SUB_TOPIC` (在 `sdkconfig` 中配置)
### 指令格式 (JSON)
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000,
"enabled": true
}
```
### 参数说明
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `command` | string | 是 | 固定为 `"modbus_poll"` |
| `channel` | number | 是 | RS485 通道号 (0 或 1) |
| `slave_addr` | number | 是 | 从机地址 (1-247) |
| `start_addr` | number | 是 | 起始寄存器地址 (0-65535) |
| `reg_count` | number | 是 | 读取寄存器数量 (1-125) |
| `interval` | number | 是 | 轮询间隔(毫秒),最小 100ms |
| `enabled` | boolean | 否 | 是否启用轮询,默认 `true` |
### 支持的指令类型
当前支持以下控制指令:
#### 1. MODBUS 轮询控制
```json
{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000,
"enabled": true
}
```
#### 2. 设备状态上报间隔控制(可选扩展)
可通过修改 `main.c` 中的参数来调整状态上报间隔:
```c
mqtt_start_device_status_task(10000); // 10000ms = 10秒
```
或运行时调用 API
```c
mqtt_update_report_interval(5000); // 5秒
```
## 注意事项
1. **轮询间隔最小为 100ms**,设置更小的值会被拒绝
2. **寄存器数量最大为 125**MODBUS RTU 限制
3. **从机地址范围 1-247**0 为广播地址
4. **通道号只能是 0 或 1**
5. 首次发送指令后会自动启动轮询任务
## 使用 mosquitto_cli 测试
### 发送控制指令
```bash
mosquitto_pub -h <broker_ip> -p 1883 -t <sub_topic> -m '{
"command": "modbus_poll",
"channel": 0,
"slave_addr": 1,
"start_addr": 0,
"reg_count": 2,
"interval": 1000
}'
```
### 监听数据上报
```bash
mosquitto_sub -h <broker_ip> -p 1883 -t <pub_topic>
```
## 硬件连接
### RS485 通道 0 (UART0)
| 引脚 | GPIO | 功能 |
|------|------|------|
| RO (RX) | GPIO 41 | RS485 接收器输出 |
| DE/RE | GPIO 42 | 数据使能/接收器使能 |
| DI (TX) | GPIO 44 | RS485 驱动器输入 |
### RS485 通道 1 (UART2)
| 引脚 | GPIO | 功能 |
|------|------|------|
| RO (RX) | GPIO 43 | RS485 接收器输出 |
| DE/RE | GPIO 2 | 数据使能/接收器使能 |
| DI (TX) | GPIO 1 | RS485 驱动器输入 |