# J-00 OpenAPI 机器可读版 · 使用说明 **文件**:`6_J-00_接入接口规格_V1.8_OpenAPI.yaml`(OpenAPI 3.0.3,v1.8.0)—— **与本说明放在同一目录**,可直接用编辑器或 Swagger Editor 打开 **对应**:`6_J-00_接入接口规格_V1.8.md`(同一个契约的人读版) **编制**:周工 | 2026-11-02 > **为什么文件名这么长**:这是故意的。同一份契约有两个形态——`.md` 讲"为什么",`.yaml` 讲"长什么样"。两个文件共用 `6_J-00_接入接口规格_V1.8` 前缀,在文件夹里**永远相邻**,谁也漏不掉;仅仅一个叫 `internal-iot.yaml` 的文件,脱离上下文就没人知道它是 J-00 的机读版。 --- ## 一、这是什么 一份**机器可读的接口契约**。内容和 J-00 V1.8 一一对应,只是换了一种能被工具直接消费的写法。 **两份文件的分工,不要理解成两份契约:** | | 管什么 | 举例 | |---|---|---| | **本文件(YAML)** | **长什么样** | 路径、方法、字段类型、必填、枚举、长度上限、错误结构 | | **J-00 V1.8** | **为什么这样** | 告警状态机、四条硬边界、幂等三档算法、断档与 0x04、`tsSource` 为什么不能伪造 | 有些东西**写不进 YAML**,比如「`deviceTime` 没有就传 null,禁止用 `receivedAt` 顶替——填了等于伪造时源」。所以:**字段定义以本文件为准,业务语义的解释权仍在 J-00。** 两者不一致时,以本文件为准,同时回改 J-00,两边同版本号。 --- ## 二、里面有什么 | 项 | 数量 | 说明 | |---|---:|---| | 接口 | **6** | 在役 5 个(I-01/02/05/12/18)+ 二期预留 1 个(I-17) | | schema | 20 | Event/DeviceStatus/RawFrame/Command/CommandResult 及其批次包装 | | 公共参数 | 8 | 鉴权头 4 个 + 幂等键 4 个(每接口一个) | | 公共响应 | 4 | 400/401/429/500 | **五个在役接口:** | 编号 | 方法 | 路径 | `operationId` | |---|---|---|---| | `I-01` | POST | `/events/batch` | `ingestEvents` | | `I-02` | POST | `/device-status/batch` | `ingestDeviceStatus` | | `I-12` | POST | `/raw-frames` | `ingestRawFrames` | | `I-18` | GET | `/commands/pending` | `pullPendingCommands` | | `I-05` | POST | `/commands/result` | `reportCommandResults` | | `I-17` | POST | `/commands/{commandId}/dump` | 二期预留,**本期固定 404,不要实现** | **枚举已全部写死,且与 J-00 逐值一致:** | 枚举 | 值数 | 内容 | |---|---:|---| | `eventType` | **29** | 10 对发生/解除 + 9 个单值 | | `sourceChannel` | 4 | `OWN_GW`/`HORN_HOST`/`HORN_CELL`/`MIR_CELL` | | `result` | 5 | `ACKED`/`SENT`/`TIMEOUT`/`DEVICE_OFFLINE`/`FAILED` | | `rejectReason` | 4 | `RATE_LIMITED`/`SCHEMA_INVALID`/`UNKNOWN_CHANNEL`/`SENSOR_ID_INVALID` | | `cmdType` | 8 | `set_mode`/`set_ack_policy`/`time_sync`/`set_report_cfg`/`del_sensor`/`reboot`/`diag_dump`/`set_ota` | --- ## 三、能拿它做什么(五件事) > 下表里的 `$Y` 指本文件名。因为它带中文和版本号,直接敲命令很累,下面给了变量写法,复制即用。 | 用途 | 怎么用 | 省了什么 | |---|---|---| | **接口校验** | 用 `swagger-cli validate` 或编辑器插件跑一遍 | 字段漏写、枚举越界当场暴露,不用等联调 | | **生成服务端骨架** | `openapi-generator-cli generate -i "$Y" -g spring` | 五个 Controller 的入参出参自动生成,外包只填业务 | | **生成前端类型** | `-g typescript-fetch` 或 `typescript-axios` | 陈工不用照表格手敲 TS 类型 | | **起 Mock 服务** | `prism mock "$Y"` | 前端不用等后端就能联调 | | **生成测试用例** | `-g jmeter` 或 `schemathesis run` | 必填、枚举、边界自动出用例,比手写清单全 | **推荐的命令(外包侧):** ```bash # 文件名太长,先存成变量,后面照抄即可 Y="6_J-00_接入接口规格_V1.8_OpenAPI.yaml" # 1. 语法与规范校验 npx @redocly/cli lint "$Y" # 2. 生成 Spring Boot 服务端接口骨架 npx @openapitools/openapi-generator-cli generate \ -i "$Y" -g spring \ -o ./generated --additional-properties=interfaceOnly=true # 3. 起 Mock 服务(前端联调用) npx @stoplight/prism-cli mock "$Y" -p 4010 ``` --- ## 四、与 J-00 V1.8 的逐项核对 已用脚本比对,以下全部一致: | 项 | J-00 位置 | YAML 位置 | |---|---|---| | 五个接口的编号与路径 | §1.1 | `paths` | | `eventType` 29 值 | §1.5.1 | `schemas.EventType.enum` | | 事件对象 12 个字段与必填性 | §1.3 | `schemas.Event` | | I-02 十个字段 | §1.8 | `schemas.DeviceStatus` | | I-12 八个字段(含 `rawFrame` 定死 Base64) | §1.9.2 | `schemas.RawFrame` | | `result` 5 值 | §3.3 | `schemas.CommandResult.result` | | I-18 四个查询参数与上限 | §3.2 | `paths./commands/pending.parameters` | | 鉴权四层 + 幂等键算法 | §1.2 | `components.parameters`(每个接口的幂等键**分别写**,因为取法不同) | | 响应结构与 `unregistered` 非错误语义 | §1.7 | `schemas.IngestResponse` | **幂等键按接口分开写,这是 V1.6 的重点修正:** | 接口 | 幂等键 | 为什么不能统一 | |---|---|---| | I-01 | `{sourceChannel}-{首条 eventId}-{条数}` | 有 `eventId` | | **I-02** | `{sourceChannel}-{首条 sensorId}-{reportedAt}-{条数}` | **I-02 报文里没有 `eventId`** | | **I-12** | `{sourceChannel}-{首条 rawRef}-{条数}` | **I-12 报文里没有 `eventId`**,`rawRef` 就是 `MD5(原始帧字节)` | | I-05 | `{nodeId}-{首条 commandId}-{条数}` | 有 `commandId` | | I-18 | **不带** | GET 拉取,重复拉天然幂等,靠租约去重 | --- ## 五、已知未定项(不藏着) | 项 | 现状 | 何时定 | |---|---|---| | **错误响应里的 `code` 具体码值** | 只写了 `{code, message}` 结构,**没固定码值** | 待与业务层错误码表统一后回填。当前按 HTTP 段理解:400xx 请求非法/401xx 鉴权失败/429xx 限流 | | **I-17 的请求体** | 只写了「本期 404」 | 二期启用诊断包时再补 | | **`params` 的结构** | `additionalProperties: true`,随 `cmdType` 变 | 八种命令字的参数结构**不在本文件里**,由业务层命令模块保证;外包按 `cmdType` 做编码即可 | --- ## 六、对陈工和外包各说一句 **给陈工**:这份 YAML 可以生成 TS 类型,`openapi-generator -g typescript-fetch`。你前端**不用照 J-00 的表格手敲字段**,也不用维护第二份接口定义——生成一次即可,接口变了重生成。 **给外包(谢工)**:五个接口全在这里。各字段的 `description` 是给你的实现提示,重点是三处最容易做错的: 1. **I-02 / I-12 的幂等键不是 `eventId`**(报文里没这个字段),按对应 `components.parameters` 的说明算。 2. **I-18 是 GET,签名时 `sha256(body)` 取空串的 hash,`path` 含 query 一并算。** 3. **`rejectedDetail` 里出现的条目一律不重试**,只有整批 5xx 才重试。