想象你是城市物业集团的总工程师,手底下管着上百万套出租公寓。楼是住满人的,你不可能为了翻新把整栋楼清空,更不可能拆了重建;可楼里的电路、水管确实老化了,必须升级换代。有经验的老师傅会给你三条锦囊:能局部修补就绝不整体翻新——哪里开裂补哪里,省料又省工;装修时永远保留一套能用的电梯和配电,出问题一键切回;给新租户发门禁钥匙时,要么管家亲自上楼面对面递钥匙,要么在楼下用喇叭喊一段只有门禁听得懂的暗号。 这三条锦囊,恰好对应 IoT 平台管理联网设备的三件大事。每一台智能灯、扫地机器人、联网门锁,都是楼里的一位租户,它们散落在用户家中,工厂无法收回换新,只能靠空中升级(行业内常叫 OTA,Over-The-Air)让设备在用户眼皮底下完成蜕变。而配网,则是让刚出厂的“空房间”第一次拿到 Wi-Fi 钥匙、接入物业网络。本文就用“翻新公寓楼”这条主线,串起 OTA 升级链路、差分包制作、A/B 分区升级、BLE 与 SmartConfig 配网,以及百万级设备下的灰度与回滚预案。

岗位关联

OTA 与配网是 IoT 平台的“最后一公里”。掌握差分包、A/B 分区与两种配网协议的设计取舍,能让你设计的平台在百万设备规模下依然升级不翻车、配网一次成功——这是 IoT 架构师面试与大规模交付中绕不开的硬功夫。

目录
  1. 可视化演示
  2. OTA升级总览
  3. 差分包制作
  4. A/B分区升级
  5. BLE配网
  6. SmartConfig配网
  7. 海量设备保障
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示OTA固件A/B分区升级流程、BLE与SmartConfig设备配网对比及百万级设备灰度推送管理,交互切换理解IoT设备管理核心技术。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+modeData.ota.caption+'

OTA升级总览

翻新大楼的第一步,是开一场总包工头会议。物业经理(云平台)制定施工计划,施工队(设备端代理)接到图纸,租户(用户 App)签字确认时间。计划定下来,后面每一步都得按图施工、记录在案,任何一步掉了链子,都要有人负责重来。

这套思路搬到 IoT 平台上,就是 OTA 升级链路。OTA 全称 Over-The-Air(空中升级),指设备不经过数据线或返厂,直接通过网络从云端获取新固件并完成更新。一次完整的 OTA 通常拆成四个阶段:任务下发、固件下载、设备写入、重启切换。任务下发阶段,平台按批次向设备推送升级指令,设备确认自身电量、版本、网络状态后应答;固件下载阶段,设备通过 HTTP 或 MQTT 拉取固件包,支持断点续传;设备写入阶段,固件被写入 Flash 存储的指定分区;重启切换阶段,引导程序(bootloader)把启动目标指向新分区。四个环节环环相扣,任何一环失败,整次升级都可视为失败,需要重试或回滚。

回到楼里:物业最清楚,施工计划再漂亮,运输队迟到一次、电工接错一根线,租户体验就崩了。所以 OTA 平台要把每个环节都埋上报点,像施工台账一样盯着,任何一环出问题立刻介入——这就是升级链路设计的第一原则:全程可观测、失败可重试。

Stotal=S下发×S下载×S写入×S切换\displaystyle S_{\text{total}} = S_{\text{下发}} \times S_{\text{下载}} \times S_{\text{写入}} \times S_{\text{切换}}
总升级成功率等于四个环节成功率的乘积,任一环节失败都会让整体失败,所以每个环节都要配备重试机制。
  1. 总成功率Stotal\displaystyle S_{\text{total}} 表示一次升级任务从云端下发到设备切换成功的整体概率。
  2. 四环连乘S下发×S下载×S写入×S切换\displaystyle S_{\text{下发}} \times S_{\text{下载}} \times S_{\text{写入}} \times S_{\text{切换}} 把四个环节各自成功率相乘,得到总成功率。
  3. 短板效应Stotal≤min⁡{S下发,S下载,S写入,S切换}\displaystyle S_{\text{total}} \le \min\{S_{\text{下发}}, S_{\text{下载}}, S_{\text{写入}}, S_{\text{切换}}\} 总成功率被最差的环节限制,所以要给每个环节加超时重试。

