跳到主要内容

域名分发管理

核心概念:域名分发 | 主UOTA | 备UOTA | 域名池

域名分发管理模块是机顶盒与服务器通信的"生命线",负责向设备下发可用域名组最新版 UOTA 程序


1. 核心概念:双APK架构

核心概念:域名分发 | 主UOTA | 备UOTA | 双APK架构

作为安卓机顶盒生产商,我们在每台设备上部署了双APK架构,确保设备与服务器之间的通信永不中断。

1.1 主UOTA(核心通信APK)

主UOTA是盒子和服务器进行通信的核心APK,承担着设备与云端之间所有数据交换的职责。

核心功能

  • 设备升级:固件OTA升级、系统更新
  • APK推送:远程安装/卸载应用
  • Launcher广告配置:桌面广告位管理
  • 黑名单管控:应用黑白名单策略
  • 设备运行状况监测:心跳上报、日志收集
主UOTA的重要性

主UOTA是设备的"心脏",一旦停止工作,设备将与服务器彻底失联,无法接收任何指令和配置更新。

1.2 备UOTA(域名分发APK)

备UOTA也称为"域名分发APK",功能相对单一,主要负责:

  • 主UOTA备UOTA下发各自的域名池
  • 推送下发最新版本的主UOTA

独立运行机制

  • 备UOTA的运行与主UOTA的状态完全无关,即使主UOTA未安装或已崩溃,备UOTA仍能正常工作
  • 备UOTA会定期向服务器请求,获取最新的域名池并存储在本地备用
  • 备UOTA会定期获取最新主UOTA信息,判断是否需要推送升级或安装

主UOTA升级/安装判断逻辑

  1. 备UOTA定期请求服务器获取主UOTA版本信息
  2. 如果服务器端配置了主UOTA包,则获取版本号
  3. 判断当前盒子中的主UOTA版本是否小于服务器配置的版本
  4. 若版本较低或主UOTA未安装,则触发下载安装流程
备UOTA的稳定性优势

备UOTA稳定性极高的原因:

  1. 功能单一:代码量少,不易出现程序崩溃
  2. 兼容性高:不依赖复杂的外部库,适配性强
  3. 政策风险低:功能简单,不易触发各国监管政策
  4. 攻击面小:不涉及敏感业务逻辑,被恶意利用的可能性低
  5. 独立运行:不依赖主UOTA,即使主UOTA异常也能正常工作

1.3 域名池机制

域名池是存储在机顶盒本地的备用域名集合,分为主UOTA域名池备UOTA域名池两个独立的域名池。

架构说明

  • 两个独立域名池:主UOTA和备UOTA各自拥有独立的域名池
  • 统一维护:由备UOTA负责维护这两个域名池
  • 独立使用:各UOTA只读取自己对应的域名池

工作原理

  1. 备UOTA定期向服务器请求,获取并更新两个域名池
  2. 主UOTA发现当前域名无法通信时,从主UOTA域名池读取可用域名
  3. 备UOTA发现当前域名无法通信时,从备UOTA域名池读取可用域名
  4. 自动轮询尝试连接,直到找到可用的域名
  5. 防止因单一域名失效导致设备彻底断联
职责划分
  • 备UOTA:负责两个域名池的维护和管理(定期更新、存储)
  • 主UOTA:负责主UOTA域名池的读取和使用(故障时切换)
  • 备UOTA:负责备UOTA域名池的读取和使用(故障时切换)

2. 模块关系图

核心概念:域名分发 | 主UOTA | 备UOTA | 模块关系

Mermaid Diagram Code:

graph TB
    subgraph 机顶盒设备
        subgraph 主UOTA["主UOTA (核心通信)"]
            A1[设备升级]
            A2[APK推送]
            A3[Launcher广告配置]
            A4[黑名单管控]
            A5[运行状况监测]
        end
        
        subgraph 备UOTA["备UOTA (域名分发)"]
            B1[域名池维护与管理]
            B2[主UOTA恢复]
            B3[定期获取域名池]
            B4[定期检测主UOTA版本]
        end
        
        subgraph 本地存储
            C1["主UOTA域名池<br/>(主UOTA专用)"]
            C2["备UOTA域名池<br/>(备UOTA专用)"]
        end
        
        备UOTA -->|维护/更新| C1
        备UOTA -->|维护/更新| C2
        主UOTA -.->|读取| C1
        备UOTA -.->|读取| C2
        备UOTA -.->|恢复/升级/安装| 主UOTA
    end
    
    subgraph 云端服务器
        subgraph 域名分发服务
            D1[域名信息管理]
            D2[UOTA-APP管理]
            D3[秘钥管理]
        end
        
        D4[规则引擎]
        D5[文件存储]
    end
    
    主UOTA <-->|数据交换| 域名分发服务
    备UOTA <-->|域名池更新/APP获取| 域名分发服务
    域名分发服务 --> D4
    域名分发服务 --> D5
关键说明
  • 两个独立域名池:主UOTA域名池和备UOTA域名池各自独立
  • 备UOTA统一维护:两个域名池都由备UOTA负责更新和管理
  • 各UOTA独立使用:主UOTA只读主UOTA域名池,备UOTA只读备UOTA域名池
  • 备UOTA独立运行:与主UOTA状态无关,定期执行域名池更新和主UOTA版本检测
  • 实线箭头:表示维护/更新操作(备UOTA负责)
  • 虚线箭头:表示读取操作(各UOTA只读自己的域名池)

3. 数据交换流程图

核心概念:域名分发 | 主UOTA | 备UOTA | 数据交换流程

3.1 正常通信流程

Mermaid Diagram Code:

