diff --git a/.env.example b/.env.example deleted file mode 100644 index 51c3850..0000000 --- a/.env.example +++ /dev/null @@ -1,36 +0,0 @@ -# ========================================== -# Water 项目环境变量模板 -# 复制此文件为 .env 并填入真实值 -# .env 文件已加入 .gitignore,不会提交到仓库 -# ========================================== - -# --- 数据库 --- -DB_USERNAME=root -DB_PASSWORD=123456 - -# --- Redis --- -REDIS_PASSWORD= - -# --- Sa-Token JWT --- -# 生产环境建议使用 openssl rand -base64 64 生成 -SA_TOKEN_JWT_SECRET_KEY=abcdefghijklmnopqrstuvwxyz - -# --- MQTT Broker --- -MQTT_ENABLED=true -MQTT_BROKER_URL=ssl://service.reinkun.com:8883 -MQTT_USERNAME=admin -MQTT_PASSWORD=yukun_mqtt - -# --- 邮件 (SMTP) --- -MAIL_PASSWORD=XZVDXjRdVrjiX8N3 - -# --- 短信 (阿里云 SMS) --- -SMS_ACCESS_KEY_ID=LTAI5t7xHqxFKG9DwMgurvrn -SMS_ACCESS_KEY_SECRET=nNFjR8YwNJUcMrrtdc4pkpPsHmYtfp - -# --- SnailJob 调度中心 --- -SNAIL_JOB_TOKEN=SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT - -# --- 第三方登录 (JustAuth) --- -# Gitee / QQ / 微信 等 OAuth 凭据请通过 application-*.yml 配置 -# 或使用 JUSTAUTH_ 前缀的环境变量覆盖 diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 2617d3d..84f75d9 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -25,18 +25,6 @@ - - - - - - - - - - - - diff --git a/.workbuddy/memory/2026-06-11.md b/.workbuddy/memory/2026-06-11.md new file mode 100644 index 0000000..fdbeb51 --- /dev/null +++ b/.workbuddy/memory/2026-06-11.md @@ -0,0 +1,17 @@ +# 2026-06-11 工作日志 + +### 14. DeviceDataHandler 和 DeviceRegisterHandler 补充设备在线状态刷新 + +**问题**:之前只有 ACK 应答会调用 `refreshDeviceOnline()` 续期 Redis 中的设备在线状态。但设备只要上报电量或注册就证明在线,这两个场景没刷新在线缓存。后果:设备只上报数据不发 ACK 时,5 分钟后重试逻辑误判它为离线。 + +**修复**: +- `DeviceDataHandler.handle()` → 收到 `/publish/power` 后调用 `refreshDeviceOnline()` +- `DeviceRegisterHandler.handle()` → 注册后调用 `refreshDeviceOnline()` +- 两个 Handler 各自注入 `MqttProperties`,避免注入 `MqttCommandAckService` 引入新的循环依赖 + +**在线判定覆盖**(修复后): +| 触发方式 | 是否刷新在线状态 | +|---|---| +| 设备上报电量 `/publish/power` | ✅ 新增 | +| 设备注册 `/publish/register` | ✅ 新增 | +| ACK 应答 `/publish/ack` | ✅ 原有 | diff --git a/.workbuddy/memory/2026-06-12.md b/.workbuddy/memory/2026-06-12.md new file mode 100644 index 0000000..38ea1b4 --- /dev/null +++ b/.workbuddy/memory/2026-06-12.md @@ -0,0 +1,23 @@ +# 2026-06-12 工作日志 + +### 15. 修复设备断电后数据库状态未更新为离线 + +**问题**:设备断电/断网后,Redis 中的在线 Key(`mqtt:device:status:{deviceNo}`)会在 TTL(默认 300s)到期后自动消失,但数据库 `app_device.status` 字段没有同步更新,始终显示在线。 + +**方案**:三层联动 + +1. **定时任务扫库(新增 `DeviceOfflineCheckTask`)**:每 90s 扫描 DB 中 `status=1` 的设备,检查 Redis Key 是否存在,不存在则批量更新 `status=0`(离线)。扫描间隔可通过 `mqtt.offline-check.interval-ms` 配置项覆盖。 + +2. **上线时同步写库**: + - `DeviceDataHandler.handle()`:收到电量上报时,`AppDeviceBo.setStatus("1")` 写库 + 刷新 Redis Key + - `DeviceRegisterHandler.buildRegisterDevice()`:注册时 `device.setStatus("1")` + +3. **修复注册默认状态**:`registerByMqtt()` 中注册默认值从 `status=2` 改为 `status=1`(在线) + +**状态值定义**(来自 `AppDeviceBo` 注释): +- `0`:离线 +- `1`:在线 +- `2`:到期 +- `3`:故障 + +**新增文件**:`water-app/src/main/java/org/dromara/app/task/DeviceOfflineCheckTask.java` diff --git a/logs/sys-console.log b/logs/sys-console.log index 750b3d6..28449be 100644 --- a/logs/sys-console.log +++ b/logs/sys-console.log @@ -1,91 +1,327 @@ -2026-06-04 07:06:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:06:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[12]毫秒 -2026-06-04 07:06:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[36]毫秒 -2026-06-04 07:06:57 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2062185771665858562],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:57 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2062185771665858562],耗时:[13]毫秒 -2026-06-04 07:06:59 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2062185771665858562],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:59 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2062185771665858562],耗时:[5]毫秒 -2026-06-04 07:07:01 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[DELETE /app/v1/deleteDevice/2062185771665858562],参数类型[json],参数:[{"clientId":"32324a04c0175c8d61ac8a282553aea1"}] -2026-06-04 07:07:01 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[DELETE /app/v1/deleteDevice/2062185771665858562],耗时:[10]毫秒 -2026-06-04 07:07:03 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:03 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[5]毫秒 -2026-06-04 07:07:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[22]毫秒 -2026-06-04 07:07:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/schedulelist],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/schedulelist],耗时:[12]毫秒 -2026-06-04 07:07:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/schedulelist],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["2"]}] -2026-06-04 07:07:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/schedulelist],耗时:[15]毫秒 -2026-06-04 07:07:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 07:07:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/dataStatistics],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/dataStatistics],耗时:[8]毫秒 -2026-06-04 07:07:14 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/waterLogList],参数类型[param],参数:[{"param[endTime]":[""],"param[beginTime]":[""],"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:14 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/waterLogList],耗时:[16]毫秒 -2026-06-04 07:07:16 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:16 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 07:07:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒 -2026-06-04 07:07:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒 -2026-06-04 07:38:43 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:43 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:38:43 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[11]毫秒 -2026-06-04 07:38:43 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[28]毫秒 -2026-06-04 07:38:46 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2059509304398151682],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:46 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2059509304398151682],耗时:[7]毫秒 -2026-06-04 07:38:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 08:11:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 08:11:32 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060265891827957762],无参数 -2026-06-04 08:11:32 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060265891827957762],耗时:[8]毫秒 -2026-06-04 08:11:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:34 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒 -2026-06-04 08:11:35 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060266873861324801],无参数 -2026-06-04 08:11:35 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060266873861324801],耗时:[3]毫秒 -2026-06-04 08:11:37 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:37 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 08:11:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060266816596492289],无参数 -2026-06-04 08:11:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060266816596492289],耗时:[2]毫秒 -2026-06-04 08:11:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /app/v1/switchDevice],参数类型[json],参数:[{"id":"2060266816596492289","workStatus":"1","durationMin":"60"}] -2026-06-04 08:11:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /app/v1/switchDevice],耗时:[13]毫秒 -2026-06-04 08:12:04 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:12:04 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 08:21:57 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:21:57 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒 -2026-06-04 08:22:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:22:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒 -2026-06-04 08:27:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:27:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[29]毫秒 -2026-06-04 09:53:05 [MQTT Rec: water-server] WARN org.dromara.mqtt.MqttClientManager - [MQTT] 连接断开: 已断开连接 -2026-06-04 10:08:12 [MQTT Rec: water-server] WARN org.dromara.mqtt.MqttClientManager - [MQTT] 连接断开: 已断开连接 -2026-06-04 10:13:27 [MQTT Rec: water-server] WARN org.dromara.mqtt.MqttClientManager - [MQTT] 连接断开: 已断开连接 -2026-06-04 10:28:49 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:28:49 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[49]毫秒 -2026-06-04 10:31:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:31:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[27]毫秒 -2026-06-04 10:44:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:44:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[23]毫秒 -2026-06-04 10:50:27 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:50:27 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 10:52:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:52:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[25]毫秒 -2026-06-04 10:52:47 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:52:47 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 10:53:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:53:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒 -2026-06-04 11:05:23 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:05:23 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒 -2026-06-04 11:08:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:08:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 11:17:17 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:17:17 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[21]毫秒 -2026-06-04 11:20:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:20:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 11:21:29 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:21:29 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 11:22:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:22:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 11:23:26 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:23:26 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 +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]毫秒 diff --git a/logs/sys-error.log b/logs/sys-error.log index 5f37dc4..efa226c 100644 --- a/logs/sys-error.log +++ b/logs/sys-error.log @@ -1,6 +1 @@ -2026-06-03 08:07:41 [MQTT Ping: water-server] ERROR o.e.p.c.mqttv3.internal.ClientState - water-server: Timed out as no write activity, keepAlive=60,000,000,000 lastOutboundActivity=1,242,491,392,259,400 lastInboundActivity=1,242,491,421,357,900 time=1,293,117,233,745,900 lastPing=1,242,491,392,263,200 -2026-06-03 11:22:23 [XNIO-1 task-2] ERROR o.d.c.s.h.SaTokenExceptionHandler - 请求地址'/app/v1/deviceList',认证失败'token 已被冻结:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJhcHBfdXNlcjoyMDU2NTQzNTA3NTE0MDk3NjY1Iiwicm5TdHIiOiI4QnM4c2RiWkdOMEFPRTVQUHZUeTFCYWtzV0ozQVVHaSIsImNsaWVudGlkIjoiNDI4YTgzMTBjZDQ0Mjc1N2FlNjk5ZGY1ZDg5NGYwNTEiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MjA1NjU0MzUwNzUxNDA5NzY2NX0.kKJvH80xg1I8iFL0-v4_aMCEGsuwYm87T19UQ7cu3l4',无法访问系统资源 -2026-06-03 11:23:01 [XNIO-1 task-2] ERROR o.d.c.w.h.GlobalExceptionHandler - 访问过于频繁,请稍候再试 -2026-06-03 11:45:09 [XNIO-1 task-2] ERROR o.d.c.s.h.SaTokenExceptionHandler - 请求地址'/app/v1/deviceList',认证失败'token 已被冻结:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJhcHBfdXNlcjoyMDU2NTQzNTA3NTE0MDk3NjY1Iiwicm5TdHIiOiJ2alU3OVV0dWhsYjc4azhhUDNRazM4YnJ3QVJ4MGt6MCIsImNsaWVudGlkIjoiNDI4YTgzMTBjZDQ0Mjc1N2FlNjk5ZGY1ZDg5NGYwNTEiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MjA1NjU0MzUwNzUxNDA5NzY2NSwidXNlck5hbWUiOiIxMzMwNTM3NjA1NCJ9.WkM2XneftUNQbnIm69pDDEAzocsvHZlkv6e5SRS4_48',无法访问系统资源 -2026-06-03 17:44:04 [XNIO-1 task-3] ERROR o.d.c.w.h.GlobalExceptionHandler - 参数校验异常 -2026-06-03 22:52:30 [XNIO-1 task-2] ERROR o.d.c.w.h.GlobalExceptionHandler - 密码输入错误1次 +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 diff --git a/logs/sys-info.log b/logs/sys-info.log index f5f26c3..0fcfdb8 100644 --- a/logs/sys-info.log +++ b/logs/sys-info.log @@ -1,88 +1,323 @@ -2026-06-04 07:06:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:06:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[12]毫秒 -2026-06-04 07:06:53 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[36]毫秒 -2026-06-04 07:06:57 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2062185771665858562],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:57 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2062185771665858562],耗时:[13]毫秒 -2026-06-04 07:06:59 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2062185771665858562],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:06:59 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2062185771665858562],耗时:[5]毫秒 -2026-06-04 07:07:01 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[DELETE /app/v1/deleteDevice/2062185771665858562],参数类型[json],参数:[{"clientId":"32324a04c0175c8d61ac8a282553aea1"}] -2026-06-04 07:07:01 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[DELETE /app/v1/deleteDevice/2062185771665858562],耗时:[10]毫秒 -2026-06-04 07:07:03 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:03 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[5]毫秒 -2026-06-04 07:07:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[22]毫秒 -2026-06-04 07:07:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/schedulelist],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/schedulelist],耗时:[12]毫秒 -2026-06-04 07:07:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/schedulelist],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["2"]}] -2026-06-04 07:07:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/schedulelist],耗时:[15]毫秒 -2026-06-04 07:07:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 07:07:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/dataStatistics],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/dataStatistics],耗时:[8]毫秒 -2026-06-04 07:07:14 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/waterLogList],参数类型[param],参数:[{"param[endTime]":[""],"param[beginTime]":[""],"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:07:14 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/waterLogList],耗时:[16]毫秒 -2026-06-04 07:07:16 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:16 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 07:07:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒 -2026-06-04 07:07:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:07:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[6]毫秒 -2026-06-04 07:38:43 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:43 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"],"pageSize":["10"],"pageNum":["1"]}] -2026-06-04 07:38:43 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[11]毫秒 -2026-06-04 07:38:43 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[28]毫秒 -2026-06-04 07:38:46 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2059509304398151682],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:46 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2059509304398151682],耗时:[7]毫秒 -2026-06-04 07:38:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/getUserInfo],参数类型[param],参数:[{"clientId":["32324a04c0175c8d61ac8a282553aea1"]}] -2026-06-04 07:38:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/getUserInfo],耗时:[4]毫秒 -2026-06-04 08:11:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 08:11:32 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060265891827957762],无参数 -2026-06-04 08:11:32 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060265891827957762],耗时:[8]毫秒 -2026-06-04 08:11:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:34 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒 -2026-06-04 08:11:35 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060266873861324801],无参数 -2026-06-04 08:11:35 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060266873861324801],耗时:[3]毫秒 -2026-06-04 08:11:37 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:11:37 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 08:11:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/device/2060266816596492289],无参数 -2026-06-04 08:11:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/device/2060266816596492289],耗时:[2]毫秒 -2026-06-04 08:11:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /app/v1/switchDevice],参数类型[json],参数:[{"id":"2060266816596492289","workStatus":"1","durationMin":"60"}] -2026-06-04 08:11:51 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /app/v1/switchDevice],耗时:[13]毫秒 -2026-06-04 08:12:04 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:12:04 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 08:21:57 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:21:57 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[17]毫秒 -2026-06-04 08:22:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:22:06 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒 -2026-06-04 08:27:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 08:27:53 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[29]毫秒 -2026-06-04 10:28:49 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:28:49 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[49]毫秒 -2026-06-04 10:31:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:31:13 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[27]毫秒 -2026-06-04 10:44:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:44:03 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[23]毫秒 -2026-06-04 10:50:27 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:50:27 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 10:52:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:52:28 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[25]毫秒 -2026-06-04 10:52:47 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:52:47 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 10:53:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 10:53:33 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[14]毫秒 -2026-06-04 11:05:23 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:05:23 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[18]毫秒 -2026-06-04 11:08:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:08:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 11:17:17 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:17:17 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[21]毫秒 -2026-06-04 11:20:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:20:07 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 11:21:29 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:21:29 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 -2026-06-04 11:22:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:22:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[16]毫秒 -2026-06-04 11:23:26 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数 -2026-06-04 11:23:26 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒 +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]毫秒 diff --git a/water-admin/src/main/java/org/dromara/DromaraApplication.java b/water-admin/src/main/java/org/dromara/DromaraApplication.java index 0590dd7..9bbf5af 100644 --- a/water-admin/src/main/java/org/dromara/DromaraApplication.java +++ b/water-admin/src/main/java/org/dromara/DromaraApplication.java @@ -18,7 +18,7 @@ public class DromaraApplication { SpringApplication application = new SpringApplication(DromaraApplication.class); application.setApplicationStartup(new BufferingApplicationStartup(2048)); application.run(args); - log.info("(♥◠‿◠)ノ゙ water-Vue-Plus启动成功 ლ(´ڡ`ლ)゙"); + log.info("(♥◠‿◠)ノ゙ 系统启动成功 ლ(´ڡ`ლ)゙"); } } diff --git a/water-admin/src/main/java/org/dromara/web/controller/AuthController.java b/water-admin/src/main/java/org/dromara/web/controller/AuthController.java index 79e77dd..26b2e9c 100644 --- a/water-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/water-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -98,7 +98,7 @@ public class AuthController { SysClientVo client = clientService.queryByClientId(clientId); // 查询不到 client 或 client 内不包含 grantType if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { - log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); + log.info("客户端ID:{} 认证类型:{} 异常!", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); } else if (!SystemConstants.NORMAL.equals(client.getStatus())) { return R.fail(MessageUtils.message("auth.grant.type.blocked")); diff --git a/water-admin/src/main/java/org/dromara/web/listener/UserActionListener.java b/water-admin/src/main/java/org/dromara/web/listener/UserActionListener.java index 6c8accb..4ee733b 100644 --- a/water-admin/src/main/java/org/dromara/web/listener/UserActionListener.java +++ b/water-admin/src/main/java/org/dromara/web/listener/UserActionListener.java @@ -73,7 +73,7 @@ public class UserActionListener implements SaTokenListener { SpringUtils.context().publishEvent(logininforEvent); // 更新登录信息 loginService.recordLoginInfo((Long) loginParameter.getExtra(LoginHelper.USER_KEY), ip); - log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); + log.info("用户登录,用户ID:{},令牌:{}", loginId, tokenValue); } /** @@ -85,7 +85,7 @@ public class UserActionListener implements SaTokenListener { TenantHelper.dynamic(tenantId, () -> { RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); }); - log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); + log.info("用户注销,用户ID:{},令牌:{}", loginId, tokenValue); } /** @@ -97,7 +97,7 @@ public class UserActionListener implements SaTokenListener { TenantHelper.dynamic(tenantId, () -> { RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); }); - log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); + log.info("用户被踢下线,用户ID:{},令牌:{}", loginId, tokenValue); } /** @@ -109,7 +109,7 @@ public class UserActionListener implements SaTokenListener { TenantHelper.dynamic(tenantId, () -> { RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); }); - log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); + log.info("用户被顶下线,用户ID:{},令牌:{}", loginId, tokenValue); } /** diff --git a/water-admin/src/main/resources/application.yml b/water-admin/src/main/resources/application.yml index eb7cb19..d1354ca 100644 --- a/water-admin/src/main/resources/application.yml +++ b/water-admin/src/main/resources/application.yml @@ -55,6 +55,9 @@ mqtt: pending-set-key: "mqtt:command:pending:ids" device-status-cache-prefix: "mqtt:device:status:" device-status-cache-ttl-seconds: 300 + offline-check: + enabled: true + interval-ms: 90000 topics: subscribe: diff --git a/water-admin/src/main/resources/i18n/messages.properties b/water-admin/src/main/resources/i18n/messages.properties index b7a37e7..701f0a3 100644 --- a/water-admin/src/main/resources/i18n/messages.properties +++ b/water-admin/src/main/resources/i18n/messages.properties @@ -1 +1,78 @@ -#错误消息 not.null=* 必须填写 user.jcaptcha.error=验证码错误 user.jcaptcha.expire=验证码已失效 user.not.exists=对不起, 您的账号:{0} 不存在. user.password.not.match=用户不存在/密码错误 user.password.retry.limit.count=密码输入错误{0}次 user.password.retry.limit.exceed=密码输入错误{0}次,账户锁定{1}分钟 user.password.delete=对不起,您的账号:{0} 已被删除 user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员 role.blocked=角色已封禁,请联系管理员 user.logout.success=退出成功 length.not.valid=长度必须在{min}到{max}个字符之间 user.username.not.blank=用户名不能为空 user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头 user.username.length.valid=账户长度必须在{min}到{max}个字符之间 user.password.not.blank=用户密码不能为空 user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间 user.password.not.valid=* 5-50个字符 user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符 user.email.not.valid=邮箱格式错误 user.email.not.blank=邮箱不能为空 user.email.not.username=邮箱号不一致 user.phonenumber.not.blank=用户手机号不能为空 user.mobile.phone.number.not.valid=手机号格式错误 ser.mobile.phone.number.not.username=手机号不一致 user.login.success=登录成功 user.register.success=注册成功 user.register.save.error=保存用户 {0} 失败,注册账号已存在 user.register.error=注册失败,请联系系统管理人员 user.notfound=请重新登录 user.forcelogout=管理员强制退出,请重新登录 user.unknown.error=未知错误,请重新登录 auth.grant.type.error=认证权限类型错误 auth.grant.type.blocked=认证权限类型已禁用 auth.grant.type.not.blank=认证权限类型不能为空 auth.clientid.not.blank=认证客户端id不能为空 ##文件上传消息 upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB! upload.filename.exceed.length=上传的文件名最长{0}个字符 ##权限 no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}] no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] repeat.submit.message=不允许重复提交,请稍候再试 rate.limiter.message=访问过于频繁,请稍候再试 sms.code.not.blank=短信验证码不能为空 sms.code.retry.limit.count=短信验证码输入错误{0}次 sms.code.retry.limit.exceed=短信验证码输入错误{0}次,账户锁定{1}分钟 email.code.not.blank=邮箱验证码不能为空 email.code.retry.limit.count=邮箱验证码输入错误{0}次 email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,账户锁定{1}分钟 xcx.code.not.blank=小程序[code]不能为空 social.source.not.blank=第三方登录平台[source]不能为空 social.code.not.blank=第三方登录平台[code]不能为空 social.state.not.blank=第三方登录平台[state]不能为空 ##租户 tenant.number.not.blank=租户编号不能为空 tenant.not.exists=对不起, 您的租户不存在,请联系管理员 tenant.blocked=对不起,您的租户已禁用,请联系管理员 tenant.expired=对不起,您的租户已过期,请联系管理员 \ No newline at end of file +#错误消息 +operation.success=操作成功 +operation.fail=操作失败 +query.success=查询成功 +not.null=* 必须填写 +user.jcaptcha.error=验证码错误 +user.jcaptcha.expire=验证码已失效 +user.not.exists=对不起, 您的账号:{0} 不存在. +user.password.not.match=用户不存在/密码错误 +user.password.retry.limit.count=密码输入错误{0}次 +user.password.retry.limit.exceed=密码输入错误{0}次,账户锁定{1}分钟 +user.password.delete=对不起,您的账号:{0} 已被删除 +user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员 +role.blocked=角色已封禁,请联系管理员 +user.logout.success=退出成功 +length.not.valid=长度必须在{min}到{max}个字符之间 +user.username.not.blank=用户名不能为空 +user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头 +user.username.length.valid=账户长度必须在{min}到{max}个字符之间 +user.password.not.blank=用户密码不能为空 +user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间 +user.password.not.valid=* 5-50个字符 +user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符 +user.email.not.valid=邮箱格式错误 +user.email.not.blank=邮箱不能为空 +user.email.not.username=邮箱号不一致 +user.phonenumber.not.blank=用户手机号不能为空 +user.mobile.phone.number.not.valid=手机号格式错误 +user.mobile.phone.number.not.username=手机号不一致 +user.login.success=登录成功 +user.register.success=注册成功 +user.register.save.error=保存用户 {0} 失败,注册账号已存在 +user.register.error=注册失败,请联系系统管理人员 +user.notfound=请重新登录 +user.forcelogout=管理员强制退出,请重新登录 +user.unknown.error=未知错误,请重新登录 +auth.grant.type.error=认证权限类型错误 +auth.grant.type.blocked=认证权限类型已禁用 +auth.grant.type.not.blank=认证权限类型不能为空 +auth.clientid.not.blank=认证客户端id不能为空 +##文件上传消息 +upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB! +upload.filename.exceed.length=上传的文件名最长{0}个字符 +##权限 +no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] +no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] +no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}] +no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] +no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] +no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] +repeat.submit.message=不允许重复提交,请稍候再试 +rate.limiter.message=访问过于频繁,请稍候再试 +sms.code.not.blank=短信验证码不能为空 +sms.code.retry.limit.count=短信验证码输入错误{0}次 +sms.code.retry.limit.exceed=短信验证码输入错误{0}次,账户锁定{1}分钟 +email.code.not.blank=邮箱验证码不能为空 +email.code.retry.limit.count=邮箱验证码输入错误{0}次 +email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,账户锁定{1}分钟 +xcx.code.not.blank=小程序[code]不能为空 +social.source.not.blank=第三方登录平台[source]不能为空 +social.code.not.blank=第三方登录平台[code]不能为空 +social.state.not.blank=第三方登录平台[state]不能为空 +##租户 +tenant.number.not.blank=租户编号不能为空 +tenant.not.exists=对不起, 您的租户不存在,请联系管理员 +tenant.blocked=对不起,您的租户已禁用,请联系管理员 +tenant.expired=对不起,您的租户已过期,请联系管理员 +##APP +app.device.no.not.blank=设备编号不能为空 +app.device.not.exists.or.denied=设备不存在或无权访问 +app.schedule.id.not.blank=排程编号不能为空 +app.schedule.not.exists.or.denied=排程不存在或无权访问 +app.schedule.id.not.blank.request=scheduleId不能为空 +app.schedule.devices.not.blank=deviceNos不能为空 +app.watering.log.id.not.blank=浇水记录编号不能为空 +app.watering.log.not.exists.or.denied=浇水记录不存在或无权访问 +app.user.data.denied=没有权限访问用户数据! +app.user.phone.exists=修改用户'{0}'失败,手机号码已存在 diff --git a/water-admin/src/main/resources/i18n/messages_en_US.properties b/water-admin/src/main/resources/i18n/messages_en_US.properties index 306a48f..e20da34 100644 --- a/water-admin/src/main/resources/i18n/messages_en_US.properties +++ b/water-admin/src/main/resources/i18n/messages_en_US.properties @@ -1,4 +1,7 @@ -#错误消息 +# error messages +operation.success=Operation successful +operation.fail=Operation failed +query.success=Query successful not.null=* Required fill in user.jcaptcha.error=Captcha error user.jcaptcha.expire=Captcha invalid @@ -6,9 +9,9 @@ user.not.exists=Sorry, your account: {0} does not exist user.password.not.match=User does not exist/Password error user.password.retry.limit.count=Password input error {0} times user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes -user.password.delete=Sorry, your account:{0} has been deleted +user.password.delete=Sorry, your account: {0} has been deleted user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator -role.blocked=Role disabled,please contact administrators +role.blocked=Role disabled, please contact administrators user.logout.success=Exit successful length.not.valid=The length must be between {min} and {max} characters user.username.not.blank=Username cannot be blank @@ -20,29 +23,31 @@ user.password.not.valid=* 5-50 characters user.password.format.valid=Password must contain uppercase, lowercase, digit, and special character user.email.not.valid=Mailbox format error user.email.not.blank=Mailbox cannot be blank +user.email.not.username=Email does not match the current user user.phonenumber.not.blank=Phone number cannot be blank user.mobile.phone.number.not.valid=Phone number format error +user.mobile.phone.number.not.username=Phone number does not match the current user user.login.success=Login successful user.register.success=Register successful user.register.save.error=Failed to save user {0}, The registered account already exists user.register.error=Register failed, please contact system administrator user.notfound=Please login again -user.forcelogout=The administrator is forced to exit,please login again +user.forcelogout=The administrator is forced to exit, please login again user.unknown.error=Unknown error, please login again auth.grant.type.error=Auth grant type error auth.grant.type.blocked=Auth grant type disabled auth.grant.type.not.blank=Auth grant type cannot be blank auth.clientid.not.blank=Auth clientid cannot be blank -##文件上传消息 -upload.exceed.maxSize=The uploaded file size exceeds the limit file size!
the maximum allowed file size is:{0}MB! +## upload messages +upload.exceed.maxSize=The uploaded file size exceeds the limit file size!
the maximum allowed file size is: {0}MB! upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters -##权限 -no.permission=You do not have permission to the data,please contact your administrator to add permissions [{0}] -no.create.permission=You do not have permission to create data,please contact your administrator to add permissions [{0}] -no.update.permission=You do not have permission to modify data,please contact your administrator to add permissions [{0}] -no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}] -no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}] -no.view.permission=You do not have permission to view data,please contact your administrator to add permissions [{0}] +## permissions +no.permission=You do not have permission to the data, please contact your administrator to add permissions [{0}] +no.create.permission=You do not have permission to create data, please contact your administrator to add permissions [{0}] +no.update.permission=You do not have permission to modify data, please contact your administrator to add permissions [{0}] +no.delete.permission=You do not have permission to delete data, please contact your administrator to add permissions [{0}] +no.export.permission=You do not have permission to export data, please contact your administrator to add permissions [{0}] +no.view.permission=You do not have permission to view data, please contact your administrator to add permissions [{0}] repeat.submit.message=Repeat submit is not allowed, please try again later rate.limiter.message=Visit too frequently, please try again later sms.code.not.blank=Sms code cannot be blank @@ -55,8 +60,19 @@ xcx.code.not.blank=Mini program [code] cannot be blank social.source.not.blank=Social login platform [source] cannot be blank social.code.not.blank=Social login platform [code] cannot be blank social.state.not.blank=Social login platform [state] cannot be blank -##租户 +## tenant tenant.number.not.blank=Tenant number cannot be blank tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator tenant.expired=Sorry, your tenant has expired. Please contact the administrator. +## APP +app.device.no.not.blank=Device number cannot be blank +app.device.not.exists.or.denied=Device does not exist or access is denied +app.schedule.id.not.blank=Schedule ID cannot be blank +app.schedule.not.exists.or.denied=Schedule does not exist or access is denied +app.schedule.id.not.blank.request=scheduleId cannot be blank +app.schedule.devices.not.blank=deviceNos cannot be blank +app.watering.log.id.not.blank=Watering log ID cannot be blank +app.watering.log.not.exists.or.denied=Watering log does not exist or access is denied +app.user.data.denied=No permission to access user data +app.user.phone.exists=Failed to update user ''{0}'': phone number already exists diff --git a/water-admin/src/main/resources/i18n/messages_zh_CN.properties b/water-admin/src/main/resources/i18n/messages_zh_CN.properties index e1e5263..701f0a3 100644 --- a/water-admin/src/main/resources/i18n/messages_zh_CN.properties +++ b/water-admin/src/main/resources/i18n/messages_zh_CN.properties @@ -1,4 +1,7 @@ #错误消息 +operation.success=操作成功 +operation.fail=操作失败 +query.success=查询成功 not.null=* 必须填写 user.jcaptcha.error=验证码错误 user.jcaptcha.expire=验证码已失效 @@ -20,8 +23,10 @@ user.password.not.valid=* 5-50个字符 user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符 user.email.not.valid=邮箱格式错误 user.email.not.blank=邮箱不能为空 +user.email.not.username=邮箱号不一致 user.phonenumber.not.blank=用户手机号不能为空 user.mobile.phone.number.not.valid=手机号格式错误 +user.mobile.phone.number.not.username=手机号不一致 user.login.success=登录成功 user.register.success=注册成功 user.register.save.error=保存用户 {0} 失败,注册账号已存在 @@ -60,3 +65,14 @@ tenant.number.not.blank=租户编号不能为空 tenant.not.exists=对不起, 您的租户不存在,请联系管理员 tenant.blocked=对不起,您的租户已禁用,请联系管理员 tenant.expired=对不起,您的租户已过期,请联系管理员 +##APP +app.device.no.not.blank=设备编号不能为空 +app.device.not.exists.or.denied=设备不存在或无权访问 +app.schedule.id.not.blank=排程编号不能为空 +app.schedule.not.exists.or.denied=排程不存在或无权访问 +app.schedule.id.not.blank.request=scheduleId不能为空 +app.schedule.devices.not.blank=deviceNos不能为空 +app.watering.log.id.not.blank=浇水记录编号不能为空 +app.watering.log.not.exists.or.denied=浇水记录不存在或无权访问 +app.user.data.denied=没有权限访问用户数据! +app.user.phone.exists=修改用户'{0}'失败,手机号码已存在 diff --git a/water-common/water-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java b/water-common/water-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java index 1cc3bd6..0a1ae1c 100644 --- a/water-common/water-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java +++ b/water-common/water-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java @@ -70,7 +70,7 @@ public class ThreadPoolConfig { if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { pool.shutdownNow(); if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { - log.info("Pool did not terminate"); + log.info("线程池未在指定时间内终止"); } } } catch (InterruptedException ie) { @@ -87,9 +87,8 @@ public class ThreadPoolConfig { * 打印线程异常信息 */ public static void printException(Runnable r, Throwable t) { - if (t == null && r instanceof Future) { + if (t == null && r instanceof Future future) { try { - Future future = (Future) r; if (future.isDone()) { future.get(); } diff --git a/water-common/water-common-core/src/main/java/org/dromara/common/core/domain/R.java b/water-common/water-common-core/src/main/java/org/dromara/common/core/domain/R.java index be85805..78d3a53 100644 --- a/water-common/water-common-core/src/main/java/org/dromara/common/core/domain/R.java +++ b/water-common/water-common-core/src/main/java/org/dromara/common/core/domain/R.java @@ -1,8 +1,9 @@ package org.dromara.common.core.domain; -import org.dromara.common.core.constant.HttpStatus; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.HttpStatus; +import org.dromara.common.core.utils.MessageUtils; import java.io.Serial; import java.io.Serializable; @@ -36,11 +37,11 @@ public class R implements Serializable { private T data; public static R ok() { - return restResult(null, SUCCESS, "操作成功"); + return restResult(null, SUCCESS, message("operation.success", "操作成功")); } public static R ok(T data) { - return restResult(data, SUCCESS, "操作成功"); + return restResult(data, SUCCESS, message("operation.success", "操作成功")); } public static R ok(String msg) { @@ -52,7 +53,7 @@ public class R implements Serializable { } public static R fail() { - return restResult(null, FAIL, "操作失败"); + return restResult(null, FAIL, message("operation.fail", "操作失败")); } public static R fail(String msg) { @@ -100,6 +101,15 @@ public class R implements Serializable { return r; } + private static String message(String code, String defaultMessage) { + try { + String message = MessageUtils.message(code); + return code.equals(message) ? defaultMessage : message; + } catch (Exception e) { + return defaultMessage; + } + } + public static Boolean isError(R ret) { return !isSuccess(ret); } diff --git a/water-common/water-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java b/water-common/water-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java index 2012cd4..53907d8 100644 --- a/water-common/water-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java +++ b/water-common/water-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java @@ -63,7 +63,7 @@ public class RegionUtils { Config v6Config = null; InputStream v6XdbInputStream = ResourceUtil.getStreamSafe(DEFAULT_IPV6_XDB_PATH); if (v6XdbInputStream == null) { - log.warn("未加载 IPv6 地址库:未在类路径下找到文件 {}。当前仅启用 IPv4 查询。如需启用 IPv6,请将 ip2region_v6.xdb 放置到 resources 目录", DEFAULT_IPV6_XDB_PATH); + log.warn("未加载 IPv6 地址库:未在类路径下找到文件 {}。当前仅启用 IPv4 查询。如需启用 IPv6,请将 ip2region_v6.xdb 放置到资源目录", DEFAULT_IPV6_XDB_PATH); } else { v6Config = Config.custom() .setCachePolicy(Config.BufferCache) @@ -128,7 +128,7 @@ public class RegionUtils { try { ip2Region.close(10000); } catch (Exception e) { - log.error("Ip2Region服务关闭异常", e); + log.error("IP地址库服务关闭异常", e); } } @@ -148,7 +148,7 @@ public class RegionUtils { try { ip2Region.close(timeout.toMillis()); } catch (Exception e) { - log.error("Ip2Region服务关闭异常", e); + log.error("IP地址库服务关闭异常", e); } } diff --git a/water-common/water-common-doc/src/main/java/org/dromara/common/doc/core/resolver/SaTokenAnnotationMetadataJavadocResolver.java b/water-common/water-common-doc/src/main/java/org/dromara/common/doc/core/resolver/SaTokenAnnotationMetadataJavadocResolver.java index 9e09619..74e7936 100644 --- a/water-common/water-common-doc/src/main/java/org/dromara/common/doc/core/resolver/SaTokenAnnotationMetadataJavadocResolver.java +++ b/water-common/water-common-doc/src/main/java/org/dromara/common/doc/core/resolver/SaTokenAnnotationMetadataJavadocResolver.java @@ -46,7 +46,7 @@ public class SaTokenAnnotationMetadataJavadocResolver extends AbstractMetadataJa SA_IGNORE_CLASS = (Class) ClassLoaderUtil.loadClass(SA_IGNORE_CLASS_NAME, false); SA_CHECK_LOGIN_CLASS = (Class) ClassLoaderUtil.loadClass(SA_CHECK_LOGIN_NAME, false); if (log.isDebugEnabled()) { - log.debug("SaTokenAnnotationJavadocResolver init success, load annotation class: {}", List.of(SA_CHECK_ROLE_CLASS, SA_CHECK_PERMISSION_CLASS, SA_IGNORE_CLASS, SA_CHECK_LOGIN_CLASS)); + log.debug("SaToken 注解 Javadoc 解析器初始化成功,已加载注解类:{}", List.of(SA_CHECK_ROLE_CLASS, SA_CHECK_PERMISSION_CLASS, SA_IGNORE_CLASS, SA_CHECK_LOGIN_CLASS)); } } diff --git a/water-common/water-common-json/src/main/java/org/dromara/common/json/config/JacksonConfig.java b/water-common/water-common-json/src/main/java/org/dromara/common/json/config/JacksonConfig.java index 0392573..10eb7a1 100644 --- a/water-common/water-common-json/src/main/java/org/dromara/common/json/config/JacksonConfig.java +++ b/water-common/water-common-json/src/main/java/org/dromara/common/json/config/JacksonConfig.java @@ -48,7 +48,7 @@ public class JacksonConfig { public Jackson2ObjectMapperBuilderCustomizer customizer() { return builder -> { builder.timeZone(TimeZone.getDefault()); - log.info("初始化 jackson 配置"); + log.info("初始化JSON序列化配置"); }; } diff --git a/water-common/water-common-mqtt/pom.xml b/water-common/water-common-mqtt/pom.xml index 884968f..d4809f2 100644 --- a/water-common/water-common-mqtt/pom.xml +++ b/water-common/water-common-mqtt/pom.xml @@ -35,6 +35,10 @@ org.dromara water-common-json + + org.dromara + water-common-core + org.dromara water-app diff --git a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/DeviceMqttCommandPublisher.java b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/DeviceMqttCommandPublisher.java index 07bb527..cd61323 100644 --- a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/DeviceMqttCommandPublisher.java +++ b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/DeviceMqttCommandPublisher.java @@ -34,7 +34,12 @@ public class DeviceMqttCommandPublisher implements IDeviceCommandPublisher { command.getPayload().put("commandType", command.getCommandType()); ackService.savePending(command); - mqttClientManager.publish(command.getTopic(), JsonUtils.toJsonString(command.getPayload())); + try { + mqttClientManager.publish(command.getTopic(), JsonUtils.toJsonString(command.getPayload())); + } catch (RuntimeException e) { + ackService.removePending(command.getCommandId()); + throw e; + } return command.getCommandId(); } diff --git a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttClientManager.java b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttClientManager.java index 6ab46c6..f93a19e 100644 --- a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttClientManager.java +++ b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttClientManager.java @@ -3,13 +3,10 @@ package org.dromara.mqtt; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.app.mqtt.MqttMessageDispatcher; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; import org.dromara.mqtt.config.properties.MqttProperties; -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; -import org.eclipse.paho.client.mqttv3.MqttAsyncClient; -import org.eclipse.paho.client.mqttv3.MqttCallbackExtended; -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; -import org.eclipse.paho.client.mqttv3.MqttException; -import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -26,11 +23,7 @@ import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; @Slf4j @@ -50,6 +43,12 @@ public class MqttClientManager implements DisposableBean { @Bean @ConditionalOnProperty(prefix = "mqtt", name = "enabled", havingValue = "true") public MqttAsyncClient mqttConnect() throws MqttException { + if (StringUtils.isBlank(props.getBrokerUrl())) { + throw new ServiceException("启用 MQTT 时必须配置 broker-url"); + } + if (StringUtils.isBlank(props.getClientId())) { + throw new ServiceException("启用 MQTT 时必须配置 client-id"); + } messageQueue = new ArrayBlockingQueue<>(Math.max(1, props.getAsync().getQueueCapacity())); consumerExecutor = createConsumerExecutor(); running = true; @@ -71,13 +70,13 @@ public class MqttClientManager implements DisposableBean { client.setCallback(new MqttCallbackExtended() { @Override public void connectionLost(Throwable cause) { - log.warn("[MQTT] connection lost: {}", cause == null ? "" : cause.getMessage()); + log.warn("[MQTT] 连接已断开:{}", cause == null ? "" : cause.getMessage()); } @Override public void connectComplete(boolean reconnect, String serverURI) { if (reconnect) { - log.info("[MQTT] reconnected: {}", serverURI); + log.info("[MQTT] 已重新连接:{}", serverURI); subscribeTopics(); } } @@ -94,7 +93,7 @@ public class MqttClientManager implements DisposableBean { }); client.connect(options).waitForCompletion(); - log.info("[MQTT] connected: {}", props.getBrokerUrl()); + log.info("[MQTT] 已连接:{}", props.getBrokerUrl()); subscribeTopics(); return client; } @@ -183,11 +182,11 @@ public class MqttClientManager implements DisposableBean { InboundMessage inboundMessage = new InboundMessage(topic, payload); try { if (!messageQueue.offer(inboundMessage, props.getAsync().getOfferTimeoutMs(), TimeUnit.MILLISECONDS)) { - log.warn("[MQTT] inbound queue full, dropped topic={}", topic); + log.warn("[MQTT] 上行消息队列已满,丢弃 主题={}", topic); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - log.warn("[MQTT] enqueue interrupted topic={}", topic); + log.warn("[MQTT] 上行消息入队被中断 主题={}", topic); } } @@ -221,7 +220,7 @@ public class MqttClientManager implements DisposableBean { try { dispatcher.dispatch(message.topic(), message.payload()); } catch (Exception e) { - log.error("[MQTT] dispatch failed topic={}", message.topic(), e); + log.error("[MQTT] 消息分发失败 主题={}", message.topic(), e); } } @@ -232,30 +231,31 @@ public class MqttClientManager implements DisposableBean { } List topics = props.getTopics() == null ? List.of() : props.getTopics().getSubscribe(); if (topics == null || topics.isEmpty()) { - log.warn("[MQTT] no subscribe topics configured"); + log.warn("[MQTT] 未配置订阅主题"); return; } int[] qos = topics.stream().mapToInt(topic -> props.getQos()).toArray(); client.subscribe(topics.toArray(new String[0]), qos).waitForCompletion(); - topics.forEach(topic -> log.info("[MQTT] subscribed: {} qos={}", topic, props.getQos())); + topics.forEach(topic -> log.info("[MQTT] 已订阅 主题={} 服务质量等级={}", topic, props.getQos())); } catch (MqttException e) { - log.error("[MQTT] subscribe failed", e); + log.error("[MQTT] 订阅失败", e); } } public void publish(String topic, String payload) { try { if (client == null || !client.isConnected()) { - log.warn("[MQTT] publish skipped, client not connected topic={}", topic); - return; + throw new ServiceException("MQTT客户端未连接"); } MqttMessage message = new MqttMessage(payload.getBytes(StandardCharsets.UTF_8)); message.setQos(props.getQos()); message.setRetained(false); - client.publish(topic, message); - log.info("[MQTT] published topic={} payload={}", topic, payload); + IMqttDeliveryToken token = client.publish(topic, message); + token.waitForCompletion(Math.max(1000L, props.getConnectionTimeout() * 1000L)); + log.info("[MQTT] 消息已发布 主题={} 消息体={}", topic, payload); } catch (MqttException e) { - log.error("[MQTT] publish failed topic={}", topic, e); + log.error("[MQTT] 消息发布失败 主题={}", topic, e); + throw new ServiceException("MQTT 消息发布失败:{}", e.getMessage()); } } diff --git a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandAckService.java b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandAckService.java index e1b3f4b..de80c2f 100644 --- a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandAckService.java +++ b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandAckService.java @@ -1,9 +1,12 @@ package org.dromara.mqtt; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.app.domain.AppDevice; import org.dromara.app.domain.mqtt.DeviceCommand; import org.dromara.app.domain.mqtt.DeviceCommandAck; +import org.dromara.app.mapper.AppDeviceMapper; import org.dromara.app.service.IDeviceCommandAckHandler; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; @@ -17,11 +20,7 @@ import org.springframework.stereotype.Service; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.TimeUnit; @Slf4j @@ -36,16 +35,24 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { @Autowired private MqttClientManager mqttClientManager; private final MqttProperties mqttProperties; + private final AppDeviceMapper appDeviceMapper; public void savePending(DeviceCommand command) { RedisUtils.setCacheObject(pendingKey(command.getCommandId()), command, Duration.ofSeconds(mqttProperties.getCommandAck().getPendingTtlSeconds())); pendingIds().add(command.getCommandId()); } + public void removePending(String commandId) { + if (StringUtils.isBlank(commandId)) { + return; + } + deletePending(commandId); + } + @Override public void handleAck(String deviceNo, String payload) { if (StringUtils.isBlank(payload)) { - log.warn("[MQTT] 收到空 ACK deviceNo={}", deviceNo); + log.warn("[MQTT] 收到空 ACK 设备编号={}", deviceNo); return; } @@ -59,26 +66,25 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { try { ack = JsonUtils.parseObject(trimmedPayload, DeviceCommandAck.class); } catch (RuntimeException e) { - log.warn("[MQTT] ACK JSON 格式错误 deviceNo={} payload={}", deviceNo, payload, e); + log.warn("[MQTT] ACK JSON 格式错误 设备编号={} 消息体={}", deviceNo, payload, e); return; } if (ack == null || ack.getCommandId() == null) { - log.warn("[MQTT] ACK 缺少 commandId deviceNo={} payload={}", deviceNo, payload); + log.warn("[MQTT] ACK 缺少命令编号 设备编号={} 消息体={}", deviceNo, payload); return; } ack.setDeviceNo(deviceNo); - RedisUtils.deleteObject(pendingKey(ack.getCommandId())); - pendingIds().remove(ack.getCommandId()); + deletePending(ack.getCommandId()); RedisUtils.setCacheObject(ackKey(ack.getCommandId()), ack, Duration.ofSeconds(mqttProperties.getCommandAck().getAckTtlSeconds())); refreshDeviceOnline(deviceNo); - log.info("[MQTT] command ack received deviceNo={} commandId={} status={}", deviceNo, ack.getCommandId(), ack.getStatus()); + log.info("[MQTT] 收到命令确认 设备编号={} 命令编号={} 状态={}", deviceNo, ack.getCommandId(), ack.getStatus()); } private void handlePlainAck(String deviceNo, String payload) { List pendingCommands = findPendingCommandsByDeviceNo(deviceNo); refreshDeviceOnline(deviceNo); if (pendingCommands.size() != 1) { - log.warn("[MQTT] 非 JSON ACK 无法唯一匹配待确认命令 deviceNo={} pendingCount={} payload={}", deviceNo, pendingCommands.size(), payload); + log.warn("[MQTT] 非 JSON ACK 无法唯一匹配待确认命令 设备编号={} 待确认数量={} 消息体={}", deviceNo, pendingCommands.size(), payload); return; } @@ -90,10 +96,9 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { ack.setStatus("1"); ack.setMessage(payload); - RedisUtils.deleteObject(pendingKey(commandId)); - pendingIds().remove(commandId); + deletePending(commandId); RedisUtils.setCacheObject(ackKey(commandId), ack, Duration.ofSeconds(mqttProperties.getCommandAck().getAckTtlSeconds())); - log.info("[MQTT] plain command ack received deviceNo={} commandId={} payload={}", deviceNo, commandId, payload); + log.info("[MQTT] 收到非 JSON 命令确认 设备编号={} 命令编号={} 消息体={}", deviceNo, commandId, payload); } private List findPendingCommandsByDeviceNo(String deviceNo) { @@ -126,7 +131,9 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { retryCommand(commandId, now); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - log.warn("[MQTT] 命令重试锁等待被中断 commandId={}", commandId); + log.warn("[MQTT] 命令重试锁等待被中断 命令编号={}", commandId); + } catch (RuntimeException e) { + log.error("[MQTT] 命令重试失败 命令编号={}", commandId, e); } finally { if (locked && lock.isHeldByCurrentThread()) { lock.unlock(); @@ -144,15 +151,20 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { return; } if (command.getRetryCount() >= mqttProperties.getCommandAck().getMaxRetryCount()) { - RedisUtils.deleteObject(pendingKey(commandId)); - pendingIds().remove(commandId); - log.warn("[MQTT] 命令重试次数已达上限 deviceNo={} commandId={}", command.getDeviceNo(), commandId); + deletePending(commandId); + log.warn("[MQTT] 命令重试次数已达上限 设备编号={} 命令编号={}", command.getDeviceNo(), commandId); return; } if (!isDeviceOnline(command.getDeviceNo())) { + command.setRetryCount(command.getRetryCount() + 1); + if (command.getRetryCount() >= mqttProperties.getCommandAck().getMaxRetryCount()) { + deletePending(commandId); + log.warn("[MQTT] 设备离线,命令达到最大等待次数,已删除待确认命令 设备编号={} 命令编号={}", command.getDeviceNo(), commandId); + return; + } command.setNextRetryAt(now + mqttProperties.getCommandAck().getRetryIntervalMs()); savePending(command); - log.debug("[MQTT] command retry delayed, device offline deviceNo={} commandId={}", command.getDeviceNo(), commandId); + log.debug("[MQTT] 设备离线,命令延后重试 设备编号={} 命令编号={} 等待次数={}", command.getDeviceNo(), commandId, command.getRetryCount()); return; } @@ -161,7 +173,7 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { command.setNextRetryAt(now + mqttProperties.getCommandAck().getRetryIntervalMs()); mqttClientManager.publish(command.getTopic(), JsonUtils.toJsonString(command.getPayload())); savePending(command); - log.info("[MQTT] command resent deviceNo={} commandId={} retry={}", command.getDeviceNo(), commandId, command.getRetryCount()); + log.info("[MQTT] 命令已重新下发 设备编号={} 命令编号={} 重试次数={}", command.getDeviceNo(), commandId, command.getRetryCount()); } private boolean isDeviceOnline(String deviceNo) { @@ -183,12 +195,22 @@ public class MqttCommandAckService implements IDeviceCommandAckHandler { statusCache, Duration.ofSeconds(mqttProperties.getCommandAck().getDeviceStatusCacheTtlSeconds()) ); + appDeviceMapper.update(null, + new LambdaUpdateWrapper() + .set(AppDevice::getStatus, "1") + .eq(AppDevice::getDeviceNo, deviceNo) + ); } private RSet pendingIds() { return RedisUtils.getClient().getSet(mqttProperties.getCommandAck().getPendingSetKey()); } + private void deletePending(String commandId) { + RedisUtils.deleteObject(pendingKey(commandId)); + pendingIds().remove(commandId); + } + private String pendingKey(String commandId) { return mqttProperties.getCommandAck().getPendingKeyPrefix() + commandId; } diff --git a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandRetryTask.java b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandRetryTask.java index 05dea8a..e2a26ac 100644 --- a/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandRetryTask.java +++ b/water-common/water-common-mqtt/src/main/java/org/dromara/mqtt/MqttCommandRetryTask.java @@ -1,10 +1,12 @@ package org.dromara.mqtt; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.mqtt.config.properties.MqttProperties; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +@Slf4j @Component @RequiredArgsConstructor public class MqttCommandRetryTask { @@ -15,6 +17,7 @@ public class MqttCommandRetryTask { @Scheduled(fixedDelayString = "${mqtt.command-ack.scan-interval-ms:5000}") public void retryExpiredCommands() { if (mqttProperties.getCommandAck().isEnabled()) { + // log.info("[设备命令重新下发] 定时器调用成功 "); ackService.retryExpiredCommands(); } } diff --git a/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java b/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java index 1fe2b3e..135b1ab 100644 --- a/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java +++ b/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java @@ -5,6 +5,7 @@ import cn.hutool.http.HttpStatus; import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.common.core.utils.MessageUtils; import java.io.Serial; import java.io.Serializable; @@ -52,7 +53,7 @@ public class TableDataInfo implements Serializable { this.rows = list; this.total = total; this.code = HttpStatus.HTTP_OK; - this.msg = "查询成功"; + this.msg = message("query.success", "查询成功"); } /** @@ -61,7 +62,7 @@ public class TableDataInfo implements Serializable { public static TableDataInfo build(IPage page) { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); - rspData.setMsg("查询成功"); + rspData.setMsg(message("query.success", "查询成功")); rspData.setRows(page.getRecords()); rspData.setTotal(page.getTotal()); return rspData; @@ -73,7 +74,7 @@ public class TableDataInfo implements Serializable { public static TableDataInfo build(List list) { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); - rspData.setMsg("查询成功"); + rspData.setMsg(message("query.success", "查询成功")); rspData.setRows(list); rspData.setTotal(list.size()); return rspData; @@ -85,7 +86,7 @@ public class TableDataInfo implements Serializable { public static TableDataInfo build() { TableDataInfo rspData = new TableDataInfo<>(); rspData.setCode(HttpStatus.HTTP_OK); - rspData.setMsg("查询成功"); + rspData.setMsg(message("query.success", "查询成功")); return rspData; } @@ -104,4 +105,13 @@ public class TableDataInfo implements Serializable { return new TableDataInfo<>(pageList, list.size()); } + private static String message(String code, String defaultMessage) { + try { + String message = MessageUtils.message(code); + return code.equals(message) ? defaultMessage : message; + } catch (Exception e) { + return defaultMessage; + } + } + } diff --git a/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java b/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java index 094785b..bc3f138 100644 --- a/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java +++ b/water-common/water-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java @@ -45,7 +45,7 @@ public class MybatisExceptionHandler { log.error("请求地址'{}', 未找到数据源", requestURI); return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "未找到数据源,请联系管理员确认"); } - log.error("请求地址'{}', Mybatis系统异常", requestURI, e); + log.error("请求地址'{}', MyBatis系统异常", requestURI, e); return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, e.getMessage()); } diff --git a/water-common/water-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java b/water-common/water-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java index 3da1ba5..798e315 100644 --- a/water-common/water-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java +++ b/water-common/water-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java @@ -60,7 +60,7 @@ public class OssFactory { client = CLIENT_CACHE.get(key); if (client == null || !client.checkPropertiesSame(properties)) { CLIENT_CACHE.put(key, new OssClient(configKey, properties)); - log.info("创建OSS实例 key => {}", configKey); + log.info("创建OSS实例 配置键 => {}", configKey); return CLIENT_CACHE.get(key); } } finally { diff --git a/water-common/water-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java b/water-common/water-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java index 2d6d82e..839dd29 100644 --- a/water-common/water-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java +++ b/water-common/water-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java @@ -69,7 +69,7 @@ public class RateLimiterAspect { } throw new ServiceException(message); } - log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存key => '{}'", count, number, combineKey); + log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存键 => '{}'", count, number, combineKey); } catch (Exception e) { if (e instanceof ServiceException) { throw e; diff --git a/water-common/water-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java b/water-common/water-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java index 7a0f1db..172b7e4 100644 --- a/water-common/water-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java +++ b/water-common/water-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java @@ -98,7 +98,7 @@ public class RedisConfig { .setReadMode(clusterServersConfig.getReadMode()) .setSubscriptionMode(clusterServersConfig.getSubscriptionMode()); } - log.info("初始化 redis 配置"); + log.info("初始化 Redis 配置"); }; } diff --git a/water-common/water-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java b/water-common/water-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java index 2c619a3..d2d556e 100644 --- a/water-common/water-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java +++ b/water-common/water-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java @@ -23,7 +23,7 @@ public class SmsExceptionHandler { @ExceptionHandler(SmsBlendException.class) public R handleSmsBlendException(SmsBlendException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); - log.error("请求地址'{}',发生sms短信异常.", requestURI, e); + log.error("请求地址'{}',发生短信异常.", requestURI, e); return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "短信发送失败,请稍后再试..."); } diff --git a/water-common/water-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/water-common/water-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index b80e561..654f069 100644 --- a/water-common/water-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/water-common/water-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -10,7 +10,6 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -210,7 +209,7 @@ public class SseEmitterManager { broadcastMessage.setMessage(sseMessageDto.getMessage()); broadcastMessage.setUserIds(sseMessageDto.getUserIds()); RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { - log.info("SSE发送主题订阅消息topic:{} session keys:{} message:{}", + log.info("SSE发送主题订阅消息 主题={} 用户ID={} 消息={}", SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage()); }); } @@ -224,7 +223,7 @@ public class SseEmitterManager { SseMessageDto broadcastMessage = new SseMessageDto(); broadcastMessage.setMessage(message); RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { - log.info("SSE发送主题订阅消息topic:{} message:{}", SSE_TOPIC, message); + log.info("SSE发送主题订阅消息 主题={} 消息={}", SSE_TOPIC, message); }); } } diff --git a/water-common/water-common-sse/src/main/java/org/dromara/common/sse/listener/SseTopicListener.java b/water-common/water-common-sse/src/main/java/org/dromara/common/sse/listener/SseTopicListener.java index 7a4dff1..d838ed1 100644 --- a/water-common/water-common-sse/src/main/java/org/dromara/common/sse/listener/SseTopicListener.java +++ b/water-common/water-common-sse/src/main/java/org/dromara/common/sse/listener/SseTopicListener.java @@ -28,7 +28,7 @@ public class SseTopicListener implements ApplicationRunner, Ordered { @Override public void run(ApplicationArguments args) throws Exception { sseEmitterManager.subscribeMessage((message) -> { - log.info("SSE主题订阅收到消息session keys={} message={}", message.getUserIds(), message.getMessage()); + log.info("SSE主题订阅收到消息 用户ID={} 消息={}", message.getUserIds(), message.getMessage()); // 如果key不为空就按照key发消息 如果为空就群发 if (CollUtil.isNotEmpty(message.getUserIds())) { message.getUserIds().forEach(key -> { diff --git a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java index f6d224b..cda55b2 100644 --- a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java +++ b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java @@ -28,7 +28,7 @@ public class PlusTenantLineHandler implements TenantLineHandler { public Expression getTenantId() { String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { - log.error("无法获取有效的租户id -> Null"); + log.error("无法获取有效的租户ID -> 空"); return new NullValue(); } // 返回固定租户 diff --git a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java index dcdef6e..5164446 100644 --- a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java @@ -39,10 +39,10 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { } String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { - log.debug("无法获取有效的租户id -> Null"); + log.debug("无法获取有效的租户ID -> 空"); return super.map(name); } - if (StringUtils.startsWith(name, tenantId + "")) { + if (StringUtils.startsWith(name, tenantId)) { // 如果存在则直接返回 return super.map(name); } @@ -70,10 +70,10 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { } String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { - log.debug("无法获取有效的租户id -> Null"); + log.debug("无法获取有效的租户ID -> 空"); return unmap; } - if (StringUtils.startsWith(unmap, tenantId + "")) { + if (StringUtils.startsWith(unmap, tenantId)) { // 如果存在则删除 return unmap.substring((tenantId + ":").length()); } diff --git a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/manager/TenantSpringCacheManager.java b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/manager/TenantSpringCacheManager.java index 346e36f..8dfe780 100644 --- a/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/manager/TenantSpringCacheManager.java +++ b/water-common/water-common-tenant/src/main/java/org/dromara/common/tenant/manager/TenantSpringCacheManager.java @@ -29,7 +29,7 @@ public class TenantSpringCacheManager extends PlusSpringCacheManager { } String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { - log.error("无法获取有效的租户id -> Null"); + log.error("无法获取有效的租户ID -> 空"); } if (StringUtils.startsWith(name, tenantId)) { // 如果存在则直接返回 diff --git a/water-common/water-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java b/water-common/water-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java index 2322cdf..c413e6a 100644 --- a/water-common/water-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java +++ b/water-common/water-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java @@ -7,11 +7,11 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.core.TranslationInterface; -import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.Map; @@ -61,7 +61,7 @@ public class TranslationHandler extends JsonSerializer implements Contex Object result = trans.translation(value, translation.other()); gen.writeObject(result); } catch (Exception e) { - log.error("翻译处理异常,type: {}, value: {}", translation.type(), value, e); + log.error("翻译处理异常,类型:{},值:{}", translation.type(), value, e); // 出现异常时输出原始值而不是中断序列化 gen.writeObject(value); } diff --git a/water-common/water-common-web/src/main/java/org/dromara/common/web/core/I18nLocaleResolver.java b/water-common/water-common-web/src/main/java/org/dromara/common/web/core/I18nLocaleResolver.java index 98ddd06..88c3a41 100644 --- a/water-common/water-common-web/src/main/java/org/dromara/common/web/core/I18nLocaleResolver.java +++ b/water-common/water-common-web/src/main/java/org/dromara/common/web/core/I18nLocaleResolver.java @@ -1,9 +1,10 @@ package org.dromara.common.web.core; -import org.springframework.web.servlet.LocaleResolver; - import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.core.utils.StringUtils; +import org.springframework.web.servlet.LocaleResolver; + import java.util.Locale; /** @@ -16,12 +17,24 @@ public class I18nLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String language = httpServletRequest.getHeader("content-language"); - Locale locale = Locale.getDefault(); - if (language != null && language.length() > 0) { - String[] split = language.split("_"); - locale = new Locale(split[0], split[1]); + if (StringUtils.isBlank(language)) { + language = httpServletRequest.getParameter("lang"); } - return locale; + if (StringUtils.isBlank(language)) { + language = httpServletRequest.getHeader("Accept-Language"); + } + if (StringUtils.isBlank(language)) { + return Locale.SIMPLIFIED_CHINESE; + } + String languageTag = language.split(",")[0].trim().replace('_', '-'); + if ("zh".equalsIgnoreCase(languageTag)) { + return Locale.SIMPLIFIED_CHINESE; + } + if ("en".equalsIgnoreCase(languageTag)) { + return Locale.US; + } + Locale locale = Locale.forLanguageTag(languageTag); + return StringUtils.isBlank(locale.getLanguage()) ? Locale.SIMPLIFIED_CHINESE : locale; } @Override diff --git a/water-common/water-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java b/water-common/water-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java index b56cec1..08bb532 100644 --- a/water-common/water-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java +++ b/water-common/water-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java @@ -51,16 +51,16 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { jsonParam = rootNode.toString(); } } - log.info("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam); + log.info("[请求]开始请求 => URL[{}],参数类型[JSON],参数:[{}]", url, jsonParam); } else { Map parameterMap = request.getParameterMap(); if (MapUtil.isNotEmpty(parameterMap)) { Map map = new LinkedHashMap<>(parameterMap); MapUtil.removeAny(map, SystemConstants.EXCLUDE_PROPERTIES); String parameters = JsonUtils.toJsonString(map); - log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters); + log.info("[请求]开始请求 => URL[{}],参数类型[表单参数],参数:[{}]", url, parameters); } else { - log.info("[PLUS]开始请求 => URL[{}],无参数", url); + log.info("[请求]开始请求 => URL[{}],无参数", url); } } @@ -105,7 +105,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { StopWatch stopWatch = KEY_CACHE.get(); if (ObjectUtil.isNotNull(stopWatch)) { stopWatch.stop(); - log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getDuration().toMillis()); + log.info("[请求]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getDuration().toMillis()); KEY_CACHE.remove(); } } diff --git a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java index 3b6e076..8ad83ea 100644 --- a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java +++ b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java @@ -31,11 +31,11 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); if (ObjectUtil.isNull(loginUser)) { session.close(CloseStatus.BAD_DATA); - log.info("[connect] invalid token received. sessionId: {}", session.getId()); + log.info("[连接] 收到无效令牌,会话ID={}", session.getId()); return; } WebSocketSessionHolder.addSession(loginUser.getUserId(), new ConcurrentWebSocketSessionDecorator(session, 10 * 1000, 64000)); - log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); + log.info("[连接] 会话ID={},用户ID={},用户类型={}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } /** @@ -90,7 +90,7 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { - log.error("[transport error] sessionId: {} , exception:{}", session.getId(), exception.getMessage()); + log.error("[传输错误] 会话ID={},异常={}", session.getId(), exception.getMessage()); } /** @@ -103,11 +103,11 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); if (ObjectUtil.isNull(loginUser)) { - log.info("[disconnect] invalid token received. sessionId: {}", session.getId()); + log.info("[断开连接] 收到无效令牌,会话ID={}", session.getId()); return; } WebSocketSessionHolder.removeSession(loginUser.getUserId()); - log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); + log.info("[断开连接] 会话ID={},用户ID={},用户类型={}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } /** diff --git a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java index c70e377..6ea0a83 100644 --- a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java +++ b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java @@ -54,7 +54,7 @@ public class PlusWebSocketInterceptor implements HandshakeInterceptor { attributes.put(LOGIN_USER_KEY, loginUser); return true; } catch (NotLoginException e) { - log.error("WebSocket 认证失败'{}',无法访问系统资源", e.getMessage()); + log.error("网络套接字认证失败'{}',无法访问系统资源", e.getMessage()); return false; } } diff --git a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java index 0ad39af..6ffa5bc 100644 --- a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java +++ b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java @@ -26,7 +26,7 @@ public class WebSocketTopicListener implements ApplicationRunner, Ordered { public void run(ApplicationArguments args) throws Exception { // 订阅WebSocket消息 WebSocketUtils.subscribeMessage((message) -> { - log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage()); + log.info("网络套接字主题订阅收到消息 会话标识={} 消息={}", message.getSessionKeys(), message.getMessage()); // 如果key不为空就按照key发消息 如果为空就群发 if (CollUtil.isNotEmpty(message.getSessionKeys())) { message.getSessionKeys().forEach(key -> { @@ -40,7 +40,7 @@ public class WebSocketTopicListener implements ApplicationRunner, Ordered { }); } }); - log.info("初始化WebSocket主题订阅监听器成功"); + log.info("初始化网络套接字主题订阅监听器成功"); } @Override diff --git a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java index afe76e0..547a1e8 100644 --- a/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java +++ b/water-common/water-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java @@ -69,7 +69,7 @@ public class WebSocketUtils { broadcastMessage.setMessage(webSocketMessage.getMessage()); broadcastMessage.setSessionKeys(unsentSessionKeys); RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { - log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}", + log.info("网络套接字发送主题订阅消息 主题={} 会话标识={} 消息={}", WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage()); }); } @@ -84,7 +84,7 @@ public class WebSocketUtils { WebSocketMessageDto broadcastMessage = new WebSocketMessageDto(); broadcastMessage.setMessage(message); RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { - log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message); + log.info("网络套接字发送主题订阅消息 主题={} 消息={}", WEB_SOCKET_TOPIC, message); }); } @@ -115,12 +115,12 @@ public class WebSocketUtils { */ private static void sendMessage(WebSocketSession session, WebSocketMessage message) { if (session == null || !session.isOpen()) { - log.warn("[send] session会话已经关闭"); + log.warn("[发送] 会话已经关闭"); } else { try { session.sendMessage(message); } catch (IOException e) { - log.error("[send] session({}) 发送消息({}) 异常", session, message, e); + log.error("[发送] 会话({}) 发送消息({}) 异常", session, message, e); } } } diff --git a/water-extend/water-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java b/water-extend/water-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java index 838eefc..427136c 100644 --- a/water-extend/water-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java +++ b/water-extend/water-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java @@ -47,7 +47,7 @@ public class CustomNotifier extends AbstractEventNotifier { case STATUS_UNKNOWN -> "服务未知异常"; //监控系统无法确定实例的当前状态 default -> "未知状态"; //没有匹配的状态 }; - log.info("Instance Status Change: 状态名称【{}】, 注册名称【{}】, 实例ID【{}】, 状态【{}】, 服务URL【{}】", + log.info("实例状态变更:状态名称【{}】, 注册名称【{}】, 实例ID【{}】, 状态【{}】, 服务URL【{}】", statusName, registName, instanceId, status, serviceUrl); } }); diff --git a/water-modules/water-app/src/main/java/org/dromara/app/controller/AppController.java b/water-modules/water-app/src/main/java/org/dromara/app/controller/AppController.java index 56d8310..546bdb2 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/controller/AppController.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/controller/AppController.java @@ -10,15 +10,19 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dromara.app.domain.bo.*; +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.common.core.exception.ServiceException; import org.dromara.app.service.impl.AppScheduleServiceImpl; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; +import org.dromara.common.core.utils.MessageUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; @@ -77,16 +81,15 @@ public class AppController extends BaseController { * */ @ApiEncrypt - @PostMapping("/addDevice") - public R addDevice(@RequestBody String body) { - AppDeviceBo appDevic = JsonUtils.parseObject(body, AppDeviceBo.class); - appDevic.setUserId(LoginHelper.getUserId()); - Boolean b = appDeviceService.insertByBo(appDevic); - if (b){ - return R.ok(); - }else { - - return R.fail(); + @PostMapping("/bindDeviceStatus") + public R bindDeviceStatus(@RequestBody String body) { + try { + AppDeviceBo appDevice = JsonUtils.parseObject(body, AppDeviceBo.class); + appDevice.setUserId(LoginHelper.getUserId()); + Map map = appDeviceService.bindDeviceStatus(appDevice); + return R.ok(map); + } catch (Exception e) { + return fail(e); } } @@ -94,11 +97,15 @@ public class AppController extends BaseController { * 绑定已通过MQTT注册上线的设备 */ @ApiEncrypt - @PostMapping("/bindDevice") + @PostMapping("/addDevice") public R bindDevice(@RequestBody String body) { - AppDeviceBo appDevice = JsonUtils.parseObject(body, AppDeviceBo.class); - appDevice.setUserId(LoginHelper.getUserId()); - return R.ok(appDeviceService.bindRegisteredDevice(appDevice)); + try { + AppDeviceBo appDevice = JsonUtils.parseObject(body, AppDeviceBo.class); + appDevice.setUserId(LoginHelper.getUserId()); + return R.ok(appDeviceService.bindRegisteredDevice(appDevice)); + } catch (Exception e) { + return fail(e); + } } /** @@ -110,7 +117,11 @@ public class AppController extends BaseController { @GetMapping("/device/{deviceNo}") public R getDeviceInfo(@NotNull(message = "主键不能为空") @PathVariable String deviceNo) { - return R.ok(appDeviceService.queryById(deviceNo)); + try { + return R.ok(getOwnedDevice(deviceNo)); + } catch (Exception e) { + return fail(e); + } } @@ -123,9 +134,11 @@ public class AppController extends BaseController { @PutMapping("/updateDeviceInfo") public R updateDeviceInfo(@Validated @RequestBody AppDeviceBo bo) { try { + assertDeviceOwned(bo.getDeviceNo()); + bo.setUserId(LoginHelper.getUserId()); return toAjax(appDeviceService.updateByBo(bo)); } catch (Exception e) { - throw new RuntimeException(e); + return fail(e); } } @@ -137,7 +150,14 @@ public class AppController extends BaseController { @DeleteMapping("/deleteDevice/{deviceNos}") public R removeDevice(@NotEmpty(message = "主键不能为空") @PathVariable String[] deviceNos) { - return toAjax(appDeviceService.deleteWithValidByIds(List.of(deviceNos), true)); + try { + for (String deviceNo : deviceNos) { + assertDeviceOwned(deviceNo); + } + return toAjax(appDeviceService.deleteWithValidByIds(List.of(deviceNos), true)); + } catch (Exception e) { + return fail(e); + } } @@ -149,11 +169,11 @@ public class AppController extends BaseController { @RepeatSubmit() @PutMapping("/switchDevice") public R switchDevice(@RequestBody String body) { - Map map = JsonUtils.parseObject(body, Map.class); try { + Map map = JsonUtils.parseObject(body, Map.class); String deviceNo = map.get("deviceNo"); String status = map.get("workStatus"); - Date date = new Date(); + String startTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); String durationMinValue = map.get("durationMin"); Integer durationMin = StringUtils.isBlank(durationMinValue) ? null : Integer.valueOf(durationMinValue); //更新设备工作状态 @@ -161,7 +181,7 @@ public class AppController extends BaseController { // 记录信息到历史表 return toAjax(flag); } catch (Exception e) { - return R.fail(e.getMessage()); + return fail(e); } } @@ -173,28 +193,32 @@ public class AppController extends BaseController { */ @GetMapping("/scheduleDeviceList/{scheduleId}") public R> scheduleDeviceList( @PathVariable Long scheduleId) { + try { - Map retMap = new HashMap(); - //所有设备列表 - AppDeviceBo appDeviceBo = new AppDeviceBo(); - appDeviceBo.setUserId(LoginHelper.getUserId()); - List appDeviceVos = appDeviceService.queryList(appDeviceBo); + Map retMap = new HashMap(); + //所有设备列表 + AppDeviceBo appDeviceBo = new AppDeviceBo(); + appDeviceBo.setUserId(LoginHelper.getUserId()); + List appDeviceVos = appDeviceService.queryList(appDeviceBo); - List appDeviceVoList = new ArrayList(); - AppSchedulingDeviceBo schedulingDeviceBo = new AppSchedulingDeviceBo(); - schedulingDeviceBo.setScheduleId(scheduleId); + List appDeviceVoList = new ArrayList(); + AppSchedulingDeviceBo schedulingDeviceBo = new AppSchedulingDeviceBo(); + schedulingDeviceBo.setScheduleId(scheduleId); - for (AppDeviceVo appDeviceVo:appDeviceVos){ - List appSchedulingDeviceVos = appSchedulingDeviceService.findByDeviceNo(appDeviceVo.getDeviceNo()); - if(appSchedulingDeviceVos.size() == 0){ - appDeviceVoList.add(appDeviceVo); + for (AppDeviceVo appDeviceVo:appDeviceVos){ + List appSchedulingDeviceVos = appSchedulingDeviceService.findByDeviceNo(appDeviceVo.getDeviceNo()); + if(appSchedulingDeviceVos.size() == 0){ + appDeviceVoList.add(appDeviceVo); + } } + retMap.put("deviceList", appDeviceVoList); + + + return R.ok(retMap); + } catch (Exception e) { + return fail(e); } - retMap.put("deviceList", appDeviceVoList); - - - return R.ok(retMap); } /** *绑定排程跟设备 @@ -202,26 +226,32 @@ public class AppController extends BaseController { @RepeatSubmit() @PostMapping("/addScheduleDevice") public R addScheduleDevice( @RequestBody String body) { - Map map = JsonUtils.parseObject(body, Map.class); - if (map == null || map.get("scheduleId") == null) { - throw new ServiceException("scheduleId不能为空"); - } - Long scheduleId = Long.valueOf(map.get("scheduleId").toString()); - List deviceNos = parseDeviceNos(map); - if (deviceNos.isEmpty()) { - throw new ServiceException("deviceNos不能为空"); - } - - for (String deviceNo:deviceNos){ - if (StringUtils.isBlank(deviceNo)) { - continue; + try { + Map map = JsonUtils.parseObject(body, Map.class); + if (map == null || map.get("scheduleId") == null) { + throw new ServiceException("app.schedule.id.not.blank.request"); } - AppSchedulingDeviceBo schedulingDeviceBo = new AppSchedulingDeviceBo(); - schedulingDeviceBo.setDeviceNo(deviceNo); - schedulingDeviceBo.setScheduleId(scheduleId); - appSchedulingDeviceService.insertByBo(schedulingDeviceBo); + Long scheduleId = Long.valueOf(map.get("scheduleId").toString()); + assertScheduleOwned(scheduleId); + List deviceNos = parseDeviceNos(map); + if (deviceNos.isEmpty()) { + throw new ServiceException("app.schedule.devices.not.blank"); + } + + for (String deviceNo:deviceNos){ + if (StringUtils.isBlank(deviceNo)) { + continue; + } + assertDeviceOwned(deviceNo); + AppSchedulingDeviceBo schedulingDeviceBo = new AppSchedulingDeviceBo(); + schedulingDeviceBo.setDeviceNo(deviceNo); + schedulingDeviceBo.setScheduleId(scheduleId); + appSchedulingDeviceService.insertByBo(schedulingDeviceBo); + } + return R.ok(); + } catch (Exception e) { + return fail(e); } - return R.ok(); } private List parseDeviceNos(Map map) { @@ -255,9 +285,22 @@ public class AppController extends BaseController { @Log(title = "排程与设备关联", businessType = BusinessType.DELETE) @DeleteMapping("/deleteScheduleDevice") - public R deleteScheduleDevice(@NotEmpty(message = "主键不能为空") - @RequestParam String scheduleId, @RequestParam String deviceNo) { - return toAjax(appSchedulingDeviceService.deleteWithValidByScheduleIdAndDeviceNo(Long.valueOf(scheduleId), deviceNo)); + public R deleteScheduleDevice(@RequestParam(required = false) String scheduleId, + @RequestParam(required = false) String deviceNo) { + try { + if (StringUtils.isBlank(scheduleId)) { + throw new ServiceException("app.schedule.id.not.blank.request"); + } + if (StringUtils.isBlank(deviceNo)) { + throw new ServiceException("app.device.no.not.blank"); + } + Long scheduleIdValue = Long.valueOf(scheduleId); + assertScheduleOwned(scheduleIdValue); + assertDeviceOwned(deviceNo); + return toAjax(appSchedulingDeviceService.deleteWithValidByScheduleIdAndDeviceNo(scheduleIdValue, deviceNo)); + } catch (Exception e) { + return fail(e); + } } @@ -289,8 +332,8 @@ public class AppController extends BaseController { } return R.fail(); // return toAjax(appScheduleService.insertByBo(bo)); - } catch (RuntimeException e) { - throw new RuntimeException(e); + } catch (Exception e) { + return fail(e); } } @@ -303,48 +346,52 @@ public class AppController extends BaseController { @GetMapping("/schedule/{id}") public R getScheduleInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { - AppScheduleVo appScheduleVo = appScheduleService.queryById(id); - if (ObjectUtil.isNotNull(appScheduleVo)){ - List list = appScheduleDetailService.queryByScheduleIdByStatus(appScheduleVo.getId()); + try { + AppScheduleVo appScheduleVo = getOwnedSchedule(id); + if (ObjectUtil.isNotNull(appScheduleVo)){ + List list = appScheduleDetailService.queryByScheduleIdByStatus(appScheduleVo.getId()); - AppSchedulingDeviceBo appSchedulingDeviceBo = new AppSchedulingDeviceBo(); - appSchedulingDeviceBo.setScheduleId(appScheduleVo.getId()); - List appSchedulingDeviceVos = appSchedulingDeviceService.queryList(appSchedulingDeviceBo); - List deviceList = new ArrayList(); - for (AppSchedulingDeviceVo appSchedulingDeviceVo:appSchedulingDeviceVos){ - AppDeviceVo appDeviceVo = appDeviceService.queryById(appSchedulingDeviceVo.getDeviceNo()); - if (ObjectUtil.isNotNull(appDeviceVo)){ - deviceList.add(appDeviceVo); + AppSchedulingDeviceBo appSchedulingDeviceBo = new AppSchedulingDeviceBo(); + appSchedulingDeviceBo.setScheduleId(appScheduleVo.getId()); + List appSchedulingDeviceVos = appSchedulingDeviceService.queryList(appSchedulingDeviceBo); + List deviceList = new ArrayList(); + for (AppSchedulingDeviceVo appSchedulingDeviceVo:appSchedulingDeviceVos){ + AppDeviceVo appDeviceVo = appDeviceService.queryById(appSchedulingDeviceVo.getDeviceNo()); + if (ObjectUtil.isNotNull(appDeviceVo)){ + deviceList.add(appDeviceVo); + } + + } + List detailList = new ArrayList(); + + for (AppScheduleDetailVo detail:list){ + List timeSlots = new ArrayList(); + JSONArray mapArray = JSONUtil.parseArray(detail.getTimeData()); + for (Object timeSlot:mapArray){ + timeSlots.add(timeSlot); + } + + Map map = new HashMap(); + map.put("id",detail.getId() ); + map.put("weekday",detail.getWeekday() ); + map.put("timeData",timeSlots ); + map.put("triggerType",detail.getTriggerType() ); + map.put("status",detail.getStatus() ); + detailList.add(map); } - } - List detailList = new ArrayList(); - for (AppScheduleDetailVo detail:list){ - List timeSlots = new ArrayList(); - JSONArray mapArray = JSONUtil.parseArray(detail.getTimeData()); - for (Object timeSlot:mapArray){ - timeSlots.add(timeSlot); - } - Map map = new HashMap(); - map.put("id",detail.getId() ); - map.put("weekday",detail.getWeekday() ); - map.put("timeData",timeSlots ); - map.put("triggerType",detail.getTriggerType() ); - map.put("status",detail.getStatus() ); - detailList.add(map); + appScheduleVo.setDetails(detailList); + appScheduleVo.setDeviceNos(deviceList); + return R.ok(appScheduleVo); } - - appScheduleVo.setDetails(detailList); - appScheduleVo.setDeviceNos(deviceList); - return R.ok(appScheduleVo); + return R.fail(appScheduleVo); + } catch (Exception e) { + return fail(e); } - - - return R.fail(appScheduleVo); } @@ -356,8 +403,13 @@ public class AppController extends BaseController { @PutMapping("/editScheduleStatus") public R editScheduleStatus(@NotNull(message = "主键不能为空") @RequestBody AppScheduleBo bo) { - - return toAjax(appScheduleService.updateStatusByBo(bo)); + try { + assertScheduleOwned(bo.getId()); + bo.setUserId(LoginHelper.getUserId()); + return toAjax(appScheduleService.updateStatusByBo(bo)); + } catch (Exception e) { + return fail(e); + } } /** @@ -367,11 +419,17 @@ public class AppController extends BaseController { @RepeatSubmit() @PutMapping("/updataschedule") public R editSchedule(@Validated(EditGroup.class) @RequestBody AppScheduleBo bo) { - Map map = appScheduleService.updateByBo(bo); - if (Boolean.valueOf(map.get("flag").toString())){ - return R.ok(map.get("appSchedule")); - }else { - return R.fail(); + try { + assertScheduleOwned(bo.getId()); + bo.setUserId(LoginHelper.getUserId()); + Map map = appScheduleService.updateByBo(bo); + if (Boolean.valueOf(map.get("flag").toString())){ + return R.ok(map.get("appSchedule")); + }else { + return R.fail(); + } + } catch (Exception e) { + return fail(e); } } @@ -386,7 +444,14 @@ public class AppController extends BaseController { @DeleteMapping("/deleteschedule/{ids}") public R removeSchedule(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { - return toAjax(appScheduleService.deleteWithValidByIds(List.of(ids), true)); + try { + for (Long id : ids) { + assertScheduleOwned(id); + } + return toAjax(appScheduleService.deleteWithValidByIds(List.of(ids), true)); + } catch (Exception e) { + return fail(e); + } } /** @@ -427,7 +492,14 @@ public class AppController extends BaseController { @DeleteMapping("/waterLog/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { - return toAjax(appWateringLogService.deleteWithValidByIds(List.of(ids), true)); + try { + for (Long id : ids) { + assertWateringLogOwned(id); + } + return toAjax(appWateringLogService.deleteWithValidByIds(List.of(ids), true)); + } catch (Exception e) { + return fail(e); + } } @@ -463,7 +535,7 @@ public class AppController extends BaseController { map.put("averageTime",averageTime); return R.ok(map); } catch (Exception e) { - throw new RuntimeException(e); + return fail(e); } } @@ -475,16 +547,20 @@ public class AppController extends BaseController { */ @GetMapping("/getUserInfo") public R getUserInfo() { - UserInfoVo userInfoVo = new UserInfoVo(); - LoginUser loginUser = LoginHelper.getLoginUser(); - SysUserVo user = DataPermissionHelper.ignore(() -> userService.selectUserById(loginUser.getUserId())); - if (ObjectUtil.isNull(user)) { - return R.fail("没有权限访问用户数据!"); + try { + UserInfoVo userInfoVo = new UserInfoVo(); + LoginUser loginUser = LoginHelper.getLoginUser(); + SysUserVo user = DataPermissionHelper.ignore(() -> userService.selectUserById(loginUser.getUserId())); + if (ObjectUtil.isNull(user)) { + return R.fail(MessageUtils.message("app.user.data.denied")); + } + userInfoVo.setUser(user); + userInfoVo.setPermissions(loginUser.getMenuPermission()); + userInfoVo.setRoles(loginUser.getRolePermission()); + return R.ok(userInfoVo); + } catch (Exception e) { + return fail(e); } - userInfoVo.setUser(user); - userInfoVo.setPermissions(loginUser.getMenuPermission()); - userInfoVo.setRoles(loginUser.getRolePermission()); - return R.ok(userInfoVo); } /** @@ -495,13 +571,17 @@ public class AppController extends BaseController { @RepeatSubmit() @PutMapping("/updataUser") public R editUser( @RequestBody SysUserBo user) { - userService.checkUserAllowed(user.getUserId()); - userService.checkUserDataScope(user.getUserId()); - if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { - return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } + try { + userService.checkUserAllowed(user.getUserId()); + userService.checkUserDataScope(user.getUserId()); + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { + return R.fail(MessageUtils.message("app.user.phone.exists", user.getUserName())); + } - return toAjax(userService.updateAppUser(user)); + return toAjax(userService.updateAppUser(user)); + } catch (Exception e) { + return fail(e); + } } /** @@ -510,15 +590,19 @@ public class AppController extends BaseController { @RepeatSubmit() @PutMapping("/updataPassword") public R updataPassword(@RequestBody SysUserVo vo) { - Long userId = LoginHelper.getUserId(); - SysUserVo sysUserVo = userService.selectUserById(userId); - if (!BCrypt.checkpw(vo.getOldPassword(), sysUserVo.getPassword())){ - throw new UserException("user.password.not.match"); + try { + Long userId = LoginHelper.getUserId(); + SysUserVo sysUserVo = userService.selectUserById(userId); + if (!BCrypt.checkpw(vo.getOldPassword(), sysUserVo.getPassword())){ + throw new UserException("user.password.not.match"); + } + SysUserBo userBo = new SysUserBo(); + userBo.setUserId(userId); + userBo.setPassword(vo.getPassword()); + return toAjax(userService.updateUserPas(userBo)); + } catch (Exception e) { + return fail(e); } - SysUserBo userBo = new SysUserBo(); - userBo.setUserId(userId); - userBo.setPassword(vo.getPassword()); - return toAjax(userService.updateUserPas(userBo)); } /** @@ -527,35 +611,99 @@ public class AppController extends BaseController { @ApiEncrypt @PostMapping("/retrievePassword") public R forgot(@RequestBody String body) { - SysUserBo bo = JsonUtils.parseObject(body, SysUserBo.class); - bo.setUserId(LoginHelper.getUserId()); + try { + SysUserBo bo = JsonUtils.parseObject(body, SysUserBo.class); + bo.setUserId(LoginHelper.getUserId()); - if(Validator.isEmail(bo.getUserName())){ - boolean checkPhoneFlag = userService.checkEmailUnique(bo); - if (!checkPhoneFlag){ - throw new UserException("user.email.not.username"); - } - }else if (Validator.isMobile(bo.getUserName())){ - boolean checkPhoneFlag = userService.checkPhoneUnique(bo); - if (!checkPhoneFlag){ - throw new UserException("user.mobile.phone.number.not.username"); + if(Validator.isEmail(bo.getUserName())){ + boolean checkPhoneFlag = userService.checkEmailUnique(bo); + if (!checkPhoneFlag){ + throw new UserException("user.email.not.username"); + } + }else if (Validator.isMobile(bo.getUserName())){ + boolean checkPhoneFlag = userService.checkPhoneUnique(bo); + if (!checkPhoneFlag){ + throw new UserException("user.mobile.phone.number.not.username"); + } } + + return toAjax(userService.updateUserPas(bo)); + } catch (Exception e) { + return fail(e); } - - return toAjax(userService.updateUserPas(bo)); } @GetMapping("/test") public R test (){ + try { - DeviceCommand deviceCommand = new DeviceCommand(); + DeviceCommand deviceCommand = new DeviceCommand(); - String bindDevice = deviceCommandService.sendBindDeviceCommand("01"); + String bindDevice = deviceCommandService.sendBindDeviceCommand("01"); - // String s = deviceCommandService.sendSwitchCommand("01", "1", "2026-06-10 14:35:31", 20); - return R.ok(bindDevice); + // String s = deviceCommandService.sendSwitchCommand("01", "1", "2026-06-10 14:35:31", 20); + return R.ok(bindDevice); + } catch (Exception e) { + return fail(e); + } + } + + private R fail(Exception e) { + return R.fail(toI18nErrorMessage(e)); + } + + private String toI18nErrorMessage(Exception e) { + String message = e.getMessage(); + if (StringUtils.isBlank(message)) { + return MessageUtils.message("operation.fail"); + } + String i18nMessage = MessageUtils.message(message); + return message.equals(i18nMessage) ? message : i18nMessage; + } + + private AppDeviceVo getOwnedDevice(String deviceNo) { + if (StringUtils.isBlank(deviceNo)) { + throw new ServiceException("app.device.no.not.blank"); + } + AppDeviceVo device = appDeviceService.queryById(deviceNo); + Long userId = LoginHelper.getUserId(); + if (device == null || !Objects.equals(device.getUserId(), userId)) { + throw new ServiceException("app.device.not.exists.or.denied"); + } + return device; + } + + private void assertDeviceOwned(String deviceNo) { + getOwnedDevice(deviceNo); + } + + private AppScheduleVo getOwnedSchedule(Long scheduleId) { + if (scheduleId == null) { + throw new ServiceException("app.schedule.id.not.blank"); + } + AppScheduleVo schedule = appScheduleService.queryById(scheduleId); + Long userId = LoginHelper.getUserId(); + if (schedule == null || !Objects.equals(schedule.getUserId(), userId)) { + throw new ServiceException("app.schedule.not.exists.or.denied"); + } + return schedule; + } + + private void assertScheduleOwned(Long scheduleId) { + getOwnedSchedule(scheduleId); + } + + private void assertWateringLogOwned(Long id) { + if (id == null) { + throw new ServiceException("app.watering.log.id.not.blank"); + } + AppWateringLogVo log = appWateringLogService.queryById(id); + Long userId = LoginHelper.getUserId(); + if (log == null || !Objects.equals(log.getUserId(), userId)) { + throw new ServiceException("app.watering.log.not.exists.or.denied"); + } } } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceDataHandler.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceDataHandler.java index d954d20..d81a24d 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceDataHandler.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceDataHandler.java @@ -1,14 +1,22 @@ package org.dromara.app.handler; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.app.domain.AppDevice; import org.dromara.app.domain.bo.AppDeviceBo; +import org.dromara.app.mapper.AppDeviceMapper; import org.dromara.app.mqtt.MqttTopicHandler; import org.dromara.app.service.IAppDeviceService; import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.redis.utils.RedisUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.time.Duration; +import java.time.Instant; import java.util.Date; +import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; @@ -22,6 +30,13 @@ public class DeviceDataHandler implements MqttTopicHandler { private static final Pattern PATTERN = Pattern.compile("^/([^/]+)/publish/power$"); private final IAppDeviceService appDeviceService; + private final AppDeviceMapper appDeviceMapper; + + @Value("${mqtt.command-ack.device-status-cache-prefix}") + private String deviceStatusCachePrefix; + + @Value("${mqtt.command-ack.device-status-cache-ttl-seconds}") + private int deviceStatusCacheTtlSeconds; @Override public Pattern topicPattern() { @@ -32,14 +47,44 @@ public class DeviceDataHandler implements MqttTopicHandler { public void handle(String deviceNo, String payload) { try { Map dto = JsonUtils.parseObject(payload, Map.class); + if (dto == null || dto.get("powerLevel") == null) { + log.warn("[MQTT] 设备电量上报缺少电量字段 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload); + refreshDeviceOnline(deviceNo); + return; + } + // 更新设备电量 + 同步在线状态到数据库 AppDeviceBo appDeviceBo = new AppDeviceBo(); appDeviceBo.setDeviceNo(deviceNo); appDeviceBo.setPowerLevel(dto.get("powerLevel").toString()); appDeviceBo.setPowerLevelUpdatatime(new Date()); + appDeviceBo.setStatus("1"); // 收到数据 = 在线 appDeviceService.updateByBo(appDeviceBo); - log.info("[MQTT] 设备电量更新 deviceNo={} payload={}", deviceNo, payload); + // 同步刷新 Redis 在线缓存(定时任务离线检测依赖此 Key) + refreshDeviceOnline(deviceNo); + log.info("[MQTT] 设备电量更新 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload); } catch (Exception e) { - log.error("[MQTT] 设备电量更新失败 deviceNo={} payload={}", deviceNo, payload, e); + log.error("[MQTT] 设备电量更新失败 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload, e); } } + + /** + * 刷新设备在线状态到 Redis(与 MqttCommandAckService 逻辑一致) + * 写入 Redis 后 TTL 到期自动过期 = 离线 + */ + private void refreshDeviceOnline(String deviceNo) { + Map statusCache = new HashMap<>(); + statusCache.put("deviceNo", deviceNo); + statusCache.put("status", "1"); + statusCache.put("lastReportTime", Instant.now().toString()); + RedisUtils.setCacheObject( + deviceStatusCachePrefix + deviceNo, + statusCache, + Duration.ofSeconds(deviceStatusCacheTtlSeconds) + ); + appDeviceMapper.update(null, + new LambdaUpdateWrapper() + .set(AppDevice::getStatus, "1") + .eq(AppDevice::getDeviceNo, deviceNo) + ); + } } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceRegisterHandler.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceRegisterHandler.java index d6a4e3f..1f8f012 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceRegisterHandler.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/DeviceRegisterHandler.java @@ -1,13 +1,21 @@ package org.dromara.app.handler; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.app.domain.AppDevice; import org.dromara.app.domain.bo.AppDeviceBo; +import org.dromara.app.mapper.AppDeviceMapper; import org.dromara.app.mqtt.MqttTopicHandler; import org.dromara.app.service.IAppDeviceService; import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.redis.utils.RedisUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.time.Duration; +import java.time.Instant; +import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; @@ -22,6 +30,13 @@ public class DeviceRegisterHandler implements MqttTopicHandler { private static final Pattern PATTERN = Pattern.compile("^/([^/]+)/publish/register$"); private final IAppDeviceService appDeviceService; + private final AppDeviceMapper appDeviceMapper; + + @Value("${mqtt.command-ack.device-status-cache-prefix}") + private String deviceStatusCachePrefix; + + @Value("${mqtt.command-ack.device-status-cache-ttl-seconds}") + private int deviceStatusCacheTtlSeconds; @Override public Pattern topicPattern() { @@ -34,15 +49,18 @@ public class DeviceRegisterHandler implements MqttTopicHandler { Map dto = JsonUtils.parseObject(payload, Map.class); AppDeviceBo device = buildRegisterDevice(deviceNo, dto); appDeviceService.registerByMqtt(device); - log.info("[MQTT] 设备注册 deviceNo={} payload={}", deviceNo, payload); + // 注册即在线 + refreshDeviceOnline(deviceNo); + log.info("[MQTT] 设备注册 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload); } catch (Exception e) { - log.error("[MQTT] 设备注册失败 deviceNo={} payload={}", deviceNo, payload, e); + log.error("[MQTT] 设备注册失败 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload, e); } } private AppDeviceBo buildRegisterDevice(String topicDeviceNo, Map dto) { AppDeviceBo device = new AppDeviceBo(); device.setDeviceNo(topicDeviceNo); + device.setStatus("1"); // 注册即在线 if (dto == null) { return device; } @@ -67,4 +85,24 @@ public class DeviceRegisterHandler implements MqttTopicHandler { private String valueAsString(Object value) { return value == null ? null : String.valueOf(value); } + + /** + * 刷新设备在线状态到 Redis + */ + private void refreshDeviceOnline(String deviceNo) { + Map statusCache = new HashMap<>(); + statusCache.put("deviceNo", deviceNo); + statusCache.put("status", "1"); + statusCache.put("lastReportTime", Instant.now().toString()); + RedisUtils.setCacheObject( + deviceStatusCachePrefix + deviceNo, + statusCache, + Duration.ofSeconds(deviceStatusCacheTtlSeconds) + ); + appDeviceMapper.update(null, + new LambdaUpdateWrapper() + .set(AppDevice::getStatus, "1") + .eq(AppDevice::getDeviceNo, deviceNo) + ); + } } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/ErromesHandler.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/ErromesHandler.java index b5b0ebb..2bc92c9 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/handler/ErromesHandler.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/ErromesHandler.java @@ -28,9 +28,9 @@ public class ErromesHandler implements MqttTopicHandler { public void handle(String deviceNo, String payload) { try { Map dto = JsonUtils.parseObject(payload, Map.class); - log.info("[MQTT] 设备异常告警 deviceNo={} payload={}", deviceNo, dto); + log.info("[MQTT] 设备异常告警 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, dto); } catch (Exception e) { - log.error("[MQTT] 设备异常处理失败 deviceNo={}", deviceNo, e); + log.error("[MQTT] 设备异常处理失败 时间={} 设备编号={}", HandlerLogTime.now(), deviceNo, e); } } } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/HandlerLogTime.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/HandlerLogTime.java new file mode 100644 index 0000000..a2ee3c6 --- /dev/null +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/HandlerLogTime.java @@ -0,0 +1,13 @@ +package org.dromara.app.handler; + +import org.dromara.common.core.utils.DateUtils; + +final class HandlerLogTime { + + private HandlerLogTime() { + } + + static String now() { + return DateUtils.getTime(); + } +} diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/KeyFinishHandler.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/KeyFinishHandler.java index 2604c11..899e8df 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/handler/KeyFinishHandler.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/KeyFinishHandler.java @@ -41,16 +41,16 @@ public class KeyFinishHandler implements MqttTopicHandler { Map dto = JsonUtils.parseObject(payload, Map.class); AppWateringLogBo logBo = buildWateringLog(deviceNo, dto); appWateringLogService.insertByBo(logBo); - log.info("[MQTT] 按键浇水完成上报已保存 deviceNo={} payload={}", deviceNo, payload); + log.info("[MQTT] 按键浇水完成上报已保存 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload); } catch (Exception e) { - log.error("[MQTT] 按键浇水完成上报处理失败 deviceNo={} payload={}", deviceNo, payload, e); + log.error("[MQTT] 按键浇水完成上报处理失败 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload, e); } } private AppWateringLogBo buildWateringLog(String topicDeviceNo, Map dto) { String payloadDeviceNo = valueAsString(dto.get("deviceNo")); if (StringUtils.isNotBlank(payloadDeviceNo) && !topicDeviceNo.equals(payloadDeviceNo)) { - log.warn("[MQTT] 按键浇水完成上报设备编号不一致 topicDeviceNo={} payloadDeviceNo={}", topicDeviceNo, payloadDeviceNo); + log.warn("[MQTT] 按键浇水完成上报设备编号不一致 时间={} 主题设备编号={} 消息体设备编号={}", HandlerLogTime.now(), topicDeviceNo, payloadDeviceNo); } Date receivedAt = new Date(); @@ -127,7 +127,7 @@ public class KeyFinishHandler implements MqttTopicHandler { } long diffMillis = endTime.getTime() - startTime.getTime(); if (diffMillis < 0) { - log.warn("[MQTT] 按键浇水完成上报结束时间早于开始时间 startTime={} endTime={}", startTime, endTime); + log.warn("[MQTT] 按键浇水完成上报结束时间早于开始时间 时间={} 开始时间={} 结束时间={}", HandlerLogTime.now(), startTime, endTime); return 0; } return (int) (diffMillis / 60000L); diff --git a/water-modules/water-app/src/main/java/org/dromara/app/handler/ScheduleFinishHandler.java b/water-modules/water-app/src/main/java/org/dromara/app/handler/ScheduleFinishHandler.java index fc62255..8d58cea 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/handler/ScheduleFinishHandler.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/handler/ScheduleFinishHandler.java @@ -1,8 +1,8 @@ package org.dromara.app.handler; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.dromara.app.domain.AppSchedulingDevice; import org.dromara.app.domain.bo.AppWateringLogBo; import org.dromara.app.domain.vo.AppDeviceVo; @@ -46,16 +46,16 @@ public class ScheduleFinishHandler implements MqttTopicHandler { Map dto = JsonUtils.parseObject(payload, Map.class); AppWateringLogBo logBo = buildWateringLog(deviceNo, dto); appWateringLogService.insertByBo(logBo); - log.info("[MQTT] 浇水排程上报 saved deviceNo={} payload={}", deviceNo, payload); + log.info("[MQTT] 浇水排程上报已保存 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload); } catch (Exception e) { - log.error("[MQTT] 浇水排程上报 failed deviceNo={} payload={}", deviceNo, payload, e); + log.error("[MQTT] 浇水排程上报处理失败 时间={} 设备编号={} 消息体={}", HandlerLogTime.now(), deviceNo, payload, e); } } private AppWateringLogBo buildWateringLog(String topicDeviceNo, Map dto) { String payloadDeviceNo = valueAsString(dto.get("deviceNo")); if (StringUtils.isNotBlank(payloadDeviceNo) && !topicDeviceNo.equals(payloadDeviceNo)) { - log.warn("[MQTT] 排程完成上报设备编号不一致 topicDeviceNo={} payloadDeviceNo={}", topicDeviceNo, payloadDeviceNo); + log.warn("[MQTT] 排程完成上报设备编号不一致 时间={} 主题设备编号={} 消息体设备编号={}", HandlerLogTime.now(), topicDeviceNo, payloadDeviceNo); } @@ -96,11 +96,11 @@ public class ScheduleFinishHandler implements MqttTopicHandler { .eq(AppSchedulingDevice::getDeviceNo, deviceNo) ); if (schedulingDevices == null || schedulingDevices.isEmpty()) { - log.warn("[MQTT] 排程完成上报未找到设备绑定的排程 deviceNo={}", deviceNo); + log.warn("[MQTT] 排程完成上报未找到设备绑定的排程 时间={} 设备编号={}", HandlerLogTime.now(), deviceNo); return 0L; } if (schedulingDevices.size() > 1) { - log.warn("[MQTT] 排程完成上报匹配到多个排程 deviceNo={} count={}", deviceNo, schedulingDevices.size()); + log.warn("[MQTT] 排程完成上报匹配到多个排程 时间={} 设备编号={} 数量={}", HandlerLogTime.now(), deviceNo, schedulingDevices.size()); } return schedulingDevices.get(0).getScheduleId(); } @@ -148,7 +148,7 @@ public class ScheduleFinishHandler implements MqttTopicHandler { } long diffMillis = endTime.getTime() - startTime.getTime(); if (diffMillis < 0) { - log.warn("[MQTT] 排程完成上报结束时间早于开始时间 startTime={} endTime={}", startTime, endTime); + log.warn("[MQTT] 排程完成上报结束时间早于开始时间 时间={} 开始时间={} 结束时间={}", HandlerLogTime.now(), startTime, endTime); return 0; } return (int) (diffMillis / 60000L); diff --git a/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppDeviceMapper.java b/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppDeviceMapper.java index 701ab0b..69377ec 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppDeviceMapper.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppDeviceMapper.java @@ -1,12 +1,11 @@ package org.dromara.app.mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import org.dromara.app.domain.AppDevice; import org.dromara.app.domain.vo.AppDeviceVo; -import org.dromara.common.mybatis.annotation.DataColumn; -import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; /** * 设备信息 @@ -18,26 +17,38 @@ Mapper接口 public interface AppDeviceMapper extends BaseMapperPlus { @Update(""" - - """) + + """) int bindIfAvailable(@Param("deviceNo") String deviceNo, @Param("userId") Long userId, @Param("deviceName") String deviceName, - @Param("status") String status); + @Param("status") String status, + @Param("workStatus") String workStatus, + @Param("wifiName") String wifiName, + @Param("wifiPassword") String wifiPassword); @Update(""" update app_device @@ -49,4 +60,11 @@ public interface AppDeviceMapper extends BaseMapperPlus @Param("userId") Long userId, @Param("workStatus") String workStatus); + @Select(""" + select * + from app_device + where mac_address = #{macAddress} + """) + AppDevice selectByMac(@Param("macAddress") String macAddress); + } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppWateringLogMapper.java b/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppWateringLogMapper.java index 4ce898c..a3626e6 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppWateringLogMapper.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/mapper/AppWateringLogMapper.java @@ -15,13 +15,13 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; public interface AppWateringLogMapper extends BaseMapperPlus { @Select("SELECT count(id) FROM app_watering_log\n" + - "WHERE user_id=${userId} AND YEAR(create_time) = YEAR(CURDATE()) AND MONTH(create_time) = MONTH(CURDATE());") + "WHERE user_id=#{userId} AND YEAR(create_time) = YEAR(CURDATE()) AND MONTH(create_time) = MONTH(CURDATE());") Long selectByMonCout(@Param("userId") Long userId); @Select("SELECT COUNT(id) \n" + "FROM app_watering_log \n" + - "WHERE user_id=${userId} AND WEEK(create_time) = WEEK(CURDATE());") + "WHERE user_id=#{userId} AND WEEK(create_time) = WEEK(CURDATE());") Long selectByWeekCount(@Param("userId") Long userId); @@ -29,11 +29,11 @@ public interface AppWateringLogMapper extends BaseMapperPlus handlers) { this.handlers = handlers; - log.info("[MQTT] dispatcher initialized with {} handlers", handlers.size()); + log.info("[MQTT] 消息分发器初始化完成,处理器数量={}", handlers.size()); for (MqttTopicHandler handler : handlers) { - log.info("[MQTT] └ registered: {} -> {}", handler.getClass().getSimpleName(), handler.topicPattern()); + log.info("[MQTT] 已注册处理器:{} -> {}", handler.getClass().getSimpleName(), handler.topicPattern()); } } @@ -33,7 +33,7 @@ public class MqttMessageDispatcher { * @param payload 消息体 */ public void dispatch(String topic, String payload) { - log.debug("[MQTT] received topic={} payload={}", topic, payload); + log.debug("[MQTT] 收到消息 主题={} 消息体={}", topic, payload); for (MqttTopicHandler handler : handlers) { Matcher matcher = handler.topicPattern().matcher(topic); @@ -44,6 +44,6 @@ public class MqttMessageDispatcher { } } - log.warn("[MQTT] no handler for topic: {} payload={}", topic, payload); + log.warn("[MQTT] 未找到匹配的处理器 主题={} 消息体={}", topic, payload); } } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/service/IAppDeviceService.java b/water-modules/water-app/src/main/java/org/dromara/app/service/IAppDeviceService.java index 799d8ab..e2a28e7 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/service/IAppDeviceService.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/service/IAppDeviceService.java @@ -1,14 +1,13 @@ package org.dromara.app.service; -import org.dromara.app.domain.vo.AppDeviceVo; import org.dromara.app.domain.bo.AppDeviceBo; -import org.dromara.common.mybatis.annotation.DataColumn; -import org.dromara.common.mybatis.annotation.DataPermission; -import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.app.domain.vo.AppDeviceVo; import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; import java.util.Collection; import java.util.List; +import java.util.Map; /** * 设备信息 @@ -97,4 +96,6 @@ public interface IAppDeviceService { * @return 是否删除成功 */ Boolean deleteWithValidByIds(Collection deviceNos, Boolean isValid); + + Map bindDeviceStatus(AppDeviceBo appDevice); } diff --git a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppDeviceServiceImpl.java b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppDeviceServiceImpl.java index 0afcaf4..aded2fb 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppDeviceServiceImpl.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppDeviceServiceImpl.java @@ -25,15 +25,12 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; @Slf4j @RequiredArgsConstructor @@ -116,7 +113,7 @@ public class AppDeviceServiceImpl implements IAppDeviceService { device.setPowerLevelUpdatatime(new Date()); // applyRegisterBindToken(device, bo, exists); if (StringUtils.isBlank(device.getStatus())) { - device.setStatus("2"); + device.setStatus("1"); // 注册默认在线 device.setWorkStatus("2"); } @@ -131,6 +128,45 @@ public class AppDeviceServiceImpl implements IAppDeviceService { return baseMapper.updateById(device) > 0; } + @Override + public Map bindDeviceStatus(AppDeviceBo bo) { + Map params = new HashMap<>(); + params.put("bindDeviceStatus", 200); + params.put("bindDeviceStatusName", ""); + if (bo == null) { + params.put("bindDeviceStatus", 300); + params.put("bindDeviceStatusName", "设备信息不能为空"); + return params; + } + + if (StringUtils.isBlank(bo.getMacAddress())) { + params.put("bindDeviceStatus", 301); + params.put("bindDeviceStatusName", "MAC地址不能为空"); + return params; + } + params.put("bindDevice", null); + Long userId = LoginHelper.getUserId(); + AppDevice exists = baseMapper.selectByMac(bo.getMacAddress()); + if (exists == null) { + params.put("bindDeviceStatus", 302); + params.put("bindDeviceStatusName", "设备未上线注册,请先完成配网"); + return params; + } + params.put("bindDevice", exists); + if (exists.getUserId() != null && !exists.getUserId().equals(userId)) { + params.put("bindDeviceStatus", 303); + params.put("bindDeviceStatusName", "设备已被其他用户绑定"); + return params; + } + if (exists.getUserId() == null ) { + params.put("bindDeviceStatus", 304); + params.put("bindDeviceStatusName", "设备未绑定,请先绑定用户"); + return params; + } + + return params; + } + @Override public AppDeviceVo bindRegisteredDevice(AppDeviceBo bo) { if (StringUtils.isBlank(bo.getDeviceNo())) { @@ -147,8 +183,10 @@ public class AppDeviceServiceImpl implements IAppDeviceService { // validBindToken(bo.getBindToken(), exists); String status = StringUtils.isBlank(bo.getStatus()) ? exists.getStatus() : bo.getStatus(); + String wifiName = StringUtils.isBlank(bo.getWifiName()) ? exists.getWifiName() : bo.getWifiName(); + String wifiPassword = StringUtils.isBlank(bo.getWifiPassword()) ? exists.getWifiPassword() : bo.getWifiPassword(); String deviceName = StringUtils.isBlank(bo.getDeviceName()) ? exists.getDeviceName() : bo.getDeviceName(); - int rows = baseMapper.bindIfAvailable(exists.getDeviceNo(), userId, deviceName, status); + int rows = baseMapper.bindIfAvailable(exists.getDeviceNo(), userId, deviceName, status,"0",wifiName,wifiPassword); if (rows <= 0) { AppDevice current = baseMapper.selectById(bo.getDeviceNo()); if (current == null) { @@ -188,7 +226,7 @@ public class AppDeviceServiceImpl implements IAppDeviceService { if (ObjectUtil.isNotNull(device) && StringUtils.isNotBlank(device.getDeviceNo())) { // 通过业务层统一下发命令(含浇水日志记录) String commandId = deviceCommandService.sendSwitchCommand(deviceNo, workStatus, startTime, durationMin); - log.info("[DEVICE] switch command sent deviceNo={} commandId={}", deviceNo, commandId); + log.info("[设备] 开关命令已下发 设备编号={} 命令编号={}", deviceNo, commandId); } return true; diff --git a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppScheduleServiceImpl.java b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppScheduleServiceImpl.java index 15b5984..d6ab07e 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppScheduleServiceImpl.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/AppScheduleServiceImpl.java @@ -25,11 +25,7 @@ import org.dromara.common.satoken.utils.LoginHelper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Slf4j @RequiredArgsConstructor @@ -88,7 +84,13 @@ public class AppScheduleServiceImpl implements IAppScheduleService { @Override public Boolean updateStatusByBo(AppScheduleBo bo) { AppSchedule update = MapstructUtils.convert(bo, AppSchedule.class); - return baseMapper.updateById(update) > 0; + Long userId = bo.getUserId() == null ? LoginHelper.getUserId() : bo.getUserId(); + return baseMapper.update( + update, + Wrappers.lambdaQuery() + .eq(AppSchedule::getId, bo.getId()) + .eq(AppSchedule::getUserId, userId) + ) > 0; } @Override @@ -98,7 +100,13 @@ public class AppScheduleServiceImpl implements IAppScheduleService { validEntityBeforeSave(update); Map repMap = new HashMap<>(); - Boolean flag = baseMapper.updateById(update) > 0; + Long userId = bo.getUserId() == null ? LoginHelper.getUserId() : bo.getUserId(); + Boolean flag = baseMapper.update( + update, + Wrappers.lambdaQuery() + .eq(AppSchedule::getId, bo.getId()) + .eq(AppSchedule::getUserId, userId) + ) > 0; repMap.put("flag", flag); repMap.put("list", new ArrayList<>()); repMap.put("appSchedule", ""); diff --git a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/DeviceCommandServiceImpl.java b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/DeviceCommandServiceImpl.java index 1f74345..9ce1e72 100644 --- a/water-modules/water-app/src/main/java/org/dromara/app/service/impl/DeviceCommandServiceImpl.java +++ b/water-modules/water-app/src/main/java/org/dromara/app/service/impl/DeviceCommandServiceImpl.java @@ -3,13 +3,13 @@ package org.dromara.app.service.impl; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.app.domain.bo.AppWateringLogBo; import org.dromara.app.domain.mqtt.DeviceCommand; import org.dromara.app.domain.vo.AppDeviceVo; import org.dromara.app.service.IAppDeviceService; import org.dromara.app.service.IAppWateringLogService; import org.dromara.app.service.IDeviceCommandPublisher; import org.dromara.app.service.IDeviceCommandService; -import org.dromara.app.domain.bo.AppWateringLogBo; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.satoken.utils.LoginHelper; @@ -50,7 +50,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService { public String sendCommand(DeviceCommand command) { validate(command); String commandId = commandPublisher.send(command); - log.info("[CMD] command sent deviceNo={} commandType={} commandId={}", + log.info("[命令] 命令已下发 设备编号={} 命令类型={} 命令编号={}", command.getDeviceNo(), command.getCommandType(), commandId); return commandId; } @@ -76,7 +76,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService { } String commandId = commandPublisher.send(command); - log.info("[CMD] switch command sent deviceNo={} workStatus={} durationMin={} commandId={}", + log.info("[命令] 开关命令已下发 设备编号={} 工作状态={} 持续分钟数={} 命令编号={}", deviceNo, workStatus, durationMin, commandId); Long userId = LoginHelper.getUserId(); @@ -86,7 +86,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService { } else { boolean updated = wateringLogService.finishManualLog(deviceNo, userId, new Date()); if (!updated) { - log.warn("[CMD] no active manual watering log found deviceNo={} userId={} stopCommandId={}", + log.warn("[命令] 未找到进行中的手动浇水记录 设备编号={} 用户ID={} 停止命令编号={}", deviceNo, userId, commandId); } } @@ -119,7 +119,7 @@ public class DeviceCommandServiceImpl implements IDeviceCommandService { command.setCommandType("bindDevice"); Map objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("bindStatus", true); - objectObjectHashMap.put("deviceNo", "01"); + objectObjectHashMap.put("deviceNo", deviceNo); objectObjectHashMap.put("cmd", -1); command.getPayload().putAll(objectObjectHashMap); return sendCommand(command); diff --git a/water-modules/water-app/src/main/java/org/dromara/app/task/DeviceOfflineCheckTask.java b/water-modules/water-app/src/main/java/org/dromara/app/task/DeviceOfflineCheckTask.java new file mode 100644 index 0000000..e0908f3 --- /dev/null +++ b/water-modules/water-app/src/main/java/org/dromara/app/task/DeviceOfflineCheckTask.java @@ -0,0 +1,86 @@ +package org.dromara.app.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.app.domain.AppDevice; +import org.dromara.app.mapper.AppDeviceMapper; +import org.dromara.common.redis.utils.RedisUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 设备离线检测定时任务 + *