差分包制作

老楼外立面旧了,但主体结构还好。老师傅的做法是只调一小桶“同色修补漆”,哪里有裂缝抹哪里,而不是把整栋楼外立面敲掉重做。修补漆用量小、干得快、运输也便宜,这就是装修界的“增量思维”。

差分包就是固件界的修补漆。完整包(full package)包含整个新固件,可能好几 MB;差分包(delta package)只记录新旧固件之间的差异,常常只有几十到几百 KB。设备收到差分包后,用自己手里的旧固件做“底漆”,把差异部分补上去,重建出完整的新固件。生成差分包的经典工具是 bsdiff,它的核心思路分三步:用滑动窗口在旧固件中查找新固件各个片段的最长匹配;把匹配片段记录为“从旧文件第 X 字节拷贝 Y 字节”的指令;把无法匹配的差异数据连同指令一起压缩。设备端用 bspatch 反向执行这些指令,并计算哈希与云端校验值比对。

装修里有个铁律:修补漆不是万能的。如果墙体结构本身烂了,或者旧漆牌号对不上,再省料也得重刷整面墙。工程上同理——差分包依赖设备当前的固件版本,如果版本未知或差分失败,平台必须准备完整包兜底。省流量,但永远留一条退路。

η=Sfull−SdeltaSfull×100%\displaystyle \eta = \frac{S_{\text{full}} - S_{\text{delta}}}{S_{\text{full}}} \times 100\%
Snew=Apply(Sold,P)\displaystyle S_{\text{new}} = \text{Apply}\left(S_{\text{old}}, P\right)
第一条公式衡量差分省了多少流量;第二条公式说明还原方式:旧固件加补丁等于新固件。
  1. 完整包与差分包Sfull\displaystyle S_{\text{full}} 是整包体积,Sdelta\displaystyle S_{\text{delta}} 是差分包体积,前者通常是后者的 5~20 倍。
  2. 节省率η\displaystyle \eta 表示差分省下的流量比例,η 越大说明差分越有效。
  3. 还原函数Apply(Sold,P)\displaystyle \text{Apply}\left(S_{\text{old}}, P\right) 表示设备用旧固件加补丁 PP 重建新固件,PP 里记录的是匹配位置、长度和差异字节。

A/B分区升级

装修最怕什么?施工到一半断电、墙拆了装不回去,租户被晾在毛坯房里。所以正规物业翻新,永远保留一部可用的电梯:先修 B 梯,A 梯照常载客;B 梯验收合格,再把客流切过去,A 梯转为备用。

A/B 分区(又称双槽位 Double Slot)升级正是这个思路的硬件实现。设备 Flash 中划分两个槽位 Slot A 和 Slot B,各自存放一份完整固件。平时系统从当前槽位启动,升级时把新固件写进另一个空闲槽位,写入完成后并不立刻使用,而是等重启时由 bootloader 决定切换。切换是一次“验收”:bootloader 查看新槽位的启动标志与校验值,决定本次启动哪个槽位;新固件启动成功后,设备向云端上报版本号和心跳,平台确认后才把该槽位标记为“已验证”;若启动失败、设备反复重启或上报超时,bootloader 在重启计数超限后自动回滚到旧槽位。

电梯维修的代价是两部电梯占双倍井道空间;A/B 分区的代价是 Flash 减半。但换来的是“绝不砖头化”:任何时刻至少有一个可用槽位。对无法返厂的 IoT 设备来说,这笔“存储换安全”的买卖非常划算——毕竟用户的扫地机变砖一次,比多花一块 Flash 芯片贵多了。

