# 设备数采 · API 调试记录 > 说明:本文档基于后端代码(`yudao-module-mes` 的 `controller/admin/dv/telemetry`)静态整理,供联调、回归、排查使用。示例报文字段对齐当前数据库真实样本(截至 2026-09-09)。 ## 一、模块与数据流概述 - 所属模块:**MES 设备管理 → 设备数采**(前端 `views/mes/dv/telemetry/`)。 - 业务数据全部来自**外部数采服务**(近 5 分钟窗口),由后端拉取后落库到本地 `mes_dv_telemetry`,页面只读查询。 - 数采接口均无新增/修改/删除/导出操作,仅有 **1 个拉取** + **5 个查询** 接口,统一权限 `mes:dv-telemetry:query`。 - 落库表 `mes_dv_telemetry` 现状:**296 条 / 4 台设备**。 | 设备名称 | tbDeviceId | 记录数 | 遥测时间范围 | |----------|------------|-------|--------------| | 单轴高低压-3 | 773544054188146757 | 64 | 2026-08-28 10:59:10 | | 单轴高低压-4 | 773543983287631941 | 128 | 2026-08-28 10:59:09 ~ 2026-09-09 10:59:20 | | 单轴高低压-5-改造 | 773543911229489221 | 64 | 2026-08-28 11:00:02 | | 真空浇筑机 | 773543828480065605 | 40 | 2026-08-28 10:59:53 ~ 2026-09-09 10:59:38 | > 注:单轴高低压-3、-5-改造 数据停留在 08-28,说明近几天数采服务仅对部分设备持续产出数据,属外部数据侧现状。 ### 数据流 ``` [外部数采服务] --GET 近5分钟--> MesDvTelemetryPullJob(定时/手动) --convert+insertBatch--> mes_dv_telemetry | 页面 latest / page / check / check-summary <----┘ (只读) ``` ## 二、调试前置条件 | 项 | 值 | 说明 | |----|----|------| | 接口前缀 | `http://<服务器IP>:<端口>/admin-api` | 后端服务地址 | | 鉴权 | `Authorization: Bearer ` | 先登录获取 token | | 登录接口 | `POST /admin-api/system/auth/login` | Body `{ "username": "…", "password": "…" }`,响应 `data.accessToken` | | 权限 | `mes:dv-telemetry:query` | 当前用户需拥有该权限,否则返回 403 | | 数据表 | `mes_dv_telemetry`(库 `mom-xgdl`) | 无写库场景,仅拉取写入 | **通用请求头示例** ```http GET /admin-api/mes/dv/telemetry/latest HTTP/1.1 Host: <服务器IP>:<端口> Authorization: Bearer ``` **通用响应壳**(所有接口): ```json { "code": 0, "msg": "", "data": … } ``` `code = 0` 成功;非 0 为业务/系统错误,见 `msg`。 ### 数采服务地址配置(拉取 /pull 依赖) 配置项 `yudao.mes.telemetry`(`MesTelemetryProperties`): | 项 | 当前值(application-local.yaml) | 说明 | |----|-------------------------------|------| | `base-url` | `http://106.227.91.252:3100` | 数采服务基础地址,未配置时 /pull 报错 | | `path` | `/api/jxjs/mesTb/getDeviceDetails` | 返回近 5 分钟设备数据 | > 若切换其它运行 profile,请同步对应 yaml(local / test 等多 profile 保持一致)。 ## 三、外部数采接口约定(/pull 后端代调) 后端 `/pull` 会以 HTTP GET 调用: ``` GET {base-url}{path} (无参,返回近 5 分钟设备数据) ``` **期望响应结构:** ```json { "code": "200", "data": [ { "tbDeviceId": "773543983287631941", "deviceName": "单轴高低压-4", "paramName": "Slave1@油变_总匝数设定", "paramKeyName": "Slave1@油变_总匝数设定", "standardValue": null, "timelyValue": "500", "avgValue": "500.00", "maxValue": "500", "minValue": "500", "whetherAnomaly": false, "telemetryDataTime": "2026-09-09 10:59:20", "billNo": null, "shiftName": "早班" } ] } ``` **字段 → 表列映射:** | 外部字段 | 表列 | 类型(库) | 说明 | |----------|------|----------|------| | tbDeviceId | tb_device_id | varchar(100) | 数采设备ID,与设备台账 `tb_device_id` 对应 | | deviceName | device_name | varchar(100) | 设备名称 | | paramName | param_name | varchar(100) | 信号名称(展示名) | | paramKeyName | param_key_name | varchar(100) | 设备 KEY 名称(去重键) | | standardValue | standard_value | varchar(64) | 标准值 | | timelyValue | timely_value | varchar(64) | 信号值(实时) | | avgValue | avg_value | varchar(64) | 均值 | | maxValue | max_value | varchar(64) | 最大值 | | minValue | min_value | varchar(64) | 最小值 | | whetherAnomaly | whether_anomaly | bit(1) | 是否异常;接受 `1/0/true/false/Y/N` 字符串 | | telemetryDataTime | telemetry_data_time | datetime | 遥测时间,后端按通用日期格式解析 | | billNo | bill_no | varchar(64) | 单据号 | | shiftName | shift_name | varchar(64) | 班次 | **容错规则(/pull 侧):** - 外部 `code != "200"` → 报错「数采数据拉取失败:数采接口返回异常」。 - 外部返回 `data` 为空数组 → 正常返回 `recordCount=0, deviceCount=0`(不报错)。 - `data` 内某行不是 JSON 对象 → 该行跳过。 ## 四、接口明细 > 统一路径前缀 `/admin-api/mes/dv/telemetry`,下同;以下均需 `Authorization: Bearer`,权限均 `mes:dv-telemetry:query`。 ### 1. 拉取数采数据 `GET /pull` 无请求参数。后端调用外部数采接口并批量入库,返回本次统计。 **请求:** ```bash curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/pull" -H "Authorization: Bearer " ``` **正常响应(有数据):** ```json { "code": 0, "data": { "recordCount": 40, "deviceCount": 2, "pullTime": "2026-09-09 11:02:29" } } ``` **正常响应(近 5 分钟无数据):** ```json { "code": 0, "data": { "recordCount": 0, "deviceCount": 0, "pullTime": "2026-09-09 11:02:29" } } ``` | data 字段 | 类型 | 说明 | |----------|------|------| | recordCount | Integer | 本次入库条数 | | deviceCount | Integer | 本次涉及设备数(按 tbDeviceId 去重) | | pullTime | LocalDateTime | 拉取时间(入库批量共用) | **异常场景:** | code | 触发条件 | |------|----------| | 1_040_308_001(数采数据拉取失败:xxx) | 未配置 base-url / 外部调用异常 / 返回为空 / code≠200 | > 排查:外部服务地址是否可达(当前 base-url 为公网/内网地址,网络不通时即报错);外部 `code` 是否字符串 `"200"`。 ### 2. 历史记录分页 `GET /page` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | pageNo | Integer | 是 | 页码,从 1 开始 | | pageSize | Integer | 是 | 每页条数 | | tbDeviceId | String | 否 | 数采设备ID(精确) | | deviceName | String | 否 | 设备名称(模糊 like) | | paramName | String | 否 | 信号名称(模糊 like) | | whetherAnomaly | Boolean | 否 | true=异常 / false=正常 | | shiftName | String | 否 | 班次(精确) | | telemetryDataTime | String[] | 否 | 遥测时间区间 `[起,止]`,格式 `yyyy-MM-dd HH:mm:ss` | **请求:** ```bash curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/page?pageNo=1&pageSize=10&shiftName=%E6%97%A9%E7%8F%AD&whetherAnomaly=false" -H "Authorization: Bearer " ``` **正常响应:** ```json { "code": 0, "data": { "total": 128, "list": [ { "id": 410, "tbDeviceId": "773543983287631941", "deviceName": "单轴高低压-4", "paramName": "Slave1@六段出头一设定", "paramKeyName": "Slave1@六段出头一设定", "standardValue": null, "timelyValue": "0", "avgValue": "0", "maxValue": "0", "minValue": "0", "whetherAnomaly": false, "telemetryDataTime": "2026-09-09 10:59:20", "billNo": null, "shiftName": "早班", "pullTime": "2026-09-09 11:02:29", "createTime": "2026-09-09 11:02:29" } ] } } ``` **分页返回结构:** 顶层 `data.total`(Long)+ `data.list`(数组)——注意是 **`list`**,不是 `records`,前端按 `{ total, list }` 解析。 > 排序:`telemetry_data_time` 倒序,再按 `id` 倒序。历史表为“每次拉取全量追加”,同信号会重复多行,联调注意用时间区间过滤。 ### 3. 各设备最新遥测(实时监控)`GET /latest` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | tbDeviceId | String | 否 | 精确过滤单台设备(设备台账「数采数据」Tab 用) | | deviceName | String | 否 | 设备名称模糊过滤 | **实现要点:** 取 `mes_dv_telemetry` 最近 **5000 条**(按遥测时间倒序),内存按 `tbDeviceId + paramKeyName` 去重保留最新,返回**裸数组**。 **请求:** ```bash curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/latest" -H "Authorization: Bearer " curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/latest?tbDeviceId=773543828480065605" -H "Authorization: Bearer " ``` **正常响应(裸数组):** ```json { "code": 0, "data": [ { "id": 380, "tbDeviceId": "773543828480065605", "deviceName": "真空浇筑机", "paramName": "信号名称示例", "paramKeyName": "key@示例", "standardValue": null, "timelyValue": "0", "avgValue": "0", "maxValue": "0", "minValue": "0", "whetherAnomaly": false, "telemetryDataTime": "2026-09-09 10:59:38", "billNo": null, "shiftName": "早班", "pullTime": "2026-09-09 11:02:29", "createTime": "2026-09-09 11:02:29" } ] } ``` **边界提醒:** - 返回是数组,不是分页对象,前端需关闭分页组件解析,否则空展示。 - 无数据时返回 `[]`(code 仍为 0)。 - 去重上限 5000 条,若历史数据量巨大导致一批内某设备早于 5000 条之外,该设备可能缺项。 ### 4. 数采设备下拉 `GET /device-list` 无参数。从遥测表按 `tb_device_id + device_name` 分组去重返回。 ```bash curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/device-list" -H "Authorization: Bearer " ``` **正常响应:** ```json { "code": 0, "data": [ { "tbDeviceId": "773543911229489221", "deviceName": "单轴高低压-5-改造" }, { "tbDeviceId": "773543828480065605", "deviceName": "真空浇筑机" }, { "tbDeviceId": "773544054188146757", "deviceName": "单轴高低压-3" }, { "tbDeviceId": "773543983287631941", "deviceName": "单轴高低压-4" } ] } ``` > 该下拉仅列出**已出现在遥测表**的设备;若某台账设备从未被拉取过,不会出现在此。 ### 5. 供电参数比对校验明细 `GET /check` **当前实现与 `/latest` 完全一致**(同一 service 方法),仅前端展示口径不同(明细逐行对比 `timelyValue` 与 `standardValue`)。 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | tbDeviceId | String | 否 | 设备过滤 | | deviceName | String | 否 | 设备名称模糊过滤 | 请求/响应结构与 `/latest` 相同(返回裸数组)。 **响应字段比对含义:** | 字段 | 在比对页的用途 | |------|----------------| | timelyValue | 实时采集值 | | standardValue | 供电标准值 | | whetherAnomaly | true=偏离标准(异常) | > 注意:当前后端仅**透传**外部数据的 `standardValue` / `whetherAnomaly`,未在内部做阈值计算。若外部未上报标准值(现库中 `standard_value` 为空),比对结论主要依赖 `whetherAnomaly`。 ### 6. 供电参数比对校验统计 `GET /check-summary` 基于 `/latest`(同上去重后的每设备最新参数行)按设备聚合统计。 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | tbDeviceId | String | 否 | 指定设备;不传则汇总全部设备 | | deviceName | String | 否 | 设备名称模糊过滤 | ```bash curl "http://<服务器IP>:<端口>/admin-api/mes/dv/telemetry/check-summary?tbDeviceId=773543983287631941" -H "Authorization: Bearer " ``` **正常响应:** ```json { "code": 0, "data": [ { "tbDeviceId": "773543983287631941", "deviceName": "单轴高低压-4", "totalCount": 64, "normalCount": 64, "anomalyCount": 0, "anomalyRate": 0.0 } ] } ``` | data 字段 | 类型 | 说明 | |----------|------|------| | tbDeviceId / deviceName | String | 设备 | | totalCount | Integer | 该设备最新参数行数 | | normalCount | Integer | 正常(whetherAnomaly=false)数 | | anomalyCount | Integer | 异常(whetherAnomaly=true)数 | | anomalyRate | BigDecimal | 异常率%,保留 1 位小数(四舍五入);无参数时为 0 | **统计口径:** totalCount = 设备在“最近 5000 条去重后”的信号数;`anomalyRate = anomalyCount * 100.0 / totalCount`(异常率百分比)。当前库中 4 台设备异常率均为 0(无异常行)。 ## 五、遥测记录公共字段(page / latest / check 通用) | 字段 | 类型 | 说明 | |------|------|------| | id | Long | 编号 | | tbDeviceId | String | 数采设备ID | | deviceName | String | 设备名称 | | paramName | String | 信号名称 | | paramKeyName | String | 设备KEY名称(去重键) | | standardValue | String | 标准值(可能为空) | | timelyValue | String | 信号值(实时) | | avgValue / maxValue / minValue | String | 均值/最大/最小 | | whetherAnomaly | Boolean | true=异常,false=正常 | | telemetryDataTime | LocalDateTime | 遥测数据时间 | | billNo | String | 单据号(可能为空) | | shiftName | String | 班次(字典类文本直存) | | pullTime | LocalDateTime | 本次拉取入库时间 | | createTime | LocalDateTime | 创建时间 | ## 六、调试注意事项与排查清单 1. **鉴权/权限**:401 检查 token 是否过期;403 检查是否缺 `mes:dv-telemetry:query`。 2. **/pull 依赖外网/内网数采服务**:当前 base-url `http://106.227.91.252:3100` 非本机,网络不可达时直接报「数采数据拉取失败」。可在服务器侧 `curl http://106.227.91.252:3100/api/jxjs/mesTb/getDeviceDetails` 前置验证。 3. **5 分钟窗口**:外部接口仅保留近 5 分钟数据,超过即丢。系统默认由定时任务(`MesDvTelemetryPullJob`,建议每 5 分钟)兜底;页面手动 `/pull` 仅用于实时补拉。 4. **分页字段**:`/page` 返回 `{ total, list }`,不是 `records`;`/latest`、`/check`、`/check-summary`、`/device-list` 返回裸数组,前端不可开启分页组件解析。 5. **whetherAnomaly 布尔**:库列为 `bit(1)`,响应为 Boolean;布尔过滤传 `true/false`。 6. **去重上限**:`/latest` 系列仅取最近 5000 条做去重,数据量增长后注意设备是否缺项。 7. **standardValue 缺失**:现库中标准值全为空,`/check` 比对主要看 `whetherAnomaly`,联调时注意界面空值展示。 8. **时间过滤**:`telemetryDataTime` 传 `yyyy-MM-dd HH:mm:ss` 数组;历史表持续增长,查询建议必带时间区间。 ## 七、数据自查 SQL(调试辅助) ```sql -- 拉取落库是否成功:最近一次拉取 SELECT pull_time, COUNT(*) FROM `mom-xgdl`.`mes_dv_telemetry` GROUP BY pull_time ORDER BY pull_time DESC LIMIT 5; -- 各设备记录与异常概况 SELECT device_name, COUNT(*) total, SUM(whether_anomaly = 1) anomaly FROM `mom-xgdl`.`mes_dv_telemetry` GROUP BY device_name; -- 单设备最近信号 SELECT param_name, timely_value, whether_anomaly, telemetry_data_time FROM `mom-xgdl`.`mes_dv_telemetry` WHERE tb_device_id = '773543983287631941' ORDER BY id DESC LIMIT 20; ```