+ * 逻辑:Redis 中 mqtt:device:status:{deviceNo} Key 的 TTL 由 device-status-cache-ttl-seconds 控制。 + * 设备断电/断网后不再上报数据,TTL 到期 Key 自动消失。 + * 本任务定期扫描数据库中非离线状态的设备,如果对应 Redis Key 已不存在, + * 则将数据库 status 更新为 0(离线)。 + *

+ * + *

扫描间隔通过 {@code mqtt.offline-check.interval-ms} 配置,建议小于设备在线 Key 的 TTL。

+ */ +@Slf4j +@Component +@RequiredArgsConstructor +public class DeviceOfflineCheckTask { + + private final AppDeviceMapper appDeviceMapper; + + @Value("${mqtt.command-ack.device-status-cache-prefix}") + private String deviceStatusCachePrefix; + + @Value("${mqtt.offline-check.enabled:true}") + private boolean enabled; + + /** + * 每 90 秒检查一次(Redis TTL 默认 300s,90s 间隔确保 1.5 个周期内同步) + * 可通过 mqtt.offline-check.interval-ms 覆盖(单位 ms) + */ + @Scheduled(fixedDelayString = "${mqtt.offline-check.interval-ms:90000}") + @Transactional(rollbackFor = Exception.class) + public void checkOfflineDevices() { + if (!enabled) { + return; + } + + // 查询数据库中所有非离线状态的设备,避免状态不是 1 但仍需离线修正的设备被漏掉 + List onlineDevices = appDeviceMapper.selectList( + new LambdaQueryWrapper() + .ne(AppDevice::getStatus, "0") + .select(AppDevice::getDeviceNo) + ); + + if (onlineDevices.isEmpty()) { + return; + } + + // 过滤出 Redis Key 已过期(不存在)的设备 + List offlineDeviceNos = onlineDevices.stream() + .map(AppDevice::getDeviceNo) + .filter(deviceNo -> !RedisUtils.hasKey(deviceStatusCachePrefix + deviceNo)) + .collect(Collectors.toList()); + + if (offlineDeviceNos.isEmpty()) { + log.debug("[设备离线] 本次检测未发现离线设备,扫描设备数:{}", onlineDevices.size()); + return; + } + + // 批量更新为离线 + int updated = appDeviceMapper.update(null, + new LambdaUpdateWrapper() + .set(AppDevice::getStatus, "0") + .ne(AppDevice::getStatus, "0") + .in(AppDevice::getDeviceNo, offlineDeviceNos) + ); + + log.info("[设备离线] 检测到 {} 台设备离线,已更新数据库状态,设备编号:{}", + updated, offlineDeviceNos); + } +} diff --git a/water-modules/water-demo/src/main/java/org/dromara/demo/controller/SaTokenTestController.java b/water-modules/water-demo/src/main/java/org/dromara/demo/controller/SaTokenTestController.java index 66fd3cd..ade71c3 100644 --- a/water-modules/water-demo/src/main/java/org/dromara/demo/controller/SaTokenTestController.java +++ b/water-modules/water-demo/src/main/java/org/dromara/demo/controller/SaTokenTestController.java @@ -56,7 +56,7 @@ public class SaTokenTestController { @SaCheckRole("none_exist") // 该注解会被忽略 @GetMapping("/basic/ignoreAll") public R ignoreAll() { - log.info("【场景4】SaIgnore忽略所有权限校验"); + log.info("【场景4】忽略注解跳过所有权限校验"); return R.ok("SaIgnore生效,所有权限校验被忽略"); } @@ -68,7 +68,7 @@ public class SaTokenTestController { @SaCheckRole(value = {"admin", "operator"}, mode = SaMode.AND) @GetMapping("/advance/multiRoleAnd") public R multiRoleAnd() { - log.info("【场景5】多角色AND模式(admin+operator)校验通过"); + log.info("【场景5】多角色且模式(admin+operator)校验通过"); return R.ok("同时拥有admin和operator角色,校验通过"); } @@ -78,7 +78,7 @@ public class SaTokenTestController { @SaCheckRole(value = {"admin", "test"}, mode = SaMode.OR) @GetMapping("/advance/multiRoleOr") public R multiRoleOr() { - log.info("【场景6】多角色OR模式(admin|test)校验通过"); + log.info("【场景6】多角色或模式(admin|test)校验通过"); return R.ok("拥有admin或test角色,校验通过"); } @@ -88,7 +88,7 @@ public class SaTokenTestController { @SaCheckPermission(value = {"system:user:edit", "system:log:view"}, mode = SaMode.AND) @GetMapping("/advance/multiPermAnd") public R multiPermAnd() { - log.info("【场景7】多权限AND模式(system:user:edit+system:log:view)校验通过"); + log.info("【场景7】多权限且模式(system:user:edit+system:log:view)校验通过"); return R.ok("同时拥有system:user:edit和system:log:view权限,校验通过"); } @@ -98,7 +98,7 @@ public class SaTokenTestController { @SaCheckPermission(value = {"system:user:add", "system:user:delete"}, mode = SaMode.OR) @GetMapping("/advance/multiPermOr") public R multiPermOr() { - log.info("【场景8】多权限OR模式(system:user:add|system:user:delete)校验通过"); + log.info("【场景8】多权限或模式(system:user:add|system:user:delete)校验通过"); return R.ok("拥有system:user:add或system:user:delete权限,校验通过"); } @@ -134,7 +134,7 @@ public class SaTokenTestController { @SaCheckPermission("system:user:all") @GetMapping("/advanced/mixRolePermAnd") public R mixRolePermAnd() { - log.info("【场景11】角色+权限混合AND(admin+system:user:all)校验通过"); + log.info("【场景11】角色+权限混合且模式(admin+system:user:all)校验通过"); return R.ok("拥有admin角色且拥有system:user:all权限,校验通过"); } @@ -146,7 +146,7 @@ public class SaTokenTestController { @SaCheckPermission(value = {"system:manage"}, mode = SaMode.OR) @GetMapping("/advanced/mixRolePermOr") public R mixRolePermOr() { - log.info("【场景12】角色+权限混合OR(super_admin|system:manage)校验通过"); + log.info("【场景12】角色+权限混合或模式(super_admin|system:manage)校验通过"); return R.ok("拥有super_admin角色或system:manage权限,校验通过"); } @@ -157,7 +157,7 @@ public class SaTokenTestController { @SaCheckPermission(value = "system:user:export", orRole = {"admin", "operator"}) @GetMapping("/advanced/permWithOrRole") public R permWithOrRole() { - log.info("【场景13】权限+orRole兜底校验通过"); + log.info("【场景13】权限+角色兜底校验通过"); return R.ok("拥有system:user:export权限,或拥有admin/operator角色,校验通过"); } @@ -170,7 +170,7 @@ public class SaTokenTestController { @SaIgnore @GetMapping("/special/ignoreOverride") public R ignoreOverride() { - log.info("【场景14】SaIgnore覆盖类级别权限注解"); + log.info("【场景14】忽略注解覆盖类级别权限注解"); return R.ok("方法级SaIgnore覆盖类级别权限校验"); } diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java index 77389bc..8aadd3e 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java @@ -107,7 +107,7 @@ public class FlwCommonServiceImpl implements IFlwCommonService { // // 指定获取一个短信服务商 configKey // SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); // SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map); - log.info("【短信发送 - TODO】用户数量={} 内容={}", userList.size(), message); + log.info("【短信发送 - 待实现】用户数量={} 内容={}", userList.size(), message); } default -> log.warn("【消息发送】未处理的消息类型:{}", messageTypeEnum); } diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java index 1cc61fe..a34bea0 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java @@ -194,8 +194,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { try { defService.removeDef(ids); } catch (Exception e) { - log.error("Error removing flow definitions: {}", e.getMessage(), e); - throw new RuntimeException("Failed to remove flow definitions", e); + log.error("删除流程定义失败:{}", e.getMessage(), e); + throw new RuntimeException("删除流程定义失败", e); } return true; } diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index 4814736..ba55a67 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -266,7 +266,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { flowInstances.forEach(instance -> { Definition definition = definitionMap.get(instance.getDefinitionId()); if (ObjectUtil.isNull(definition)) { - log.warn("实例 ID: {} 对应的流程定义信息未找到,跳过删除事件触发。", instance.getId()); + log.warn("实例ID:{} 对应的流程定义信息未找到,跳过删除事件触发。", instance.getId()); return; } flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId()); diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java index 8e39869..767a61c 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java @@ -267,7 +267,7 @@ public class FlwNodeExtServiceImpl implements NodeExtService, IFlwNodeExtService nodeExtVo.setVariables(variables); } else { // 未知扩展类型,记录日志 - log.warn("未知扩展类型:code={}, value={}", code, value); + log.warn("未知扩展类型:编码={},值={}", code, value); } } return nodeExtVo; diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 8edccd0..d8557f8 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -283,7 +283,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand return Pair.of(type, parts[1]); } } catch (Exception e) { - log.warn("解析 storageId 失败,格式非法:{},错误信息:{}", storageId, e.getMessage()); + log.warn("解析存储ID失败,格式非法:{},错误信息:{}", storageId, e.getMessage()); return null; } } diff --git a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java index af693e6..dbbf42a 100644 --- a/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java +++ b/water-modules/water-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -754,8 +754,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService { public boolean taskOperation(TaskOperationBo bo, String taskOperation) { TaskOperationEnum op = TaskOperationEnum.getByCode(taskOperation); if (op == null) { - log.error("Invalid operation type:{} ", taskOperation); - throw new ServiceException("Invalid operation type " + taskOperation); + log.error("无效的操作类型:{}", taskOperation); + throw new ServiceException("无效的操作类型 " + taskOperation); } FlowParams flowParams = FlowParams.build().message(bo.getMessage());