Compare commits

...

5 Commits

Author SHA1 Message Date
yuhaiming
319ebd19ad MQTT通信修改 使用服务器数据库 2026-06-30 08:12:35 +08:00
yuhaiming
0098220a9a chore(sql): 5.5.3→5.6.0 升级脚本补充设备二维码与浇水日志备注字段
- app_device 增加 qrcode 字段(设备二维码 URL,1000)
- app_watering_log 增加 remark 字段(备注,500)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-23 15:38:33 +08:00
yuhaiming
0f165b50ff fix: MQTT 排程完成回调移除无效的 LoginHelper.getUserId
MQTT 消息处理线程没有登录上下文,LoginHelper.getUserId() 取不到值
还会覆盖 buildWateringLog 里基于设备查询设置的 userId

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-23 15:38:19 +08:00
yuhaiming
228a01843f chore: 补充忽略 AI 工具本地目录与构建产物
新增 .flattened-pom.xml、node_modules、各类 AI 工具目录
(.claude/.codex/.workbuddy/... 共 30+)的忽略规则,避免
本地工具痕迹进入版本控制

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-23 15:38:09 +08:00
yuhaiming
694e32abbf fix: 设备删除增加用户校验、ACK 在线状态刷新改非阻塞、停止跟踪日志
- AppDeviceServiceImpl#deleteWithValidByIds 校验设备归属当前用户,
  避免任意已登录用户越权删除其他用户的设备及关联数据
- MqttCommandAckService#refreshDeviceOnline 由 lock.lock 改为 tryLock,
  防止 MQTT 处理线程在状态刷新锁上排队堆积;状态写入幂等,跳过本次刷新
  由后续 ACK 兜底
- 从版本控制中移除 logs/ 历史日志,gitignore 已忽略该目录

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-23 15:36:38 +08:00
34 changed files with 440 additions and 731 deletions

43
.gitignore vendored
View File

@@ -3,6 +3,49 @@
/water-modules/*/target/
/logs/
/water-extend/*/target/
/.flattened-pom.xml
/**/.flattened-pom.xml
# Node / local AI tooling
/node_modules/
/package-lock.json
/package.json
/skills-lock.json
/.codegraph/
/.agent/
/.agents/
/.amazonq/
/.augment/
/.bob/
/.claude/
/.cline/
/.clinerules/
/.codebuddy/
/.codex/
/.comet/
/.continue/
/.cospec/
/.crush/
/.cursor/
/.factory/
/.forge/
/.gemini/
/.github/
/.iflow/
/.junie/
/.kilocode/
/.kimi/
/.kimi-code/
/.kiro/
/.lingma/
/.opencode/
/.pi/
/.qoder/
/.qwen/
/.roo/
/.trae/
/.windsurf/
/.workbuddy/
# IDE
.idea/

View File