sequenceDiagram
    participant Device as 机顶盒设备
    participant MainUOTA as 主UOTA
    participant BackupUOTA as 备UOTA
    participant Server as 云端服务器
    
    Note over Device, Server: 设备开机/周期性检查
    Device->>MainUOTA: 启动主UOTA
    Device->>BackupUOTA: 启动备UOTA
    
    Note over BackupUOTA, Server: 备UOTA独立运行(与主UOTA状态无关)
    
    Note over BackupUOTA, Server: 任务1:定期获取域名池
    BackupUOTA->>Server: 请求域名分发接口
    Server->>Server: 规则引擎匹配
    Server-->>BackupUOTA: 返回两个域名池
    BackupUOTA->>BackupUOTA: 更新本地域名池(主UOTA域名池+备UOTA域名池)
    
    Note over BackupUOTA, Server: 任务2:定期获取主UOTA信息
    BackupUOTA->>Server: 请求主UOTA版本信息
    Server-->>BackupUOTA: 返回最新主UOTA配置(如有)
    
    alt 服务器配置了主UOTA且版本更新
        BackupUOTA->>BackupUOTA: 判断版本:当前版本 < 服务器版本?
        BackupUOTA->>Server: 下载最新主UOTA APK
        BackupUOTA->>Device: 安装/升级主UOTA
    else 主UOTA未安装
        BackupUOTA->>Server: 下载主UOTA APK
        BackupUOTA->>Device: 安装主UOTA
    end
    
    Note over MainUOTA, Server: 主UOTA正常业务通信
    MainUOTA->>Server: 心跳上报/任务请求
    Server-->>MainUOTA: 返回配置/指令

3.2 域名失效切换流程

Mermaid Diagram Code:

sequenceDiagram
    participant MainUOTA as 主UOTA
    participant BackupUOTA as 备UOTA
    participant MainPool as 主UOTA域名池<br/>(备UOTA维护)
    participant BackupPool as 备UOTA域名池<br/>(备UOTA维护)
    participant Server as 云端服务器
    
    Note over MainUOTA, Server: 主UOTA域名失效切换
    MainUOTA->>Server: 尝试连接域名A
    Server--xMainUOTA: 连接失败
    
    MainUOTA->>MainPool: 从主UOTA域名池读取下一个域名
    MainPool-->>MainUOTA: 返回域名B
    
    MainUOTA->>Server: 尝试连接域名B
    Server--xMainUOTA: 连接失败
    
    MainUOTA->>MainPool: 从主UOTA域名池读取下一个域名
    MainPool-->>MainUOTA: 返回域名C
    
    MainUOTA->>Server: 尝试连接域名C
    Server-->>MainUOTA: 连接成功
    
    Note over BackupUOTA, Server: 备UOTA域名失效切换(同理)
    BackupUOTA->>Server: 尝试连接域名X
    Server--xBackupUOTA: 连接失败
    
    BackupUOTA->>BackupPool: 从备UOTA域名池读取下一个域名
    BackupPool-->>BackupUOTA: 返回域名Y
    
    BackupUOTA->>Server: 尝试连接域名Y
    Server-->>BackupUOTA: 连接成功
    
    Note over MainUOTA, BackupUOTA: 各UOTA独立读取自己的域名池

3.3 主UOTA故障恢复流程

Mermaid Diagram Code:

sequenceDiagram
    participant Device as 机顶盒设备
    participant MainUOTA as 主UOTA
    participant BackupUOTA as 备UOTA
    participant Server as 云端服务器
    
    Note over Device, Server: 主UOTA异常场景
    Device->>MainUOTA: 尝试启动主UOTA
    MainUOTA--xDevice: 启动失败/无响应
    
    Device->>BackupUOTA: 启动备UOTA
    BackupUOTA->>Server: 请求域名分发接口
    Server->>Server: 检测到主UOTA异常
    Server-->>BackupUOTA: 返回最新主UOTA下载地址
    
    BackupUOTA->>Server: 下载主UOTA APK
    Server-->>BackupUOTA: 返回APK文件
    
    BackupUOTA->>Device: 安装/修复主UOTA
    Device->>MainUOTA: 重新启动主UOTA
    MainUOTA-->>Device: 启动成功
    
    Note over Device, Server: 恢复正常通信

4. 利害关系与风险分析

核心概念:域名分发 | 主UOTA | 备UOTA | 风险分析

4.1 主UOTA的脆弱性

主UOTA可能因以下情况无法正常运行:

风险类型具体场景影响程度
出厂问题出厂时忘记预装主UOTA严重
兼容性问题出厂预装版本与硬件不兼容严重
升级失败在线升级过程中断导致崩溃中等
恶意卸载用户或恶意软件主动卸载严重
政策封禁某些国家/地区封禁当前版本严重
系统异常Android系统异常导致无法启动中等
存储损坏设备存储损坏导致APK丢失严重

4.2 备UOTA的稳定性保障

备UOTA能够作为"心脏起搏器"的原因:

  1. 功能单一:仅负责域名分发和主UOTA恢复,代码量小,Bug少
  2. 兼容性高:不依赖复杂的外部库,适配各种硬件平台
  3. 政策风险低:功能简单,不易触发各国政策监管
  4. 攻击面小:不涉及敏感业务逻辑,被恶意利用的可能性低

4.3 出厂预装的不确定性

重要提示

主UOTA和备UOTA出厂不一定预装!

早期生产的设备可能没有预装这两个APK,是通过其他途径逐步推送安装的。这意味着:

  • 早期设备的稳定性更差
  • 可能存在部分设备完全无法恢复的情况
  • 需要通过其他渠道(如固件升级)来安装这些APK

4.4 最坏情况

如果主UOTA备UOTA都出现故障:

  • 设备将彻底断联
  • 无法远程恢复,只能通过线下刷机返厂维修
  • 造成运维成本大幅增加

5. 兜底机制详解

核心概念:域名分发 | 主UOTA | 备UOTA | 兜底机制

系统设计了三层兜底机制,最大程度保障设备在线率。

