Skip to content

7. 已知限制与坑(必读)

本章条目按严重程度排序:P0 = 会静默失败或损坏数据;P1 = 会误判成败;P2 = 约束与行为差异;P3 = 并发、安全与运维。

P0 级:会静默失败或造成数据不一致

P0-1 一批写操作「响应恒成功」

  • 现象:通道重启、上传点增删改清、批量生成上传点等接口,无论设备端是否真的执行成功,响应都返回成功。
  • 原因:服务端 pkg/dhandleHandle()空函数,这些 gRPC 调用的返回值被直接丢弃。
  • 规避:把响应只当「请求已受理」,必须用 《用户手册》附录「错误码」→「响应恒成功的接口」 的回查表逐个确认。批量操作后至少回查一次列表接口。

P0-2 points[].ae 传中文会被静默改成 0(读)

  • 现象:JSON 新增 / 更新测点时,ae 传「写」或「读写」,结果是「读」;不报错。
  • 原因ae 在请求结构体中声明为 string,但服务端用整数转换读取,中文转换失败静默得到 0
  • 规避:JSON 路径只传 "0""1""2";中文枚举只用于文件导入路径。

P0-3 upoint/update 传空 points 会触发服务端 panic

  • 现象:HTTP 500,接口不可用。
  • 原因:服务端先访问 points[0],之后才检查数组长度。
  • 规避:客户端必须保证 points 至少 1 个元素;批量更新时按点拆分,不要传空数组。

P0-4 建服务的成功响应是裸 {"app":[...]}

  • 现象:按统一包装去找 code 会找不到;误判为失败并重复建服务。
  • 原因:控制器自行写响应,跳过了统一包装。
  • 规避:判成功看 app[0].err.code == 200;建服务前用 POST /config/das/check 做幂等判断。

P0-5 没有服务级 / 设备级写锁

  • 现象:多个客户端并发建服务 / 通道时会互相覆盖,最终结构缺失或错乱。
  • 原因:服务端只在批量任务、WS 推送等局部使用互斥,未对配置写入加锁。
  • 规避:批量任务必须串行执行;同一网关同一时刻只允许一个写入方。

P0-6 删除操作无引用保护

  • 现象:删除服务后,引用它的上传服务配置悬空;删除应用后,使用该应用的服务异常。
  • 原因:服务端在控制器层不校验引用关系。
  • 规避:删除前自行查询引用(上传服务树、服务配置详情),或把删除动作收回人工执行。

P1 级:会误判成败

P1-1 通道重启 err.code 恒为 0

  • 现象:重启实际成功,但客户端按 code 判断认为失败。
  • 原因:同 P0-1,设备端返回值被丢弃。
  • 规避:改用 stop + start 两步;或用状态接口回查。

P1-2 通道克隆失败时 code 是 0 而不是 -1

  • 现象:把非 200 一律当失败时,克隆失败被当作成功。
  • 原因:服务端失败分支未给 code 赋值,保持零值。
  • 规避:只在 code == 200 时判成功,其余一律当失败。

P1-3 采集点新增成功时可能返回 {"app":[]}

  • 现象:明明建成功了,app 却是空数组。
  • 原因:服务端只在设备端返回错误码时才填充 app
  • 规避:成功 / 失败以回查为准;不要用 app 是否为空判成败。

P1-4 建服务存在「部分成功」风险

  • 现象:接口报错,但服务其实已经建成。
  • 原因das_type=das 且网关版本低于 5.0.0 时,服务端会自动创建默认通道 DEC;DEC 失败会导致整体报错,但服务已写入。
  • 规避:报错后仍要回查一次服务树,避免重复创建。

P1-5 HTTP 驱动服务的通道操作被整体拦截

  • 现象:通道创建 / 更新 / 删除返回 HTTP 500 与「默认通道不可操作」。
  • 原因:服务端对 HTTP 驱动的服务统一拦截通道操作。
  • 规避:确认驱动类型;HTTP 驱动服务不要尝试自行建通道。

P1-6 失败报告需要两步下载

  • 现象:导入返回 failNum 大于 0,但拿不到失败明细。
  • 原因:导入只返回 tempFileName,明细在另一个接口。
  • 规避:用 POST /config/point/export/errInfotempFileName 下载失败报告 xlsx。

P2 级:约束与行为差异

P2-1 服务名不超过 11 字节

  • 现象:服务名稍长即被设备端拒绝。
  • 原因:设备端限制,11 字节意味着最多 3 个汉字
  • 规避:生成服务编码时做字节级截断并用编码而非全名。

P2-2 一次只能建 1 个通道,且 channels 空数组会 panic

  • 现象:一次传多个通道只生效第一个;传空数组报 500。
  • 原因:服务端固定取 channels[0],且取用前无长度校验。
  • 规避:逐个创建;批量改走 batch/insert + batch/progress

P2-3 创建用 alisa,更新用 alias

  • 现象:别名设置无效且无报错。
  • 原因:两个接口字段名不一致,写错不会报错。
  • 规避:按接口分别使用正确字段名;创建后用详情接口回查别名。

P2-4 通道更新会丢弃 desc / keywords / status / log_level

  • 现象:更新这些字段后详情里没有变化。
  • 原因:服务端只把 name / alias / para 下发到设备端。
  • 规避:不要依赖这些字段;需要改日志级别请走服务级接口或界面。

P2-5 deviceCode 是行 ID,且默认值不可用

  • 现象:忘记传或凭空填 deviceCode 时报「数据不存在」。
  • 原因deviceCode 是控制台连接记录的自增主键,不是盒子码;路径参数的默认占位值在真机上不存在。
  • 规避:每次会话先查连接列表;不要缓存过期 ID。

P2-6 deviceCode 里含冒号会走 host 查询分支

  • 现象:传 host:port 形式的 deviceCode 时行为与预期不符。
  • 原因:服务端有按 host 查询的隐藏分支。
  • 规避deviceCode 只传纯数字 ID。

P2-7 通道列表的 page 是 Offset,不是页码

  • 现象:按页码翻页会跳数据。
  • 原因:服务端把 page 直接当偏移量传给设备端。
  • 规避:按 page = (页码 - 1) * limit 计算,或统一用 page=0 配合大 limit

P2-8 通道 info 接口字段全大写

  • 现象:按驼峰 / 小写解析取不到值。
  • 原因:该接口返回 CodeMsgPidCPUPercentMemoryPercentCreateTime,且值全是字符串。
  • 规避:单独适配该接口的字段大小写与类型。

P2-9 通道导出文件的测点表头在第 2 行

  • 现象:回导时列名解析错位。
  • 原因:导出模板第 1 行为空。
  • 规避:解析时从第 2 行取表头,共 21 列。

P2-10 测点 ID 的「不小于 1024」未被服务端强制

  • 现象:0 ~ 1023 的 ID 被放行,后续可能与自增分配冲突。
  • 原因:服务端只拒绝负数。
  • 规避:客户端自行保证 ID 不小于 1024;不确定时留空让设备端自增。

P2-11 上传点 ID 是外键,不是新 ID

  • 现象:自造 ID 导致上传点指向不存在的测点。
  • 原因:上传点的 ID 是已存在的采集 / 计算测点 ID 的引用,必填且无自增语义
  • 规避:先查采集点列表拿到真实 ID,再建上传点;sncalc / sys 时会强制 fk / tv / bv,注意不要覆盖。

P2-12 filter.rt / filter.ds 非法值直接报错

  • 现象:筛选条件写错导致整个查询失败。
  • 原因:服务端对这两个筛选值做严格校验。
  • 规避ds 只用 GoodBadTimeoutsFirstUnknownrt 的取值口径见 5.2 的存疑说明(本轮真机验证为只读探测,未覆盖此项)

P2-13 tv 小于等于 bv 的错误文案不直观

  • 现象:返回「tv <= bv 不合法」,容易被误读为格式问题。
  • 原因:这是量程上下限关系校验。
  • 规避:建点前先做量程关系自检。

P2-14 服务树只含采集服务

  • 现象:在服务树里找不到上传服务。
  • 原因:服务树只返回采集服务节点。
  • 规避:上传服务用 GET /config/upload/tree/{dc}

P2-15 服务树通道 nodeId 无分隔符拼接

  • 现象:服务名与通道名互为前缀时匹配到错误节点。
  • 原因nodeId 是「服务名 + 通道名」直接拼接。
  • 规避:命名上避免互为前缀(如 MC06MC0606);匹配时同时核对 textentityId

P2-16 建议用文件导入,而不是逐点 JSON

  • 现象:逐点 JSON 调用量大、字段全为字符串且校验分散,容易出错。
  • 原因:导入接口按 5000 点/批分片,并返回结构化的失败报告。
  • 规避:批量场景一律走 POST /config/point/import/{dc}

P2-17 log_level / flag 等字段语义不明

  • 现象:不知道能填什么。
  • 原因log_level 的合法枚举在设备端 proto 中;flag 在代码中从未被读取。
  • 规避log_level 参考界面上的可选值;flag 建议留空。

P3 级:并发、安全与运维

P3-1 密码必须传 md5(明文) 小写 hex

  • 现象:传明文 100% 登录失败,返回「账号或密码错误」。
  • 原因:服务端对该字段再做一次哈希运算,约定输入是 MD5。
  • 规避:登录与改密都传 md5(明文) 小写 hex;不要传大写或加盐结果。
  • 现象:浏览器 / 客户端不自动带 token 时接口报未登录。
  • 原因:DASSConsole 前端本身靠 localStorage 手工加 Authorization 头;Cookie 路径只在同源浏览器场景可靠。
  • 规避:统一显式设置 Authorization: Bearer <token>;WebSocket 用 query token

P3-3 登录是全局串行且带双重锁定

  • 现象:并发登录互相阻塞;脚本重试会触发 IP 级锁定。
  • 原因:登录逻辑被全局互斥锁包裹,失败计数同时按账号与 IP 累计。
  • 规避:单进程内复用 token;实现「失效重登一次」而不是循环重试。

P3-4 token 24 小时有效且为文件缓存

  • 现象:DASSConsole 重启后旧 token 失效。
  • 原因:token 缓存为文件模式,进程重启或缓存文件丢失即失效。
  • 规避:客户端必须实现 token 失效后的自动重登,并把 401 作为重登触发条件。

P3-5 删除连接不级联

  • 现象:删除连接后,网关上的服务 / 通道 / 测点仍然存在并继续运行。
  • 原因:连接只是控制台的记录,删除仅移除记录。
  • 规避:删除连接前先决定网关侧配置的去留。

P3-6 连接密码字段会原样回显密文

  • 现象:列表接口返回 password 字段。
  • 原因:服务端不脱敏。
  • 规避:客户端自行脱敏,不要把该字段写入日志。

P3-7 连接默认凭据不要依赖

  • 现象:不传账号密码时使用了内置默认值。
  • 原因:服务端为兼容旧版内置了默认账号密码。
  • 规避:生产环境显式传 user_namepassword

P3-8 权限模型极简,连接按创建者隔离

  • 现象:同一台网关,A 建的连接 B 看不到、也删不掉。
  • 原因:连接查询按创建者过滤;但服务 / 通道 / 测点数据在设备端按 deviceCode 共享。
  • 规避:多用户协同时统一由同一账号创建连接;不要把一个账号的连接 ID 交给其他职责的账号使用。
  • 【存疑】 B 拿到 A 的 deviceCode 后能否直接操作设备端配置,未在真机验证。但「连接记录按创建者隔离、设备端配置不隔离」这一口径差异是代码确证的(待真机确认) (相关常量/实现在设备端,本仓库无从确证)

P3-9 服务端无 CORS 头

  • 现象:浏览器跨域调用失败。
  • 原因:CORS 中间件已被注释,不返回跨域响应头。
  • 规避:生产走同源反向代理;脚本客户端不受限。

P3-10 设备离线与授权容量要显式处理

  • 现象:批量建点中途失败;接口返回「设备已离线,请稍后再试」「连接超时」「服务未启动」。
  • 原因:网关离线与授权点数上限都不在接口层拦截。
  • 规避:执行前用 GET /monitor/base/{dc} 核对 license_pointused_point;对上述三类错误做显式分支处理。