Files
junhong_cmp_fiber/openspec/specs/iot-device/spec.md
huang 590614aecc 清理 OpenSpec 规范文档中的重复标题
移除 IoT 相关规范文档中的重复 "## ADDED Requirements" 标题行:
- iot-agent-commission
- iot-device
- iot-number-card
- iot-order
- iot-package

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 16:06:59 +08:00

325 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# IoT Device Management
## Purpose
Manage IoT devices and their bindings with IoT cards (SIM cards), supporting device lifecycle management, device-card binding relationships, device-level package purchases, batch allocation, and remote device operations.
This capability supports:
- Device entity definition and lifecycle management
- Device-IoT card binding relationships (1-4 cards per device)
- Device-level package purchases with shared data pool
- Batch device allocation to agents
- Remote device operations (reboot, password change, reset)
## Requirements
### Requirement: 设备实体定义
系统 SHALL 定义设备(Device)实体,用于管理用户的物联网设备(如 GPS 追踪器、智能传感器等),支持设备与 IoT 卡的绑定关系、设备批量分配和设备操作。
**核心概念**: 设备不在卡管系统中销售,主要用于:
1. 用户设备管理(用户添加自己的设备,绑定 IoT 卡)
2. 方便运营人员管理投诉和代理要求(通过设备维度批量查看绑定的所有 IoT 卡)
3. 设备操作(重启、修改账号密码、重置等)
4. 设备批量分配(运营人员在别的系统报单后发货,把设备和绑定的 IoT 卡一起分配给代理)
**实体字段**:
**基本属性**:
- `id`: 设备 ID(主键,BIGINT)
- `device_no`: 设备编号(唯一,VARCHAR(50))
- `device_name`: 设备名称(VARCHAR(255))
- `device_model`: 设备型号(VARCHAR(100))
- `device_type`: 设备类型(VARCHAR(50),如 "GPS Tracker"、"Camera"、"Sensor")
- `max_sim_slots`: 最大 IoT 卡插槽数量(INT,1-4,默认 4)
- `manufacturer`: 设备制造商(VARCHAR(255),可选)
- `batch_no`: 批次号(VARCHAR(100),用于批量导入追溯)
**所有权和状态**:
- `owner_type`: 所有者类型(VARCHAR(20),"platform"-平台库存(等待分配) | "agent"-代理商 | "user"-用户)
- `owner_id`: 所有者 ID(BIGINT,platform 时为 0,agent/user 时为对应的 ID)
- `status`: 设备状态(INT,1-未激活 2-已激活 3-已停用)
- `activated_at`: 激活时间(TIMESTAMP,可空)
**设备操作配置**(预留字段,用于后续设备操作功能):
- `device_username`: 设备登录账号(VARCHAR(100),可选)
- `device_password_encrypted`: 设备登录密码(加密存储,TEXT,可选)
- `device_api_endpoint`: 设备 API 接口地址(VARCHAR(500),可选)
**系统字段**:
- `created_at`: 创建时间(TIMESTAMP,自动填充)
- `updated_at`: 更新时间(TIMESTAMP,自动填充)
#### Scenario: 用户添加设备
- **WHEN** 用户添加自己的设备(设备编号为 "GPS-001",设备名称为 "物流车辆追踪器")
- **THEN** 系统创建设备记录,`owner_type` 为 "user",`owner_id` 为用户 ID,状态为 1(未激活)
#### Scenario: 平台导入设备到库存
- **WHEN** 平台批量导入设备数据(准备发货给代理)
- **THEN** 系统创建设备记录,`owner_type` 为 "platform",`owner_id` 为 0,状态为 1(未激活)
#### Scenario: 运营人员批量分配设备给代理
- **WHEN** 运营人员将平台库存设备(ID 为 1001)分配给代理商(用户 ID 为 123)
- **THEN** 系统将设备的 `owner_type` 变更为 "agent",`owner_id` 设置为 123,同时自动分配该设备绑定的所有 IoT 卡给代理
---
### Requirement: 设备状态流转
系统 SHALL 管理设备的状态流转,确保状态变更符合业务规则。
**状态定义**:
- **1-未激活**: 设备尚未激活使用
- **2-已激活**: 设备已被用户激活使用
- **3-已停用**: 设备已停用,不可使用
**状态流转规则**:
- 未激活(1) → 已激活(2): 用户激活设备
- 已激活(2) → 已停用(3): 用户或平台主动停用设备
- 已停用(3) → 已激活(2): 用户或平台主动恢复设备(仅在符合业务规则时)
#### Scenario: 用户激活设备
- **WHEN** 用户激活自己的设备
- **THEN** 系统将设备状态从 1(未激活) 变更为 2(已激活),`activated_at` 记录激活时间
#### Scenario: 用户停用设备
- **WHEN** 用户停用已激活的设备
- **THEN** 系统将设备状态从 2(已激活) 变更为 3(已停用),同时可选择是否停用该设备绑定的所有 IoT 卡
---
### Requirement: 设备与 IoT 卡绑定关系
系统 SHALL 管理设备与 IoT 卡的绑定关系,一个设备可以绑定 1-4 张 IoT 卡。
**绑定规则**:
- 一个设备最多绑定 4 张 IoT 卡(由 `max_sim_slots` 字段控制)
- 一个 IoT 卡同一时间只能绑定一个设备
- 绑定时记录插槽位置(slot_position: 1, 2, 3, 4)
- 绑定时记录绑定时间和绑定状态(1-已绑定 2-已解绑)
- 设备绑定 IoT 卡后,IoT 卡的 `owner_type` 变更为 "device",`owner_id` 变更为设备 ID
**中间表 device_sim_bindings**:
- `id`: 绑定记录 ID(主键,BIGINT)
- `device_id`: 设备 ID(BIGINT)
- `iot_card_id`: IoT 卡 ID(BIGINT)
- `slot_position`: 插槽位置(INT,1-4)
- `bind_status`: 绑定状态(INT,1-已绑定 2-已解绑)
- `bind_time`: 绑定时间(TIMESTAMP)
- `unbind_time`: 解绑时间(TIMESTAMP,可空)
- `created_at`: 创建时间(TIMESTAMP,自动填充)
- `updated_at`: 更新时间(TIMESTAMP,自动填充)
#### Scenario: 绑定 IoT 卡到设备
- **WHEN** 用户将 IoT 卡(ID 为 101)绑定到设备(ID 为 1001)的插槽 1
- **THEN** 系统创建绑定记录,`device_id` 为 1001,`iot_card_id` 为 101,`slot_position` 为 1,`bind_status` 为 1(已绑定),`bind_time` 为当前时间,IoT 卡的 `owner_type` 变更为 "device",`owner_id` 变更为 1001
#### Scenario: 绑定超过最大插槽数量
- **WHEN** 用户尝试将第 5 张 IoT 卡绑定到最大插槽数为 4 的设备
- **THEN** 系统拒绝绑定,返回错误信息"设备插槽已满,最多支持 4 张 IoT 卡"
#### Scenario: 绑定已被占用的 IoT 卡
- **WHEN** 用户尝试绑定已被其他设备绑定的 IoT 卡
- **THEN** 系统拒绝绑定,返回错误信息"该 IoT 卡已被其他设备绑定"
#### Scenario: 解绑 IoT 卡
- **WHEN** 用户解绑设备的 IoT 卡(绑定记录 ID 为 10)
- **THEN** 系统将绑定记录的 `bind_status` 从 1(已绑定) 变更为 2(已解绑),`unbind_time` 记录解绑时间,IoT 卡的 `owner_type``owner_id` 重置
#### Scenario: 查询设备当前绑定的 IoT 卡
- **WHEN** 用户查询设备(ID 为 1001)当前绑定的 IoT 卡
- **THEN** 系统返回 `device_id` 为 1001 且 `bind_status` 为 1(已绑定) 的所有绑定记录,包含 IoT 卡信息(ICCID、运营商、激活状态等)和插槽位置
---
### Requirement: 设备套餐购买和流量共享
系统 SHALL 支持用户为设备购买套餐,套餐自动分配到设备绑定的所有 IoT 卡,流量在设备级别共享。
**设备套餐业务规则**:
- 用户为设备购买套餐时,套餐会分配到设备绑定的**所有 IoT 卡**(1-4 张)
- 套餐的流量是**设备级别共享的**(例如 3000G/月共享,不管用哪张卡)
- 分佣**只计算一次**(不按卡数倍增)
- 订单表通过 `device_id` 字段关联设备,通过 `device_sim_bindings` 表查找绑定的所有 IoT 卡
**套餐分配示例**:
- 设备绑定 3 张 IoT 卡
- 用户购买套餐:399 元/年,每月 3000G 流量,长期佣金 100 元
- 用户支付:399 元
- 套餐分配:设备的 3 张 IoT 卡都获得该套餐
- 流量使用:3000G/月 在 3 张卡之间共享(不是每张卡 3000G,而是总共 3000G)
- 分佣:代理获得 100 元分佣(只分一次,不是 3 × 100 元)
#### Scenario: 用户为设备购买套餐
- **WHEN** 用户为设备(ID 为 1001,绑定 3 张 IoT 卡)购买套餐(套餐 ID 为 3001,399 元/年,3000G/月)
- **THEN** 系统创建套餐订单,`device_id` 为 1001,`package_id` 为 3001,订单金额为 399 元,将套餐分配到设备绑定的 3 张 IoT 卡,设置流量共享模式为设备级别
#### Scenario: 设备级流量共享
- **WHEN** 设备(ID 为 1001)的套餐流量为 3000G/月,设备绑定 3 张 IoT 卡
- **THEN** 系统设置流量共享模式,3 张 IoT 卡共享 3000G/月(不是每张卡 3000G),无论使用哪张卡,都从这个流量池扣除
#### Scenario: 设备套餐分佣
- **WHEN** 用户为设备购买套餐,订单金额为 399 元,代理的长期分佣规则为 100 元
- **THEN** 系统为代理创建一条分佣记录,分佣金额为 100 元(只分一次,不按设备绑定的卡数倍增)
---
### Requirement: 设备批量分配
系统 SHALL 支持运营人员批量分配设备给代理,设备分配时自动分配该设备绑定的所有 IoT 卡。
**分配规则**:
- 只能分配 `owner_type` 为 "platform" 的设备(平台库存)
- 分配时,设备的 `owner_type` 变更为 "agent",`owner_id` 设置为代理用户 ID
- 分配时,设备绑定的所有 IoT 卡的 `owner_type` 也变更为 "agent",`owner_id` 设置为代理用户 ID
- 分配操作记录到操作日志
#### Scenario: 运营人员批量分配设备
- **WHEN** 运营人员将 10 台设备(平台库存)分配给代理商(用户 ID 为 123)
- **THEN** 系统将这 10 台设备的 `owner_type` 变更为 "agent",`owner_id` 设置为 123,同时将这些设备绑定的所有 IoT 卡也分配给代理 123
#### Scenario: 分配已分配的设备
- **WHEN** 运营人员尝试分配 `owner_type` 为 "agent" 的设备
- **THEN** 系统拒绝分配,返回错误信息"该设备已分配给代理,不能重复分配"
---
### Requirement: 设备操作
系统 SHALL 支持对设备的远程操作(重启、修改账号密码、重置等),用于设备管理和故障排查。
**设备操作类型**:
- **重启设备**: 远程重启设备
- **修改账号密码**: 修改设备的登录账号和密码
- **重置设备**: 将设备恢复到出厂设置
- **查询设备状态**: 查询设备的在线状态、运行状态等
- **设备配置更新**: 更新设备的配置参数
**操作说明**:
- 本阶段只设计数据模型字段和接口定义,不实现设备操作的具体代码
- 后续 Service 层将调用设备厂商提供的 API 或通过 MQTT/HTTP 协议与设备通信
- 设备操作需要记录操作日志(操作类型、操作人、操作时间、操作结果)
#### Scenario: 重启设备
- **WHEN** 用户或运营人员请求重启设备(ID 为 1001)
- **THEN** 系统调用设备 API 发送重启命令,记录操作日志,返回操作结果
#### Scenario: 修改设备密码
- **WHEN** 用户或运营人员修改设备(ID 为 1001)的登录密码
- **THEN** 系统更新设备的 `device_password_encrypted` 字段(加密存储),调用设备 API 同步密码修改,记录操作日志
---
### Requirement: 设备批量导入
系统 SHALL 支持批量导入设备数据,用于平台库存管理。
**导入字段**:
- 设备编号(必填)
- 设备名称(必填)
- 设备型号(必填)
- 设备类型(必填)
- 最大插槽数(可选,默认 4)
- 设备制造商(可选)
- 批次号(必填)
**导入规则**:
- 设备编号必须唯一,重复编号将被拒绝
- 导入的设备默认 `owner_type` 为 "platform",`owner_id` 为 0,状态为 1(未激活)
- 导入成功后记录操作日志
#### Scenario: 批量导入设备成功
- **WHEN** 平台上传包含 50 条设备数据的 CSV 文件
- **THEN** 系统创建 50 条设备记录,`owner_type` 为 "platform",`owner_id` 为 0,状态为 1(未激活),返回导入成功消息
#### Scenario: 批量导入包含重复编号
- **WHEN** 平台上传的 CSV 文件中包含已存在的设备编号
- **THEN** 系统拒绝重复编号的设备,返回错误信息并列出重复编号,其他有效设备正常导入
---
### Requirement: 设备查询和筛选
系统 SHALL 支持多维度查询和筛选设备,包括状态、所有者、批次号、设备类型等。
**查询条件**:
- 设备编号(精确匹配或模糊匹配)
- 设备名称(模糊匹配)
- 设备状态(单选或多选)
- 所有者类型(platform | agent | user)
- 所有者 ID(仅当所有者类型为 agent/user 时有效)
- 批次号(精确匹配)
- 设备类型(单选或多选)
- 设备制造商(模糊匹配)
- 激活时间范围(开始时间 - 结束时间)
- 创建时间范围(开始时间 - 结束时间)
**分页**:
- 默认每页 20 条,最大每页 100 条
- 返回总记录数和总页数
#### Scenario: 查询平台库存设备
- **WHEN** 运营人员查询平台库存设备
- **THEN** 系统返回 `owner_type` 为 "platform" 的设备列表
#### Scenario: 代理查询自己的设备
- **WHEN** 代理商(用户 ID 为 123)查询自己的设备
- **THEN** 系统返回 `owner_type` 为 "agent" 且 `owner_id` 为 123 的设备列表
#### Scenario: 用户查询自己的设备
- **WHEN** 用户(用户 ID 为 2001)查询自己的设备
- **THEN** 系统返回 `owner_type` 为 "user" 且 `owner_id` 为 2001 的设备列表,包含设备绑定的所有 IoT 卡信息
#### Scenario: 运营人员通过设备查看绑定的所有 IoT 卡
- **WHEN** 运营人员需要处理投诉,查询设备(ID 为 1001)绑定的所有 IoT 卡
- **THEN** 系统返回设备信息和绑定的所有 IoT 卡详细信息(ICCID、运营商、激活状态、流量使用等),方便统一查看和管理
---
### Requirement: 设备数据校验
系统 SHALL 对设备数据进行校验,确保数据完整性和一致性。
**校验规则**:
- 设备编号(device_no):必填,长度 1-50 字符,唯一
- 设备名称(device_name):必填,长度 1-255 字符
- 设备型号(device_model):必填,长度 1-100 字符
- 设备类型(device_type):必填,长度 1-50 字符
- 最大插槽数(max_sim_slots):必填,1-4 之间的整数
- 所有者类型(owner_type):必填,枚举值 "platform" | "agent" | "user"
- 所有者 ID(owner_id):必填,≥ 0,当 owner_type 为 "platform" 时必须为 0
- 设备状态(status):必填,枚举值 1(未激活) | 2(已激活) | 3(已停用)
#### Scenario: 创建设备时插槽数超出范围
- **WHEN** 用户创建设备,最大插槽数为 5
- **THEN** 系统拒绝创建,返回错误信息"最大插槽数必须在 1-4 之间"
#### Scenario: 创建设备时设备编号重复
- **WHEN** 用户创建设备,设备编号为已存在的 "DEV-001"
- **THEN** 系统拒绝创建,返回错误信息"设备编号已存在"