5.1 第一层:域名池兜底

触发条件:当前域名无法访问
处理方式:
- 主UOTA:从主UOTA域名池读取下一个可用域名
- 备UOTA:从备UOTA域名池读取下一个可用域名
维护方:备UOTA统一维护两个域名池
恢复时间:秒级
成功率:高(只要有一个域名可用即可恢复)

5.2 第二层:备UOTA兜底

触发条件:主UOTA无法正常运行
处理方式:备UOTA下载并安装最新主UOTA
恢复时间:分钟级(取决于网络速度和APK大小)
成功率:中(依赖备UOTA正常运行)

5.3 第三层:无兜底情况

触发条件:主UOTA和备UOTA都故障
处理方式:无远程恢复手段
后果:设备彻底断联
解决方案:线下刷机/返厂维修

5.4 兜底机制流程图

Mermaid Diagram Code:

flowchart TB
    A[设备尝试通信] --> B{当前域名可用?}
    B -->|是| C[正常通信]
    B -->|否| D{是主UOTA还是备UOTA?}
    
    D -->|主UOTA| E[从主UOTA域名池读取下一个域名]
    D -->|备UOTA| F[从备UOTA域名池读取下一个域名]
    
    E --> B
    F --> B
    
    C --> G{主UOTA正常?}
    G -->|是| C
    G -->|否| H{备UOTA可用?}
    
    H -->|是| I[备UOTA下载最新主UOTA]
    I --> J[安装/修复主UOTA]
    J --> A
    
    H -->|否| K[设备彻底断联]
    K --> L[需要线下刷机/返厂维修]
    
    Note1[两个域名池均由备UOTA维护]
    Note2[各UOTA只读自己的域名池]

6. 域名信息管理

核心概念:域名分发 | 主UOTA | 备UOTA | 域名信息管理

域名信息管理用于管理系统中的各类域名配置,为主UOTA和备UOTA分别分配各自的域名池。

核心价值

防止域名不可用导致失联

双域名池架构

  • 主UOTA域名池:主UOTA专用,存储主UOTA通信所需的域名集合
  • 备UOTA域名池:备UOTA专用,存储备UOTA通信所需的域名集合

域名轮询与兜底机制

  1. 预置域名:设备出厂时会在主UOTA和备UOTA中分别预置一组域名。
  2. 动态下发:备UOTA定期请求本模块,获取并更新两个域名池。
  3. 独立轮询
    • 主UOTA遍历主UOTA域名池逐个尝试连接
    • 备UOTA遍历备UOTA域名池逐个尝试连接
  4. 故障转移:一旦当前使用的域名访问失败,各UOTA会自动从自己的域名池中寻找下一个可用域名,确保设备永远"在线"。

点击访问:域名信息管理


列表查询 (域名信息)

核心概念:域名分发 | 域名分发APP | 域名列表查询

在域名信息管理页面,您可以查询和管理域名配置。

查询列表

查询条件:

  • 域名类型:选择域名类型。
  • 域名:输入域名地址。
  • 是否开启:选择启用状态。
  • 备注:输入备注。

列表字段:

  • ID:唯一标识。
  • 域名类型:域名的分类(主UOTA域名池、备UOTA域名池等)。
  • 域名:具体的域名地址。
  • 是否开启:启用/禁用状态。
  • 设备数量:显示规则引擎绑定的设备数量统计。
  • 备注:备注说明。
  • 创建者:操作人信息。
  • 创建时间:时间记录。
  • 更新者:操作人信息。
  • 更新时间:时间记录。

新增/编辑 (域名信息)

核心概念:域名分发 | 域名分发APP | 域名配置编辑

在域名信息管理页面,您可以新增或编辑域名配置。

新增与修改

表单字段:

  • 域名类型:必填,选择域名的类型。
  • 域名:必填,输入完整的域名地址。
  • 是否开启:选择是否立即启用。
  • 备注:选填。

7. UOTA-APP管理

核心概念:域名分发 | 主UOTA | 备UOTA | UOTA-APP管理

UOTA-APP管理用于管理域名分发关联的 UOTA 应用包信息,主要服务于备UOTA恢复主UOTA的场景。

核心价值

终端设备的"终极救援"方案

当盒子上的主UOTA发生意外(如被恶意卸载、自升级失败崩溃、政策封禁等)导致与服务器断联时,设备上的备UOTA可以通过本模块下载最新的主UOTA安装包进行重装或修复,恢复设备正常功能。

平台差异说明

不同芯片方案的主板(如 Allwinner 全志Rockchip 瑞芯微Amlogic 晶晨)底层代码存在差异,因此需要针对不同平台下发对应的 UOTA 版本。

  • 所属平台:来源于数据字典 device_platform

点击访问:UOTA-APP


列表查询 (UOTA-APP)

核心概念:域名分发 | 域名分发APP | UOTA包列表查询

在UOTA-APP管理页面,您可以查询和管理UOTA应用包。

列表查询

查询条件:

  • 包名:应用包名。
  • 版本号:应用版本号。
  • 版本名称:应用版本名称。
  • 所属平台:设备平台(Allwinner/Rockchip/Amlogic 等)。
  • 是否开启:启用状态。
  • 创建时间:时间范围。

列表字段:

  • ID:唯一标识。
  • 文件表ID:关联的文件ID。
  • 文件url:文件下载地址。
  • 文件大小:文件字节大小。
  • 包名:应用包名(从文件元数据自动获取)。
  • 版本号:内部版本号(从文件元数据自动获取)。
  • 版本名称:显示版本名称(从文件元数据自动获取)。
  • 所属平台:适用的设备平台(Allwinner/Rockchip/Amlogic 等)。
  • 是否开启:启用状态。
  • 设备数量:显示规则引擎绑定的设备数量统计。
  • 备注:备注说明。
  • 创建时间:记录创建时间。