Slotboot={A,verify(B)=0B,verify(B)=1\displaystyle \text{Slot}_{\text{boot}} = \begin{cases} A, & \text{verify}(B) = 0 \\ B, & \text{verify}(B) = 1 \end{cases}
启动槽位的选择完全由新分区校验结果决定:不通过就回 A,通过就切 B。
  1. 校验函数verify(B)∈{0,1}\displaystyle \text{verify}(B) \in \{0, 1\} 表示对新槽位 B 的完整性和启动结果校验,0 为不通过、1 为通过。
  2. 失败回退Slotboot=A\displaystyle \text{Slot}_{\text{boot}} = A 校验不通过时,引导程序仍从旧槽位启动,设备不受影响。
  3. 成功切换Slotboot=B\displaystyle \text{Slot}_{\text{boot}} = B 校验通过后才切到新槽位,且旧槽位保留作下次升级的回滚副本。

BLE配网

新租户搬进来,物业要发一把门禁钥匙。最稳妥的方式是管家亲自上楼,敲门、核对身份、面对面把钥匙递进屋里——距离近、认人准、不怕被走廊里的摄像头拍走。

BLE 配网就是 IoT 世界的“管家递钥匙”。设备出厂时没有 Wi-Fi 连接信息,配网的第一步是建立一条近场通信信道。BLE(蓝牙低功耗)模块成本低、功耗小,手机打开蓝牙即可发现设备,建立连接后,通过 GATT(通用属性协议)的自定义 Service 和 Characteristic,把 Wi-Fi 的 SSID 与密码写进设备。BLE 配网的工程要点有三个:一是安全,BLE 配对可协商出会话密钥,对写入的 Wi-Fi 凭据做 AES 加密,防止密码在空气中裸奔;二是流程,App 发现设备→连接→校验临时 PIN→下发网络凭据→设备连接路由器→回连确认,每一步都有超时和重试;三是动态密码,设备连上 Wi-Fi 后立即销毁临时 BLE 凭据与网络密码,防止后续被未授权访问。

管家递完钥匙不会赖在门口——他转身就走,下次再有人敲门,门禁只认新钥匙。BLE 配网同此理:近场信道只做“第一次信任”的搬运工,配网完成后立即断开并清空凭据。把最敏感的信息交给最可靠的信道,这就是近场配网的设计哲学。

C=EncKsession(SSID∥Passphrase)\displaystyle C = \text{Enc}_{K_{\text{session}}}\left(\text{SSID} \parallel \text{Passphrase}\right)
Wi-Fi 名称与密码拼接后,用 BLE 配对协商出的会话密钥加密,再通过 GATT 通道写入设备。
  1. 会话密钥Ksession\displaystyle K_{\text{session}} 是 BLE 配对时协商出的临时密钥,每次会话都不同。
  2. 凭据拼接SSID∥Passphrase\displaystyle \text{SSID} \parallel \text{Passphrase} 表示把 Wi-Fi 名称和密码拼成一串明文。
  3. 加密传输Enc\displaystyle \text{Enc} 表示用会话密钥加密,监听者即使截获报文也无法读出明文凭据。

SmartConfig配网

但有些老楼连对讲机都没装,管家没法上楼递钥匙。物业灵机一动:让保安在楼下拿高音喇叭,把门禁密码编成一段暗号喊出去——“门牌号是奇数念 1、偶数念 0”。新租户趴在窗边听,把整串数字记下来拼成密码。这就是无线世界的广播配网。

SmartConfig(典型代表是乐鑫的 ESP-Touch)就是这套“喇叭暗号”。它不需要设备预先连接任何网络,甚至不需要 BLE 模块:手机 App 把 Wi-Fi 密码编码进一串 UDP 报文的长度和数据中,以广播形式发到空中;设备此时开启混杂监听模式(sniffer),在 Wi-Fi 信道里抓取所有空气里的报文,按约定规则解码出密码,再主动去连接路由器。以包长奇偶编码为例:App 把密码拆成一个个 bit,约定“包长为偶数代表 0、奇数代表 1”,连续发出多个 UDP 包;设备抓包后统计每个 UDP 包的长度,还原出 bit 流,8 个 bit 拼成一个字节,最终得到密码文本。为对抗丢包和干扰,SmartConfig 通常会连续多轮重发,并在多个 Wi-Fi 信道上扫描,提升解码成功率。

喇叭暗号的缺点是明显的:楼下路过的行人也能听见暗号。SmartConfig 同样如此——它对抗的是“没带钥匙”的尴尬,却防不住同信道上的有心人。所以工程上,SmartConfig 常配合动态密钥或作为低端设备的兜底方案;对安全要求高的门锁、摄像头,仍然首选 BLE 这类近场加密信道。

bi=len(Pi) mod 2,Bytek=∑j=07b8k+j×2 7−j\displaystyle b_{i} = \text{len}\left(P_{i}\right) \bmod 2, \qquad \text{Byte}_{k} = \sum_{j=0}^{7} b_{8k+j} \times 2^{\,7-j}
密码的每个 bit 藏在 UDP 包长的奇偶性里,设备抓包解析包长序列,每 8 个 bit 还原出一个字符。
  1. 包长奇偶映射len(Pi)\displaystyle \text{len}\left(P_{i}\right) 是第 i 个 UDP 包的长度,偶数为 0、奇数为 1,密码的每个 bit 就此藏在包长中。
  2. 比特合成字节Bytek\displaystyle \text{Byte}_{k} 每 8 个 bit 按二进制权重拼成一个字节,还原出一个字符。
  3. 解码链路b8k+0…b8k+7\displaystyle b_{8k+0} \dots b_{8k+7} 设备在混杂模式下抓包后按序解析,最终得到完整密码文本。

海量设备保障

物业集团一共管着 100 个小区、上万栋楼。就算施工方案再好,也不可能一夜之间全部同时翻新——电梯会堵、施工队不够、万一某栋楼出了岔子都不知道是谁干的。所以老练的集团会在 1 栋楼试点,再推 1 个小区,再铺一个街道;每个批次都有巡检记录,任何一栋楼的返工率超标,立刻全城停工。

百万级设备的 OTA 同样必须“分批施工”。灰度发布(gray release)是标准做法:先给 1% 的设备推送,观察升级成功率、设备离线率、异常回滚率等指标;指标健康再推进到 10%、50%、100%。每个批次都是一个小实验,把风险锁在可控范围内。支撑灰度的是三个工程机制:一是分片下载与断点续传,设备网络不稳定时从断点继续,避免从头再来;二是监控告警,平台实时汇总各批次成功率、失败原因码、设备在线率,任一指标跌破阈值就自动暂停批次并告警;三是回滚预案,云端可强制设备回退到旧版本,或依靠设备端 A/B 分区自动回滚,把损失控制在分钟级。

看板上的成功率和施工巡检表一样,都是用来“踩刹车”的。百万设备的升级战,比拼的不是谁推得快,而是谁能在 95% 的设备都升级成功时,冷静地停下那 5% 的异常批次。楼是慢慢翻新的,设备也是——稳,才是规模化的第一原则。

SR=NsuccessNtotal×100%\displaystyle \text{SR} = \frac{N_{\text{success}}}{N_{\text{total}}} \times 100\%
批次升级成功率等于成功上报数除以已下发数,低于阈值(如 95%)就自动暂停灰度。
  1. 下发总数Ntotal\displaystyle N_{\text{total}} 是本批次已下发升级任务的设备数量。
  2. 成功数Nsuccess\displaystyle N_{\text{success}} 是新固件启动并向云端上报成功的设备数量。
  3. 阈值刹车SR\displaystyle \text{SR} 低于预设阈值时,平台自动暂停该批次并触发回滚预案,防止故障扩散。

AI 应用场景

场景一:扫地机器人固件灰度升级

阶段:设备管理 / OTA 升级

解决的问题:传统方式需要用户手动下载固件或返厂刷机,升级失败会导致设备变砖、售后成本高。平台通过差分包 + A/B 分区 + 灰度发布,让千万台机器人在用户睡觉时自动完成算法升级,出问题自动回滚。

具体案例:某扫地机器人厂商推送“避障算法 v2.0”,固件 8MB、差分包仅 600KB。平台先选 1% 设备(覆盖各 CPU 型号和地图版本)灰度,监控成功率 98.6%;随后发现老款陀螺仪机型回滚率偏高,自动暂停该型号批次,回退代码修复后重新灰度,最终全量升级成功。

场景二:智能门锁 BLE 配网与安全接入

阶段:设备接入 / 配网

解决的问题:门锁没有屏幕和键盘,输入 Wi-Fi 密码困难;若密码明文广播则存在窃听风险。BLE 近场加密信道解决“首次信任”问题。

具体案例:安装师傅在用户家门口打开 App,手机与门锁通过 BLE 配对,经 AES 加密通道下发 Wi-Fi 密码和临时管理密钥;门锁连上路由器后立即销毁临时密钥,用户后续通过云平台远程管理门锁,全程无密码泄露。

场景三:智能插座 SmartConfig 兜底配网

阶段:设备接入 / 配网兜底

解决的问题:低成本智能插座没有 BLE 模块,需要一种“零额外硬件”的配网方式。

具体案例:某品牌智能插座使用 SmartConfig:用户 App 输入 Wi-Fi 密码后,连续广播编码报文约 30 秒,插座通过混杂模式抓包解码并连网;平台统计配网成功率约 90%,对失败设备引导用户切换信道重试后提升至 96%。

Python 演示

python95 行
"""IoT设备管理: 差分包生成, A/B分区升级与SmartConfig配网模拟"""import hashlibimport random  def make_delta(old, new):    """简化差分: 保留最长公共前缀/后缀, 中间差异独立成块"""    limit = min(len(old), len(new))    prefix = 0    while prefix < limit and old[prefix] == new[prefix]:        prefix += 1    suffix = 0    while suffix < limit - prefix and old[-1 - suffix] == new[-1 - suffix]:        suffix += 1    core = new[prefix:len(new) - suffix] if suffix else new[prefix:]    return {        "prefix": prefix,        "suffix": suffix,        "core": core,        "checksum": hashlib.md5(new).hexdigest(),    }  def apply_delta(old, delta):    """旧固件 + 差分包 = 新固件"""    head = old[:delta["prefix"]]    tail = old[len(old) - delta["suffix"]:] if delta["suffix"] else b""    return head + delta["core"] + tail  def smartconfig_encode(text):    """把字符串编码为UDP包长度列表, 奇偶代表bit"""    bits = "".join("{:08b}".format(ord(c)) for c in text)    return [20 + int(b) for b in bits]  def smartconfig_decode(lengths):    """从包长度列表还原字符串"""    chars = []    for i in range(0, len(lengths) - 7, 8):        byte = 0        for j in range(8):            byte = (byte << 1) | (lengths[i + j] % 2)        chars.append(chr(byte))    return "".join(chars)  class OtaManager:    """A/B双分区升级管理器, 模拟写入, 校验与回滚"""     def __init__(self, slot_a, slot_b):        self.slot_a = slot_a        self.slot_b = slot_b        self.active = "A"        self.verified = {"A": True, "B": False}     def upgrade(self, new_fw):        target = "B" if self.active == "A" else "A"        old = self._read(self.active)        delta = make_delta(old, new_fw)        self._write(target, apply_delta(old, delta))        if random.random() < 0.2:            self.verified[target] = False            return "升级失败自动回滚至%s分区" % self.active        self.active = target        self.verified[target] = True        return "升级成功切换至%s分区" % target     def _read(self, slot):        return getattr(self, "slot_" + slot.lower())     def _write(self, slot, data):        setattr(self, "slot_" + slot.lower(), data)  if __name__ == "__main__":    random.seed(1)    # 1. 差分包生成与还原    old_fw = bytes(range(256)) * 4    new_fw = bytearray(old_fw)    new_fw[160:288] = bytes([0xEE] * 128)    new_fw = bytes(new_fw)    delta = make_delta(old_fw, new_fw)    restored = apply_delta(old_fw, delta)    assert restored == new_fw and hashlib.md5(restored).hexdigest() == delta["checksum"]    full_size = len(new_fw)    delta_size = len(delta["core"]) + 16    print("完整包:%dB 差分包:%dB 节省:%.1f%%" % (full_size, delta_size, (1 - delta_size / full_size) * 100))    # 2. A/B 分区升级    ota = OtaManager(old_fw, old_fw)    for i in range(3):        print("第%d次%s" % (i + 1, ota.upgrade(new_fw)))    # 3. SmartConfig 编码与解码    lengths = smartconfig_encode("SmartHome2026")    print("还原密码:%s" % smartconfig_decode(lengths))
目的:模拟了差分包生成与还原、A/B 分区升级与回滚、SmartConfig 的 UDP 包长编码与解码,覆盖正文三大核心机制。
  1. def make_delta(old, new):核心差分函数:找出新旧固件的最长公共前缀和后缀,只把中间差异存进补丁。
  2. core = new[prefix:len(new) - suffix] if suffix else new[prefix:]截取“既不在公共前缀也不在公共后缀”的中间差异字节。
  3. return head + delta["core"] + tail还原时把旧固件头尾拼接差异核心,等价于 bspatch 的最小形式。
  4. lengths = [20 + int(b) for b in bits]SmartConfig 编码:每个 bit 映射为 UDP 包长 20 或 21,包长奇偶即信息。
  5. byte = (byte << 1) | (lengths[i + j] % 2)解码:把包长奇偶串回位流,每 8 位合成一个字节。
  6. self.verified[target] = False模拟升级校验失败,标记回滚隐患,对应 A/B 分区自动回滚机制。
  7. self.active = target校验通过才切换活动槽位,对应 bootloader 启动槽位切换。
  8. if random.random() < 0.2:用随机数模拟小概率升级失败,便于演示失败回滚分支。

常见误区

误区差分包制作越极致越好,最好只有几百字节,省下来的流量都是成本。

正解过度追求小包会消耗大量计算资源,补丁逻辑变复杂,设备端解码失败率反而上升。工程上更看重“差分失败时有完整包兜底”:当设备版本未知或差分还原出错时,平台应自动回退到完整包。就像装修只补墙却忘了检查承重——省涂料的钱可能赔上结构安全。

为何常见:流量成本直观可见,而解码失败率难以预先量化,容易陷入局部最优。

误区A/B 双分区让可用存储直接减半,对成本敏感的硬件设计太浪费了。

正解A/B 分区的价值是用存储换“永不砖”的可靠性。单分区升级一旦断电或写入损坏固件,设备变砖只能返厂;A/B 让升级无感、回滚自动。对售后成本高、无法返厂的 IoT 产品,省下的返厂费用远超 Flash 芯片成本。

为何常见:硬件工程师习惯“寸土寸金”地优化存储,容易低估升级事故的真实成本。

误区我用 SmartConfig 把 Wi-Fi 密码广播出去,那岂不是整层楼的人都能听到密码?

正解SmartConfig 不直接广播密码明文,而是把密码编码成一组看似随机的 UDP 包长度和数据;设备也必须处于同一信道并开启混杂模式才能抓包解码。但它确实不是强加密方案,所以对安全敏感的产品仍首选 BLE,或配合动态密钥使用。

为何常见:把“广播”理解成公开喊话,忽略了编码规则和信道限制,导致安全模型理解偏差。

误区设备下载完固件、重启后能跑起来,这不就是升级成功了吗?

正解工程上“升级成功”必须等设备新固件正常启动并连接云端上报(心跳 + 版本号),平台才确认成功。若设备崩溃重启或无法上报,平台应判定失败并触发回滚。就像搬家后要等住户打电话报平安,才算安全入住。

为何常见:本地视角只看到进程切换成功,忽视了端云联动确认才是 OTA 可靠性的闭环。

误区灰度很简单,按比例随机选一批设备推送,观察一下就行。

正解灰度要按设备型号、固件版本、地域、活跃度分层抽样,保证样本代表性;同时设定暂停阈值,异常率超限自动停止。随机抽样可能恰好撞不到“最容易出问题的那批老型号设备”,从而把风险悄悄带到全量。

为何常见:把统计抽样想得太简单,忽略了 IoT 设备高度碎片化的特征。

面试题

Q1. 下列哪项不属于 OTA 升级的标准四阶段?

单选题 · easy

  • A.任务下发
  • B.固件下载
  • C.设备报废← 正确答案
  • D.重启切换

答案:C。OTA 四阶段是任务下发、固件下载、设备写入、重启切换。“设备报废”显然不在其中。好比翻新计划里没有“把楼拆了”这一步——升级链路设计的核心原则是全程可观测、失败可重试,而不是让设备进回收站。

Q2. 差分包相比完整包的主要优势是什么?

单选题 · easy

  • A.提高设备算力
  • B.节省流量与功耗← 正确答案
  • C.加密更简单
  • D.不依赖旧固件

答案:B。差分包只记录新旧固件的差异,体积从几 MB 压到几百 KB,直接节省流量和下载耗电。它不会提高算力,加密方式与差分无关,而且恰恰依赖旧固件版本。就像补墙漆只补裂缝,不负责加固楼体,但确实省料。

Q3. Bsdiff 生成差分包的思路核心是什么?

单选题 · mid

  • A.逐字节记录整个新固件
  • B.滑动窗口匹配差异块← 正确答案
  • C.仅压缩而不做对比
  • D.将新固件拆半发送

答案:B。bsdiff 用滑动窗口在新旧固件之间查找匹配片段,把“匹配位置 + 长度 + 差异数据”写进补丁。逐字节记录整个新固件等于没差分,仅压缩不对比也生成不了增量。对应装修里的“哪里旧补哪里”,而不是整栋重刷。

Q4. A/B 分区升级中,新槽位被标记为“验证通过”的时机是?

单选题 · mid

  • A.差分包下载完毕
  • B.写入备用分区完成
  • C.新固件启动后上报成功← 正确答案
  • D.用户点击确认升级

答案:C。写入完成只是中间态,必须等设备从新槽位启动、正常连接云端并上报版本号,平台才确认验证通过。下载完、写完都不算数,App 确认也非必要。就像搬家后要等住户打电话报平安,才算真正入住。

Q5. A/B 升级失败时实现自动回滚主要依赖什么?

单选题 · mid

  • A.云端重新下发包
  • B.引导程序回滚旧槽位← 正确答案
  • C.用户手动连接刷机
  • D.手机App远程重装

答案:B。自动回滚由 bootloader 完成:它读取新槽位校验标志和重启计数,发现新固件反复启动失败后,自动切回旧槽位。云端重发、用户刷机、App 重装都不是设备侧自动回滚机制,无法做到用户无感恢复。

Q6. BLE 配网相比 SmartConfig 的主要优势是什么?

单选题 · mid

  • A.不需路由器参与
  • B.点对点加密传输凭据← 正确答案
  • C.传输距离更远
  • D.无需手机参与

答案:B。BLE 是点对点近场信道,配对时可协商会话密钥,对 Wi-Fi 凭据做 AES 加密传输;SmartConfig 广播则缺乏强加密。BLE 距离更近而非更远,配网仍需要手机和路由器。这对应“管家面对面递钥匙”,天然比喇叭喊话更安全。

Q7. SmartConfig 配网中,设备是如何获得 Wi-Fi 密码的?

单选题 · mid

  • A.直接连路由器取包
  • B.混杂抓包解码包长数据← 正确答案
  • C.扫描路由器上的二维码
  • D.通过NFC碰一碰读取

答案:B。设备此时还没联网,无法从路由器取包,也不支持扫码和 NFC。它开启混杂模式抓取空中的 UDP 包,按“包长奇偶代表 bit”的规则解码出密码,再主动发起 Wi-Fi 连接。这正是“喇叭暗号”的数字化实现。

Q8. 以下哪些是提升百万级设备 OTA 成功率的工程手段?

多选题 · mid

  • A.采用灰度分批发布← 正确答案
  • B.支持断点续传下载← 正确答案
  • C.全量同时推送固件
  • D.失败自动回滚监控← 正确答案

答案:ABD。灰度分批把风险锁在小范围,断点续传应对弱网环境,失败自动回滚加监控保证事故可控。全量同时推送是典型的“升级风暴”,会造成带宽拥塞和服务器过载,是工程上极力避免的做法。

Q9. 关于 OTA 差分包,下列说法正确的是?

多选题 · hard

  • A.还原后需校验哈希← 正确答案
  • B.可能比完整包更大← 正确答案
  • C.失败时可回退完整包← 正确答案
  • D.不依赖旧固件版本

答案:ABC。差分还原后必须校验哈希,防止数据损坏;极端情况下新旧固件差异过大,差分包可能接近甚至超过完整包;版本未知或差分失败时平台会用完整包兜底。但差分一定依赖旧固件版本,所以 D 错误。

Q10. 关于 IoT 设备配网安全,下列说法正确的有?

多选题 · hard

  • A.BLE可加密传输密码← 正确答案
  • B.SmartConfig无任何编码
  • C.配网完成销毁临时凭据← 正确答案
  • D.动态密码降低泄露风险← 正确答案

答案:ACD。BLE 配对可协商密钥加密传输口令,属实;配网完成后销毁临时 BLE 凭据、使用动态密码都是标准安全实践,属实。SmartConfig 虽然没有强加密,但仍有长度奇偶等编码规则,说“无任何编码”不准确,故 B 错误。