1821 lines
43 KiB
Markdown
1821 lines
43 KiB
Markdown
# Water IoT APP 接口文档
|
||
|
||
> **业务接口 Base URL**: `/app/v1`
|
||
> **认证接口前缀**: `/auth`、`/resource`
|
||
> **认证方式**: Sa-Token;`/app/v1/**` 业务接口需携带 `Authorization: Bearer <token>`,登录/注册/普通验证码接口免登录
|
||
> **响应编码**: UTF-8
|
||
> **最后更新**: 2026-07-14
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [通用说明](#通用说明)
|
||
- [统一响应结构 R\<T\>](#统一响应结构-rt)
|
||
- [分页响应结构 TableDataInfo\<T\>](#分页响应结构-tabledatainfot)
|
||
- [分页请求参数](#分页请求参数)
|
||
- [特殊标注说明](#特殊标注说明)
|
||
- [零、登录、注册与验证码](#零登录注册与验证码)
|
||
- [0.1 获取租户列表](#01-获取租户列表)
|
||
- [0.2 获取图形验证码](#02-获取图形验证码)
|
||
- [0.3 获取通用手机号或邮箱验证码](#03-获取通用手机号或邮箱验证码)
|
||
- [0.4 获取短信验证码](#04-获取短信验证码)
|
||
- [0.5 获取邮箱验证码](#05-获取邮箱验证码)
|
||
- [0.6 用户登录](#06-用户登录)
|
||
- [0.7 用户注册](#07-用户注册)
|
||
- [0.8 忘记密码](#08-忘记密码)
|
||
- [0.9 退出登录](#09-退出登录)
|
||
- [0.10 获取账号注销验证码](#010-获取账号注销验证码)
|
||
- [0.11 注销账号](#011-注销账号)
|
||
- [一、设备管理](#一设备管理)
|
||
- [1.1 查询设备列表(分页)](#11-查询设备列表分页)
|
||
- [1.2 绑定设备状态检查](#12-绑定设备状态检查)
|
||
- [1.3 绑定已上线设备](#13-绑定已上线设备)
|
||
- [1.4 获取设备详情](#14-获取设备详情)
|
||
- [1.5 修改设备信息](#15-修改设备信息)
|
||
- [1.6 删除设备(解绑)](#16-删除设备解绑)
|
||
- [1.7 手动开关设备](#17-手动开关设备)
|
||
- [二、排程管理](#二排程管理)
|
||
- [2.1 查询排程列表(分页)](#21-查询排程列表分页)
|
||
- [2.2 新增排程](#22-新增排程)
|
||
- [2.3 排程详情](#23-排程详情)
|
||
- [2.4 修改排程状态](#24-修改排程状态)
|
||
- [2.5 修改排程](#25-修改排程)
|
||
- [2.6 删除排程](#26-删除排程)
|
||
- [三、排程-设备关联](#三排程-设备关联)
|
||
- [3.1 查询排程可关联的设备](#31-查询排程可关联的设备)
|
||
- [3.2 绑定排程与设备](#32-绑定排程与设备)
|
||
- [3.3 删除排程与设备绑定](#33-删除排程与设备绑定)
|
||
- [四、浇水记录](#四浇水记录)
|
||
- [4.1 查询浇水记录列表(分页)](#41-查询浇水记录列表分页)
|
||
- [4.2 查询设备最新进行中的浇水记录](#42-查询设备最新进行中的浇水记录)
|
||
- [4.3 删除浇水记录](#43-删除浇水记录)
|
||
- [五、数据统计](#五数据统计)
|
||
- [5.1 数据统计](#51-数据统计)
|
||
- [六、用户管理](#六用户管理)
|
||
- [6.1 获取用户信息](#61-获取用户信息)
|
||
- [6.2 修改用户信息](#62-修改用户信息)
|
||
- [6.3 修改登录密码](#63-修改登录密码)
|
||
- [6.4 找回密码](#64-找回密码)
|
||
- [七、文件上传](#七文件上传)
|
||
- [7.1 上传图片](#71-上传图片)
|
||
- [八、版本检查](#八版本检查)
|
||
- [8.1 检查APP版本更新](#81-检查app版本更新)
|
||
- [九、内部调试接口](#九内部调试接口)
|
||
- [9.1 MQTT绑定命令测试](#91-mqtt绑定命令测试)
|
||
- [附录:数据模型](#附录数据模型)
|
||
|
||
---
|
||
|
||
## 通用说明
|
||
|
||
### 统一响应结构 R\<T\>
|
||
|
||
大多数接口返回统一的 `R<T>` 包装结构:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": { }
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `code` | `int` | `200` 表示成功,`500` 表示失败 |
|
||
| `msg` | `string` | 提示消息(支持 i18n 国际化) |
|
||
| `data` | `T` | 业务数据,类型视接口而定;无数据时为 `null` |
|
||
|
||
**判断逻辑**:`code === 200` 为成功,其余均为失败。
|
||
|
||
---
|
||
|
||
### 分页响应结构 TableDataInfo\<T\>
|
||
|
||
列表查询接口返回 `TableDataInfo<T>`:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"total": 100,
|
||
"rows": [ ]
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `code` | `int` | `200` 表示成功 |
|
||
| `msg` | `string` | 提示消息 |
|
||
| `total` | `long` | 总记录数 |
|
||
| `rows` | `T[]` | 当前页数据列表 |
|
||
|
||
---
|
||
|
||
### 分页请求参数
|
||
|
||
所有分页查询接口(GET 请求)支持以下 Query 参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `pageNum` | `int` | 否 | 当前页码,默认 `1` |
|
||
| `pageSize` | `int` | 否 | 每页条数,默认查全部 |
|
||
|
||
> **注意**:设备列表、排程列表、浇水记录列表的排序方向固定为 `createTime desc`(服务端强制设置),前端无需传排序参数。
|
||
|
||
---
|
||
|
||
### 特殊标注说明
|
||
|
||
| 标注 | 说明 |
|
||
|------|------|
|
||
| `@ApiEncrypt` | 启用 `api-decrypt` 后强制请求体加密;默认配置关闭时仍使用普通 JSON |
|
||
| `@RepeatSubmit` | 防重复提交,相同请求在短时间内只能提交一次 |
|
||
| `@Log` | 操作会被记录到系统日志 |
|
||
|
||
> 当前默认配置 `api-decrypt.enabled=false`,因此 `@ApiEncrypt` 接口可直接发送普通 JSON。
|
||
> 当部署环境启用接口加密后,标注 `@ApiEncrypt` 的 POST/PUT 接口必须携带 `encrypt-key` 请求头并发送加密后的 body;该标注不代表免登录。
|
||
|
||
---
|
||
|
||
## 零、登录、注册与验证码
|
||
|
||
本章节接口来自 `AuthController` 和 `CaptchaController`。两个控制器使用了 `@SaIgnore`,普通登录、注册和验证码接口免登录;退出登录、账号注销验证码和账号注销仍会在方法内部校验 Token。
|
||
|
||
默认 APP 客户端配置:
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|------|------|
|
||
| `clientId` | `428a8310cd442757ae699df5d894f051` | APP 客户端 ID,来源于 `sys_client` 初始化数据 |
|
||
| `tenantId` | `000000` | 默认租户 ID;关闭多租户时仍可沿用该值 |
|
||
| `userType` | `app_user` | APP 注册用户类型 |
|
||
| `grantType` | `password` / `sms` | 默认 APP 客户端支持密码、短信和社交授权 |
|
||
|
||
|
||
|
||
---
|
||
|
||
### 0.1 获取图形验证码
|
||
|
||
```
|
||
GET /auth/code
|
||
```
|
||
|
||
**认证**:免登录。验证码开启时按 IP 限流,每 60 秒最多 10 次。
|
||
|
||
**响应**:`R<CaptchaVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"captchaEnabled": true,
|
||
"uuid": "54ef90b79e384d29a44d59f863f83a52",
|
||
"img": "data:image/png;base64,..."
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `captchaEnabled` | `boolean` | 是否启用图形验证码 |
|
||
| `uuid` | `string` | 验证码缓存标识 |
|
||
| `img` | `string` | Base64 图片数据 |
|
||
|
||
> 当前密码登录和注册服务中的图形验证码校验代码已注释,APP 注册实际使用手机号/邮箱验证码。
|
||
|
||
---
|
||
|
||
### 0.2 获取通用手机号或邮箱验证码
|
||
|
||
根据 `username` 格式自动选择短信或邮件发送,主要用于注册和找回密码。
|
||
|
||
```
|
||
GET /resource/code?username={username}
|
||
```
|
||
|
||
**认证**:免登录。相同 `username` 每 60 秒最多请求 1 次。
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `username` | `string` | **是** | 手机号或邮箱;手机号发送短信,其他值按邮箱发送 |
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "123456",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> 当前实现会把验证码同时放入响应 `msg`,生产环境存在验证码泄露风险,建议生产部署时改为固定提示文本。
|
||
|
||
---
|
||
|
||
### 0.3 获取短信验证码
|
||
|
||
用于短信验证码登录。
|
||
|
||
```
|
||
GET /resource/sms/code?phonenumber={phonenumber}
|
||
```
|
||
|
||
**认证**:免登录。相同手机号每 60 秒最多请求 1 次。
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `phonenumber` | `string` | **是** | 接收验证码的手机号 |
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 0.4 获取邮箱验证码
|
||
|
||
```
|
||
GET /resource/email/code?email={email}
|
||
```
|
||
|
||
**认证**:免登录。相同邮箱每 60 秒最多请求 1 次。
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `email` | `string` | **是** | 接收验证码的邮箱地址 |
|
||
|
||
**响应**:`R<Void>`。未开启邮件功能时返回 `当前系统没有开启邮箱功能!`。
|
||
|
||
---
|
||
|
||
### 0.5 用户登录
|
||
|
||
```
|
||
POST /auth/login
|
||
```
|
||
|
||
**认证**:免登录。接口标注 `@ApiEncrypt`,加密规则参见通用说明。
|
||
|
||
**密码登录请求体**(`grantType=password`)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `clientId` | `string` | **是** | APP 客户端 ID |
|
||
| `grantType` | `string` | **是** | 固定为 `password` |
|
||
| `username` | `string` | **是** | 用户名、手机号或邮箱,长度 2~30 |
|
||
| `password` | `string` | **是** | 密码,长度 5~30 |
|
||
|
||
```json
|
||
{
|
||
"clientId": "428a8310cd442757ae699df5d894f051",
|
||
"grantType": "password",
|
||
"username": "13800000000",
|
||
"password": "123456"
|
||
}
|
||
```
|
||
|
||
**短信登录请求体**(`grantType=sms`)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `clientId` | `string` | **是** | APP 客户端 ID |
|
||
| `grantType` | `string` | **是** | 固定为 `sms` |
|
||
| `phonenumber` | `string` | **是** | 手机号 |
|
||
| `smsCode` | `string` | **是** | `/resource/sms/code` 获取的验证码 |
|
||
|
||
```json
|
||
{
|
||
"clientId": "428a8310cd442757ae699df5d894f051",
|
||
"grantType": "sms",
|
||
"phonenumber": "13800000000",
|
||
"smsCode": "123456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<LoginVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"access_token": "登录Token",
|
||
"refresh_token": null,
|
||
"expire_in": 1800,
|
||
"refresh_expire_in": null,
|
||
"client_id": "428a8310cd442757ae699df5d894f051",
|
||
"scope": null,
|
||
"openid": null
|
||
}
|
||
}
|
||
```
|
||
|
||
后续业务请求头:
|
||
|
||
```http
|
||
Authorization: Bearer 登录Token
|
||
```
|
||
|
||
---
|
||
|
||
### 0.6 用户注册
|
||
|
||
```
|
||
POST /auth/register
|
||
```
|
||
|
||
**认证**:免登录。接口标注 `@ApiEncrypt`;系统配置必须允许注册。
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|-----------------------------------------|
|
||
| `clientId` | `string` | **是** | APP 客户端 ID |
|
||
| `grantType` | `string` | **是** | 可传 `password、sms`,用于通过基础请求校验 |
|
||
| `username` | `string` | **是** | 手机号、邮箱或用户名,长度 2~30 |
|
||
| `password` | `string` | **是** | 密码,长度 5~30 |
|
||
| `userType` | `string` | **是** | APP 用户固定传 `app_user` |
|
||
| `code` | `string` | **是** | 调用 `/resource/code?username=...` 获取的验证码 |
|
||
|
||
```json
|
||
{
|
||
"clientId": "428a8310cd442757ae699df5d894f051",
|
||
"grantType": "password",
|
||
"username": "13800000000",
|
||
"password": "123456",
|
||
"userType": "app_user",
|
||
"code": "123456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> 注册验证码以 `username` 为缓存键,因此获取验证码和注册时的 `username` 必须完全一致。
|
||
|
||
---
|
||
|
||
### 0.7 忘记密码
|
||
|
||
```
|
||
PUT /auth/forgot
|
||
```
|
||
|
||
**认证**:免登录。接口标注 `@ApiEncrypt`。
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `username` | `string` | **是** | 已注册的用户名或手机号 |
|
||
| `smsCode` | `string` | **是** | 以 `username` 为缓存键的验证码,可通过 `/resource/code` 获取 |
|
||
| `password` | `string` | **是** | 新密码,长度 5~30 |
|
||
|
||
```json
|
||
{
|
||
"username": "13800000000",
|
||
"smsCode": "123456",
|
||
"password": "NewPass456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
> **当前实现限制**:邮箱分支查询结果未赋值给用户对象,因此邮箱找回密码当前会被判定为“账号未注册”;建议修复后再开放邮箱找回。
|
||
|
||
---
|
||
|
||
### 0.8 退出登录
|
||
|
||
```
|
||
POST /auth/logout
|
||
```
|
||
|
||
**认证**:需要 `Authorization: Bearer <token>`。
|
||
|
||
**响应**:`R<Void>`,成功消息为 `退出成功`。
|
||
|
||
---
|
||
|
||
### 0.9 获取账号注销验证码
|
||
|
||
根据当前登录账号优先向已绑定手机号发送短信;没有有效手机号时发送到邮箱。
|
||
|
||
```
|
||
GET /resource/account/cancel/code
|
||
```
|
||
|
||
**认证**:需要 `Authorization: Bearer <token>`。每个用户每 60 秒最多请求 1 次。
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
> 验证码以当前登录用户名为缓存键。账号未绑定手机号或邮箱时返回失败。
|
||
|
||
---
|
||
|
||
### 0.11 注销账号
|
||
|
||
```
|
||
DELETE /auth/account
|
||
```
|
||
|
||
**认证**:需要 `Authorization: Bearer <token>`。
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `code` | `string` | **是** | `/resource/account/cancel/code` 获取的验证码 |
|
||
|
||
```json
|
||
{
|
||
"code": "123456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`,成功消息为 `注销成功`。
|
||
|
||
> 注销成功后会解绑并初始化用户名下设备,删除排程、浇水记录及系统用户关联数据,并退出当前账号。该操作不可恢复,超级管理员账号不允许注销。
|
||
|
||
---
|
||
|
||
## 一、设备管理
|
||
|
||
### 1.1 查询设备列表(分页)
|
||
|
||
查询当前登录用户名下的设备列表。
|
||
|
||
```
|
||
GET /app/v1/deviceList
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `pageNum` | `int` | 否 | 页码,默认 1 |
|
||
| `pageSize` | `int` | 否 | 每页条数 |
|
||
| `deviceNo` | `string` | 否 | 设备编号(精确查询) |
|
||
| `deviceName` | `string` | 否 | 设备名称(模糊查询) |
|
||
| `status` | `string` | 否 | 设备状态:`1`-在线 `0`-离线 `2`-到期 `3`-故障 |
|
||
| `wifiName` | `string` | 否 | WiFi 名称(模糊查询) |
|
||
| `deviceEm` | `string` | 否 | 设备型号(精确查询) |
|
||
| `deviceSn` | `string` | 否 | 设备序列号(精确查询) |
|
||
| `fwVer` | `string` | 否 | 固件版本(精确查询) |
|
||
| `macAddress` | `string` | 否 | MAC 地址(精确查询) |
|
||
|
||
**响应**:`TableDataInfo<AppDeviceVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"total": 2,
|
||
"rows": [
|
||
{
|
||
"deviceNo": "D20260101001",
|
||
"userId": 1,
|
||
"deviceName": "前院浇灌器",
|
||
"deviceInitName": "智能浇灌器Pro",
|
||
"deviceImg": "https://oss.example.com/device/xxx.png",
|
||
"qrcode": "D20260101001",
|
||
"status": "1",
|
||
"workStatus": "0",
|
||
"powerLevel": "85",
|
||
"powerLevelUpdatatime": "2026-07-14 08:30:00",
|
||
"wifiName": "Home-WiFi",
|
||
"wifiPassword": "12345678",
|
||
"deviceEm": "WATER-PRO-1",
|
||
"deviceSn": "SN20260101001",
|
||
"fwVer": "1.0.3",
|
||
"macAddress": "AA:BB:CC:DD:EE:FF",
|
||
"nickName": "张三",
|
||
"expirationTime": "2027-01-01 00:00:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 1.2 绑定设备状态检查
|
||
|
||
检查设备绑定状态(加密接口)。
|
||
|
||
```
|
||
POST /app/v1/bindDeviceStatus
|
||
```
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**(JSON;启用接口加密时发送加密后的 JSON 字符串)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | 否 | 设备编号 |
|
||
| `macAddress` | `string` | 否 | MAC 地址 |
|
||
| `deviceInitName` | `string` | 否 | 设备初始名称 |
|
||
|
||
以上三个设备标识至少填写一个。查询顺序为 `deviceNo`、`macAddress`、`deviceInitName`。
|
||
|
||
**响应**:`R<Map<String, Object>>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"bindDeviceStatus": 304,
|
||
"bindDeviceStatusName": "设备未绑定,请先绑定用户",
|
||
"bindDevice": {
|
||
"deviceNo": "D20260101001",
|
||
"macAddress": "AA:BB:CC:DD:EE:FF",
|
||
"userId": null,
|
||
"status": "1",
|
||
"workStatus": "2"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
`bindDeviceStatus` 业务状态码:
|
||
|
||
| 状态码 | 说明 |
|
||
|------|------|
|
||
| `200` | 设备已绑定当前用户,可正常使用 |
|
||
| `300` | 设备信息为空 |
|
||
| `301` | 未提供设备编号、MAC 地址或设备初始名称 |
|
||
| `302` | 设备未入库注册 |
|
||
| `303` | 设备已被其他用户绑定 |
|
||
| `304` | 设备存在但尚未绑定用户,可以继续调用 `/addDevice` |
|
||
| `305` | 设备尚未完成配网 |
|
||
|
||
> 这些是 `data.bindDeviceStatus` 的业务状态码;接口外层 `code` 在正常处理时仍为 `200`。
|
||
|
||
---
|
||
|
||
### 1.3 绑定已上线设备
|
||
|
||
绑定通过 MQTT 注册上线的设备到当前用户(加密接口)。
|
||
|
||
```
|
||
POST /app/v1/addDevice
|
||
```
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**(JSON;启用接口加密时发送加密后的 JSON 字符串)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | **是** | MQTT 注册后服务端分配的设备编号 |
|
||
| `deviceName` | `string` | 否 | 设备名称 |
|
||
| `status` | `string` | 否 | 绑定后保留/设置的设备在线状态 |
|
||
| `wifiName` | `string` | 否 | WiFi 名称 |
|
||
| `wifiPassword` | `string` | 否 | WiFi 密码 |
|
||
|
||
**响应**:`R<AppDeviceVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"deviceNo": "D20260101001",
|
||
"userId": 1,
|
||
"deviceName": "前院浇灌器",
|
||
"deviceInitName": "智能浇灌器Pro",
|
||
"deviceImg": "https://oss.example.com/device/xxx.png",
|
||
"status": "1",
|
||
"workStatus": "0",
|
||
"macAddress": "AA:BB:CC:DD:EE:FF",
|
||
"expirationTime": "2027-01-01 00:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 1.4 获取设备详情
|
||
|
||
```
|
||
GET /app/v1/device/{deviceNo}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | **是** | 设备编号 |
|
||
|
||
**响应**:`R<AppDeviceVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"deviceNo": "D20260101001",
|
||
"userId": 1,
|
||
"deviceName": "前院浇灌器",
|
||
"deviceInitName": "智能浇灌器Pro",
|
||
"deviceImg": "https://oss.example.com/device/xxx.png",
|
||
"qrcode": "D20260101001",
|
||
"status": "1",
|
||
"workStatus": "0",
|
||
"powerLevel": "85",
|
||
"powerLevelUpdatatime": "2026-07-14 08:30:00",
|
||
"wifiName": "Home-WiFi",
|
||
"wifiPassword": "12345678",
|
||
"deviceEm": "WATER-PRO-1",
|
||
"deviceSn": "SN20260101001",
|
||
"fwVer": "1.0.3",
|
||
"macAddress": "AA:BB:CC:DD:EE:FF",
|
||
"nickName": "张三",
|
||
"expirationTime": "2027-01-01 00:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
> **权限**:只能查询当前用户名下的设备,否则返回错误。
|
||
|
||
---
|
||
|
||
### 1.5 修改设备信息
|
||
|
||
```
|
||
PUT /app/v1/updateDeviceInfo
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`AppDeviceBo`(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | **是** | 设备编号(EditGroup 校验) |
|
||
| `deviceName` | `string` | 否 | 设备名称 |
|
||
| `deviceImg` | `string` | 否 | 设备图片 URL |
|
||
| `wifiName` | `string` | 否 | WiFi 名称 |
|
||
| `wifiPassword` | `string` | 否 | WiFi 密码 |
|
||
|
||
```json
|
||
{
|
||
"deviceNo": "D20260101001",
|
||
"deviceName": "后院浇灌器",
|
||
"deviceImg": "https://oss.example.com/device/new.png"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **权限**:只能修改当前用户名下的设备。
|
||
|
||
---
|
||
|
||
### 1.6 删除设备(解绑)
|
||
|
||
解绑一个或多个设备。
|
||
|
||
```
|
||
DELETE /app/v1/deleteDevice/{deviceNos}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNos` | `string` | **是** | 设备编号,多个用逗号分隔。例:`D001,D002` |
|
||
|
||
**示例**
|
||
|
||
```
|
||
DELETE /app/v1/deleteDevice/D20260101001,D20260101002
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **权限**:只能解绑当前用户名下的设备。
|
||
|
||
---
|
||
|
||
### 1.7 手动开关设备
|
||
|
||
手动开启或关闭设备工作状态,并可通过 MQTT 下发指令到设备。
|
||
|
||
```
|
||
PUT /app/v1/switchDevice
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | **是** | 设备编号 |
|
||
| `workStatus` | `string` | **是** | 工作状态:`1`-开启 `0`-关闭 |
|
||
| `durationMin` | `int` | 条件必填 | 持续时长(分钟);`workStatus=1` 时必须大于 `0`,关闭时可不传 |
|
||
|
||
```json
|
||
{
|
||
"deviceNo": "D20260101001",
|
||
"workStatus": "1",
|
||
"durationMin": 20
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **说明**:开启时 `startTime` 由服务端按当前时间生成,格式为 `yyyy-MM-dd HH:mm:ss`。
|
||
|
||
---
|
||
|
||
## 二、排程管理
|
||
|
||
### 2.1 查询排程列表(分页)
|
||
|
||
```
|
||
GET /app/v1/schedulelist
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `pageNum` | `int` | 否 | 页码 |
|
||
| `pageSize` | `int` | 否 | 每页条数 |
|
||
| `name` | `string` | 否 | 排程名称(模糊查询) |
|
||
| `status` | `string` | 否 | 状态:`0`-关闭 `1`-开启 |
|
||
|
||
**响应**:`TableDataInfo<AppScheduleVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"total": 1,
|
||
"rows": [
|
||
{
|
||
"id": 1,
|
||
"userId": 1,
|
||
"name": "工作日早晨浇水",
|
||
"status": "1",
|
||
"details": null,
|
||
"deviceNos": null
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> **注意**:列表查询返回的 `details` 和 `deviceNos` 为 `null`,完整信息请通过 [2.3 排程详情](#23-排程详情) 获取。
|
||
|
||
---
|
||
|
||
### 2.2 新增排程
|
||
|
||
```
|
||
POST /app/v1/addschedule
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`AppScheduleBo`(JSON,AddGroup 校验)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | `string` | 否 | 排程名称 |
|
||
| `status` | `string` | 否 | 状态:`0`-关闭 `1`-开启 |
|
||
| `details` | `array` | **是** | 排程详情列表(至少一天) |
|
||
|
||
**`details` 数组元素结构(`AppScheduleDetail`)**
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `weekday` | `int` | **是** | 星期几:`1`-周一 ~ `7`-周日 |
|
||
| `timeData` | `array` | **是** | 时间段列表 |
|
||
| `zones` | `int` | 否 | 浇水区域(位掩码) |
|
||
| `triggerType` | `string` | 否 | 触发类型:`0`-排程(默认) |
|
||
| `status` | `string` | 否 | 状态:`0`-关闭(默认) |
|
||
|
||
**`timeData` 数组元素结构(`TimeSlot`)**
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `startTime` | `string` | **是** | 开始时间,格式 `HH:mm` |
|
||
| `durationMin` | `int` | 否 | 持续时长(分钟) |
|
||
|
||
```json
|
||
{
|
||
"name": "工作日早晨浇水",
|
||
"status": "1",
|
||
"details": [
|
||
{
|
||
"weekday": 1,
|
||
"timeData": [
|
||
{ "startTime": "06:30", "durationMin": 15 },
|
||
{ "startTime": "18:00", "durationMin": 20 }
|
||
],
|
||
"triggerType": "0",
|
||
"status": "1"
|
||
},
|
||
{
|
||
"weekday": 2,
|
||
"timeData": [
|
||
{ "startTime": "06:30", "durationMin": 15 }
|
||
],
|
||
"triggerType": "0",
|
||
"status": "1"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**响应**:`R<AppScheduleVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 10,
|
||
"userId": 1,
|
||
"name": "工作日早晨浇水",
|
||
"status": "1",
|
||
"details": [
|
||
{
|
||
"id": 101,
|
||
"weekday": 1,
|
||
"timeData": [
|
||
{ "startTime": "06:30", "durationMin": 15 },
|
||
{ "startTime": "18:00", "durationMin": 20 }
|
||
],
|
||
"triggerType": "0",
|
||
"status": "1"
|
||
}
|
||
],
|
||
"deviceNos": null
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2.3 排程详情
|
||
|
||
获取排程完整信息,包含排程详情列表和已绑定设备列表。
|
||
|
||
```
|
||
GET /app/v1/schedule/{id}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | `long` | **是** | 排程 ID |
|
||
|
||
**响应**:`R<AppScheduleVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 10,
|
||
"userId": 1,
|
||
"name": "工作日早晨浇水",
|
||
"status": "1",
|
||
"details": [
|
||
{
|
||
"id": 1,
|
||
"weekday": 1,
|
||
"timeData": [
|
||
{ "startTime": "06:30", "durationMin": 15 },
|
||
{ "startTime": "18:00", "durationMin": 20 }
|
||
],
|
||
"triggerType": "0",
|
||
"status": "1"
|
||
}
|
||
],
|
||
"deviceNos": [
|
||
{
|
||
"deviceNo": "D20260101001",
|
||
"userId": 1,
|
||
"deviceName": "前院浇灌器",
|
||
"status": "1",
|
||
"workStatus": "0"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
> **说明**:
|
||
> - `details` 返回该排程当前查询到的全部明细,不在控制器中额外过滤状态。
|
||
> - `deviceNos` 为已绑定设备的完整 `AppDeviceVo` 列表。
|
||
> - `timeData` 已从 JSON 字符串解析为数组。
|
||
|
||
---
|
||
|
||
### 2.4 修改排程状态
|
||
|
||
开启或关闭排程,状态变更后通过 MQTT 通知所有已绑定设备。
|
||
|
||
```
|
||
PUT /app/v1/editScheduleStatus
|
||
```
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`AppScheduleBo`(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | `long` | **是** | 排程 ID |
|
||
| `status` | `string` | **是** | 目标状态:`0`-关闭 `1`-开启 |
|
||
|
||
```json
|
||
{
|
||
"id": 10,
|
||
"status": "0"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **MQTT 通知**:
|
||
> - 关闭(`status=0`):向绑定设备下发排程取消指令。
|
||
> - 开启(`status=1`):向绑定设备重新下发完整排程信息。
|
||
|
||
---
|
||
|
||
### 2.5 修改排程
|
||
|
||
修改排程内容,更新后通过 MQTT 向所有绑定设备重新下发排程。
|
||
|
||
```
|
||
PUT /app/v1/updataschedule
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`AppScheduleBo`(JSON,EditGroup 校验)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | `long` | **是** | 排程 ID(EditGroup 校验) |
|
||
| `name` | `string` | 否 | 排程名称 |
|
||
| `status` | `string` | 否 | 状态:`0`-关闭 `1`-开启 |
|
||
| `details` | `array` | 否 | 排程详情列表(同 [2.2 新增排程](#22-新增排程)) |
|
||
|
||
```json
|
||
{
|
||
"id": 10,
|
||
"name": "周末浇水计划",
|
||
"status": "1",
|
||
"details": [
|
||
{
|
||
"id": 101,
|
||
"weekday": 6,
|
||
"timeData": [
|
||
{ "startTime": "08:00", "durationMin": 30 }
|
||
],
|
||
"triggerType": "0",
|
||
"status": "1"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Object>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 10,
|
||
"userId": 1,
|
||
"name": "周末浇水计划",
|
||
"status": "1",
|
||
"details": [ ]
|
||
}
|
||
}
|
||
```
|
||
|
||
> **说明**:`data` 为更新后的 `AppScheduleVo` 对象。修改已有排程明细时应传明细 `id`,否则服务端无法按主键更新该明细。
|
||
|
||
---
|
||
|
||
### 2.6 删除排程
|
||
|
||
删除一个或多个排程,并通知所有绑定设备解绑。
|
||
|
||
```
|
||
DELETE /app/v1/deleteschedule/{ids}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `ids` | `long` | **是** | 排程 ID,多个用逗号分隔。例:`10,11` |
|
||
|
||
**示例**
|
||
|
||
```
|
||
DELETE /app/v1/deleteschedule/10,11
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **MQTT 通知**:删除成功后,向每个排程关联的所有设备下发解绑指令。
|
||
|
||
---
|
||
|
||
## 三、排程-设备关联
|
||
|
||
### 3.1 查询排程可关联的设备
|
||
|
||
查询当前用户名下**未被其他排程关联**的设备列表。
|
||
|
||
```
|
||
GET /app/v1/scheduleDeviceList/{scheduleId}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `scheduleId` | `long` | **是** | 排程 ID |
|
||
|
||
**响应**:`R<Map<String, Object>>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"deviceList": [
|
||
{
|
||
"deviceNo": "D20260101003",
|
||
"userId": 1,
|
||
"deviceName": "阳台浇灌器",
|
||
"status": "1",
|
||
"workStatus": "0"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
> **说明**:返回的设备列表为当前用户名下未与任何排程关联的设备。已关联其他排程的设备不会出现在列表中。
|
||
|
||
---
|
||
|
||
### 3.2 绑定排程与设备
|
||
|
||
将一个或多个设备绑定到指定排程,绑定后通过 MQTT 向设备下发排程信息。
|
||
|
||
```
|
||
POST /app/v1/addScheduleDevice
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `scheduleId` | `long` | **是** | 排程 ID |
|
||
| `deviceNos` | `array` | **是** | 设备编号列表。也可用 `deviceNo`(逗号分隔字符串)或 `deviceIds` |
|
||
|
||
```json
|
||
{
|
||
"scheduleId": 10,
|
||
"deviceNos": ["D20260101001", "D20260101003"]
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **说明**:
|
||
> - `deviceNos` 支持数组或逗号分隔字符串格式。
|
||
> - 已绑定该排程的设备会自动跳过(幂等)。
|
||
> - 绑定后,服务端通过 MQTT 向设备下发排程详情。
|
||
|
||
---
|
||
|
||
### 3.3 删除排程与设备绑定
|
||
|
||
解除排程与设备的绑定关系,并通知设备取消排程。
|
||
|
||
```
|
||
DELETE /app/v1/deleteScheduleDevice
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `scheduleId` | `string` | **是** | 排程 ID |
|
||
| `deviceNo` | `string` | **是** | 设备编号 |
|
||
|
||
**示例**
|
||
|
||
```
|
||
DELETE /app/v1/deleteScheduleDevice?scheduleId=10&deviceNo=D20260101001
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **MQTT 通知**:解绑成功后,向设备下发排程解绑指令。若 MQTT 下发失败,不影响接口返回成功(仅记录日志警告)。
|
||
|
||
---
|
||
|
||
## 四、浇水记录
|
||
|
||
### 4.1 查询浇水记录列表(分页)
|
||
|
||
```
|
||
GET /app/v1/waterLogList
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `pageNum` | `int` | 否 | 页码 |
|
||
| `pageSize` | `int` | 否 | 每页条数 |
|
||
| `deviceNo` | `string` | 否 | 设备编号 |
|
||
| `commandId` | `string` | 否 | MQTT 命令 ID |
|
||
| `scheduleId` | `long` | 否 | 关联排程 ID |
|
||
| `startTime` | `date` | 否 | 开始时间(精确匹配) |
|
||
| `endTime` | `date` | 否 | 结束时间(精确匹配) |
|
||
| `durationMin` | `string` | 否 | 持续时间(精确匹配) |
|
||
| `zones` | `string` | 否 | 浇水区域 |
|
||
| `triggerType` | `string` | 否 | 触发类型:`0`-排程 `1`-手动 |
|
||
| `remark` | `string` | 否 | 备注(模糊匹配) |
|
||
| `params[beginTime]` | `date` | 否 | 创建时间范围开始;需与 `params[endTime]` 同时传入 |
|
||
| `params[endTime]` | `date` | 否 | 创建时间范围结束;需与 `params[beginTime]` 同时传入 |
|
||
|
||
**响应**:`TableDataInfo<AppWateringLogVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"total": 50,
|
||
"rows": [
|
||
{
|
||
"id": 1,
|
||
"userId": 1,
|
||
"deviceNo": "D20260101001",
|
||
"deviceName": "前院浇灌器",
|
||
"commandId": "CMD_20260714001",
|
||
"scheduleId": 10,
|
||
"startTime": "2026-07-14 06:30:00",
|
||
"endTime": "2026-07-14 06:45:00",
|
||
"durationMin": "15",
|
||
"zones": "1",
|
||
"triggerType": "0",
|
||
"remark": null,
|
||
"status": "0",
|
||
"createTime": "2026-07-14 06:30:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> **说明**:响应中 `deviceName` 由服务端关联查询后填充。
|
||
|
||
---
|
||
|
||
### 4.2 查询设备最新进行中的浇水记录
|
||
|
||
```
|
||
GET /app/v1/latestWaterLog
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `deviceNo` | `string` | **是** | 设备编号 |
|
||
|
||
**响应**:`R<Map<String, Object>>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"startTime": "2026-07-14 08:00:00",
|
||
"endTime": "2026-07-14 08:20:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
> **说明**:控制器按当前用户、设备编号和状态 `1` 发起查询,并取 ID 最大的一条记录。若无进行中的记录,`data` 为 `null`。时间格式为 `yyyy-MM-dd HH:mm:ss`。
|
||
>
|
||
> **当前实现限制**:`AppWateringLogServiceImpl.buildQueryWrapper` 尚未把 `status` 加入查询条件,因此现有代码实际可能取到该设备 ID 最大但已结束的记录。客户端依赖“进行中”语义前,应先修复该服务查询条件。
|
||
|
||
---
|
||
|
||
### 4.3 删除浇水记录
|
||
|
||
```
|
||
DELETE /app/v1/waterLog/{ids}
|
||
```
|
||
|
||
**路径参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `ids` | `long` | **是** | 记录 ID,多个用逗号分隔。例:`1,2,3` |
|
||
|
||
**示例**
|
||
|
||
```
|
||
DELETE /app/v1/waterLog/1,2,3
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **权限**:只能删除当前用户的浇水记录。
|
||
|
||
---
|
||
|
||
## 五、数据统计
|
||
|
||
### 5.1 数据统计
|
||
|
||
获取当前用户的浇水数据统计汇总。
|
||
|
||
```
|
||
GET /app/v1/dataStatistics
|
||
```
|
||
|
||
**请求参数**:无
|
||
|
||
**响应**:`R<Map<String, Object>>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"count": 120,
|
||
"monCount": 15,
|
||
"weekCount": 4,
|
||
"schedule": 80,
|
||
"manualNum": 40,
|
||
"allTime": 3600,
|
||
"averageTime": 30
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `count` | `long` | 总浇水次数 |
|
||
| `monCount` | `long` | 本月浇水次数 |
|
||
| `weekCount` | `long` | 本周浇水次数 |
|
||
| `schedule` | `long` | 排程触发浇水次数 |
|
||
| `manualNum` | `long` | 手动触发浇水次数 |
|
||
| `allTime` | `long` | 总浇水时间(分钟) |
|
||
| `averageTime` | `long` | 平均每次浇水时间(分钟) |
|
||
|
||
---
|
||
|
||
## 六、用户管理
|
||
|
||
### 6.1 获取用户信息
|
||
|
||
```
|
||
GET /app/v1/getUserInfo
|
||
```
|
||
|
||
**请求参数**:无
|
||
|
||
**响应**:`R<UserInfoVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"user": {
|
||
"userId": 1,
|
||
"deptId": 100,
|
||
"userName": "admin",
|
||
"nickName": "管理员",
|
||
"email": "admin@example.com",
|
||
"phonenumber": "138****8888",
|
||
"sex": "0",
|
||
"avatar": "https://oss.example.com/avatar/xxx.png",
|
||
"status": "0",
|
||
"loginIp": "192.168.1.1",
|
||
"loginDate": "2026-07-14 09:00:00",
|
||
"remark": null,
|
||
"createTime": "2026-01-01 00:00:00"
|
||
},
|
||
"permissions": ["*:*:*"],
|
||
"roles": ["admin"]
|
||
}
|
||
}
|
||
```
|
||
|
||
> **说明**:`phonenumber` 和 `email` 字段做了脱敏处理(需 `system:user:edit` 权限才能看到完整内容)。
|
||
|
||
---
|
||
|
||
### 6.2 修改用户信息
|
||
|
||
```
|
||
PUT /app/v1/updataUser
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`SysUserBo`(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `userId` | `long` | **是** | 用户 ID |
|
||
| `nickName` | `string` | 否 | 用户昵称(最长 30 字符) |
|
||
| `email` | `string` | 否 | 邮箱(需符合邮箱格式,最长 50 字符) |
|
||
| `phonenumber` | `string` | 否 | 手机号(需唯一) |
|
||
| `code` | `string` | 条件必填 | 修改手机号时使用的短信验证码 |
|
||
| `sex` | `string` | 否 | 性别:`0`-男 `1`-女 `2`-未知 |
|
||
| `avatar` | `string` | 否 | 头像 URL |
|
||
|
||
```json
|
||
{
|
||
"userId": 1,
|
||
"nickName": "新昵称",
|
||
"phonenumber": "13900001111",
|
||
"code": "123456",
|
||
"email": "new@example.com",
|
||
"sex": "0"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **校验**:手机号需全局唯一;请求中包含 `phonenumber` 时,服务层会校验 `code` 短信验证码。
|
||
|
||
---
|
||
|
||
### 6.3 修改登录密码
|
||
|
||
```
|
||
PUT /app/v1/updataPassword
|
||
```
|
||
|
||
> `@RepeatSubmit` — 防重复提交
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**:`SysUserVo`(JSON)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `oldPassword` | `string` | **是** | 旧密码(明文,服务端 BCrypt 校验) |
|
||
| `password` | `string` | **是** | 新密码(明文) |
|
||
|
||
```json
|
||
{
|
||
"oldPassword": "OldPass123",
|
||
"password": "NewPass456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **说明**:旧密码使用 BCrypt 校验,不匹配则返回 `user.password.not.match` 错误。
|
||
|
||
---
|
||
|
||
### 6.4 找回密码
|
||
|
||
通过手机号或邮箱找回密码(加密接口)。
|
||
|
||
```
|
||
POST /app/v1/retrievePassword
|
||
```
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**(JSON;启用接口加密时发送加密后的 JSON 字符串)
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `userName` | `string` | **是** | 用户名(手机号或邮箱) |
|
||
| `password` | `string` | **是** | 新密码 |
|
||
| `code` | `string` | 条件必填 | `userName` 为手机号时使用的短信验证码 |
|
||
|
||
```json
|
||
{
|
||
"userName": "13900001111",
|
||
"password": "NewPass456",
|
||
"code": "123456"
|
||
}
|
||
```
|
||
|
||
**响应**:`R<Void>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> **校验逻辑**:
|
||
> - 若 `userName` 为邮箱格式:校验邮箱是否已注册,未注册则报错 `user.email.not.username`。
|
||
> - 若 `userName` 为手机号格式:校验手机号是否已注册及短信验证码,未注册则报错 `user.mobile.phone.number.not.username`。
|
||
> - 当前实现仍从登录 Token 获取 `userId`,因此该接口不是匿名接口,并且控制器内未校验短信/邮箱验证码。
|
||
|
||
---
|
||
|
||
## 七、文件上传
|
||
|
||
### 7.1 上传图片
|
||
|
||
上传图片到 OSS 对象存储,仅支持图片类型。
|
||
|
||
```
|
||
POST /app/v1/uploadImage
|
||
```
|
||
|
||
**请求头**
|
||
|
||
```
|
||
Content-Type: multipart/form-data
|
||
```
|
||
|
||
**请求参数(FormData)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `file` | `file` | **是** | 图片文件(Content-Type 必须以 `image/` 开头) |
|
||
|
||
当前 Spring Multipart 配置允许单文件最大 `100MB`、单次请求最大 `100MB`;实际部署还可能受网关和 OSS 配置限制。
|
||
|
||
**响应**:`R<SysOssUploadVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"url": "https://oss.example.com/2026/07/14/xxx.png",
|
||
"fileName": "screenshot.png",
|
||
"ossId": "123456"
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `url` | `string` | 文件访问 URL |
|
||
| `fileName` | `string` | 原始文件名 |
|
||
| `ossId` | `string` | 对象存储记录 ID |
|
||
|
||
---
|
||
|
||
## 八、版本检查
|
||
|
||
### 8.1 检查APP版本更新
|
||
|
||
```
|
||
GET /app/v1/checkVersion
|
||
```
|
||
|
||
**请求参数(Query)**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `platform` | `string` | 否 | 平台类型:`android`(默认)或 `ios` |
|
||
| `currentVersion` | `string` | **是** | APP 当前版本号 |
|
||
|
||
**示例**
|
||
|
||
```
|
||
GET /app/v1/checkVersion?platform=android¤tVersion=1.0.2
|
||
```
|
||
|
||
**响应**:`R<AppVersionCheckVo>`
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"platform": "android",
|
||
"currentVersion": "1.0.2",
|
||
"latestVersion": "1.0.3",
|
||
"versionCode": 3,
|
||
"updateAvailable": true,
|
||
"forceUpdate": false,
|
||
"downloadUrl": "https://oss.example.com/app/water-1.0.3.apk",
|
||
"releaseNotes": "1. 修复设备绑定问题\n2. 优化排程功能"
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `platform` | `string` | 平台类型 |
|
||
| `currentVersion` | `string` | 客户端当前版本 |
|
||
| `latestVersion` | `string` | 服务端最新版本 |
|
||
| `versionCode` | `int` | 版本序号(用于排序) |
|
||
| `updateAvailable` | `boolean` | 是否有可更新版本 |
|
||
| `forceUpdate` | `boolean` | 是否强制更新 |
|
||
| `downloadUrl` | `string` | 安装包下载地址 |
|
||
| `releaseNotes` | `string` | 更新说明 |
|
||
|
||
> 当前版本判断采用版本字符串是否完全相等:`currentVersion` 与 `latestVersion` 不相等时,`updateAvailable=true`,未进行语义化版本大小比较。
|
||
|
||
---
|
||
|
||
## 九、内部调试接口
|
||
|
||
### 9.1 MQTT绑定命令测试
|
||
|
||
```
|
||
GET /app/v1/test
|
||
```
|
||
|
||
该接口会直接调用 `sendBindDeviceCommand("01")`,向固定设备编号 `01` 下发绑定命令,并返回生成的命令 ID。
|
||
|
||
**响应**:`R<Void>`(运行时实际将命令 ID 作为消息文本返回)
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "生成的命令ID",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
> 该路由仅用于后端联调,不属于 APP 正式业务接口。生产环境建议删除、关闭或增加管理员权限控制。
|
||
|
||
---
|
||
|
||
## 附录:数据模型
|
||
|
||
### AppDeviceVo(设备信息)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `deviceNo` | `string` | 设备编号 |
|
||
| `userId` | `long` | 用户 ID |
|
||
| `deviceName` | `string` | 设备名称 |
|
||
| `deviceInitName` | `string` | 设备初始名称 |
|
||
| `deviceImg` | `string` | 设备图片 URL |
|
||
| `qrcode` | `string` | 二维码内容 |
|
||
| `status` | `string` | 设备状态:`1`-在线 `0`-离线 `2`-到期 `3`-故障 |
|
||
| `workStatus` | `string` | 工作状态:`0`-休息 `1`-工作 `2`-初始/未配网 |
|
||
| `powerLevel` | `string` | 电量百分比 |
|
||
| `powerLevelUpdatatime` | `date` | 电量更新时间 |
|
||
| `wifiName` | `string` | WiFi 名称 |
|
||
| `wifiPassword` | `string` | WiFi 密码 |
|
||
| `deviceEm` | `string` | 设备型号 |
|
||
| `deviceSn` | `string` | 设备序列号 |
|
||
| `fwVer` | `string` | 固件版本 |
|
||
| `macAddress` | `string` | MAC 地址 |
|
||
| `nickName` | `string` | 用户昵称 |
|
||
| `expirationTime` | `date` | 到期时间 |
|
||
|
||
### AppScheduleVo(排程信息)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `long` | 排程 ID |
|
||
| `userId` | `long` | 用户 ID |
|
||
| `name` | `string` | 排程名称 |
|
||
| `status` | `string` | 状态:`0`-关闭 `1`-开启 |
|
||
| `details` | `array` | 排程详情列表;新增和详情接口会返回,列表接口通常为空 |
|
||
| `deviceNos` | `array` | 已绑定设备列表(仅详情接口返回) |
|
||
|
||
### AppScheduleDetail(排程详情)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `long` | 详情 ID |
|
||
| `weekday` | `int` | 星期几:`1`-周一 ~ `7`-周日 |
|
||
| `timeData` | `array` | 时间段列表 |
|
||
| `triggerType` | `string` | 触发类型:`0`-排程 `1`-手动 |
|
||
| `status` | `string` | 状态:`0`-关闭 `1`-开启 |
|
||
|
||
### TimeSlot(时间段)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `startTime` | `string` | 开始时间(格式 `HH:mm`) |
|
||
| `durationMin` | `int` | 持续时长(分钟) |
|
||
|
||
### AppWateringLogVo(浇水记录)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `long` | 记录 ID |
|
||
| `userId` | `long` | 用户 ID |
|
||
| `deviceNo` | `string` | 设备编号 |
|
||
| `deviceName` | `string` | 设备名称 |
|
||
| `commandId` | `string` | 命令 ID |
|
||
| `scheduleId` | `long` | 关联排程 ID |
|
||
| `startTime` | `date` | 开始时间 |
|
||
| `endTime` | `date` | 结束时间 |
|
||
| `durationMin` | `string` | 持续时间(分钟) |
|
||
| `zones` | `string` | 浇水区域 |
|
||
| `triggerType` | `string` | 触发类型:`0`-排程 `1`-手动 |
|
||
| `remark` | `string` | 备注 |
|
||
| `status` | `string` | 状态:`0`-已结束 `1`-进行中 |
|
||
| `createTime` | `date` | 创建时间 |
|
||
|
||
### 枚举值速查
|
||
|
||
| 枚举 | 值 | 说明 |
|
||
|------|------|------|
|
||
| **设备状态 `status`** | `1` | 在线 |
|
||
| | `0` | 离线 |
|
||
| | `2` | 到期 |
|
||
| | `3` | 故障 |
|
||
| **工作状态 `workStatus`** | `0` | 休息 |
|
||
| | `1` | 工作 |
|
||
| | `2` | 初始/未配网 |
|
||
| **排程状态 `status`** | `0` | 关闭 |
|
||
| | `1` | 开启 |
|
||
| **触发类型 `triggerType`** | `0` | 排程触发 |
|
||
| | `1` | 手动触发 |
|
||
| **浇水记录状态 `status`** | `0` | 已结束 |
|
||
| | `1` | 进行中 |
|
||
| **星期 `weekday`** | `1`~`7` | 周一~周日 |
|
||
| **用户性别 `sex`** | `0` | 男 |
|
||
| | `1` | 女 |
|
||
| | `2` | 未知 |
|
||
| **强制更新 `forceUpdate`** | `0` | 否 |
|
||
| | `1` | 是 |
|
||
|
||
---
|
||
|
||
> **联调提示**:
|
||
> 1. `/app/v1/**` 业务接口及明确标注“需要登录”的认证接口,请求头需携带 `Authorization: Bearer <token>`;登录、注册、忘记密码、租户列表和普通验证码接口免登录。
|
||
> 2. 当前 `api-decrypt.enabled=false` 时发送普通 JSON;启用后,标注 `@ApiEncrypt` 的接口(绑定设备状态检查、绑定设备、找回密码)需按约定加密请求体并携带 `encrypt-key`。
|
||
> 3. 标注 `@RepeatSubmit` 的接口,短时间内重复提交会被拦截,前端应在收到响应前禁用提交按钮。
|
||
> 4. 删除类接口的路径参数支持逗号分隔多个 ID。
|
||
> 5. 分页接口排序固定为 `createTime desc`,前端无需传排序参数。
|
||
> 6. 时间字段统一使用 `yyyy-MM-dd HH:mm:ss` 格式,时间段 `startTime` 使用 `HH:mm` 格式。
|