新增/编辑 (UOTA-APP)

核心概念:域名分发 | 域名分发APP | UOTA包配置编辑

在UOTA-APP管理页面,您可以新增或编辑UOTA应用包信息。

新增与修改

表单字段:

  • 文件表:必填,从文件管理中选择已上传的APK文件(下拉选择)。
  • 所属平台:必填,选择设备平台(来源于数据字典 device_platform)。
  • 是否开启:必填,选择是否启用。
  • 备注:选填。
自动获取信息

选择APK文件后,系统会自动从文件元数据中读取包名版本号版本名称文件URL文件大小等信息,无需手动填写。


8. 秘钥管理

核心概念:域名分发 | 主UOTA | 备UOTA | 秘钥管理

秘钥管理用于管理服务器与盒子 APP(主UOTA和备UOTA)通信过程中的加密与签名秘钥。

核心价值

保障通信安全,防止数据被篡改或伪造。秘钥类型来源于数据字典 task_secret_key_type

秘钥类型与用途说明

  1. 域名分发加解密 (DOMAIN_DISPATCH_ENCRYPT)

    • 用途:用于备UOTA与服务器交互时的敏感数据加密。
    • 技术细节:参考 签名和加解密 文档。
  2. 域名分发签名 (DOMAIN_DISPATCH_SIGN)

    • 用途:盒子请求服务器时进行签名,服务器进行验签,确保请求来源合法。
    • 技术细节:参考 签名和加解密 文档。
  3. 固件请求加解密 (FIRMWARE_REQUEST_ENCRYPT)

点击访问:秘钥管理


列表查询 (秘钥管理)

核心概念:域名分发 | 域名分发APP | 秘钥列表查询

在秘钥管理页面,您可以查询和管理通信秘钥。

列表查询

查询条件:

  • 秘钥类型:选择类型。
  • 创建时间:时间范围。

列表字段:

  • 主键:唯一标识。
  • 秘钥类型:秘钥的分类。
  • 秘钥唯一标识:Key ID。
  • 秘钥值:Key Value。
  • 时间差(毫秒):允许的时间误差。
  • 备注:备注说明。
  • 创建时间:记录创建时间。

新增/编辑 (秘钥管理)

核心概念:域名分发 | 域名分发APP | 秘钥配置编辑

在秘钥管理页面,您可以新增或编辑通信秘钥。

新增与修改

表单字段:

  • 秘钥类型:必填。
  • 秘钥唯一标识:必填。
  • 秘钥值:必填(修改时填入新值)。
  • 时间差:必填,单位毫秒。用于签名或解密时验证时间是否超出限制,防止重放攻击。
  • 备注:选填。
异步导出

当导出数据量较大时,系统会采用异步导出方式。您可以在 导出任务管理 中查看导出进度并下载文件。


9. 规则引擎集成 (高级分发)

核心概念:域名分发 | 主UOTA | 备UOTA | 规则引擎集成

域名分发模块已全面接入 规则引擎,实现了从"静态分发"到"智能分发"的跨越。

9.1 为什么要结合规则引擎?

在没有规则引擎之前,域名通常只能全局生效,或者硬编码一些简单的逻辑。结合规则引擎后,您可以实现:

  1. 灰度发布“只对 5% 的随机设备下发新域名”
  2. 地域优化“巴西设备下发南美洲节点域名,中国设备下发亚洲节点域名”
  3. 设备兼容“只对内存大于 2GB 的设备下发高清资源域名”
  4. A/B 测试:针对不同用户群下发不同配置,验证效果。

9.2 如何配置规则 (域名分发)

核心概念:域名分发 | 主UOTA | 备UOTA | 规则配置

在域名分发列表页,选中某一行域名记录,下方会显示 规则配置组件 (RuleBusinessTabs)。

  1. 定义规则

    • 您可以直接引用规则中心已有的规则(如“高端机型通用规则”)。
    • 也可以点击“新增”,现场创建一个专用规则(如“域名灰度测试规则”)。
  2. 绑定业务

    • 域名分发 (DOMAIN_DISPATCH):将规则与域名绑定。当设备命中该规则时,系统会下发该域名。
    • UOTA分发 (DOMAIN_DISPATCH_UOTA):将规则与UOTA包绑定。当设备命中该规则时,系统会下发该升级包。
  3. 实时生效

    • 域名分发业务不需要审批
    • 一旦绑定完成,配置即刻生效。设备下次请求时(调用 DomainDistributeController 接口),系统会自动运行规则引擎匹配逻辑,返回命中的结果。
提示

规则引擎支持数十种设备属性(CPU、内存、系统版本、IP、MAC等)的组合判断,配合 EL表达式,可以实现极其复杂的业务逻辑。详情请参考 规则引擎使用手册


10. 请求处理流程 (域名分发)

核心概念:域名分发 | 主UOTA | 备UOTA | 请求处理流程

10.1 简易流程图 (用户视角)

Mermaid Diagram Code:

sequenceDiagram
    participant Device as "终端设备 (机顶盒)"
    participant Server as "云端服务器"

    Device->>Server: "1. 发起请求 (携带MAC/机型等信息)"
    Server->>Server: "2. 识别设备身份"
    Server->>Server: "3. 匹配适用规则 (地区/灰度/机型)"
    Server-->>Device: "4. 返回可用域名列表 & UOTA升级包"
    Device->>Device: "5. 更新本地配置"

10.2 详细处理流程 (技术视角)

Mermaid Diagram Code:

