Files
ReinLoopTest/server/features.md
T
2026-08-03 11:16:49 +08:00

138 lines
9.6 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.
# ReinLoop Server 功能与接口
## 通用约定
业务接口为 `POST /`。请求与响应均为 JSON,响应包含 `success`
标注为 Admin 的接口需要附加:
```json
{"adminToken":"<B_ADMIN_TOKEN>"}
```
`deviceId` 统一为两段格式:`<company-code>/<line-code>`
## 服务入口
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `POST` | `/` | 主业务 API |
| `POST` | `/device` | ReinLoop 设备侧 APIlicense -> deviceToken |
| `POST` | `/upload/:token` | 根据上传凭证接收 multipart 文件 |
| `GET` | `/downloads/:ticket` | 使用一次性临时下载票据获取文件 |
| `GET` | `/files/:fileID` | 旧直链下载入口(已停用,固定返回 403) |
| `GET` | `/health` | 服务存活检查 |
## 设备侧鉴权与分路由
`/device` 仅用于 ReinLoop 客户端,禁止使用 `adminToken`
调用方式:
1.`POST /device``type=deviceAuth`,字段 `licenseId``deviceId`
2. 服务端校验许可证状态(存在、未过期、未撤销、deviceId 匹配)后签发 `deviceToken`
3. ReinLoop 后续调用 `/device` 白名单接口时携带 `deviceToken`
`deviceToken` 默认有效期由 `DEVICE_TOKEN_TTL_MS` 控制(默认 15 分钟)。
离线宽限由 ReinLoop 客户端控制,当前默认 `REINLOOP_LICENSE_OFFLINE_HOURS=100`100 小时)。
## 下载安全调用链
统一链路为:业务 `POST /`(鉴权) -> 返回临时 URL -> `GET /downloads/:ticket`(一次性消费)。
安全校验点:
- `POST /`:按业务类型执行权限校验。
- `GET /downloads/:ticket`
- 票据存在且未过期(`DOWNLOAD_URL_TTL_MS`,兼容旧环境变量 `DOWNLOAD_TOKEN_TTL_MS`)。
- 票据仅可消费一次,成功下载或校验失败后均失效。
- 下载请求来源 IP 必须与签发票据的 `POST` 请求来源 IP 一致。
## 设备心跳与组织
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `deviceHeartbeat` | 无 | `deviceId` | 已登记设备每 10 秒上报。返回 `deviceId`、服务器记录的 `lastSeenAt`;未登记设备失败。 |
| `listOrganizations` | Admin | 无 | 返回 `companies`,每家公司包含 `productionLines`。产线包含 `id``companyId``name``code``deviceId``lastSeenAt``online`。最近 30 秒有心跳时 `online``true`。 |
| `createCompany` | Admin | `name``code` | 创建公司。`code` 全局唯一,只允许 2-64 位小写字母、数字、`_``-`。 |
| `createProductionLine` | Admin | `companyId``name``code` | 创建产线。产线编码在公司内唯一;服务端固定生成 `<company.code>/<line.code>`。 |
Panel 应每 10 秒调用 `listOrganizations` 刷新在线状态,不应自行推测设备状态。
## 许可证
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `createLicense` | Admin | `licenseId``companyId``productionLineId``customer``issued``expiry``features``license` | 创建已签名许可证。服务端以 RSA-PSS 公钥验签,校验签名载荷、组织关系和设备 ID。`issued`/`expiry` 使用 `YYYY-MM-DD HH:MM`,按 `Asia/Shanghai` 解析并存为 UTC。相同 ID 和内容幂等成功,不同内容冲突。 |
| `listLicenses` | Admin | 无 | 返回许可证摘要列表,不返回原始 `license`。 |
| `getLicense` | Admin | `licenseId` | 返回完整许可证详情,可包含原始 `license`。 |
| `revokeLicense` | Admin | `licenseId``reason` | 撤销许可证,保留历史、撤销时间和原因。`licenseId` 会去除首尾空白。失败时返回 `errCode``ADMIN_TOKEN_INVALID``ADMIN_TOKEN_NOT_CONFIGURED``LICENSE_ID_REQUIRED``LICENSE_NOT_FOUND`。兼容旧类型 `revoke_license``licenseRevoke``revoke`,以及旧字段 `license_id``admin_token`。每次撤销会记录不含令牌的结构化审计日志。 |
| `validateLicense` | 无 | `licenseId``deviceId` | 返回 `valid``status``licenseId`。状态为 `active``revoked``expired``not_found``device_mismatch`;不泄露客户信息和许可证原文。 |
许可证格式为 `payloadBase64|signatureBase64`。服务端只读取 `LICENSE_PUBLIC_KEY_PATH` 的公钥,绝不接收或保存 RSA 私钥。
## 文件与模型
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `uploadDataFile` | 视目录而定 | `fileName``folder` | 签发通用两步上传凭证。目录为 `*/model_config` 时必须 Admin;其他既有 ReinLoop 数据上传保持兼容。 |
| `issueModelUpload` | Admin | `deviceId``fileName`、可选 `modelName``overwrite` | `fileName` 是本地原始文件名;传入 `modelName` 时以该名称存储和识别模型,并保留 `originalFileName`。同名模型已存在时返回 `conflict: true`;仅 `overwrite: true` 可签发覆盖凭证。 |
| `listModels` | 无 | `folder` | 返回 `files` 当前模型名数组和 `fileList` 元数据数组,最多 100 条;每条同时包含 `fileName``originalFileName`。 |
| `downloadModel` | Admin | `fileID` | 返回一次性临时下载 URL`/downloads/:ticket`)。 |
| `deleteFile` | Admin | `fileID`,或 `folder``fileName` | 删除文件及元数据;同名文件不唯一时必须使用 `fileID`。 |
| `deleteModel` | Admin | 同 `deleteFile` | 模型删除的明确管理端别名。 |
上传分两步:先调用 `uploadDataFile``issueModelUpload`,再将文件作为 `multipart/form-data``file` 字段提交到响应中的 `uploadMetadata.url`。上传成功返回 HTTP `204`;响应中的 `fileID` 可用于下载和删除。
模型重命名不会修改文件格式,因此 `modelName` 与原始 `fileName` 的扩展名必须一致。未传 `modelName` 时两者相同,旧客户端行为不变。
设备侧(`/device`)模型访问约束:
- `listModels` 固定返回当前 `deviceId/model_config` 目录。
- `downloadModel` 仅允许下载当前 `deviceId/model_config` 下文件。
- 设备侧不允许模型上传与删除。
上传到 `<deviceId>/ind_data``.csv``.json` 会自动进入 Panel inbox。
## 配置发布与读取
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `publishIdentificationConfig` | Admin | `deviceId``parameters` | 校验辨识参数并为 `<deviceId>/identification_config/identification_config.csv` 签发上传凭证。 |
| `getIdentificationConfig` | 无 | `deviceId` | 返回该设备辨识 CSV 的 `fileID``url`。 |
| `publishVolumeConfig` | Admin | `parameters` | 校验容积参数并签发 `volume_config.json` 上传凭证。上传完成后更新功能参数记录。 |
| `getVolumeConfigFile` | Admin | `deviceId` | 返回指定设备已发布容积 JSON 的 `fileID``cloudPath``url`。 |
| `getFunctionConfig` | 无 | `configType: "volume"` | 返回已发布容积参数的 `parameters``version``updateTime`。 |
发布接口仅签发上传凭证;客户端完成二步上传后,读取接口才会返回新文件或参数。
## 辨识结果与 Panel 收件箱
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `registerIdentificationResult` | 无 | `deviceId``runId`、可选 `fileName` | ReinLoop 登记待审核辨识结果。 |
| `getIdentificationFeedback` | 无 | `deviceId``runId` | 未就绪时 `ready: false`;就绪时返回 `ready: true``result``0``1`)。 |
| `setIdentificationFeedback` | Admin | `deviceId`、可选 `runId``result` | Panel 提交辨识审核结果,`result` 必须为数字 `0``1`。 |
| `ackIdentificationFeedback` | 无 | `deviceId``runId` | ReinLoop 消费后清理反馈。 |
| `getPendingPanelFile` | Admin | `deviceId` | 获取指定设备下一条待处理 CSV/JSON;无数据时 `pending: false`,有数据时返回文件信息和 `url`。 |
| `ackPanelFile` | Admin | `deviceId``fileID` | Panel 处理完成后确认,移除 inbox 项并标记历史记录为 `processed`,不立即删除文件。 |
| `listIdentificationFiles` | Admin | `deviceId`、可选 `mediaType``status``page``pageSize` | 分页返回设备的辨识 CSV/JSON 暂存历史。 |
| `getIdentificationFileDownload` | Admin | `fileID` | 返回原始辨识文件的一次性临时下载 URL。 |
| `deleteIdentificationFile` | Admin | `fileID` | 显式删除辨识文件、历史记录及待处理消息。 |
CSV 辨识文件须先以同名 `runId` 调用 `registerIdentificationResult`,才会出现在 `getPendingPanelFile`;初始行程 JSON 可直接获取。
已处理文件默认保留 30 天,从 `processedAt` 开始计算;待处理文件不会被 TTL 清理。
保留时长和清理周期分别由 `IDENTIFICATION_RETENTION_MS``IDENTIFICATION_PURGE_INTERVAL_MS` 配置。
## 容积配置请求
| type | 鉴权 | 请求字段 | 功能与响应要点 |
| --- | --- | --- | --- |
| `createVolumeConfigRequest` | 无 | `deviceId` | ReinLoop 创建一次性上传请求,返回 `requestId``createdAtMs``expiresAtMs`。同设备旧请求会被替换。 |
| `getPendingVolumeConfigRequest` | 无 | `deviceId` | 查询是否存在待上传请求,返回 `pending` 和请求时间信息。 |
| `submitVolumeConfigFile` | 无 | `deviceId``requestId``fileID`、可选 `fileName` | 将已上传到 `<deviceId>/volume_config_requests/<requestId>/` 的文件绑定至请求。 |
| `getVolumeConfigRequest` | 无 | `deviceId``requestId` | 轮询配置是否就绪,返回 `ready``expired`;就绪时包含一次性临时下载 `url`。 |
| `ackVolumeConfigRequest` | 无 | `deviceId``requestId` | ReinLoop 下载完成后确认,清理请求及关联文件。 |
请求有效期由 `VOLUME_REQUEST_TTL_MS` 控制,默认 300000 毫秒(5 分钟)。