@@ -2,6 +2,8 @@
本文档说明后端服务与嵌入式设备之间的 MQTT Topic、通信方向、Payload 类型和 JSON 数据格式。
> **Topic 标识变更v5.6 起)**:除首次注册回复 `registerDeviceNo` 仍按 **MAC 地址** 下发外,其余 MQTT 下行命令 Topic 第一段统一使用**设备编号 deviceNo**。后端上行处理通过 `DeviceIdentityResolver` 兼容 MAC / 设备编号两种入参;下行命令请按 `deviceNo` 订阅 `subscriber/cmd` 或 `subscriber/schedule`。业务字段payload 中的 `deviceNo`、数据库主键、API 入参)仍是设备编号,未变更。
当前配置位置:
- 后端订阅配置:`water-admin/src/main/resources/application.yml`
@@ -14,8 +16,8 @@
| --- | --- |
| Broker | `mqtt.broker-url` |
| QoS | `mqtt.qos`,当前默认 `1` |
| 设备编号 | Topic 第一段 `{deviceNo}` |
| Topic 变量 | 文档中的 `{deviceNo}` 替换为真实设备编号,例如 `/01/publish/register` |
| 设备标识 | 上行 Topic 第一段可为设备 **MAC** `deviceNo`;下行命令 Topic 第一段统一使用 `deviceNo`,仅 `registerDeviceNo` 例外仍使用 MAC |
| Topic 变量 | 上行文档中的 `{deviceNo}` 表示设备标识占位符;下行文档中的 `{deviceNo}` 即设备编号 |
| JSON 编码 | UTF-8 |
| 时间格式 | `yyyy-MM-dd HH:mm:ss` |
@@ -52,22 +54,19 @@
| Topic | `/{deviceNo}/publish/register` |
| Payload 类型 | JSON |
后端以 Topic 中的 `{deviceNo}` 作为设备编号payload 中的 `deviceNo` 即使传入也会被 Topic 覆盖。
后端以 Topic 中的设备标识作为解析入口payload 中的 `deviceNo` 即使传入也会被 Topic 覆盖。
示例:
```json
{
"deviceName": "一号浇水设备",
"status": "1",
"workStatus": "0",
"powerLevel": "86",
"wifiName": "office-wifi",
"deviceEm": "WATER-EM-01",
"deviceSn": "SN202606100001",
"fwVer": "1.0.0",
"macAddress": "AA:BB:CC:DD:EE:FF",
"bindToken": "123456"
"macAddress": "AA:BB:CC:DD:EE:FF"
}
```
@@ -76,15 +75,11 @@
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| deviceName | string | 否 | 设备名称 |
| status | string | 否 | 设备状态:`1` 在线,`0` 离线,`2` 到期,`3` 故障;为空时后端默认 `2` |
| workStatus | string | 否 | 工作状态:`0` 休息,`1` 工作 |
| powerLevel | string | 否 | 电量 |
| wifiName | string | 否 | WiFi 名称 |
| deviceEm | string | 否 | 设备型号 |
| deviceSn | string | 否 | 设备序列号 |
| fwVer | string | 否 | 固件版本 |
| macAddress | string | 否 | MAC 地址 |
| bindToken | string | 否 | 设备绑定令牌 |
## 电量上报
@@ -99,7 +94,9 @@
```json
{
"powerLevel": "86"
"deviceName": "Waterer_01",
"powerLevel": "86",
"charging": 1
}
```
@@ -193,6 +190,17 @@ receive
}
```
## 设备编号下发
| 项目 | 内容 |
| --- | --- |
| 功能名称 | 设备编号下发 |
| 通信方向 | 后端发布,设备订阅 |
| Topic | `/{deviceMac}/subscriber/cmd` |
| Payload 类型 | JSON |
说明:这是首次注册后的唯一例外,后端按设备 MAC 回传设备编号;其余下行命令都使用 `deviceNo` 作为 Topic 第一段。
## 排程任务完成上报
| 项目 | 内容 |
@@ -300,7 +308,7 @@ JSON 示例:
1. 设备启动后发布注册消息到 `/{deviceNo}/publish/register`
2. 设备定时或电量变化时发布电量到 `/{deviceNo}/publish/power`
3. 设备订阅自己的命令 Topic`/{deviceNo}/subscriber/cmd`
3. 设备订阅自己的命令 Topic`/{deviceNo}/subscriber/cmd``/{deviceNo}/subscriber/schedule`
4. 设备收到命令后立即返回 ACK 到 `/{deviceNo}/publish/ack`,推荐返回 JSON 并携带 `commandId`
5. 排程或按键浇水完成后,分别发布到 `/{deviceNo}/publish/finish/schedule``/{deviceNo}/publish/finish/key`
6. 硬件异常时发布到 `/{deviceNo}/publish/error`

View File

@@ -1,327 +0,0 @@
2026-06-13 08:59:11 [master:housekeeper] WARN com.zaxxer.hikari.pool.HikariPool - master - Thread starvation or clock leap detected (housekeeper delta=14h57m13s457ms410µs100ns).
2026-06-13 08:59:32 [MQTT Ping: water-server-8081] ERROR o.e.p.c.mqttv3.internal.ClientState - water-server-8081: Timed out as no write activity, keepAlive=60,000,000,000 lastOutboundActivity=150,167,329,517,400 lastInboundActivity=150,167,356,610,400 time=204,053,810,500,400 lastPing=150,167,329,537,400
2026-06-13 08:59:32 [MQTT Ping: water-server-8081] WARN org.dromara.mqtt.MqttClientManager - [MQTT] 连接已断开Timed out while waiting to write messages to the server
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已重新连接ssl://service.reinkun.com:8883
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/finish/schedule 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/register 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/power 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/ack 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/finish/key 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/error 服务质量等级=1
2026-06-13 08:59:34 [mqtt-consumer-7] WARN o.d.a.handler.ScheduleFinishHandler - [MQTT] 排程完成上报未找到设备绑定的排程 时间=2026-06-13 08:59:34 设备编号=01
2026-06-13 08:59:34 [mqtt-consumer-4] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 50,
"charging": 0
}
2026-06-13 08:59:34 [mqtt-consumer-7] INFO o.d.a.handler.ScheduleFinishHandler - [MQTT] 浇水排程上报已保存 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceNo": "01",
"startWeek": 5,
"startTime": "2026-06-11 8:20",
"durationMin": 20,
"triggerType": "mqtt on",
"triggerON":"mqtt on",
"triggerOFF":"mqtt off"
}
2026-06-13 08:59:34 [mqtt-consumer-8] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 63,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:00:02 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:00:02 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[19]毫秒
2026-06-13 09:00:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:00:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:00:52 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:00:52 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[9]毫秒
2026-06-13 09:01:28 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:01:28 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:02:04 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:02:04 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:02:06 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:02:06 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:05:12 [schedule-pool-10] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[3]毫秒
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:06:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:06:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[8]毫秒
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:08:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9c"}]
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[2]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:08:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:08:49 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:49 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:08:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:08:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 09:08:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:09:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:09:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:09:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:09:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:11:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:11:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:12:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:12:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:12:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:12:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 09:13:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:13:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:15:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:15:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:15:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[5]毫秒
2026-06-13 09:15:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/scheduleDeviceList/2062827585485807618],无参数
2026-06-13 09:15:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/scheduleDeviceList/2062827585485807618],耗时:[7]毫秒
2026-06-13 09:15:36 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addScheduleDevice],参数类型[JSON],参数:[{"scheduleId":"2062827585485807618","deviceNos":["1779176626954"]}]
2026-06-13 09:15:36 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addScheduleDevice],耗时:[20]毫秒
2026-06-13 09:15:37 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:37 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[11]毫秒
2026-06-13 09:15:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[4]毫秒
2026-06-13 09:15:46 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:46 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[6]毫秒
2026-06-13 09:15:50 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:15:50 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:15:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[6]毫秒
2026-06-13 09:17:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:17:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:17:47 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:17:47 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[8]毫秒
2026-06-13 09:17:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:17:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[9]毫秒
2026-06-13 09:17:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:17:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:24:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:24:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:24:17 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:24:17 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:26:05 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:26:05 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:26:07 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:26:07 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:27:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:27:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:27:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:27:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[22]毫秒
2026-06-13 09:46:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:46:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[26]毫秒
2026-06-13 09:46:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[16]毫秒
2026-06-13 09:46:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[20]毫秒
2026-06-13 09:46:58 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:58 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:47:10 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:47:10 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:47:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:47:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:49:16 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:49:16 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:49:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:49:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["666"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[12]毫秒
2026-06-13 09:49:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:51:11 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 09:51:11 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[34]毫秒
2026-06-13 09:51:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:51:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:51:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:51:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:51:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:51:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:51:33 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:51:33 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[7]毫秒
2026-06-13 09:53:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:53:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9c"}]
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[4]毫秒
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:54:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:21 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9e"}]
2026-06-13 09:54:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[1]毫秒
2026-06-13 09:54:21 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:46 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:46 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[4]毫秒
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:55:12 [mqtt-consumer-16] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 09:55:12 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:55:12 [mqtt-consumer-13] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 09:55:12 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 09:55:12 [mqtt-consumer-14] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"浇水设备007","wifiName":"研发部","wifiPassword":"ckkj123456","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 09:55:38 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"73669072eb924e9f9772d80fb9be57f8","bindStatus":true}
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=73669072eb924e9f9772d80fb9be57f8
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[39]毫秒
2026-06-13 09:55:38 [mqtt-consumer-11] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=73669072eb924e9f9772d80fb9be57f8 状态=null
2026-06-13 09:55:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:55:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:55:59 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:56:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[1]毫秒
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:57:15 [mqtt-consumer-8] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 09:57:15 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:57:15 [mqtt-consumer-8] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 09:57:15 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 09:57:15 [mqtt-consumer-12] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"智能浇水","wifiName":"测试机","wifiPassword":"66668888","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 09:57:39 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"a783262582fd41fcb09d59d55a07c9e3","bindStatus":true}
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=a783262582fd41fcb09d59d55a07c9e3
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[35]毫秒
2026-06-13 09:57:40 [mqtt-consumer-3] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=a783262582fd41fcb09d59d55a07c9e3 状态=null
2026-06-13 09:57:40 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:57:40 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:59:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:59:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:59:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:59:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:02:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:02:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:02:11 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:02:11 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 10:02:12 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:02:12 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 10:03:42 [schedule-pool-5] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 10:04:26 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:04:26 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:11:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:11:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 10:12:03 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:12:03 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 10:12:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:12:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[13]毫秒
2026-06-13 10:12:28 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:28 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 10:12:36 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:36 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[7]毫秒
2026-06-13 10:12:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["66"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 10:12:42 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:42 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:16:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:16:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[7]毫秒
2026-06-13 10:16:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:16:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:16:46 [mqtt-consumer-1] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 10:16:46 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 10:16:46 [mqtt-consumer-16] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 10:16:46 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 10:16:47 [mqtt-consumer-16] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"还是浇水设备","wifiName":"研发部","wifiPassword":"ckkj123456","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 10:16:57 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"00119ae0fc844c1c88d61052e1ded66b","bindStatus":true}
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=00119ae0fc844c1c88d61052e1ded66b
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[36]毫秒
2026-06-13 10:16:57 [mqtt-consumer-6] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=00119ae0fc844c1c88d61052e1ded66b 状态=null
2026-06-13 10:16:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:16:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[5]毫秒
2026-06-13 10:17:04 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:17:04 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:18:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:18:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:23:12 [schedule-pool-4] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 10:34:56 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:34:56 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[22]毫秒
2026-06-13 10:34:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:34:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:37:22 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:37:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:37:22 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 10:37:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:02 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 10:38:02 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[14]毫秒
2026-06-13 10:38:06 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:38:06 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[12]毫秒
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:38:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:38:13 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:13 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[9]毫秒
2026-06-13 10:38:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:38:16 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:16 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒
2026-06-13 10:38:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[5]毫秒
2026-06-13 10:38:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:38:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +0,0 @@
2026-06-13 08:59:32 [MQTT Ping: water-server-8081] ERROR o.e.p.c.mqttv3.internal.ClientState - water-server-8081: Timed out as no write activity, keepAlive=60,000,000,000 lastOutboundActivity=150,167,329,517,400 lastInboundActivity=150,167,356,610,400 time=204,053,810,500,400 lastPing=150,167,329,537,400

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,323 +0,0 @@
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已重新连接ssl://service.reinkun.com:8883
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/finish/schedule 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/register 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/power 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/ack 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/finish/key 服务质量等级=1
2026-06-13 08:59:34 [MQTT Call: water-server-8081] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 已订阅 主题=/+/publish/error 服务质量等级=1
2026-06-13 08:59:34 [mqtt-consumer-4] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 50,
"charging": 0
}
2026-06-13 08:59:34 [mqtt-consumer-7] INFO o.d.a.handler.ScheduleFinishHandler - [MQTT] 浇水排程上报已保存 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceNo": "01",
"startWeek": 5,
"startTime": "2026-06-11 8:20",
"durationMin": 20,
"triggerType": "mqtt on",
"triggerON":"mqtt on",
"triggerOFF":"mqtt off"
}
2026-06-13 08:59:34 [mqtt-consumer-8] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 08:59:34 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 63,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:00:02 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:00:02 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[19]毫秒
2026-06-13 09:00:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:00:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:00:52 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:00:52 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[9]毫秒
2026-06-13 09:01:28 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:01:28 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:02:04 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:02:04 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:02:06 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:02:06 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:05:12 [schedule-pool-10] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[3]毫秒
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:05:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:06:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:06:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[8]毫秒
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:07:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:08:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9c"}]
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[2]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:08:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:08:49 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:49 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:08:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:08:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:08:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 09:08:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:08:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:09:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:09:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:09:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:09:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:11:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:11:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:12:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:12:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:12:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:12:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 09:13:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:13:56 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 09:15:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:15:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:15:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[5]毫秒
2026-06-13 09:15:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/scheduleDeviceList/2062827585485807618],无参数
2026-06-13 09:15:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/scheduleDeviceList/2062827585485807618],耗时:[7]毫秒
2026-06-13 09:15:36 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addScheduleDevice],参数类型[JSON],参数:[{"scheduleId":"2062827585485807618","deviceNos":["1779176626954"]}]
2026-06-13 09:15:36 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addScheduleDevice],耗时:[20]毫秒
2026-06-13 09:15:37 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:37 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[11]毫秒
2026-06-13 09:15:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[4]毫秒
2026-06-13 09:15:46 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:46 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[6]毫秒
2026-06-13 09:15:50 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:15:50 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:15:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:15:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[6]毫秒
2026-06-13 09:17:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:17:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:17:47 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:17:47 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[8]毫秒
2026-06-13 09:17:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedule/2062827585485807618],无参数
2026-06-13 09:17:48 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedule/2062827585485807618],耗时:[9]毫秒
2026-06-13 09:17:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:17:51 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:24:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:24:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:24:17 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:24:17 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:26:05 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:26:05 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:26:07 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:26:07 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:27:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:27:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:27:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:27:40 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[22]毫秒
2026-06-13 09:46:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:46:39 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[26]毫秒
2026-06-13 09:46:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:42 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[16]毫秒
2026-06-13 09:46:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:54 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[20]毫秒
2026-06-13 09:46:58 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:46:58 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:47:10 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:47:10 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[11]毫秒
2026-06-13 09:47:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:47:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:49:16 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:49:16 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:49:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:49:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["666"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[12]毫秒
2026-06-13 09:49:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:49:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 09:51:11 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 09:51:11 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[34]毫秒
2026-06-13 09:51:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 09:51:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 09:51:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:51:24 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:51:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:51:32 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:51:33 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:51:33 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[7]毫秒
2026-06-13 09:53:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 09:53:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9c"}]
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[4]毫秒
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:53:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:54:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:12 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:21 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"dc:da:0c:fa:28:9e"}]
2026-06-13 09:54:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[1]毫秒
2026-06-13 09:54:21 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:46 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:46 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[4]毫秒
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:54:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 09:55:12 [mqtt-consumer-16] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 09:55:12 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:55:12 [mqtt-consumer-13] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 09:55:12 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 09:55:12 [mqtt-consumer-14] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"浇水设备007","wifiName":"研发部","wifiPassword":"ckkj123456","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 09:55:38 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"73669072eb924e9f9772d80fb9be57f8","bindStatus":true}
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=73669072eb924e9f9772d80fb9be57f8
2026-06-13 09:55:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[39]毫秒
2026-06-13 09:55:38 [mqtt-consumer-11] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=73669072eb924e9f9772d80fb9be57f8 状态=null
2026-06-13 09:55:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:55:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:55:59 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:56:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/bindDeviceStatus],参数类型[JSON],参数:[{"macAddress":"DC:DA:0C:FA:28:9E"}]
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/bindDeviceStatus],耗时:[1]毫秒
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:56:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 09:57:15 [mqtt-consumer-8] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 09:57:15 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 09:57:15 [mqtt-consumer-8] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 09:57:15 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 09:57:15 [mqtt-consumer-12] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"智能浇水","wifiName":"测试机","wifiPassword":"66668888","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 09:57:39 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"a783262582fd41fcb09d59d55a07c9e3","bindStatus":true}
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=a783262582fd41fcb09d59d55a07c9e3
2026-06-13 09:57:39 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[35]毫秒
2026-06-13 09:57:40 [mqtt-consumer-3] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=a783262582fd41fcb09d59d55a07c9e3 状态=null
2026-06-13 09:57:40 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 09:57:40 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 09:59:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:59:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 09:59:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 09:59:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:02:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:02:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:02:11 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:02:11 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[3]毫秒
2026-06-13 10:02:12 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:02:12 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 10:03:42 [schedule-pool-5] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 10:04:26 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:04:26 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:11:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:11:55 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[2]毫秒
2026-06-13 10:12:03 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:12:03 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 10:12:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:12:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["fuck"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[13]毫秒
2026-06-13 10:12:28 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:28 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 10:12:36 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:36 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[7]毫秒
2026-06-13 10:12:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":["66"],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:38 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[10]毫秒
2026-06-13 10:12:42 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:12:42 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:16:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:16:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[7]毫秒
2026-06-13 10:16:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:16:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:16:46 [mqtt-consumer-1] INFO o.d.a.handler.DeviceRegisterHandler - [MQTT] 设备注册 时间=2026-06-13 10:16:46 设备编号=01 消息体={
"deviceNo": "01",
"deviceName": "Waterer_01",
"powerLevel": 48,
"deviceEm": "11667796A-Y43-2606",
"deviceSn": "260601",
"deviceMac": "dc:da:0c:fa:28:9c",
"version": "1.0"
}
2026-06-13 10:16:46 [mqtt-consumer-16] INFO o.d.app.handler.DeviceDataHandler - [MQTT] 设备电量更新 时间=2026-06-13 10:16:46 设备编号=01 消息体={
"deviceName": "Waterer_01",
"powerLevel": 48,
"charging": 0
}
2026-06-13 10:16:47 [mqtt-consumer-16] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=2ab3a6e58d1b4a89919d218fda63b3f7 状态=null
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[POST /app/v1/addDevice],参数类型[JSON],参数:[{"deviceName":"还是浇水设备","wifiName":"研发部","wifiPassword":"ckkj123456","macAddress":"DC:DA:0C:FA:28:9E","deviceNo":"01"}]
2026-06-13 10:16:57 [XNIO-1 task-4] INFO org.dromara.mqtt.MqttClientManager - [MQTT] 消息已发布 主题=/01/subscriber/cmd 消息体={"commandType":"bindDevice","deviceNo":"01","cmd":-1,"commandId":"00119ae0fc844c1c88d61052e1ded66b","bindStatus":true}
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.a.s.i.DeviceCommandServiceImpl - [命令] 命令已下发 设备编号=01 命令类型=bindDevice 命令编号=00119ae0fc844c1c88d61052e1ded66b
2026-06-13 10:16:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[POST /app/v1/addDevice],耗时:[36]毫秒
2026-06-13 10:16:57 [mqtt-consumer-6] INFO o.dromara.mqtt.MqttCommandAckService - [MQTT] 收到命令确认 设备编号=01 命令编号=00119ae0fc844c1c88d61052e1ded66b 状态=null
2026-06-13 10:16:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/device/01],无参数
2026-06-13 10:16:58 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/device/01],耗时:[5]毫秒
2026-06-13 10:17:04 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:17:04 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:18:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:18:48 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:23:12 [schedule-pool-4] INFO o.d.app.task.DeviceOfflineCheckTask - [设备离线] 检测到 1 台设备离线,已更新数据库状态,设备编号:[01]
2026-06-13 10:34:56 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:34:56 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[22]毫秒
2026-06-13 10:34:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:34:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:35:05 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:37:22 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:37:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:37:22 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒
2026-06-13 10:37:22 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:02 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 10:38:02 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[14]毫秒
2026-06-13 10:38:06 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:38:06 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/waterLogList],参数类型[表单参数],参数:[{"pageNum":["1"]}]
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/waterLogList],耗时:[12]毫秒
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/schedulelist],参数类型[表单参数],参数:[{"name":[""],"pageSize":["10"],"pageNum":["1"]}]
2026-06-13 10:38:08 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/schedulelist],耗时:[9]毫秒
2026-06-13 10:38:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-06-13 10:38:13 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:13 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[9]毫秒
2026-06-13 10:38:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:38:16 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:16 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒
2026-06-13 10:38:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/getUserInfo],无参数
2026-06-13 10:38:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[5]毫秒
2026-06-13 10:38:19 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒
2026-06-13 10:38:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:21 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:25 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[13]毫秒
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-06-13 10:38:27 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [请求]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒

View File

@@ -21,6 +21,8 @@ INSERT INTO sys_menu VALUES ('11655', '流程变量修改', '11621', '3', '#', '
-- Device binding and device_no primary key migration.
ALTER TABLE app_device ADD COLUMN bind_token_hash varchar(255) NULL COMMENT '设备绑定令牌哈希' AFTER device_no;
ALTER TABLE app_device ADD COLUMN qrcode varchar(1000) NULL COMMENT '设备二维码' AFTER device_img;
ALTER TABLE app_watering_log ADD COLUMN remark varchar(500) NULL COMMENT '备注' AFTER trigger_type;
ALTER TABLE app_scheduling_device ADD COLUMN device_no varchar(64) NULL COMMENT '设备编号' AFTER schedule_id;
UPDATE app_scheduling_device sd
INNER JOIN app_device d ON sd.device_id = d.id

View File

@@ -47,9 +47,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/water?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://47.97.217.123:3306/water?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123456
password: 267a976b31c7a649
# # 从库数据源
# slave:
# lazy: true

View File

@@ -50,9 +50,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://localhost:3306/water?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
password: 267a976b31c7a649
# # 从库数据源
# slave:
# lazy: true
@@ -105,7 +105,7 @@ spring.data:
# 数据库索引
database: 0
# redis 密码必须配置
password: water123
password: waterx123
# 连接超时时间
timeout: 10s
# 是否开启ssl
@@ -136,17 +136,17 @@ redisson:
--- # mail 邮件发送
mail:
enabled: false
enabled: true
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
from: watexdevice@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
user: watexdevice@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
pass: XZVDXjRdVrjiX8N3
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
@@ -175,10 +175,10 @@ sms:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
access-key-id: LTAI5t7xHqxFKG9DwMgurvrn
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
access-key-secret: nNFjR8YwNJUcMrrtdc4pkpPsHmYtfp
signature: 山东春雨润集雨节灌设备
sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分

View File

@@ -59,6 +59,7 @@ mqtt:
enabled: true
interval-ms: 90000
topics:
# 订阅/下发主题第一段为设备 MAC小写、去分隔符上行业务侧由 DeviceIdentityResolver 解析为设备编号
subscribe:
- /+/publish/finish/schedule #排程任务完成上报

View File

@@ -33,9 +33,9 @@ public class JacksonConfig {
public Module registerJavaTimeModule() {
// 全局配置序列化返回 JSON 处理
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));

View File

@@ -43,5 +43,10 @@
<groupId>org.dromara</groupId>
<artifactId>water-app</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -3,6 +3,7 @@ package org.dromara.mqtt;
import lombok.RequiredArgsConstructor;
import org.dromara.app.domain.mqtt.DeviceCommand;
import org.dromara.app.service.IDeviceCommandPublisher;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.mqtt.config.properties.MqttProperties;
@@ -44,14 +45,18 @@ public class DeviceMqttCommandPublisher implements IDeviceCommandPublisher {
}
private String buildCommandTopic(String deviceNo) {
if (StringUtils.isBlank(deviceNo)) {
throw new ServiceException("命令下发缺少设备编号,无法拼接主题");
}
String device = deviceNo.trim().toLowerCase();
String prefix = mqttProperties.getTopics().getPublishPrefix();
if (StringUtils.isBlank(prefix)) {
return "/" + deviceNo + "/subscriber/cmd";
return "/" + device + "/subscriber/cmd";
}
String normalizedPrefix = prefix.startsWith("/") ? prefix : "/" + prefix;
if (normalizedPrefix.endsWith("/")) {
normalizedPrefix = normalizedPrefix.substring(0, normalizedPrefix.length() - 1);
}
return normalizedPrefix + "/" + deviceNo + "/subscriber/cmd";
return normalizedPrefix + "/" + device + "/subscriber/cmd";
}
}

View File

@@ -75,10 +75,14 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler {
return;
}
ack.setDeviceNo(deviceNo);
withCommandLock(ack.getCommandId(), () -> {
boolean ackSaved = withCommandLock(ack.getCommandId(), () -> {
deletePending(ack.getCommandId());
RedisUtils.setCacheObject(ackKey(ack.getCommandId()), ack, Duration.ofSeconds(mqttProperties.getCommandAck().getAckTtlSeconds()));
});
if (!ackSaved) {
log.warn("[MQTT] ACK 处理未获得命令锁,本次跳过 设备编号={} 命令编号={}", deviceNo, ack.getCommandId());
return;
}
refreshDeviceOnline(deviceNo);
log.info("[MQTT] 收到命令确认 设备编号={} 命令编号={} 状态={}", deviceNo, ack.getCommandId(), ack.getStatus());
}
@@ -99,10 +103,14 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler {
ack.setStatus("1");
ack.setMessage(payload);
withCommandLock(commandId, () -> {
boolean ackSaved = withCommandLock(commandId, () -> {
deletePending(commandId);
RedisUtils.setCacheObject(ackKey(commandId), ack, Duration.ofSeconds(mqttProperties.getCommandAck().getAckTtlSeconds()));
});
if (!ackSaved) {
log.warn("[MQTT] 非 JSON ACK 处理未获得命令锁,本次跳过 设备编号={} 命令编号={}", deviceNo, commandId);
return;
}
log.info("[MQTT] 收到非 JSON 命令确认 设备编号={} 命令编号={} 消息体={}", deviceNo, commandId, payload);
}
@@ -177,8 +185,11 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler {
RLock lock = RedisUtils.getClient().getLock(DEVICE_STATUS_LOCK_PREFIX + deviceNo);
boolean locked = false;
try {
lock.lock(10, TimeUnit.SECONDS);
locked = true;
locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
if (!locked) {
// 其他线程正在刷新,本次跳过;状态写入幂等,下条 ACK 仍会兜底刷新
return;
}
Map<String, Object> statusCache = new HashMap<>();
statusCache.put("deviceNo", deviceNo);
statusCache.put("status", "1");
@@ -193,6 +204,9 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler {
.set(AppDevice::getStatus, "1")
.eq(AppDevice::getDeviceNo, deviceNo)
);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("[MQTT] 刷新设备在线状态被中断 设备编号={}", deviceNo);
} finally {
if (locked && lock.isHeldByCurrentThread()) {
lock.unlock();
@@ -209,20 +223,23 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler {
pendingIds().remove(commandId);
}
private void withCommandLock(String commandId, Runnable action) {
private boolean withCommandLock(String commandId, Runnable action) {
RLock lock = RedisUtils.getClient().getLock(mqttProperties.getCommandAck().getRetryLockKeyPrefix() + commandId);
boolean locked = false;
try {
locked = lock.tryLock(0, mqttProperties.getCommandAck().getRetryLockTtlMs(), TimeUnit.MILLISECONDS);
if (!locked) {
return;
return false;
}
action.run();
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("[MQTT] 命令锁等待被中断 命令编号={}", commandId);
return false;
} catch (RuntimeException e) {
log.error("[MQTT] 命令锁内处理失败 命令编号={}", commandId, e);
return false;
} finally {
if (locked && lock.isHeldByCurrentThread()) {
lock.unlock();

View File

@@ -123,6 +123,11 @@
<groupId>org.dromara</groupId>
<artifactId>water-system</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -14,7 +14,6 @@ import org.dromara.app.domain.bo.AppDeviceBo;
import org.dromara.app.domain.bo.AppScheduleBo;
import org.dromara.app.domain.bo.AppSchedulingDeviceBo;
import org.dromara.app.domain.bo.AppWateringLogBo;
import org.dromara.app.domain.mqtt.DeviceCommand;
import org.dromara.app.domain.vo.*;
import org.dromara.app.service.*;
import org.dromara.app.service.impl.AppScheduleServiceImpl;
@@ -37,11 +36,16 @@ import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysOssUploadVo;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.domain.vo.UserInfoVo;
import org.dromara.system.service.ISysOssService;
import org.dromara.system.service.ISysUserService;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
@@ -61,6 +65,7 @@ public class AppController extends BaseController {
private final ISysUserService userService;
private final IAppWateringLogService appWateringLogService;
private final IDeviceCommandService deviceCommandService;
private final ISysOssService ossService;
/**
*查询设备
@@ -243,10 +248,15 @@ public class AppController extends BaseController {
continue;
}
assertDeviceOwned(deviceNo);
if (appSchedulingDeviceService.queryByScheduleIdAndDeviceNo(scheduleId, deviceNo) != null) {
continue;
}
AppSchedulingDeviceBo schedulingDeviceBo = new AppSchedulingDeviceBo();
schedulingDeviceBo.setDeviceNo(deviceNo);
schedulingDeviceBo.setScheduleId(scheduleId);
appSchedulingDeviceService.insertByBo(schedulingDeviceBo);
if (appSchedulingDeviceService.insertByBo(schedulingDeviceBo)) {
deviceCommandService.sendScheduleBindCommand(deviceNo, buildScheduleBindPayload(scheduleId, deviceNo));
}
}
return R.ok();
} catch (Exception e) {
@@ -277,6 +287,47 @@ public class AppController extends BaseController {
.toList();
}
private Map<String, Object> buildScheduleBindPayload(Long scheduleId, String deviceNo) {
// AppScheduleVo schedule = getOwnedSchedule(scheduleId);
List<AppScheduleDetailVo> details = appScheduleDetailService.queryByScheduleIdByStatus(scheduleId);
// Map<String, Object> schedulePayload = new HashMap<>();
// schedulePayload.put("id", schedule.getId());
// schedulePayload.put("name", schedule.getName());
// schedulePayload.put("status", schedule.getStatus());
Map<String, Object> payload = new HashMap<>();
// payload.put("cmd", -1);
payload.put("deviceNo", deviceNo);
// payload.put("schedule", schedulePayload);
payload.put("details", toScheduleDetailPayload(details));
return payload;
// return toScheduleDetailPayload(details);
}
private List<Map<String, Object>> toScheduleDetailPayload(List<AppScheduleDetailVo> details) {
List<Map<String, Object>> detailPayload = new ArrayList<>();
if (details == null) {
return detailPayload;
}
for (AppScheduleDetailVo detail : details) {
List<Object> timeSlots = new ArrayList<>();
JSONArray timeArray = JSONUtil.parseArray(detail.getTimeData());
for (Object timeSlot : timeArray) {
timeSlots.add(timeSlot);
}
Map<String, Object> item = new HashMap<>();
item.put("id", detail.getId());
item.put("weekday", detail.getWeekday());
item.put("timeData", timeSlots);
item.put("triggerType", detail.getTriggerType());
item.put("status", detail.getStatus());
detailPayload.add(item);
}
return detailPayload;
}
/**
* 删除排程与设备绑定
* @param scheduleId,deviceNo
@@ -297,7 +348,17 @@ public class AppController extends BaseController {
Long scheduleIdValue = Long.valueOf(scheduleId);
assertScheduleOwned(scheduleIdValue);
assertDeviceOwned(deviceNo);
return toAjax(appSchedulingDeviceService.deleteWithValidByScheduleIdAndDeviceNo(scheduleIdValue, deviceNo));
Boolean deleted = appSchedulingDeviceService.deleteWithValidByScheduleIdAndDeviceNo(scheduleIdValue, deviceNo);
if (deleted) {
// 通知设备解绑排程
try {
deviceCommandService.sendScheduleUnbindCommand(deviceNo, scheduleIdValue);
} catch (Exception mqttEx) {
log.warn("[排程通知] 删除排程设备绑定后下发解绑命令失败 排程ID={} 设备编号={} 原因={}",
scheduleIdValue, deviceNo, mqttEx.getMessage());
}
}
return toAjax(deleted);
} catch (Exception e) {
return fail(e);
}
@@ -406,7 +467,12 @@ public class AppController extends BaseController {
try {
assertScheduleOwned(bo.getId());
bo.setUserId(LoginHelper.getUserId());
return toAjax(appScheduleService.updateStatusByBo(bo));
Boolean updated = appScheduleService.updateStatusByBo(bo);
if (updated) {
// 向所有绑定设备下发排程状态变更
notifyBoundDevicesScheduleUpdate(bo.getId());
}
return toAjax(updated);
} catch (Exception e) {
return fail(e);
}
@@ -424,6 +490,8 @@ public class AppController extends BaseController {
bo.setUserId(LoginHelper.getUserId());
Map<String, Object> map = appScheduleService.updateByBo(bo);
if (Boolean.valueOf(map.get("flag").toString())){
// 向所有绑定设备下发排程更新
notifyBoundDevicesScheduleUpdate(bo.getId());
return R.ok(map.get("appSchedule"));
}else {
return R.fail();
@@ -448,7 +516,17 @@ public class AppController extends BaseController {
for (Long id : ids) {
assertScheduleOwned(id);
}
return toAjax(appScheduleService.deleteWithValidByIds(List.of(ids), true));
Map<Long, List<String>> boundDeviceNosBySchedule = new HashMap<>();
for (Long id : ids) {
boundDeviceNosBySchedule.put(id, findBoundDeviceNos(id));
}
Boolean deleted = appScheduleService.deleteWithValidByIds(List.of(ids), true);
if (deleted) {
for (Map.Entry<Long, List<String>> entry : boundDeviceNosBySchedule.entrySet()) {
notifyScheduleUnbind(entry.getKey(), entry.getValue());
}
}
return toAjax(deleted);
} catch (Exception e) {
return fail(e);
}
@@ -475,7 +553,7 @@ public class AppController extends BaseController {
vo.setDeviceNo(appDeviceVo.getDeviceNo());
}
}
vo.setTriggerType(vo.getTriggerType().equals("0")?"排程":"手动");
// vo.setTriggerType(vo.getTriggerType().equals("0")?"排程":"手动");
l.add(vo);
}
appWateringLogVoTableDataInfo.setRows(l);
@@ -563,6 +641,31 @@ public class AppController extends BaseController {
}
}
/**
* 上传图片到OSS对象存储
*/
@PostMapping(value = "/uploadImage", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysOssUploadVo> uploadImage(@RequestPart("file") MultipartFile file) {
try {
if (file == null || file.isEmpty()) {
throw new ServiceException("上传图片不能为空");
}
String contentType = file.getContentType();
if (StringUtils.isBlank(contentType) || !contentType.toLowerCase(Locale.ROOT).startsWith("image/")) {
throw new ServiceException("只能上传图片文件");
}
SysOssVo oss = ossService.upload(file);
SysOssUploadVo uploadVo = new SysOssUploadVo();
uploadVo.setUrl(oss.getUrl());
uploadVo.setFileName(oss.getOriginalName());
uploadVo.setOssId(oss.getOssId() == null ? null : oss.getOssId().toString());
return R.ok(uploadVo);
} catch (Exception e) {
return fail(e);
}
}
/**
* 修改用户
*/
@@ -638,9 +741,6 @@ public class AppController extends BaseController {
@GetMapping("/test")
public R<Void> test (){
try {
DeviceCommand deviceCommand = new DeviceCommand();
String bindDevice = deviceCommandService.sendBindDeviceCommand("01");
// String s = deviceCommandService.sendSwitchCommand("01", "1", "2026-06-10 14:35:31", 20);
@@ -706,4 +806,48 @@ public class AppController extends BaseController {
}
}
/**
* 查找排程关联的所有设备编号
*/
private List<String> findBoundDeviceNos(Long scheduleId) {
AppSchedulingDeviceBo bo = new AppSchedulingDeviceBo();
bo.setScheduleId(scheduleId);
List<AppSchedulingDeviceVo> bindings = appSchedulingDeviceService.queryList(bo);
return bindings.stream()
.map(AppSchedulingDeviceVo::getDeviceNo)
.filter(StringUtils::isNotBlank)
.toList();
}
/**
* 向排程关联的所有设备重新下发排程信息(用于排程内容/状态变更)
*/
private void notifyBoundDevicesScheduleUpdate(Long scheduleId) {
List<String> deviceNos = findBoundDeviceNos(scheduleId);
for (String deviceNo : deviceNos) {
try {
deviceCommandService.sendScheduleBindCommand(deviceNo, buildScheduleBindPayload(scheduleId, deviceNo));
} catch (Exception e) {
log.warn("[排程通知] 下发排程更新失败 排程ID={} 设备编号={} 原因={}", scheduleId, deviceNo, e.getMessage());
}
}
}
/**
* 向排程关联的所有设备下发排程解绑通知
*/
private void notifyBoundDevicesScheduleUnbind(Long scheduleId) {
notifyScheduleUnbind(scheduleId, findBoundDeviceNos(scheduleId));
}
private void notifyScheduleUnbind(Long scheduleId, List<String> deviceNos) {
for (String deviceNo : deviceNos) {
try {
deviceCommandService.sendScheduleUnbindCommand(deviceNo, scheduleId);
} catch (Exception e) {
log.warn("[排程通知] 下发排程解绑失败 排程ID={} 设备编号={} 原因={}", scheduleId, deviceNo, e.getMessage());
}
}
}
}

View File

@@ -15,6 +15,7 @@ public class DeviceCommand implements Serializable {
private String commandId;
private String deviceNo;
private String deviceMac;
private String commandType;
private String topic;
private Map<String, Object> payload = new HashMap<>();

View File

@@ -81,14 +81,16 @@ public class DeviceDataHandler implements MqttTopicHandler {
/**
* 刷新设备在线状态到 Redis与 MqttCommandAckService 逻辑一致)
* 写入 Redis 后 TTL 到期自动过期 = 离线
* 写入幂等,未拿到锁则跳过由后续上报兜底
*/
private void refreshDeviceOnline(String deviceNo) {
RLock lock = RedisUtils.getClient().getLock(DEVICE_STATUS_LOCK_PREFIX + deviceNo);
boolean locked = false;
try {
lock.lock(10, TimeUnit.SECONDS);
locked = true;
locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
if (!locked) {
return;
}
Map<String, Object> statusCache = new HashMap<>();
statusCache.put("deviceNo", deviceNo);
statusCache.put("status", "1");
@@ -103,6 +105,9 @@ public class DeviceDataHandler implements MqttTopicHandler {
.set(AppDevice::getStatus, "1")
.eq(AppDevice::getDeviceNo, deviceNo)
);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("[MQTT] 刷新设备在线状态被中断 设备编号={}", deviceNo);
} finally {
if (locked && lock.isHeldByCurrentThread()) {
lock.unlock();

View File

@@ -47,8 +47,6 @@ DeviceRegisterHandler implements MqttTopicHandler {
@Value("${mqtt.command-ack.device-status-cache-ttl-seconds}")
private int deviceStatusCacheTtlSeconds;
private final DeviceIdentityResolver deviceIdentityResolver;
@Value("${mqtt.topics.publish-prefix:}")
private String mqttPublishPrefix;
@Override
public Pattern topicPattern() {
@@ -77,8 +75,7 @@ DeviceRegisterHandler implements MqttTopicHandler {
AppDeviceBo device = buildRegisterDevice(deviceNo, normalizedDeviceMac, dto);
appDeviceService.registerByMqtt(device);
refreshDeviceOnline(deviceNo);
String commandTarget = normalizedDeviceMac == null ? deviceIdentity : normalizedDeviceMac;
sendDeviceNoToDevice(commandTarget, deviceNo);
sendDeviceNoToDevice(deviceNo, normalizedDeviceMac);
log.info("[MQTT] 设备注册 时间={} MAC={} 设备编号={} 消息体={}",
HandlerLogTime.now(), normalizedDeviceMac, deviceNo, payload);
} catch (Exception e) {
@@ -115,19 +112,25 @@ DeviceRegisterHandler implements MqttTopicHandler {
return text.isBlank() ? null : text.toLowerCase(Locale.ROOT);
}
private void sendDeviceNoToDevice(String deviceMac, String deviceNo) {
private void sendDeviceNoToDevice(String deviceNo, String deviceMac) {
IDeviceCommandPublisher commandPublisher = commandPublisherProvider.getIfAvailable();
if (commandPublisher == null) {
log.warn("[MQTT] 设备编号下发失败,未找到命令发布器 时间={} MAC={} 设备编号={}",
HandlerLogTime.now(), deviceMac, deviceNo);
return;
}
if (deviceMac == null) {
log.warn("[MQTT] 设备编号下发失败,缺少设备 MAC 时间={} 设备编号={}",
HandlerLogTime.now(), deviceNo);
return;
}
try {
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(deviceMac);
command.setCommandType("registerDeviceNo");
command.setTopic(buildCommandTopic(deviceMac));
command.setTopic("/" + deviceMac.trim().toLowerCase(Locale.ROOT) + "/subscriber/cmd");
command.getPayload().put("deviceNo", deviceNo);
command.getPayload().put("deviceMac", deviceMac);
@@ -140,17 +143,6 @@ DeviceRegisterHandler implements MqttTopicHandler {
}
}
private String buildCommandTopic(String deviceMac) {
if (mqttPublishPrefix == null || mqttPublishPrefix.isBlank()) {
return "/" + deviceMac + "/subscriber/cmd";
}
String normalizedPrefix = mqttPublishPrefix.startsWith("/") ? mqttPublishPrefix : "/" + mqttPublishPrefix;
if (normalizedPrefix.endsWith("/")) {
normalizedPrefix = normalizedPrefix.substring(0, normalizedPrefix.length() - 1);
}
return normalizedPrefix + "/" + deviceMac + "/subscriber/cmd";
}
private String firstNotBlank(Object first, Object second) {
String firstText = valueAsString(first);
if (firstText != null && !firstText.isBlank()) {
@@ -165,14 +157,16 @@ DeviceRegisterHandler implements MqttTopicHandler {
}
/**
* 刷新设备在线状态到 Redis
* 刷新设备在线状态到 Redis;状态写入幂等,未拿到锁则跳过由后续上报兜底
*/
private void refreshDeviceOnline(String deviceNo) {
RLock lock = RedisUtils.getClient().getLock(DEVICE_STATUS_LOCK_PREFIX + deviceNo);
boolean locked = false;
try {
lock.lock(10, TimeUnit.SECONDS);
locked = true;
locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
if (!locked) {
return;
}
Map<String, Object> statusCache = new HashMap<>();
statusCache.put("deviceNo", deviceNo);
statusCache.put("status", "1");
@@ -187,6 +181,9 @@ DeviceRegisterHandler implements MqttTopicHandler {
.set(AppDevice::getStatus, "1")
.eq(AppDevice::getDeviceNo, deviceNo)
);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("[MQTT] 刷新设备在线状态被中断 设备编号={}", deviceNo);
} finally {
if (locked && lock.isHeldByCurrentThread()) {
lock.unlock();

View File

@@ -12,7 +12,6 @@ import org.dromara.app.service.IAppDeviceService;
import org.dromara.app.service.IAppWateringLogService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Component;
import java.text.ParseException;
@@ -54,7 +53,6 @@ public class ScheduleFinishHandler implements MqttTopicHandler {
}
Map<String, Object> dto = JsonUtils.parseObject(payload, Map.class);
AppWateringLogBo logBo = buildWateringLog(deviceNo, dto);
logBo.setUserId(LoginHelper.getUserId());
appWateringLogService.confirmScheduleLog(logBo);
log.info("[MQTT] 浇水排程上报已保存 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload);
} catch (Exception e) {

View File

@@ -41,8 +41,26 @@ public interface IDeviceCommandService {
* @return commandId
*/
String sendCustomCommand(String deviceNo, String commandType, Map<String, Object> extra);
/**
* 下发排程绑定命令。
*
* @param deviceNo 设备编号
* @param payload 排程信息
* @return commandId
*/
String sendScheduleBindCommand(String deviceNo, Map<String, Object> payload);
String sendBindDeviceCommand(String deviceNo);
/**
* 下发排程解绑命令,通知设备清除指定排程。
*
* @param deviceNo 设备编号
* @param scheduleId 排程ID
* @return commandId
*/
String sendScheduleUnbindCommand(String deviceNo, Long scheduleId);
/**
* 下发设备初始化指令。用于解绑设备,允许设备未绑定用户时下发。
*

View File

@@ -109,9 +109,7 @@ public class AppDeviceServiceImpl implements IAppDeviceService {
AppDevice add = MapstructUtils.convert(bo, AppDevice.class);
validEntityBeforeInsert(add);
normalizeMacAddress(add);
if (baseMapper.selectByMac(add.getMacAddress()) != null) {
throw new ServiceException("MAC地址已存在不能重复新增设备");
}
ensureMacAddressAvailable(add);
return baseMapper.insert(add) > 0;
}
@@ -120,6 +118,8 @@ public class AppDeviceServiceImpl implements IAppDeviceService {
// fillBindTokenHash(bo);
AppDevice update = MapstructUtils.convert(bo, AppDevice.class);
validEntityBeforeUpdate(update);
normalizeMacAddress(update);
ensureMacAddressAvailable(update);
return baseMapper.updateById(update) > 0;
}
@@ -142,6 +142,7 @@ public class AppDeviceServiceImpl implements IAppDeviceService {
try {
return baseMapper.insert(device) > 0;
} catch (org.springframework.dao.DuplicateKeyException ignored) {
device.setDeviceName(null);
return baseMapper.updateById(device) > 0;
}
}
@@ -302,6 +303,16 @@ public class AppDeviceServiceImpl implements IAppDeviceService {
}
}
private void ensureMacAddressAvailable(AppDevice entity) {
if (StringUtils.isBlank(entity.getMacAddress())) {
return;
}
AppDevice exists = baseMapper.selectByMac(entity.getMacAddress());
if (exists != null && !Objects.equals(exists.getDeviceNo(), entity.getDeviceNo())) {
throw new ServiceException("MAC地址已存在不能重复绑定设备");
}
}
private void validEntityBeforeUpdate(AppDevice entity) {
if (StringUtils.isBlank(entity.getDeviceNo())) {
throw new ServiceException("设备编号不能为空");
@@ -311,12 +322,42 @@ public class AppDeviceServiceImpl implements IAppDeviceService {
@Override
@Transactional
public Boolean deleteWithValidByIds(Collection<String> deviceNos, Boolean isValid) {
boolean flag = baseMapper.deleteByIds(deviceNos) > 0;
if (deviceNos == null || deviceNos.isEmpty()) {
throw new ServiceException("设备编号不能为空");
}
List<String> distinctDeviceNos = deviceNos.stream()
.filter(StringUtils::isNotBlank)
.distinct()
.toList();
if (distinctDeviceNos.isEmpty()) {
throw new ServiceException("设备编号不能为空");
}
Long userId = LoginHelper.getUserId();
if (userId == null) {
throw new ServiceException("用户未登录");
}
Long ownedCount = baseMapper.selectCount(
Wrappers.<AppDevice>lambdaQuery()
.in(AppDevice::getDeviceNo, distinctDeviceNos)
.eq(AppDevice::getUserId, userId)
);
if (ownedCount == null || ownedCount.intValue() != distinctDeviceNos.size()) {
throw new ServiceException("设备不存在或无权操作");
}
boolean flag = baseMapper.delete(
Wrappers.<AppDevice>lambdaUpdate()
.in(AppDevice::getDeviceNo, distinctDeviceNos)
.eq(AppDevice::getUserId, userId)
) > 0;
if (flag) {
schedulingDeviceMapper.delete(
new QueryWrapper<AppSchedulingDevice>().in("device_no", deviceNos)
new QueryWrapper<AppSchedulingDevice>().in("device_no", distinctDeviceNos)
);
wateringLogMapper.delete(new QueryWrapper<AppWateringLog>().in("device_no", deviceNos));
wateringLogMapper.delete(new QueryWrapper<AppWateringLog>().in("device_no", distinctDeviceNos));
}
return flag;
}

View File

@@ -19,10 +19,7 @@ import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* 设备命令下发业务实现。
@@ -49,6 +46,9 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
@Override
public String sendCommand(DeviceCommand command) {
validate(command);
if (StringUtils.isBlank(command.getDeviceMac())) {
command.setDeviceMac(requireDeviceMac(command.getDeviceNo()));
}
String commandId = commandPublisher.send(command);
log.info("[命令] 命令已下发 设备编号={} 命令类型={} 命令编号={}",
command.getDeviceNo(), command.getCommandType(), commandId);
@@ -67,6 +67,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(requireDeviceMac(deviceNo));
command.setCommandType("switchDevice");
command.getPayload().put("deviceNo", deviceNo);
command.getPayload().put("cmd", workStatus);
@@ -100,6 +101,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(requireDeviceMac(deviceNo));
command.setCommandType(commandType);
if (extra != null) {
command.getPayload().putAll(extra);
@@ -107,15 +109,37 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
return sendCommand(command);
}
@Override
public String sendScheduleBindCommand(String deviceNo, Map<String, Object> payload) {
AppDeviceVo device = requireCommandDevice(deviceNo);
if (StringUtils.isBlank(device.getMacAddress())) {
throw new ServiceException("设备未登记 MAC无法下发排程" + deviceNo);
}
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(device.getMacAddress());
command.setCommandType("bindSchedule");
command.setTopic(buildScheduleTopic(deviceNo));
if (payload != null) {
command.getPayload().putAll(payload);
}
return sendCommand(command);
}
@Override
public String sendBindDeviceCommand(String deviceNo) {
AppDeviceVo device = deviceService.queryById(deviceNo);
if (ObjectUtil.isNull(device)) {
throw new ServiceException("设备不存在:" + deviceNo);
}
if (StringUtils.isBlank(device.getMacAddress())) {
throw new ServiceException("设备未登记 MAC无法下发绑定命令" + deviceNo);
}
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(device.getMacAddress());
command.setCommandType("bindDevice");
Map<String, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("bindStatus", true);
@@ -125,15 +149,38 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
return sendCommand(command);
}
@Override
public String sendScheduleUnbindCommand(String deviceNo, Long scheduleId) {
AppDeviceVo device = requireCommandDevice(deviceNo);
if (StringUtils.isBlank(device.getMacAddress())) {
throw new ServiceException("设备未登记 MAC无法下发排程解绑命令" + deviceNo);
}
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(device.getMacAddress());
command.setCommandType("unbindSchedule");
command.setTopic(buildScheduleTopic(deviceNo));
command.getPayload().put("cmd", -1);
command.getPayload().put("deviceNo", deviceNo);
command.getPayload().put("scheduleId", scheduleId);
command.getPayload().put("unbind", true);
return sendCommand(command);
}
@Override
public String sendInitDeviceCommand(String deviceNo) {
AppDeviceVo device = deviceService.queryById(deviceNo);
if (ObjectUtil.isNull(device)) {
throw new ServiceException("设备不存在:" + deviceNo);
}
if (StringUtils.isBlank(device.getMacAddress())) {
throw new ServiceException("设备未登记 MAC无法下发初始化命令" + deviceNo);
}
DeviceCommand command = new DeviceCommand();
command.setDeviceNo(deviceNo);
command.setDeviceMac(device.getMacAddress());
command.setCommandType("initDevice");
Map<String, Object> payload = new HashMap<>();
payload.put("deviceNo", deviceNo);
@@ -167,6 +214,29 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService {
}
}
private String requireDeviceMac(String deviceNo) {
AppDeviceVo device = deviceService.queryById(deviceNo);
if (device == null || StringUtils.isBlank(device.getMacAddress())) {
throw new ServiceException("设备未登记 MAC无法下发命令" + deviceNo);
}
return device.getMacAddress();
}
private AppDeviceVo requireCommandDevice(String deviceNo) {
AppDeviceVo device = deviceService.queryById(deviceNo);
if (ObjectUtil.isNull(device)) {
throw new ServiceException("设备不存在:" + deviceNo);
}
if (device.getUserId() == null) {
throw new ServiceException("设备未绑定用户,无法下发命令:" + deviceNo);
}
return device;
}
private String buildScheduleTopic(String deviceNo) {
return "/" + deviceNo.trim().toLowerCase(Locale.ROOT) + "/subscriber/schedule";
}
private void assertSwitchStatus(String workStatus) {
if (!"0".equals(workStatus) && !"1".equals(workStatus)) {
throw new ServiceException("设备工作状态只能为0或1");