第一次提交:完成了网关的单路485数据采集,还有以太网链接和MQTT配置,实现数据上报和命令下发,差一个断网储存
This commit is contained in:
441
README.md
Normal file
441
README.md
Normal file
@@ -0,0 +1,441 @@
|
||||
# Distributed Collector Gateway - 使用说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
本设备是一个分布式采集网关,支持通过 MQTT 远程控制 MODBUS RTU 轮询参数,并定期上报设备状态信息。
|
||||
|
||||
## SNTP 时间同步
|
||||
|
||||
设备内置 SNTP(Simple 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 驱动器输入 |
|
||||
Reference in New Issue
Block a user