sequenceDiagram
    participant STB as "机顶盒/设备"
    participant Biz as "域名分发模块"
    participant Rule as "规则引擎 (RuleRunUtil)"
    participant Redis as "Redis缓存"
    participant LiteFlow as "LiteFlow规则链"

    STB->>Biz: "1. 请求域名配置 (MAC, 平台信息)"
    Biz->>Rule: "2. 调用 matchBusinessIds(业务类型=DOMAIN, 设备详情)"
    
    Note right of Rule: "3. 初筛候选规则"
    Rule->>Redis: "获取 MAC专属规则"
    Rule->>Redis: "获取 渠道关联规则"
    Rule->>Redis: "获取 域名业务规则"
    Rule->>Redis: "获取 无限制规则"
    
    Rule->>Rule: "4. 集合运算 (求交集/并集)"
    Note right of Rule: "候选集 = (MAC规则 U 无限制 U 渠道规则) ∩ 业务类型规则"
    
    loop "5. 遍历候选规则"
    Rule->>Redis: "获取规则详情"
    Rule->>Rule: "检查地区限制 (Region Check)"
    alt "地区匹配通过"
    Rule->>LiteFlow: "执行EL表达式匹配 (传入设备上下文)"
    LiteFlow-->>Rule: "返回匹配结果 (True/False)"
    else "地区不匹配"
    Rule->>Rule: "跳过该规则"
    end
    end
    
    Rule-->>Biz: "6. 返回匹配成功的 域名规则ID集合"
    Biz->>Biz: "根据规则ID查询绑定的域名列表"
    Biz-->>STB: "7. 返回最终可用域名列表"

10.3 逻辑详解

  1. 设备接入: 机顶盒开机或周期性发起请求,上传 MAC 地址、CPU 型号、内存大小、Android 版本等设备指纹信息。
  2. 规则匹配: 服务器端规则引擎接管请求,进行多维度匹配:
    • 身份识别: 优先查找该 MAC 是否有专属测试规则。
    • 分组筛选: 根据设备所属渠道(Channel)查找关联规则。
    • 通用规则: 加载所有无设备限制的全局规则。
    • 特征过滤: 运行 LiteFlow 引擎,执行 EL 表达式判断设备硬件特征(如 内存 > 2GAndroid版本 >= 10)。
  3. 结果聚合:
    • 系统取所有命中规则所绑定的域名集合的并集
    • 如果没有任何规则命中,则返回空或默认兜底配置(视具体策略而定)。
  4. 下发响应: 将最终计算出的可用域名列表(包含主域名、备用域名)加密签名后返回给设备。

11. 测试环境模拟配置

核心概念:域名分发 | 主UOTA | 备UOTA | 测试环境模拟

为了在测试环境中模拟真实生产环境的域名解析,我们需要使用 AdGuard Home 进行 DNS 重写。

11.1 配置步骤

  1. 登录 AdGuard Home

  2. 添加 DNS 重写规则

    • 在“DNS 重写”页面,点击“添加 DNS 重写”。
    • 输入要劫持的生产环境域名(如 uota.ikb03.com)和测试服务器 IP(如 192.168.1.87)。

    DNS重写

  3. 验证配置

    • 将电脑或测试设备的 DNS 修改为 192.168.1.87
    • 在终端执行 nslookup 命令验证解析结果。
    nslookup uota.ikb03.com

    如果返回的 Address 是 192.168.1.87,则说明配置生效。

    验证结果

11.2 机顶盒连接配置

  1. 机顶盒连接测试 Wi-Fi(如 ASUS_2G4ASUS_5G),密码一般为 88888888
  2. 确保路由器已将 DNS 分配指向 192.168.1.87,或者在机顶盒网络设置中手动将 DNS 设置为 192.168.1.87

12. 快速验证手册

核心概念:域名分发 | 主UOTA | 备UOTA | 快速验证手册

本章节提供两种验证配置是否生效的方法。模式一适合快速检查后台配置,模式二适合模拟真实设备行为进行全链路测试。

12.1 模式一:快速验证(免签名)

为了方便测试,服务端提供了一个跳过签名和加密验证的测试接口。

  • 接口地址/app-api/hnc2fng/ghbn1hebdsh2/yh65hbfvg3jfdbs
  • 请求方式:POST
  • 特点:不需要 signtime 头,直接返回明文 JSON 数据。

无需新建请求。本项目接口文档已全量导入 Apifox,且包含详细的 测试用例 (Test Cases)

  1. 搜索接口:在 Apifox 中搜索关键词(如 快速验证yh65hbfvg3jfdbs)。
  2. 选择用例:接口下通常挂载了多个测试用例(如 Allwinner平台, Rockchip平台),直接选择对应场景。
  3. 一键运行:无需手动填写参数,点击“运行”即可。

入参示例 (JSON)

{
"platform": "Allwinner",
"mac": "AA:BB:CC:DD:EE:FF",
"cpu": "test_cpu_001"
}

12.2 模式二:全流程仿真(带签名)

核心概念:域名分发 | 主UOTA | 备UOTA | 全流程仿真验证

模拟真实机顶盒的交互流程,包含 获取时间 -> 签名 -> 请求 -> 解密 四个步骤。服务端提供了辅助接口来帮助测试人员生成签名和解密数据。

步骤 1:获取服务器时间

首先获取服务器当前时间,用于后续签名。

  1. 搜索接口:在 Apifox 中搜索 获取服务器时间dhgb35dg
  2. 运行:直接点击“运行”,无需参数。

响应示例

{ "code": 0, "data": { "time": 1753181666064 } }

记下这个 time 值。

步骤 2:生成签名

调用辅助接口生成签名(模拟设备端算法)。

  1. 搜索接口:在 Apifox 中搜索 签名sign
  2. 入参示例
    {
    "domain": "localhost:48080",
    "mac": "9C:00:D3:58:B3:DF",
    "cpu": "82422823dde3caa6",
    "time": 1753181666064,
    "sdkVersion": 47
    }

响应示例

{ "code": 0, "data": "2111360344febfc8a6179b19c9450871" }

记下 data 中的签名串。

步骤 3:发起正式请求(获取域名)

