后端接口
这个文档用于协定前后端的交互接口,前后端使用 http 请求交互,下面是个简单的草稿,前后端的同学可以根据实际需要任意修改。数据传输使用 json 格式。
通用
基础 URL:
http://localhost:****/api/v1
请求头(带 Bearer 验证信息):
响应格式
成功响应
后面若给出了成功响应,都是只包含 data
数据项的内容。若没给出,则代表该接口成功响应没有 data
数据项。
错误响应
权限级别定义(暂时)
none
- 不可见visible
- 可见usable
- 可使用configurable
- 可配置monitorable
- 可监视manageable
- 可管理
账户
登录 ✅
- 接口:
POST /auth/login
- 输入参数:email、password
- 输出参数:token
- 注释:传入参数账户和密码之后获得 token,用作通行证,后续请求时需附上 token
- 请求体:
- 返回体:
注册 ✅
- 接口:
POST /auth/register
- 输入参数:email、password
- 输出参数:signal
- 注释:尝试注册之后,后端需要返回标识,指示是否注册成功;此外,如果失败,需要附带失败原因,例如账户已被注册、email 无效等
- 请求体:
更改(暂未实现)
- 接口:
PUT
- 输入参数:info_dict
- 注释:尝试更改个人信息,输入一个字典,字典的 key 对应需要修改的对象,例如呢称、邮箱、密码等,value 对应新的值
- 请求头:需要 user_token
- 请求体
刷新令牌 ✅
- 接口:
POST /auth/``re``fresh
- 输入参数:refresh_token
获取全部用户 ✅
- 接口:
GET /auth/all
- 输入参数:admin_token
- 注释:管理员调用获取全部用户信息
验证令牌有效 ✅
- 接口:
POST /auth/verify
- 输入参数 user_token
- 注释:这个 token 不是放在 Authorization 头中,而是在请求体中以 JSON 格式发送
权限
对设备
查看用户对设备的权限 ✅
- 接口:
GET /permissions/user/{user_id}
- 输入参数:admin_token、user_email(或者 user_id)
- 输出参数:list
- 注释:管理员传入自己的 token,查看某用户对于所有设备的权限。返回一个 list,list 的每个元素都是 dict,dict 的 key 包括:【类型】(用于指示某个设备是真实设备还是设备组)、【名】(设备名或者设备组名)、【权限】
- 请求头:需要 admin_token
- 返回体:
修改用户对设备的权限 ✅
- 接口:
PUT /permissions/user/{user_id}
- 输入参数:admin_token、device_id、target_permission
- 输出参数:signal
- 注释:管理员传入自己的 token,设置某用户对于指定设备的权限;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
查看用户组对设备的权限 ✅
- 接口:
GET /permissions/user-groups/{group_id}
- 输入参数:admin_token
- 输出参数:list
- 注释:管理员传入自己的 token,查看某用户组对于所有设备的权限。返回一个 list,list 的每个元素都是 dict,dict 的 key 包括【类型】(用于指示某个设备是真实设备还是设备组)、【名】(设备名或者设备组名)、【权限】
- 请求头:需要 admin_token
- 返回体:
修改用户组对设备的权限 ✅
- 接口:
PUT /permissions/user-groups/{group_id}
- 输入参数:admin_token、device_id、target_permission
- 输出参数:signal
- 注释:管理员传入自己的 token,设置某用户对于指定设备的权限;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
- 返回体:
对设备组
查看用户对设备组的权限 ✅
- 接口:
GET /permissions``/device-``group``s``/user/{user_id}
- 输入参数:admin_token、user_email(或者 user_id)
- 输出参数:list
- 注释:管理员传入自己的 token,查看某用户对于所有设备的权限。返回一个 list,list 的每个元素都是 dict,dict 的 key 包括:【类型】(用于指示某个设备是真实设备还是设备组)、【名】(设备名或者设备组名)、【权限】
- 请求头:需要 admin_token
- 返回体:
[
{
"id":6,
"type":"device_type", // 设备组都是固定值
"name":"客厅空调",
"permission":"configurable"
},
......
]
修改用户对设备组的权限 ✅
- 接口:
PUT /permissions``/device-``group``s``/user/{user_id}
- 输入参数:admin_token、device_group_id、target_permission
- 输出参数:signal
- 注释:管理员传入自己的 token,设置某用户对于指定设备的权限;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
查看用户组对设备组的权限 ✅
- 接口:
GET /permissions``/device-``group``s``/``user-``group``s``/{group_id}
- 输入参数:admin_token
- 输出参数:list
- 注释:管理员传入自己的 token,查看某用户组对于所有设备组的权限。返回一个 list,list 的每个元素都是 dict,dict 的 key 包括【类型】(用于指示某个设备是真实设备还是设备组)、【名】(设备名或者设备组名)、【权限】
- 请求头:需要 admin_token
- 返回体:
修改用户组对设备组的权限 ✅
- 接口:
PUT /permissions``/device-``group``s``/``user-``group``s``/{group_id}
- 输入参数:admin_token、device_group_id、target_permission
- 输出参数:signal
- 注释:管理员传入自己的 token,设置某用户对于指定设备的权限;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
- 返回体:
用户组
创建用户组 ✅
- 接口:
POST /user-groups
- 输入参数:admin_token、group_name
- 输出参数:signal
- 注释:由管理员调用,用于创建组,返回创建结果,并附加合适的说明
- 请求头:需要 admin_token
- 请求体:
- 返回体:
删除用户组 ✅
- 接口:
DELETE /user-groups/{group_id}
- 输入参数:admin_token
- 输出参数:signal
-
注释:
-
由管理员调用,用于删除用户组,返回执行结果,并附加合适的说明。
- 需要删除与之相关的所有用户以及与之相关的设备组才能正常执行,否则失败。
- (可选需求,未实现)不允许删除特定用户组
- 请求头:需要 admin_token
- 请求体:(空)
- 返回状态码 200
- 返回体:
修改用户组名 ✅
- 接口:
PUT /user-groups/{group_id}
- 输入参数:admin_token、new_group_name
- 输出参数:signal
- 注释:管理员调用,用于修改用户组名
- 请求头:需要 admin_token
- 请求体:
- 返回体:
加入用户到其他组 ✅
- 接口:
POST /user-groups/{group_id}/members
- 输入参数:admin_token、user_email(或者 user_id)、target_group_id
- 输出参数:signal
- 注释:管理员传入自己的 token,将用户加入到指定组;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
- 返回体:
从组中移除用户 ✅
- 接口:
DELETE /user``-``groups/{group_id}/members/{user_id}
- 输入参数:admin_token、user_email(或者 user_id)、target_group_id
- 输出参数:signal
- 注释:管理员传入自己的 token,将用户移出指定组;如果用户从 public 组中移除,删除用户;返回是否成功的标识。
- 请求头:需要 admin_token
- 返回体:
设备组
创建设备组 ✅
- 接口:
POST /device-groups
- 输入参数:admin_token、group_name
- 输出参数:signal
- 注释:由管理员调用,用于创建组,返回创建结果,并附加合适的说明
- 请求头:需要 admin_token
- 请求体:
- 返回体:
删除设备组 ✅
- 接口:
DELETE /device-groups/{``group``_id}
- 输入参数:admin_token
- 输出参数:signal
-
注释:
-
由管理员调用,用于删除设备组,返回执行结果,并附加合适的说明
- 需要移除设备组内所有设备,所有与之相关的用户权限和用户组权限后才能执行成功。否则执行失败
- (可选功能,未实现) 不允许删除特定设备组
- 请求头:需要 admin_token
- 请求体:(空)
- 返回体:
查询设备组 ✅
- 接口:
GET /device-groups
- 输入参数: admin_token
- 输出参数:
- 注释:由管理员调用,用于查询所有设备组,返回执行结果,并附加合适的说明
- 请求头:需要 admin_token
- 返回体
{
"count": 13,
"next": **null**,
"previous": **null**,
"results": [
{
"id": 1,
"name": "crazy",
"description": "crrazzy",
"devices": [],
"devices_count": 0
},
// ...
]
}
修改设备组名 ✅
-
接口:
PUT /device-groups/{group_id}
-
输入参数:admin_token、group_ip、new_group_name
-
输出参数:signal
-
注释:管理员调用,用于修改用户组名
-
请求头:需要admin_token
-
请求体:
- 返回体:
加入设备到其他组 ✅
- 接口:
POST /device-groups/{group-id}/devices
- 输入参数:admin_token、device_id、target_group_id
- 输出参数:signal
- 注释:管理员传入自己的 token,将设备加入到指定组;返回是否成功的标识。
- 请求头:需要 admin_token
- 请求体:
从组中移除设备 ✅
- 接口:
DELETE /device-groups/{group_id}/devices/{device_id}
- 输入参数:admin_token、device_id、target_group_id
- 输出参数:signal
- 注释:管理员传入自己的 token,将设备移出指定组;如果设备从 public 组中移除,删除设备;返回是否成功的标识。
- 请求头:需要 admin_token
设备
发现设备 ✅
- 接口:
GET /devices/discover
- 输入参数:admin-token
- 输出参数:list[device]
-
注释:
-
管理员尝试发现附近设备,后端服务检查周围是否有设备,返回一个 list.
- list 中的每个元素都是一个用于设备信息的 dict,dict 至少要包含【设备名】、【设备 ip】、【设备类型】、【设备标识】等信息
- 请求头:需要 admin_token
- 返回体:
"success": **true**,
"message": "通过SSDP发现 2 个设备",
"data": [
{
"device_identifier": "eb370a3c-b9dc-42bf-a0fb-61e311c6d79c",
"name": "refrigerator (eb370a3c-b9dc-42bf-a0fb-61e311c6d79c)",
"ip": "127.0.0.1",
"port": 5001,
"device_type": "refrigerator",
"status": "off",
"power": 100,
"ssdp_location": "http://0.0.0.0:5001",
"ssdp_nt": "urn:schemas-example-com:device:refrigerator:1",
"ssdp_usn": "uuid:eb370a3c-b9dc-42bf-a0fb-61e311c6d79c::urn:schemas-example-com:device:refrigerator:1",
"already_added": **false**,
"database_id": **null**
},
{
"device_identifier": "e7f4fe33-e201-47f4-943b-16b3fe97bbcf",
"name": "refrigerator (e7f4fe33-e201-47f4-943b-16b3fe97bbcf)",
"ip": "127.0.0.1",
"port": 5000,
"device_type": "refrigerator",
"status": "off",
"power": 100,
"ssdp_location": "http://0.0.0.0:5000",
"ssdp_nt": "urn:schemas-example-com:device:refrigerator:1",
"ssdp_usn": "uuid:e7f4fe33-e201-47f4-943b-16b3fe97bbcf::urn:schemas-example-com:device:refrigerator:1",
"already_added": **true**,
"database_id": 6
}
]
}
同步设备✅
- 接口:
POST /devices/sync
- 输入参数:admin-token
- 输出参数:
-
注释:
-
将发现设备返回的结果传入,可以将设备添加到数据库中
- 请求体:
{
"device_data": [
{
"device_identifier": "b067db59-7194-47a1-8a24-ebdfeb9fcb61",
"name": "refrigerator (b067db59-7194-47a1-8a24-ebdfeb9fcb61)",
"ip": "127.0.0.1",
"port": 5001,
"device_type": "refrigerator",
"status": "off",
"power": 100,
"ssdp_location": "http://127.0.0.1:5001",
"ssdp_nt": "urn:schemas-example-com:device:refrigerator:1",
"ssdp_usn": "uuid:b067db59-7194-47a1-8a24-ebdfeb9fcb61::urn:schemas-example-com:device:refrigerator:1",
"already_added": false,
"database_id": null
}
]
}
- 返回体:
{
"success": true,
"message": "成功同步 1 个设备",
"data": {
"synced_devices": [
{
"action": "created",
"device_id": 4,
"device_identifier": "b067db59-7194-47a1-8a24-ebdfeb9fcb61"
}
],
"errors": [],
"total_processed": 1,
"successful": 1,
"failed": 0
}
}
添加设备 ✅(弃用)
- 接口:
POST /devices
- 输入参数:admin-token、device
- 输出参数:signal
- 注释:管理员尝试在发现设备之后添加设备,返回是否成功的标识,如果失败,需要返回足够错误信息。这里我们做一些简单假设,新的设备可以通过 ip 和 port 标识
- 请求头:需要 admin-token
- 请求体:
- 返回体:
移除设备 ✅
- 接口:
DELETE /devices/{device_id}
- 输入参数:admin-token、device
- 输出参数:signal
- 注释:管理员尝试移除设备,返回是否成功的标识,如果失败,需要返回足够错误信息。
- 请求头:需要 admin-token
- 请求体:
- 返回体:
修改设备信息 ✅
- 接口:
PUT /devices/{device_id}
- 输入参数:admin-token、device_id、new_device_info
- 输出参数:signal
- 注释:管理员尝试修改设备信息,传入设备 id 和新的设备信息,设备信息可以包括【设备名】、【设备描述】、【设备品牌】等
- 请求头:需要 admin-token
- 请求体:
控制设备 ✅
- 接口:
POST /devices/{device_id}/control
- 输入参数:token、device_id、action、param
- 输出参数:signal
- 注释:尝试控制设备,需要上传通行证(token)、设备唯一标识(device_id)、对设备的操作(action)(例如开机、关机等)、附带的参数(比如控制空调时也许需要温度之类的参数);后端需要通过 token 检查用户是否合法,用户对于指定设备进行的操作是否具有足够权限。返回是否成功的标识,或者其他 http 状态码,另外需要附带足够的错误信息。
- 请求头:需要 user_token
- 请求体:
- 返回体:
查询设备概要 ✅
- 接口:
GET /devices/overview
- 输入参数:token
- 输出参数:list
- 注释:该方法允许普通用户和管理员用户调用,区别在于,普通用户只能看到部分设备的概要(那些用户至少拥有【可见】权限的设备)。管理员将会得到所有设备的概要。返回一个 list,list 的每个元素都是一个 dict,代表某个设备的概要,key 包括【设备名】、【设备状态】
- 请求头:需要 user_token
- 返回体:
查询设备详情 ✅
- 接口:
GET /devices/{device_id}/detail
- 输入参数:token、device_id
- 输出参数:detail_dict
- 注释:用户查询某个设备的详情,注意,只有用户对于该设备的权限达到【可监视】的级别才能得到详细信息。detail_dict 中至少要包括【设备名】、【设备状态】、【设备当前功耗】、【设备运行时间】、【设备运行日志】、【设备使用记录】,其余参数根据设备类别补充
- 请求头:需要 user_token
- 返回体:
接受设备心跳 ✅
- 接口:
POST /devices/heartbeat
- 输入参数:info
- 输出参数:signal
- 注释:接受设备发送的周期性心跳包,记录设备信息
- 请求体(参考):
{
"device_identifier": "xiaomi_ac_001",
"timestamp": "2024-01-01T00:00:00Z",
"status": "online",
"data": {
"current_power_consumption": 1200.5,
"current_temperature": 26,
"target_temperature": 24,
"error_codes": []
}
}
- 返回体:
接受设备事件(弃用)
这一接口弃用,设备事件会随着心跳发送
- 接口:
POST /devices/event
- 输入参数:info
- 输出参数:signal
- 注释:接受设备发送的事件通知
- 请求体(参考):
{
"device_identifier": "xiaomi_ac_001",
"timestamp": "2024-01-01T00:00:00Z",
"event_type": "state_change",
"event_data": {"status": "on","brightness": 100},
}
}
- 返回体: