排查手册
按现象组织。先看症状,再跳到对应小节。
连接问题
连不上
按顺序检查:
关联被拒绝
这是业务失败,不是传输失败 —— TCP 连上了,但 CONNECT 被设备拒绝。
busy
库采用单在途事务策略:第二个请求直接返回 busy,不入队。
如果确实需要并发读不同设备,为每个设备各建一个 Client。
超时
线上没有 generation 字段,无法区分迟到响应。库的取舍是:超时就断开,不做"再等一会儿看看有没有迟到响应"的尝试。
这意味着超时后必须重新连接,且超时前发出的写操作可能已经在设备侧执行。
常见原因:
读取问题
返回 Result 成功但没数据
这是最容易误判的一点。外层 Result 成功只表示"请求-响应往返完成",业务结果在字段里。
DAR 速查
库里定义了某个 OI,不代表你的设备实现了它。DL/T 698.45 定义了大量对象,实际电表只实现其中一部分。
库里内置的模拟设备(示例程序)覆盖的对象也比真实电表少。写代码前先确认目标设备的点表。
读到了属性但类型不对
按精确类型访问:Data::as<T>() 在类型不符时抛 std::bad_variant_access。
常见原因:
- 索引 0(整体数组)和索引 1(单元素)类型不同
- 索引 2、3 是相别,1 是总量 —— 别把 B 相当成总量
- 谐波相别在属性号(2/3/4),不在索引
- 记录列的 OAD 与普通点位 OAD 相同,但设备可能返回聚合类型
engineering_values 报错
无倍率属性的典型例子:200D/5(最高谐波次数)、4010(计量元件数)。这些是计数值不是测量值,用原始整数即可。
resource_limit
四种可能:
记录查询给了行数据却给空表头时也返回 resource_limit —— 这是防止无法解释列含义的数据被误读,属正常保护。
数据不对
数值差一个数量级
十有八九是倍率换算搞反了。原始值是整数,工程值需要乘/除以倍率:
用 engineering_values + decimal_text 换算,不要自己乘除:
各数据类别页有完整的倍率表。
符号错了
有符号量用二进制补码。协议原码是负数时(C++ 的 uint8_t 看不到负号):
用 Int32/Int16 类型的 Value 取值,不要按 UInt* 解读。
数组长度不对
两个决定长度的参数要从设备读:
读不到这些参数时只能猜,猜错就会数组越界或长度不符。
需量结构取错字段
需量是 Array<Structure>,每个结构两个成员:数值 + DateTimeS 发生时间。
DateTimeS 没有 year/month/day 字段
它是 Value<date_time_s, std::array<std::uint8_t, 7>>:
写成 t.year 编译不过。
库里不做时区换算、不转 time_t、不校验日期合法性(记录查询的时间校验除外)。
时间对不上
串口问题
详见串口连接。
记录查询问题
排查流程
遇到问题时按这个顺序走:
- 抓包,用
dlt698_decode确认链路层通不通 - 链路层通了 → 看 APDU 的服务号和选择子对不对
- 请求正确 → 看响应里的逐项 DAR
- DAR 是 0 但值不对 → 查类型和倍率
- 类型对值还不对 → 查数组长度和索引语义
大部分问题在前三步就能定位。
该报告什么
向库或设备方反馈问题时,提供这些信息能大幅加快定位: