Appearance
7. 已知限制与坑(必读)
本章条目按严重程度排序:P0 = 会静默失败或损坏数据;P1 = 会误判成败;P2 = 约束与行为差异;P3 = 并发、安全与运维。
P0 级:会静默失败或造成数据不一致
P0-1 一批写操作「响应恒成功」
- 现象:通道重启、上传点增删改清、批量生成上传点等接口,无论设备端是否真的执行成功,响应都返回成功。
- 原因:服务端
pkg/dhandle的Handle()是空函数,这些 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/errInfo传tempFileName下载失败报告 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 接口字段全大写
- 现象:按驼峰 / 小写解析取不到值。
- 原因:该接口返回
Code、Msg、Pid、CPUPercent、MemoryPercent、CreateTime,且值全是字符串。 - 规避:单独适配该接口的字段大小写与类型。
P2-9 通道导出文件的测点表头在第 2 行
- 现象:回导时列名解析错位。
- 原因:导出模板第 1 行为空。
- 规避:解析时从第 2 行取表头,共 21 列。
P2-10 测点 ID 的「不小于 1024」未被服务端强制
- 现象:0 ~ 1023 的 ID 被放行,后续可能与自增分配冲突。
- 原因:服务端只拒绝负数。
- 规避:客户端自行保证 ID 不小于 1024;不确定时留空让设备端自增。
P2-11 上传点 ID 是外键,不是新 ID
- 现象:自造 ID 导致上传点指向不存在的测点。
- 原因:上传点的
ID是已存在的采集 / 计算测点 ID 的引用,必填且无自增语义。 - 规避:先查采集点列表拿到真实 ID,再建上传点;
sn为calc/sys时会强制fk/tv/bv,注意不要覆盖。
P2-12 filter.rt / filter.ds 非法值直接报错
- 现象:筛选条件写错导致整个查询失败。
- 原因:服务端对这两个筛选值做严格校验。
- 规避:
ds只用Good、Bad、Timeouts、First、Unknown;rt的取值口径见 5.2 的存疑说明(本轮真机验证为只读探测,未覆盖此项)
P2-13 tv 小于等于 bv 的错误文案不直观
- 现象:返回「
tv <= bv 不合法」,容易被误读为格式问题。 - 原因:这是量程上下限关系校验。
- 规避:建点前先做量程关系自检。
P2-14 服务树只含采集服务
- 现象:在服务树里找不到上传服务。
- 原因:服务树只返回采集服务节点。
- 规避:上传服务用
GET /config/upload/tree/{dc}。
P2-15 服务树通道 nodeId 无分隔符拼接
- 现象:服务名与通道名互为前缀时匹配到错误节点。
- 原因:
nodeId是「服务名 + 通道名」直接拼接。 - 规避:命名上避免互为前缀(如
MC06与MC0606);匹配时同时核对text与entityId。
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;不要传大写或加盐结果。
P3-2 不要依赖 Cookie 传 token
- 现象:浏览器 / 客户端不自动带 token 时接口报未登录。
- 原因:DASSConsole 前端本身靠 localStorage 手工加
Authorization头;Cookie 路径只在同源浏览器场景可靠。 - 规避:统一显式设置
Authorization: Bearer <token>;WebSocket 用 querytoken。
P3-3 登录是全局串行且带双重锁定
- 现象:并发登录互相阻塞;脚本重试会触发 IP 级锁定。
- 原因:登录逻辑被全局互斥锁包裹,失败计数同时按账号与 IP 累计。
- 规避:单进程内复用 token;实现「失效重登一次」而不是循环重试。
P3-4 token 24 小时有效且为文件缓存
- 现象:DASSConsole 重启后旧 token 失效。
- 原因:token 缓存为文件模式,进程重启或缓存文件丢失即失效。
- 规避:客户端必须实现 token 失效后的自动重登,并把 401 作为重登触发条件。
P3-5 删除连接不级联
- 现象:删除连接后,网关上的服务 / 通道 / 测点仍然存在并继续运行。
- 原因:连接只是控制台的记录,删除仅移除记录。
- 规避:删除连接前先决定网关侧配置的去留。
P3-6 连接密码字段会原样回显密文
- 现象:列表接口返回
password字段。 - 原因:服务端不脱敏。
- 规避:客户端自行脱敏,不要把该字段写入日志。
P3-7 连接默认凭据不要依赖
- 现象:不传账号密码时使用了内置默认值。
- 原因:服务端为兼容旧版内置了默认账号密码。
- 规避:生产环境显式传
user_name与password。
P3-8 权限模型极简,连接按创建者隔离
- 现象:同一台网关,A 建的连接 B 看不到、也删不掉。
- 原因:连接查询按创建者过滤;但服务 / 通道 / 测点数据在设备端按
deviceCode共享。 - 规避:多用户协同时统一由同一账号创建连接;不要把一个账号的连接 ID 交给其他职责的账号使用。
- 【存疑】 B 拿到 A 的
deviceCode后能否直接操作设备端配置,未在真机验证。但「连接记录按创建者隔离、设备端配置不隔离」这一口径差异是代码确证的(待真机确认) (相关常量/实现在设备端,本仓库无从确证)
P3-9 服务端无 CORS 头
- 现象:浏览器跨域调用失败。
- 原因:CORS 中间件已被注释,不返回跨域响应头。
- 规避:生产走同源反向代理;脚本客户端不受限。
P3-10 设备离线与授权容量要显式处理
- 现象:批量建点中途失败;接口返回「设备已离线,请稍后再试」「连接超时」「服务未启动」。
- 原因:网关离线与授权点数上限都不在接口层拦截。
- 规避:执行前用
GET /monitor/base/{dc}核对license_point与used_point;对上述三类错误做显式分支处理。
帮助中心