调用正式接口,带上签名头。

  • 接口: /app-api/hnc2fng/ghbn1hebdsh/yh65hbfvg3jfdbs (注意与模式一的接口路径区别)
  • Header: 必须包含 time, sign, mac, cpu

无需手动签名。本项目接口文档已全量导入 Apifox,且包含详细的 测试用例

  1. 搜索接口:在 Apifox 中搜索 正式请求 或路径 yh65hbfvg3jfdbs
  2. 选择用例:选择对应的测试用例(如 正常请求)。
  3. 一键运行:点击“运行”。(部分用例已配置前置脚本自动计算 signtime)。

入参示例 (JSON)

{
"platform": "Allwinner"
}

响应示例(Data是加密的):

{
"code": 0,
"data": "DC15hFmkezrskGUxijhd47DMxzS8IXKtuXAwJ6YC0C6mrBBxHJi0Cw6VVJxkIDxSeHU..."
}

步骤 4:解密数据

调用辅助接口解密响应内容。

  1. 搜索接口:在 Apifox 中搜索 解密decrypt
  2. 入参示例
    {
    "encryptedText": "DC15hFmkezrskGUxijhd47DMxzS8IXKtuXAwJ6YC0C6mrBBxHJi0Cw6VVJxkIDxSeHU...",
    "sdkVersion": 47
    }

最终结果

{
"code": 0,
"data": "{\"uotaApps\":[...], \"domains\":[...]}"
}

此时你可以看到服务端下发的明文域名列表和 UOTA 版本信息。


13. Python一键测试

核心概念:域名分发 | 主UOTA | 备UOTA | Python测试脚本

为了方便测试人员快速验证域名分发功能,我们提供了两个Python脚本,可以一键模拟真实的机顶盒客户端请求。

13.1 环境准备

依赖安装

pip install pycryptodome requests

脚本下载


13.2 域名分发HTTP接口测试

核心概念:域名分发 | 主UOTA | 备UOTA | HTTP测试脚本

该脚本模拟机顶盒应用层的HTTP请求,支持**快速测试(免签名)全流程仿真(带签名)**两种模式。

快速测试(推荐)

无需签名验证,直接返回结果:

python test_domain_dispatch.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform Allwinner --host 192.168.1.87:48080 --sdk-version 47 --salt jdh2dh7hdbhu3hbfcyHvdhf87NFH67b47 --encryption-key 1234567887654347

全流程仿真

模拟真实设备行为,包含签名验证:

# 全流程测试 - 模式1(本地签名/解密)
python test_domain_dispatch.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform Allwinner --host 192.168.1.87:48080 --sdk-version 47 --salt jdh2dh7hdbhu3hbfcyHvdhf87NFH67b47 --encryption-key 1234567887654347 --full --mode 1

# 全流程测试 - 模式2(服务端签名/解密)
python test_domain_dispatch.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform Allwinner --host 192.168.1.87:48080 --sdk-version 47 --salt jdh2dh7hdbhu3hbfcyHvdhf87NFH67b47 --encryption-key 1234567887654347 --full --mode 2

参数说明

参数必填说明
--mac设备MAC地址
--cpu设备CPU标识
--platform设备平台 (Allwinner/Rockchip/Amlogic)
--host服务器地址 (例如: 192.168.1.87:48080)
--sdk-versionSDK版本
--salt签名salt
--encryption-key加密密钥
--full执行全流程测试
--mode全流程测试模式: 1=本地签名/解密, 2=服务端签名/解密 (默认: 1)

SDK版本对应秘钥

SDK版本签名Salt (singKey)加密密钥 (encryptionKey)时间差(毫秒)
47jdh2dh7hdbhu3hbfcyHvdhf87NFH67b471234567887654347600000
103jdh2dh7hdbhu3hbfcyHvdhf87NFH67b471234567887654347600000
104jdh2dh7hdbhu3hbfcyHvdhf87NFH67b471234567887654347600000
105jdh2dh7hdbhu3hbfcyHvdhf87NFH67b471234567887654347600000

输出示例

============================================================
域名分发HTTP接口快速测试(免签名)
============================================================
参数: MAC=AA:BB:CC:DD:EE:FF, CPU=test_cpu_001, Platform=Allwinner
服务器: localhost:48080
------------------------------------------------------------
请求: POST http://localhost:48080/app-api/hnc2fng/ghbn1hebdsh2/yh65hbfvg3jfdbs
响应: {
"code": 0,
"data": {
"uotaApps": [...],
"domains": [...]
}
}
============================================================
测试完成
============================================================

13.3 固件TCP协议测试

核心概念:域名分发 | 主UOTA | 备UOTA | TCP测试脚本

该脚本模拟固件层的TCP协议请求,适用于测试底层固件升级场景。

基本用法

# 基本测试
python test_firmware_tcp.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform allwinner

# 指定服务器和端口
python test_firmware_tcp.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform allwinner --host 192.168.1.87 --port 8520

# 指定SDK版本
python test_firmware_tcp.py --mac AA:BB:CC:DD:EE:FF --cpu test_cpu_001 --platform allwinner --sdk-version allwinner-202510-01

参数说明

参数必填说明默认值
--mac设备MAC地址-
--cpu设备CPU标识-
--platform设备平台 (allwinner/rockchip/amlogic)-
--host服务器地址192.168.1.87
--port服务器端口8520
--sdk-versionSDK版本allwinner-202510-01
--encryption-key加密密钥12345678123456781234567812345678
--no-ignore-time不忽略时间戳校验false
--encrypt-response要求响应加密false
固件层加密密钥

固件层TCP协议使用的加密密钥与域名分发HTTP接口不同,需要在秘钥管理中配置类型为FIRMWARE_AES的密钥。 测试环境密钥:12345678123456781234567812345678(32字节)

输出示例

