本文金额按 2026 年 10 月汇率基准换算:1 USD ≈ 6.71 元人民币,1 EUR ≈ 7.88 元人民币。文中人民币为折算值,原始报价币种保留。
排障现场最常见的浪费不是缺工具,而是猜。
现象只有一句话:"设备掉线了。"但这句话可以对应五种完全不同的故障:网关断电了、网关在线但没收到射频帧、帧收到了但解密失败了、解密成功但解析脚本报错了、解析成功了但数据没进库也没转发。这五种原因分布在不同层,用的工具、看的页面、判断依据全都不一样。
如果没有顺序,排查就会变成把每个页面都刷一遍,然后凭感觉挑一个最像的改。改完发现没用,再换一个。一天就这么过去了。
五层漏斗的意义是把"猜"换成"排除":每一层只需要回答一个问题,答"是"就往下走,答"否"就停在这一层。走完五层,故障位置必然被锁定在某一个格子里——不需要运气。
一、先看漏斗:五层对应五个不同的问题
这张表是整篇文章的骨架。下面逐层展开,每层给三样东西:看什么、怎么判、判错了会误伤什么。
那个"判错了会误伤什么"是重点。绝大多数排障悲剧不是因为没看到现象,而是因为看到了现象、归错了因、然后把一个本来正常的配置改坏了——最典型的是为了"让数据快点上来"去动 ADR,结果把电池设备的功耗预算打穿。
二、第一层:网关在不在线
打开运维管理 → 网关管理,列表里每个网关会显示位置、类型、在线状态、启用状态、硬件版本、固件版本、LoRa 标准、总在线时间、心跳时间和更新时间。
多数人只看"在线状态"这一列。这一列恰恰是最容易骗人的。
三个时间字段必须一起读
- 心跳时间:网关最后一次上报心跳的时刻
- 总在线时间:累计在线的时长
- 更新时间:这条记录被更新的时刻
一个网关可能显示"在线",但心跳时间停在四十分钟前。心跳周期默认 60 秒,四十分钟没心跳意味着这四十分钟里它其实什么都没在干,只是平台还没来得及把它标成离线——判离线是要满足时间条件的,不是收到消息才标在线。
反过来,总在线时间很短、心跳时间却在推进,说明这个网关在反复掉线重连。这是电源或网络抖动的典型特征,而不是信号问题。
判据:心跳时间与当前时间的差,应该小于两倍心跳周期。超过这个差值还在显示在线,就不要相信这一列,直接看心跳时间。
在线有三个口径,不能互换
这是 ThinkLink 上一个必须提前搞清楚的事。平台里"在线"至少有三种来源,各自的算法和适用边界都不一样:
三条路径各自用在不同地方:页面展示、统计报表、自动化联动。混用的后果很具体——你在仪表盘上看的是 server_attrs._online,告警规则读的是 API 的 online,两个数不一致时,你会以为是数据错了,其实只是口径不同。
还有一个容易踩的坑:关闭在离线通知后,_online 会保留最后一次的值。那个残留的 0 或 1 不是当前状态的证据。看到 1 就认为设备活着,是错的。
网关离线了,先分清是"没电"还是"没网"
平台侧能做的验证有三件:
- Ping:网关列表里 ManThink 类型网关的专用操作之一,用于确认平台到网关这条链路的可达性
- 编辑 → 看 IP 地址:网关上线时会自动上报当前 IP,通过这个字段能确认它真实的网络地址,判断是不是 IP 变了、是不是跑到另一个网段去了
- 状态趋势:点开能看指定时间范围内的在线/离线状态变化曲线,用来定位掉线的具体时段。这一步的价值在于把"一直掉"和"某个时刻开始掉"区分开——后者能直接对上施工、断电、雷击、换设备这些事件
如果 Ping 不通、IP 也是旧的或空的,问题就在网关侧或者它到服务器之间的网络,不在平台。这时候再去改平台配置是白费力气。
三、第二层:网关有没有把帧交给 NS
平台侧对应的是网络数据 → NS 数据。这一层看的是原始 LoRaWAN 帧,以及接收时的频率、RSSI、SNR、数据速率。
关键在于用哪个标识去搜,这一步选错,就会得出"NS 没收到"的错误结论:
一个刚出厂的设备搜 DevEUI 搜不到东西,但搜它的 DevAddr 也搜不到——因为它根本没有 DevAddr。反过来,一台正常运行的设备用 DevEUI 去搜普通上行,同样搜不到,因为数据帧里带的是 DevAddr。这两种"搜不到"都跟故障无关,纯粹是搜错了字段。
判据:NS 有数据 → 问题在 NS 以上(第三层开始)。NS 无数据 → 问题在射频或回传,不在平台。
NS 无数据时,往下查的方向是:
- 设备到底在不在发(用串口或厂商工具看设备侧有没有发包日志)
- 频点对不对(设备的信道计划和网关的区域标准是否一致)
- 距离和遮挡(RSSI 与 SNR,但前提是至少有帧进来,没帧就没有信号可读)
- 网关的回传通不通(Semtech UDP 的 1700 端口有没有放行——这条后面单独说,它是最高频的坑)
四、第三层:NS 有没有解密成功
平台侧对应的是网络数据 → AS 数据。AS 数据是 NS 把 LoRaWAN 帧解密、解帧之后输出的结构化应用层报文:LoRaWAN 加密已经去掉,但 userdata.payload 仍然是 Base64 编码的业务负载,还没经过物模型解析。
这是排障最有信息量的一层。一条 AS 上行报文长这样:
{ "if": "loraWAN", "type": "data", "moteeui": "6353012af1090498", "version": "3.0", "gwrx": [ { "eui": "5a53012501030056", "chan": 0, "lsnr": 14.2, "rfch": 0, "rssi": -21, "time": "2025-09-24T07:07:03.807677Z", "tmst": 1152383989 } ], "moteTx": { "codr": "4/5", "datr": "SF7BW125", "freq": 470.9, "modu": "LORA" }, "userdata": { "port": 11, "class": "ClassA", "seqno": 27464, "payload": "IQcDDG4BAADaBB0C538J", "confirmed": false } }
每个字段在排障时都有明确用途:
NS 有数据、AS 为空,只有三种可能
官方的判断表非常干脆:
"档案 enable 为 false"这条特别隐蔽。它不会报错,NS 就是不响应该设备,从外面看跟密钥错了完全一样。而且它是个静默开关——档案还在,密钥也在,只是不生效。
还有一条容易忽略的:同一设备档案在同一时间只应在一个平台(云 / TKG / TKE)处于启用状态,否则会入网冲突。设备在云上还挂着一份没关的档案,现场又接进边缘服务器,两台 NS 抢同一个 DevAddr,表现是"一会儿好一会儿不好",比彻底坏掉更难查。
FPort 不只是业务分类
平台上有几个 FPort 是约定好的:
看到 209 端口的报文,别拿它当业务数据去解析——它是心跳,payload 里没有你要的测点。物模型脚本如果没按 port 分支,就会把心跳包也当业务数据解,解出一堆垃圾值。这是"字段值时不时变成一个奇怪的数"的常见来源。
五、第四层:物模型有没有解析出来
平台侧有两个入口:应用数据 → 实时数据,以及设备详情 → 遥测数据 Tab。
设备详情里的遥测数据是按物模型分组的,展示每个物模型最近一次解析后的全部字段值和时间戳,并且通过 MQTT 实时推送更新——不用手动刷新。这一点对排障很有用:如果打开页面盯着看三分钟,值和时间戳都不动,那说明解析侧停了;如果时间戳在动但某个字段是空的,那是脚本里那个字段没赋值。
AS 有数据、实时数据为空,只有两类原因
第三条"手动喂 payload"是整个排障体系里性价比最高的动作。脚本报错、返回 null、返回了结构不对的对象,绝大多数时候不用去现场、不用重启任何东西,复制一个 Base64 字符串进来就能复现。
脚本层的三个固定陷阱
写物模型脚本时有三件事会稳定地制造"解析不出来":
第一,脚本的唯一输出通道是返回值。 脚本运行在一个受限沙箱里,console.log 不可用、async 不可用,执行时间上限是 1000 毫秒。所有调试信息、所有结果,都只能通过 return 出来。指望用打印排错的人,会看到"什么都没输出",然后误判成"脚本没执行"。
第二,payload 要从 msg.userdata.payload 取,而且是 Base64。 直接把它当字符串处理,得到的是乱码而不是字节。要先用 Base64 解开再按字节读。
第三,脚本存在不等于映射完成。 脚本写好了、保存了、没报错,不代表这个字段已经进了遥测。字段有没有真正入库,只能在遥测数据 Tab 里看到值了才算数。这两件事在平台上是分开的状态,混为一谈就会在"我明明写了"和"为什么没数据"之间反复横跳。
六、第五层:数据去哪了
到这一层,AS 有报文、遥测有值,但下游还是说"没收到"。这时候问题不在采集链路,而在数据出口。
出口一:原始报文留存开关
有一条特别容易误判的现象:AS 数据页是空的,但遥测数据正常。
这不是矛盾。原始报文的留存是要单独开的——设备的 real_time_storage 开关。不开的时候,NS 收到帧、解密、走完物模型、写进遥测,全过程正常,只是这一层不给你留一份原始报文。
所以"AS 数据页看不到东西"有两种完全不同的含义:一种是信号没进来,一种是信号进来了但没留档。判断方法很简单——看遥测有没有值。有值,就是没开留存;没值,才是链路问题。
出口二:转发白名单
从 2.00.066 起,服务端属性和共享属性默认不转发,只发送勾选转发的字段。这是为防止无关字段把 MQTT 流量顶爆而设计的,但它的副作用是:你新加了一个服务端属性,页面上一看有值,MQTT 那边永远收不到——因为没勾。
同理,目标 Broker 断线不缓冲、不补发,也不提供 exactly-once。转发器不是消息队列,它是实时通道。订阅端重启的那几分钟里产生的数据,就是没有了。
出口三:订阅端自己的问题
MQTT 这一侧最常见的一句话是"我订阅了但没数据"。三个固定原因:
- **{tenant} 没替换成组织账号**。订阅主题是 /v32/{tenant}/as/up/data/# 这种形态,{tenant} 是占位符,不是字面量。照抄不替换,能连上、能订阅成功、就是收不到
- 订阅到的是已解析主题,但设备没配转发。tkl/up/telemetry/# 是解析后的,as/up/data/# 是原始的,两条主题的数据来源不同,一条有数据不代表另一条也有
- 收到后被脚本丢弃了。转发脚本返回 null 就是丢弃,这既是过滤的正路,也是最常见的隐性故障
还有一个版本相关的事实值得记住:登记订阅不等于订阅成功,只有收到 SUBACK 才算真的订上了。2.00.070 之后这个语义是明确的,但排障时很多人还是把"界面上显示已配置"当成"已经在收数据"。
分页加载带来的假空值
2.00.075 起,配置、属性、遥测是按需要分别读取的。切页签之后要先等加载成功再编辑保存,未加载的字段不能当作空值。MQTT 消息也可能只含白名单里的属性子集,接收端应该按字段合并,而不是整组覆盖。
这两条加在一起会造成一种很别扭的故障:保存的时候把一个"没加载出来"的字段写成了空,或者接收端拿一条不完整的消息覆盖了完整的状态。表现是"某个配置自己变回去了",而且很难复现。
七、现场三件套:不用登平台也能查
平台侧解决的是"哪一层坏了",现场侧解决的是"这一层为什么坏"。三样东西足够。
一、网关本地 Web 控制台
GD6 系列走的是 gwTool6 Web 控制台。几个关键入口:
- Ethernet 默认 DHCP,在同一网段直接访问网关 IP 就能进
- **Wi-Fi AP 的 SSID 是 GD6-<Gateway EUI>**,只有在没有有效 EUI 时才回退成 LGW-Config
- **出厂热点密码与 Web 密码都是 wifi!0804**,两项独立管理,首次登录后应当改掉
现场没网的时候,手机连上这个热点就能进配置页,这是最省事的一条路。要注意的是热点必须真的出现并且能连上访问,才算这条路径可用——"界面上显示已开启"不算。
Radio 页的频点、NS 页的服务器地址和端口、以及"保存并重启生效"这个确认动作,都在这里。有一个操作细节值得写下来:页底的"提交"才保存 Radio,NS 页面用的是"保存并重启生效",等服务恢复后要重新读取核对。改完不重新读取,你看到的是表单里的旧值,不是设备里的当前值。
顺便说一个 GD62 的边界:它的外部没有 REC 按键,所以任何"长按 REC 约两秒"的恢复步骤对这台机器都不成立。需要恢复出厂要走技术支持流程,恢复后 Web 默认密码回到 wifi!0804,而已写入的 Gateway EUI 会保留。
二、一个 MQTT 客户端
不管是 mosquitto_sub、MQTTX 还是自己写的脚本,订阅一次 /v32/{tenant}/as/up/data/#,你会直接看到所有设备的原始上行。这是判断"到底有没有数据在流动"最快的方式,比翻页面快得多。
看的时候关注三件事:有没有报文、报文的 moteeui 是不是你要的那台、userdata.seqno 是不是在连续推进。第三条能立刻区分"设备没发"和"设备发了但没到"。
三、一条能算账的现场流程
排障的时间成本是可以量化的。一次现场上门的综合成本(人工加差旅)在国内一线城市大约 300–800 元,海外按公开的服务报价大约 150–400 美元(约 1,000–2,700 元)。这个数字的意义不在于精确,而在于它给"远程能不能解决"定了个价:如果一个问题能靠远程把五层走一遍定位到具体某一层,那么上门就变成了"去换那个件",而不是"去现场看看什么问题"——这两者的时间差通常是半天和三天。
更贵的是误判。为了"让数据快点上来"去关掉 ADR,电池设备的功耗会在一周内被打穿;这种损失现场看不出来,三个月后才以"电池不耐用"的形式出现,而那时已经很难回溯到当初改了哪一项。
八、七条真机联调踩出来的坑
下面这七条来自实际联调记录,不是理论推演。它们共同的特征是:现象都在平台侧,根因都在平台之外。
第一条(UDP 1700)值得单独强调。它是所有排障里出现频率最高、也最容易在"我以为我配好了"这一步翻车的一条——因为本地测试时往往没有安全组,上云之后才出现。同样的逻辑在第 24 期讲 BACnet 时也出现过:Docker 手册的入站端口清单里不含 47808 和 502,安装器不建映射也不放行,表现是"平台显示服务在跑,对面就是扫不到"。端口清单永远要单独核对一遍,不要相信安装器的默认行为。
第五条(转发器订阅假死)也是同类问题:连接是通的、进程是活的、配置是对的,就是不收数据。这类故障没有报错,只能靠"重新保存一遍看会不会恢复"来验证。它提醒我们一件事——**"运行中"和"工作中"是两个状态**。
九、把五层压缩进 20 分钟
真正的排障不需要把所有页面刷一遍。按时间盒走:
0–3 分钟:确认网关。 看心跳时间和当前时间的差,看总在线时间是否在长时间稳定增长。Ping 一次。如果网关就不在线,后面四层都不用看。
3–8 分钟:确认帧进来了没有。 NS 数据页,用正确的那把钥匙搜:未入网搜 DevEUI,已入网搜 DevAddr。搜到就说明射频和回传都通,问题在上面;搜不到就直接转去查频点和端口。
8–13 分钟:确认解密。 AS 数据页用同一个标识搜。有帧无报文,就是密钥或档案 enable,只有这两种。
13–17 分钟:确认解析。 实时数据页和设备详情的遥测 Tab 一起看。时间戳在动就是活的;不动就把 AS 的 payload 复制到脚本编辑器里手动跑一遍。
17–20 分钟:确认出口。 遥测有值但下游没有,查三件事:real_time_storage、转发白名单有没有勾、订阅端主题里的 {tenant} 换没换。
二十分钟走完,故障一定落在某一条判据上。剩下的是修,不是找。
十、这套方法真正解决的是什么
工具本身不复杂:五个页面、一个 MQTT 客户端、一个网关 Web 控制台。
复杂的是顺序。同样的五个页面,按对的顺序看是排除法,按错的顺序看是抽样调查。抽样调查的结论依赖运气,而运气在故障现场从来不够用。
还有一个附带的好处:当你清楚地知道每一层用什么证明时,你也就知道了哪些现象不能作为结论。"在线"不能证明在工作,"有配置"不能证明在运行,"脚本存在"不能证明映射完成,"页面上有值"不能证明数据发出去了。这四句话每一句都对应上面某一层的一个具体陷阱。
排障能力的上限,往往不在"知道多少工具",而在"知道哪些证据不算证据"。
官方手册
- 网关管理:www.think-link.net/docs/zh/Mai…
- 设备管理:www.think-link.net/docs/zh/Mai…
- NS 数据:www.think-link.net/docs/zh/Dat…
- AS 数据:www.think-link.net/docs/zh/Dat…
- ThinkLink 协议说明:www.think-link.net/docs/zh/Pro…
本文由 AI图鉴自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。