============================================================
固件TCP协议测试
============================================================
参数: MAC=AA:BB:CC:DD:EE:FF, CPU=test_cpu_001, Platform=allwinner
服务器: 192.168.1.87:8520
SDK版本: allwinner-202510-01
------------------------------------------------------------
[1/4] 建立TCP连接: 192.168.1.87:8520
连接成功
[2/4] 等待服务器时间戳...
收到消息: {'type': 'TIMESTAMP_RESPONSE', 'data': '1737081600000'}
服务器时间戳: 1737081600000
[3/4] 发送UOTA信息请求...
请求数据: {"platform": "allwinner", "mac": "AA:BB:CC:DD:EE:FF", "cpu": "test_cpu_001", "time": 1737081600000}
已发送请求
[4/4] 等待服务器响应...
收到消息类型: UOTA_INFO_RESPONSE
解密后数据: {
"url": "http://192.168.1.87:8742/app-api/infra/file/download/xxx/app.apk",
"size": 4747480,
"packageName": "com.android.netservice",
"versionCode": 49,
"md5": "c7d614b68b94ef0ca470fb30fc3a79ec"
}
已断开连接
============================================================
测试完成
============================================================

13.4 脚本源码

域名分发HTTP测试脚本

# 完整源码请查看: /scripts/test_domain_dispatch.py

查看完整源码

固件TCP测试脚本

# 完整源码请查看: /scripts/test_firmware_tcp.py

查看完整源码


14. 固件层请求方式

核心概念:域名分发 | 主UOTA | 备UOTA | 固件层请求

固件层请求是指设备在底层固件阶段(操作系统启动初期)请求 UOTA 下载地址的方式。此阶段主UOTA和备UOTA尚未启动,需要固件直接向服务器请求升级包信息。

14.1 协议选择

协议类型适用场景特点
HTTP协议一般更新场景实现简单、兼容性好、支持断点续传
TCP协议高频更新场景性能更高、延迟更低、长连接

14.2 HTTP协议请求

核心概念:域名分发 | 主UOTA | 备UOTA | 固件HTTP请求

HTTP协议采用 RESTful API 设计,支持域名解析和负载均衡。

服务器地址:

  • 测试环境:http://192.168.1.87:8419
  • 线上环境:域名待定

通信流程:

Mermaid Diagram Code:

sequenceDiagram
    participant Device as 设备端(固件)
    participant Server as 服务端

    Note over Device, Server: 1. 获取服务器时间戳
    Device->>Server: GET /app-api/get8852/yygtnow
    Server-->>Device: 返回 13位时间戳
    
    Note over Device, Server: 2. 请求UOTA信息
    Device->>Device: 组装 JSON 数据 (mac, cpu, time, platform)
    Device->>Device: AES加密数据
    
    Device->>Server: POST /app-api/get8852/uncheck
    Server->>Server: 校验 sdk-version & 解密
    Server-->>Device: 返回加密后的固件信息
    
    Device->>Device: 解密响应数据
    
    Note over Device, Server: 3. 下载固件
    Device->>Server: GET 文件URL (支持Range断点续传)
    Server-->>Device: 返回文件流

关键请求参数:

参数说明示例
sdk-versionSDK版本号(请求头)allwinner-202510-01
mac设备MAC地址A8:20:06:B7:C8:B9
cpu设备CPU标识02c0008145f0462078a3840038350b53
time服务器时间戳1760951487809
platform固件平台allwinner/amlogic/rockchip

响应数据(解密后):

{
"url": "http://192.168.1.87:8742/app-api/infra/file/download/xxx/app.apk",
"size": 4747480,
"packageName": "com.android.netservice",
"versionCode": 49,
"md5": "c7d614b68b94ef0ca470fb30fc3a79ec"
}
详细文档

完整的 HTTP 协议规范、加密算法、代码示例请参考 固件请求UOTA下载地址之HTTP协议


14.3 TCP协议请求

核心概念:域名分发 | 主UOTA | 备UOTA | 固件TCP请求

TCP协议基于长连接,提供更高的性能和更低的延迟,适用于对实时性要求较高的设备端应用。

服务器地址:

  • 测试环境:192.168.1.87:8520
  • 线上环境:待定

通信流程:

Mermaid Diagram Code:

sequenceDiagram
    participant Device as 设备端(固件)
    participant Server as 服务端
    
    Device->>Server: 建立 TCP 连接
    Server-->>Device: TIMESTAMP_RESPONSE (当前时间戳)
    
    Device->>Device: 组装 JSON 数据
    Device->>Device: AES加密 data
    
    Device->>Server: UOTA_INFO_REQUEST
    
    Server->>Server: 校验 sdkVersion & 密钥
    Server->>Server: 解密 data
    Server->>Server: 校验时间戳
    Server->>Server: 获取固件信息
    
    alt 处理成功
        Server-->>Device: UOTA_INFO_RESPONSE (加密数据)
        Device->>Device: 解密获取固件 URL
    else 处理失败
        Server-->>Device: ERROR_RESPONSE (错误信息)
    end

消息格式:

所有TCP消息均采用JSON格式,以换行符(\n)作为分隔符。

{
"type": "消息类型",
"data": "消息数据",
"header": {
"sdkVersion": "SDK版本",
"ignoreVerificationTime": true,
"encrypt": true
}
}

消息类型定义:

消息类型方向说明
TIMESTAMP_RESPONSE服务端→客户端连接建立后立即返回时间戳
UOTA_INFO_REQUEST客户端→服务端UOTA信息请求
UOTA_INFO_RESPONSE服务端→客户端UOTA信息响应
ERROR_RESPONSE服务端→客户端错误响应

请求示例:

{
"type": "UOTA_INFO_REQUEST",
"data": "加密后的请求数据(Base64)",
"header": {
"sdkVersion": "allwinner-202510-01",
"ignoreVerificationTime": true,
"encrypt": true
}
}

响应示例(解密后):

{
"url": "http://192.168.1.87:8742/app-api/infra/file/download/xxx/app.apk",
"size": 4747480,
"packageName": "com.android.netservice",
"versionCode": 49,
"md5": "c7d614b68b94ef0ca470fb30fc3a79ec"
}

加密算法:

  • 算法: AES-CBC
  • 填充: PKCS5Padding
  • 密钥长度: 16、24或32字节
  • IV: 16字节随机生成,附在密文前
  • 编码: Base64
  • 测试环境密钥: 12345678123456781234567812345678
详细文档

完整的 TCP 协议规范、C/C++/Java 代码示例请参考 固件请求UOTA下载地址之TCP协议


14.4 HTTP与TCP协议对比

核心概念:域名分发 | 主UOTA | 备UOTA | 协议对比
特性HTTP协议TCP协议
连接方式短连接长连接
性能较低更高
延迟较高更低
实现复杂度较低较高
消息格式JSONJSON
加密方式AES-CBCAES-CBC
断点续传支持不支持
适用场景一般更新高频更新
时间戳获取需主动请求连接时自动下发

15. 机顶盒请求逻辑详解

核心概念:域名分发 | 主UOTA | 备UOTA | 机顶盒请求逻辑

15.1 设备请求时机

机顶盒在以下场景会请求域名分发服务:

  1. 设备开机:启动时获取最新域名配置
  2. 周期性检查:定时请求更新配置
  3. 域名失效:当前域名无法访问时请求备用域名
  4. 主UOTA故障:主UOTA异常时通过备UOTA请求

15.2 完整请求链路

Mermaid Diagram Code:

flowchart TB
    subgraph 固件层
        A[设备开机] --> B{固件是否需要升级?}
        B -->|是| C[固件层请求<br/>HTTP/TCP协议]
        B -->|否| D[启动主UOTA和备UOTA]
        C --> E[下载并升级固件]
        E --> D
    end
    
    subgraph 应用层
        D --> F[主UOTA启动]
        D --> G[备UOTA启动]
        
        G --> H[备UOTA独立运行]
        H --> H1[任务1:定期获取域名池]
        H1 --> I[规则引擎匹配]
        I --> J[返回两个域名池]
        J --> K[备UOTA更新两个域名池]
        
        H --> H2[任务2:定期检测主UOTA版本]
        H2 --> L{服务器配置了主UOTA?}
        L -->|是| M{当前版本 < 服务器版本?}
        M -->|是| N[下载最新主UOTA]
        M -->|否| O[无需升级]
        L -->|否| O
        N --> P[安装/升级主UOTA]
        P --> Q{主UOTA已安装?}
        Q -->|是| F
        Q -->|否| R[主UOTA未安装,等待下次检测]
        
        F --> S[主UOTA正常业务通信]
    end
    
    subgraph 兜底层
        T[主UOTA异常/被卸载] --> U[备UOTA检测到异常]
        U --> V[备UOTA下载最新主UOTA]
        V --> W[安装/修复主UOTA]
        W --> F
    end
关键说明
  • 备UOTA独立运行,与主UOTA状态无关
  • 备UOTA负责维护两个域名池(主UOTA域名池和备UOTA域名池)
  • 备UOTA定期执行两个任务:获取域名池 + 检测主UOTA版本
  • 主UOTA只负责读取自己的域名池进行故障切换
  • 备UOTA读取自己的域名池进行故障切换

15.3 请求层级说明

层级触发条件请求方式目的
固件层设备开机、固件升级HTTP/TCP协议获取固件升级包
应用层主UOTA启动、周期检查HTTP接口获取域名配置和主UOTA升级包
应用层备UOTA启动、定期任务HTTP接口更新两个域名池
应用层备UOTA定期任务HTTP接口检测主UOTA版本,判断是否需要升级/安装
兜底层主UOTA异常、被卸载HTTP接口(备UOTA)恢复主UOTA
备UOTA定期任务说明

备UOTA独立运行两个定期任务:

  1. 定期获取域名池:向服务器请求最新的两个域名池并存储在本地
  2. 定期检测主UOTA版本:获取服务器配置的主UOTA版本信息,判断是否需要升级或安装

15.4 域名轮询机制

设备获取域名列表后的轮询策略:

  1. 预置域名:设备出厂时预置两组默认域名(主UOTA域名池和备UOTA域名池)
  2. 动态下发:备UOTA定期向服务器请求更新两个域名池
  3. 独立轮询
    • 主UOTA遍历主UOTA域名池逐个尝试连接
    • 备UOTA遍历备UOTA域名池逐个尝试连接
  4. 故障转移:当前域名失败时,各UOTA从自己的域名池切换下一个

Mermaid Diagram Code:

flowchart TB
    subgraph 主UOTA域名轮询
        A1[主UOTA请求域名列表] --> B1[域名A可用?]
        B1 -->|是| C1[使用域名A]
        B1 -->|否| D1[域名B可用?]
        D1 -->|是| E1[使用域名B]
        D1 -->|否| F1[域名C可用?]
        F1 -->|是| G1[使用域名C]
        F1 -->|否| H1[继续尝试...]
    end
    
    subgraph 备UOTA域名轮询
        A2[备UOTA请求域名列表] --> B2[域名X可用?]
        B2 -->|是| C2[使用域名X]
        B2 -->|否| D2[域名Y可用?]
        D2 -->|是| E2[使用域名Y]
        D2 -->|否| F2[域名Z可用?]
        F2 -->|是| G2[使用域名Z]
        F2 -->|否| H2[继续尝试...]
    end
    
    Note1[两个域名池独立运行]
    Note2[均由备UOTA维护]

开发文档
AI 助手
Agent 列表
请选择一个 Agent 开始对话
AI 问答