Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67fa393296 | ||
|
|
430a3e3381 | ||
|
|
9694b7586f | ||
|
|
e49bb9888f | ||
|
|
91e9b2e66b | ||
|
|
53d480c1fd | ||
|
|
0422d754a1 | ||
|
|
dfc738a699 | ||
|
|
3deb51d838 |
@@ -2,6 +2,9 @@
|
||||
/target/
|
||||
/version/
|
||||
|
||||
# Local legacy-board packages retained when switching to the new-board branch.
|
||||
/artifacts/legacy-no-gnss/
|
||||
|
||||
# Extracted toolchain and local compiler license; keep compile_tools.zip in LFS.
|
||||
/ql-cross-tool/win32/owtoolchain/
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# 旧板专用分支:legacy-board
|
||||
|
||||
此分支用于没有 GNSS 芯片的旧板,后续旧板修改在此分支维护。
|
||||
|
||||
`ql-config/config/board_features.h` 中 `NFC_GNSS_BOARD_HAS_GNSS` 默认为 `0`,
|
||||
跳过内核 GNSS 型号识别,关闭应用定位任务和定位模式切换。
|
||||
切换到此版本时必须重新编译并更新内核和 APP。
|
||||
|
||||
修改说明、构建步骤和板上验收要求见 [旧板说明](artifacts/legacy-no-gnss/README.md)。
|
||||
@@ -1,6 +0,0 @@
|
||||
# Local firmware exports, build logs, verification output and build-file backups.
|
||||
*.zip
|
||||
*.log
|
||||
*.disasm.txt
|
||||
/verification.json
|
||||
/build-backup/
|
||||
@@ -1,53 +0,0 @@
|
||||
# 无 GNSS 旧板调试版本
|
||||
|
||||
本分支名称为 `legacy-board`,用于后续无 GNSS 旧板开发。
|
||||
本目录的说明和验证脚本纳入版本控制;烧录包、日志、验证结果及备份仅保留在本地。
|
||||
|
||||
当前开关位于 `ql-config/config/board_features.h`:
|
||||
|
||||
```c
|
||||
#define NFC_GNSS_BOARD_HAS_GNSS 0
|
||||
```
|
||||
|
||||
- 内核不创建 `q_gocg` 型号识别任务,避免无定位芯片时触发 `gps_app.c` 的断言复位。
|
||||
- `app_gnss_init()` 不创建定位任务,包括联网成功后的调用。
|
||||
- `set_gnss_mode()` 忽略定位模式请求,避免无定位任务时无法退出 FAST 模式、阻止休眠。
|
||||
- 定位数据保持无效,不伪造坐标或定位成功状态。
|
||||
- 未保存音量时默认使用 100% 档位;已有保存音量时仍使用保存值。
|
||||
|
||||
在 SDK 根目录依次运行:
|
||||
|
||||
```bat
|
||||
build.bat kernel
|
||||
build.bat app
|
||||
build.bat firmware
|
||||
```
|
||||
|
||||
必须更新内核和 APP;只烧 APP 无法移除旧内核中的断言。
|
||||
烧录输入使用生成目录中的内层 ZIP,不使用包含 DBG 的外层归档。
|
||||
`original-EG800AKCN_11LG.zip` 是修改前外层归档的备份。
|
||||
|
||||
本次已导出可直接交给烧录工具的 `EG800AKCN_11LG-legacy-no-gnss.zip`
|
||||
(6,519,833 字节)。`EG800AKCN_11LG-legacy-no-gnss-debug.zip` 保存对应调试归档。
|
||||
仍沿用 EG800AKCN_11LG 的分区布局和 GNSS 资源文件;本修改关闭定位启动行为,
|
||||
不是更换模组型号或重做其他硬件的板级适配。
|
||||
|
||||
验证结果:内核、APP 和打包完成;内层 ZIP 的 CRC 检查通过;包内 `cp.bin`
|
||||
及 `customer_app.bin` 与本次构建输出逐字节一致;反汇编确认型号识别入口
|
||||
和应用定位初始化只输出日志,模式设置函数直接返回。
|
||||
详情和 SHA256 见 `verification.json`,构建日志及反汇编保存在同目录。
|
||||
本次未烧录设备,尚未完成板上功能验证。
|
||||
|
||||
重新构建后,将 `target/EG800AKCN_11LG/EG800AKCN_11LG.zip` 复制到本目录,
|
||||
命名为 `EG800AKCN_11LG-legacy-no-gnss.zip`,在 SDK 根目录执行:
|
||||
|
||||
```bat
|
||||
ql-cross-tool\win32\owtoolchain\Python\python.exe artifacts\legacy-no-gnss\verify_package.py
|
||||
```
|
||||
|
||||
恢复带 GNSS 板时将开关改为 `1`,重新编译内核和 APP 并打包。
|
||||
两份构建都必须重新编译对应 GNSS 源文件;检查日志,不要只依赖批处理退出码。
|
||||
|
||||
板上验收:启动后不再出现 `No model was found for val` / `q_gocg` 断言;
|
||||
联网后继续运行至少一分钟,并实际检查网络、音频和 NFC 等所需功能。
|
||||
构建成功不能代替上述板上验证。
|
||||
@@ -1,45 +0,0 @@
|
||||
"""Verify the exported legacy-board package against this SDK build."""
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import zipfile
|
||||
|
||||
output = Path(__file__).resolve().parent
|
||||
root = output.parent.parent
|
||||
package = output / "EG800AKCN_11LG-legacy-no-gnss.zip"
|
||||
objdump = root / "ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi/bin/arm-none-eabi-objdump.exe"
|
||||
report = {"package": package.name, "sha256": hashlib.sha256(package.read_bytes()).hexdigest()}
|
||||
app_symbols = subprocess.check_output(
|
||||
[str(objdump.with_name("arm-none-eabi-nm.exe")), str(root / "ql-application/threadx/build/app.elf")], text=True
|
||||
)
|
||||
printf_address = int(re.search(r"^([0-9a-fA-F]+) T printf$", app_symbols, re.MULTILINE).group(1), 16)
|
||||
with zipfile.ZipFile(package) as archive:
|
||||
assert archive.testzip() is None, "ZIP CRC failure"
|
||||
for entry, source in {
|
||||
"cp.bin": "ql-kernel/threadx/build/release_kernel.bin",
|
||||
"customer_app.bin": "ql-application/threadx/build/app.bin",
|
||||
}.items():
|
||||
data = archive.read(entry)
|
||||
assert data == (root / source).read_bytes(), f"Stale image: {entry}"
|
||||
report[entry] = {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
|
||||
report["download_manifest"] = json.loads(archive.read("download.json"))
|
||||
|
||||
for symbol, binary, required in [
|
||||
("quec_get_gnssid_task", "ql-kernel/threadx/build/kernel.axf", "<RTI_LOG>"),
|
||||
("app_gnss_init", "ql-application/threadx/build/app.elf", f"0x{printf_address | 1:08x}"),
|
||||
("set_gnss_mode", "ql-application/threadx/build/app.elf", "bx\tlr"),
|
||||
]:
|
||||
disassembly = subprocess.check_output(
|
||||
[str(objdump), "-d", f"--disassemble={symbol}", str(root / binary)], text=True
|
||||
)
|
||||
assert f"<{symbol}>:" in disassembly, f"Missing function: {symbol}"
|
||||
assert required in disassembly, f"Unexpected function body: {symbol}"
|
||||
assert "task_create" not in disassembly, f"Task still created: {symbol}"
|
||||
(output / f"{symbol}.disasm.txt").write_text(disassembly, encoding="utf-8")
|
||||
report["verification"] = "PASS: ZIP CRC, kernel and APP byte identity, GNSS entry disassembly"
|
||||
report["hardware_test"] = "Not performed"
|
||||
(output / "verification.json").write_text(json.dumps(report, indent=2), encoding="utf-8")
|
||||
print(report["verification"])
|
||||
print("SHA256:", report["sha256"])
|
||||
+11
-7
@@ -1,9 +1,13 @@
|
||||
# 旧板 WSS 联调包
|
||||
# WSS 联调包
|
||||
|
||||
最新优化包为 `full-handshake/EG800AKCN_11LG-legacy-wss-x25519.zip`,供无 GNSS 旧板联调,默认连接 `wss://banban.api.talkingq.com:443/ws`。默认音量仍为 100(已有保存值按原逻辑读取)。这是完整多分区包,沿用上一版 NIST 加速内核,APP 调整 WSS 的 ECDHE 曲线优先级为 X25519 优先,保留其他已启用曲线作为回退。每次仍执行完整握手,按键后建连。
|
||||
最新域名试验包:new-board/mqtt-domain/EG800AKCN_11LG-new-board-wss-mqtt-domain.zip。MQTT 改为 banban.api.talkingq.com:1883,保留诊断日志;用户已确认改域名后新板连接成功,详细成功日志和其他业务验收尚未提供。
|
||||
|
||||
2026-09-16 14:38 板端确认 NIST 加速后完整 TLS 握手为 1820 ms;15:52 补充日志进一步确认 X25519 实际协商为 group=9,客户端密钥交换从 445 ms 降至 135 ms,完整 TLS 握手降至 1455 ms,HTTP 101 正常。两份日志样本中 TLS 再缩短约 20%。包校验与 SHA-256 见 `full-handshake/verification.json`;其中待上板字段为生成时历史状态,新增运行证据见 [完整总结](D:/banban/project/nfc_gnss/docs/WSS适配与性能优化完整总结.md)。
|
||||
|
||||
2026-09-16 11:32 复测:443 `/ws` 已返回 HTTP 101,TLS 和证书校验通过;8080 仍是明文 WS。`tls-speed/EG800AKCN_11LG-legacy-wss-fast.zip`(1820 ms)和 `recv-fix/EG800AKCN_11LG-legacy-wss-recv.zip` 均保留作已上板通过的回退版本。本目录原 `EG800AKCN_11LG-legacy-wss.zip` 缺少 ECDSA,`ecc-fix` 包存在接收误判,均仅用于历史对照。
|
||||
|
||||
原旧板包保留在 `../legacy-no-gnss/`。构建日志、探测 JSON、导出的公共证书和包体在此目录本地保存并被 Git 忽略。源码和详细步骤见 `../../docs/talkingq_wss.md`。
|
||||
最新网络诊断包:new-board/mqtt-diag/EG800AKCN_11LG-new-board-wss-mqtt-diag.zip。沿用新板 WSS 内核,APP 补充 MQTT 收发、CONNACK 和语音键网络准入日志,具体根因待新板日志确认。
|
||||
|
||||
当前 main 对应新板,下载包为 [EG800AKCN_11LG-new-board-wss-x25519.zip](D:/banban/project/nfc_gnss/artifacts/wss/new-board/EG800AKCN_11LG-new-board-wss-x25519.zip)。这是包含本次内核和 APP 的完整多分区包,默认连接 `wss://banban.api.talkingq.com:443/ws`,保留新板 GNSS。音量沿用原 main 逻辑,读取不到保存值时回退至 70。
|
||||
|
||||
新板已经完成内核、APP、固件打包和主机/静态验证,尚待新板上板测试。包哈希、镜像一致性、GNSS 任务入口、TLS 算法与时间检查结果见 `new-board/verification.json`;迁移说明见 [新板 WSS 文档](D:/banban/project/nfc_gnss/docs/new_board_wss.md)。
|
||||
|
||||
旧板包 `full-handshake/EG800AKCN_11LG-legacy-wss-x25519.zip` 保持原样,属于无 GNSS、默认音量 100 的旧板配置。旧板 2026-09-16 日志确认 X25519 完整 TLS 握手 1455 ms;该数值不是新板实测结果。旧板 NIST 版本、接收修复版本及更早实验包保留用于历史追溯。完整旧板过程见 [旧板总结](D:/banban/project/nfc_gnss/docs/WSS适配与性能优化完整总结.md)。
|
||||
|
||||
构建日志、测试报告、公共证书和包体在本目录本地保存并被 Git 忽略;提交源码与文档不会把这些本地包一并上传。
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
@echo off
|
||||
set CURDIR=%~dp0
|
||||
set time0=%time: =0%
|
||||
set hour=%time0:~0,2%
|
||||
set appbuildtime=%date:~0,4%%date:~5,2%%date:~8,2%%hour%%time:~3,2%%time:~6,2%
|
||||
for /f %%i in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMddHHmmss"') do set appbuildtime=%%i
|
||||
set appbuildrev=NULL
|
||||
set appbuildmodel=EG800AKCN_11LG
|
||||
set appbuildver=beta1
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 旧板 WSS 适配、故障修复与性能优化完整总结
|
||||
|
||||
> 新板 main 说明:本文保留旧板历史过程、配置与实测数据。新板已迁入 WSS,保留 GNSS 与原 main 音量行为;新板构建、下载包及验收请见 [新板 WSS 迁移说明](D:/banban/project/nfc_gnss/docs/new_board_wss.md)。旧板实测耗时不代表新板实测。
|
||||
|
||||
> 整理日期:2026-09-16;设备日志时间按用户提供的串口时间记录。
|
||||
>
|
||||
> 工作区:`D:\banban\project\nfc_gnss`。分支:`legacy-board-wss`。本文覆盖的最新代码提交:`551a7bb1e657c12f45ac0a1f2ca851625723a63d`。
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
# 新板 main 分支 WSS 迁移说明
|
||||
|
||||
> 最新上板反馈(2026-09-16):用户确认将 MQTT 改为 banban.api.talkingq.com:1883 后已连接成功。该反馈支持域名访问方式适配新板受限 eSIM 的判断;未提供本次成功日志,本文不据此宣称 GNSS、全部业务及 WSS 性能均已验收。
|
||||
|
||||
更新日期:2026-09-16。适用工作区:`D:\banban\project\nfc_gnss`,分支:`main`。
|
||||
|
||||
## 1. 迁移范围
|
||||
|
||||
以原主分支 `2746cc3d4ebbd90f8fa0c1e68db93b199b297714` 的新板代码为基础,迁入旧板已经完成联调的 WSS 实现、故障修复、完整握手优化与测试工具。新板仍使用自身的 GNSS 检测和定位任务。
|
||||
|
||||
| 旧板来源提交 | 迁入内容 |
|
||||
| --- | --- |
|
||||
| `3e463f5` | WSS 地址解析、可信根 CA、服务器证书及域名验证、WebSocket Upgrade 校验 |
|
||||
| `5c3e7ee` | 内核 ECDSA/GCM 能力、APP 与内核共享配置、RTC 证书日期校验、TLS 接收重试修复 |
|
||||
| `3a0714c` | NIST 曲线模约减加速、握手阶段计时、连接循环日志修正 |
|
||||
| `551a7bb` | 完整握手优先协商 X25519,保留原有其他曲线作为回退 |
|
||||
| `54bf67c` | 旧板联调过程、算法说明与实测总结,作为历史资料保留 |
|
||||
|
||||
这些提交的修改迁入工作区,不直接合并旧板分支。旧板关闭 GNSS 的提交 `f283223` 和音量改为 100 的提交 `4b56595` 未迁入。
|
||||
|
||||
## 2. 新板硬件与业务行为
|
||||
|
||||
- 内核 `quec_get_gnssid_task()` 仍创建 GNSS 型号识别任务 `quec_get_ocname_by_gnss_task`。
|
||||
- APP `app_gnss_init()` 仍创建定位任务 `quec_gnss_test`,`set_gnss_mode()` 仍更新定位模式。
|
||||
- `audio.c` 与原主分支一致:音量优先读取设备保存值,读取失败时回退至 70。
|
||||
- 设备身份仍沿用 `device_id` / `serial_number`,不改后台鉴权格式。
|
||||
- 按键触发连接;每次新连接仍执行完整 TLS 握手,没有提前建连或新增会话恢复逻辑。
|
||||
|
||||
## 3. WSS 与密码算法
|
||||
|
||||
默认地址:`wss://banban.api.talkingq.com:443/ws`。
|
||||
|
||||
使用 TLS 1.2,配置 ISRG Root X2 公共根 CA,验证服务器证书链、有效期和主机名。单向 TLS 不需要设备客户端证书,但服务器证书校验仍必须通过。WebSocket 层继续验证 HTTP 101 与 `Sec-WebSocket-Accept`。
|
||||
|
||||
内核提供 ECDSA 签名验证、ECDHE 密钥交换及 AES-GCM 等能力。APP 和内核共用 `talkingq_mbedtls_config.h`,避免跨边界使用 mbedTLS 结构体时因宏配置不同导致布局不一致。证书时间检查使用真实 RTC 和 UTC 转换,不再依赖原空时间实现。
|
||||
|
||||
ECDHE 优先使用 X25519;证书签名算法不因此改变。NIST 优化针对证书链和回退曲线的有限域计算,X25519 优化针对临时密钥交换,二者可同时受益。服务器最终选择的曲线以设备协商日志为准。
|
||||
|
||||
TLS 非阻塞读写返回 `WANT_READ` / `WANT_WRITE` 时继续等待或重试,不把暂时没有数据误判为连接断开。工作线程使用 16 KiB 栈,并保留完整握手总耗时、各阶段耗时及协商信息日志。
|
||||
|
||||
更多算法和问题根因见 [旧板完整总结](D:/banban/project/nfc_gnss/docs/WSS适配与性能优化完整总结.md)。其中的默认音量、关闭 GNSS 和实测性能均属于旧板历史。
|
||||
|
||||
## 4. 构建与切分支缓存
|
||||
|
||||
从原新板 main 升级至此版本,需要同时更新内核和 APP,因为原内核没有本次补齐的完整 TLS 算法与配置。不能只编译 APP 并沿用原 main 内核。
|
||||
|
||||
在仓库根目录执行:
|
||||
|
||||
```bat
|
||||
build.bat kernel
|
||||
build.bat app
|
||||
build.bat firmware
|
||||
```
|
||||
|
||||
首次切换发现旧 GNSS `.d` 文件仍引用旧板专用 `board_features.h`,导致内核构建提示依赖不存在。这是跨分支残留编译缓存,不是新板缺失硬件配置。处理方法为备份并移走内核 `gps_app` 和 APP `gnss` 的旧 `.o`、`.d` 文件,再重新构建;没有添加旧板配置头或跳过 GNSS 编译。
|
||||
|
||||
本次缓存备份和构建日志位于 `artifacts/wss/new-board/`。SDK 生成的诊断对象和链接反馈文件另行备份,包生成后恢复其原始受版本控制的内容,避免把构建副产物混入源码修改。
|
||||
|
||||
`build.bat firmware` 生成完整多分区固件包。提供的下载包来自 `target/EG800AKCN_11LG/EG800AKCN_11LG.zip` 内层 ZIP;它不是仅含 APP 的更新包。
|
||||
|
||||
## 5. 产物与验证
|
||||
|
||||
新板包:[EG800AKCN_11LG-new-board-wss-x25519.zip](D:/banban/project/nfc_gnss/artifacts/wss/new-board/EG800AKCN_11LG-new-board-wss-x25519.zip)。
|
||||
|
||||
本地验证报告:[verification.json](D:/banban/project/nfc_gnss/artifacts/wss/new-board/verification.json)。该报告记录包 SHA-256、镜像大小和哈希、下载清单及检查结果。
|
||||
|
||||
验证覆盖:
|
||||
|
||||
- WSS URL、HTTP Upgrade、TLS 读写及接收回归测试。
|
||||
- APP/内核 mbedTLS ABI、实际 SDK 证书链验证及 ECDH 运算测试。
|
||||
- ZIP CRC,以及包内 `cp.bin`、`customer_app.bin` 与本次构建输出逐字节一致性。
|
||||
- 最终 ELF 中 ECDSA、GCM、NIST 优化、RTC 时间转换和 WSS 关键符号。
|
||||
- 反汇编确认 GNSS 识别及定位入口仍创建任务,且对应 worker 存在;新板镜像不包含旧板跳过 GNSS 的日志标记。
|
||||
|
||||
主机算法测试仅证明算法与配置可用,不能代替设备端速度测量。构建和静态校验也不代表已经完成新板上电、定位或语音业务测试。
|
||||
|
||||
## 6. 上板验收与影响
|
||||
|
||||
新板仍需验证正常启动、GNSS 识别、定位任务和语音业务。WSS 日志应出现证书/域名验证成功、HTTP 101,以及原有设备身份发送流程。关注 RTC 是否有效、网络信号、完整握手协商曲线与各阶段耗时。
|
||||
|
||||
旧板实测从最初约 9.6 秒 TLS 握手,经 NIST 优化降至 1820 ms,再经 X25519 优化降至 1455 ms。上述数据不能直接标注为新板测试结果;新板 GNSS 等任务可能影响调度和 CPU 负载,需要采集新日志比较。
|
||||
|
||||
证书校验继续要求正确时间、匹配域名和受信任证书链;未来后台更换证书链或根 CA 时需要复核。共享 TLS 配置改变了内核密码能力,其他使用相同内核接口的模块也需在新板回归时观察。
|
||||
|
||||
旧板分支和历史包保留,供旧板使用与回溯。新板使用本说明中的独立包目录,避免与 `artifacts/wss/full-handshake/` 的旧板包混淆。
|
||||
|
||||
|
||||
## 7. MQTT 连接诊断版本(2026-09-16)
|
||||
|
||||
新板 16:43 日志确认拨号获得 IP,但 MQTTConnect 返回 -1。语音键被识别后,因现有入口要求“拨号在线且 MQTT 在线”,播放网络检查提示,尚未发起 WSS。本轮增加连接诊断,GNSS 及网络准入、鉴权、重连策略保持原逻辑。
|
||||
|
||||
诊断包:[EG800AKCN_11LG-new-board-wss-mqtt-diag.zip](D:/banban/project/nfc_gnss/artifacts/wss/new-board/mqtt-diag/EG800AKCN_11LG-new-board-wss-mqtt-diag.zip)。这是完整多分区包;内核与上一新板 WSS 包逐字节相同,APP 增加日志。已刷入上一新板 WSS 内核时,本轮只需 build.bat app 和 build.bat firmware,无需重编内核。报告和构建日志位于包的同一目录。
|
||||
|
||||
| 日志 | 含义 |
|
||||
| --- | --- |
|
||||
| [MQTT-DIAG] TCP begin/end | MQTT 服务地址、端口、拨号状态、连接返回值与耗时 |
|
||||
| CONNECT begin | 协议版本、会话选项、超时及 SDK 客户端状态 |
|
||||
| write request / rc | SDK 写回调请求及返回字节数;负值表示失败 |
|
||||
| read request / rc | SDK 读回调返回值及耗时;0 或负值不等于鉴权拒绝 |
|
||||
| CONNECT end | MQTT 最终返回值、总耗时、读写次数及字节数 |
|
||||
| CONNACK code=0 | 服务端接受连接 |
|
||||
| CONNACK code=1/2/3/4/5 | 协议版本不支持 / Client ID 被拒绝 / 服务不可用 / 用户名或密码错误 / 未授权 |
|
||||
| no response bytes returned by SDK read | SDK 读回调未返回有效字节,不能单凭此项断定服务端原因 |
|
||||
| no valid initial CONNACK | 已收到数据,但开头不构成完整合法 CONNACK |
|
||||
| failed before transport write | 尚未调用发送回调,优先检查客户端状态或 CONNECT 序列化 |
|
||||
| [NET-GATE] blocked_mqtt_offline | 按键已识别,但 MQTT 未在线,因此未尝试 WSS |
|
||||
| [NET-GATE] start_voice | 通过网络准入,进入原语音流程 |
|
||||
|
||||
SDK 读回调把 EOF 和部分 socket 错误统一映射为 -1。errno_snapshot 是即时读取的错误快照,可能残留旧值,不能单凭它断言服务端拒绝或关闭。只有完整合法 CONNACK 中的拒绝码才作为服务端拒绝证据。诊断只观察原回调,不替换底层 socket 实现。
|
||||
|
||||
诊断仅在同步 MQTT CONNECT 期间挂接原有读写回调,结束即恢复,随后才启动 MQTT 后台线程。代码不打印 CONNECT 原文、账号、密码或业务报文,仅暂存接收开头四字节用于识别 CONNACK。诊断状态按现有单一 MQTT 连接工作线程的串行使用约束实现。
|
||||
|
||||
在 Visual Studio 开发命令行运行 tools/test_mqtt_diag.py,可测试参数和返回值透传、成功与失败后回调恢复、分片 CONNACK、服务端拒绝、无效响应、读写错误、无发送提前返回、时钟回绕,以及凭据测试标记不出现在日志中。
|
||||
|
||||
APP 构建、诊断测试和固件镜像校验已通过。SDK 原有隐式声明等编译警告仍存在,本轮没有修改这些接口。具体 MQTT 根因仍需新板运行诊断包后取得日志。
|
||||
|
||||
## 8. MQTT 域名试验版本(2026-09-16)
|
||||
|
||||
根据新板使用受限 eSIM 的情况,将 mqtt.c 中 DEFAULT_SERVER_DOMAIN 从 101.35.224.118 改为 banban.api.talkingq.com,端口仍为 1883,沿用明文 MQTT 和原有鉴权、注册流程。保留 MQTT-DIAG 与 NET-GATE 日志。
|
||||
|
||||
电脑侧已验证该域名解析到 101.35.224.118,使用固件现有账号、临时 Client ID 可收到 CONNACK=0。该结果不能代替新板 eSIM 白名单验证:若卡商还限制端口或协议,仅改域名可能仍无法通过。
|
||||
|
||||
本次包:[EG800AKCN_11LG-new-board-wss-mqtt-domain.zip](D:/banban/project/nfc_gnss/artifacts/wss/new-board/mqtt-domain/EG800AKCN_11LG-new-board-wss-mqtt-domain.zip)。内核与上一诊断包相同,APP 编译、固件打包和镜像校验通过;用户随后确认改域名后已连接成功。已使用本轮新板 WSS 内核时,只需 build.bat app 和 build.bat firmware。本包仍是完整多分区包。
|
||||
|
||||
开机应看到 [MQTT-DIAG] TCP begin host=banban.api.talkingq.com port=1883。随后观察 CONNACK、设备注册和按语音键后的 WSS 连接结果。本轮不更改提示音下载地址。
|
||||
@@ -1,5 +1,7 @@
|
||||
# 旧板 WSS 适配与联调
|
||||
|
||||
> 新板 main 说明:本文保留旧板历史过程、配置与实测数据。新板已迁入 WSS,保留 GNSS 与原 main 音量行为;新板构建、下载包及验收请见 [新板 WSS 迁移说明](D:/banban/project/nfc_gnss/docs/new_board_wss.md)。旧板实测耗时不代表新板实测。
|
||||
|
||||
本次修改位于 `legacy-board-wss`(基于 `legacy-board`),默认地址为 `wss://banban.api.talkingq.com:443/ws`。沿用无 GNSS、默认音量 100 的旧板配置。上板暴露内核缺少 ECDSA 后,已补齐内核 TLS 能力并统一 APP/内核配置;从原明文旧板版本升级时必须更新内核和 APP。已有匹配 NIST 加速内核时,最新 X25519 调整只需更新 APP。
|
||||
|
||||
完整的问题根因、算法、提交、性能数据和影响说明见 [WSS 适配与性能优化完整总结](D:/banban/project/nfc_gnss/docs/WSS适配与性能优化完整总结.md)。2026-09-16 15:52 最新板端已确认 X25519 协商、完整 TLS 握手 1455 ms 和 HTTP 101。
|
||||
|
||||
@@ -81,6 +81,7 @@ SRC_FILES+= \
|
||||
nfc.c \
|
||||
DP1312EA.c \
|
||||
mqtt.c \
|
||||
mqtt_connect_diag.c \
|
||||
vad_det.c \
|
||||
sleep_wake.c \
|
||||
battery.c \
|
||||
|
||||
@@ -414,9 +414,9 @@ uint8_t app_get_volume(void)
|
||||
printf("get volume:%d, ret:%d\r\n", value, ret);
|
||||
//ret = read_volume_file(&value, 1);
|
||||
if(ret<0){
|
||||
g_cur_volume = 100;
|
||||
g_cur_volume = 70;
|
||||
hal_kv_set("volume", &g_cur_volume, 1);
|
||||
return VOLUME_100;
|
||||
return VOLUME_70;
|
||||
}
|
||||
|
||||
g_cur_volume = value;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "sockets.h"
|
||||
#include "netdb.h"
|
||||
#include "app_inc.h"
|
||||
#include "../../../../ql-config/config/board_features.h"
|
||||
|
||||
// 新增宏定义(原代码中未定义)
|
||||
#define GNSS_FAST_MODE_HOLD_TIME (5 * 60 * 1000) // FAST模式持续5分钟后切SLOW
|
||||
@@ -321,14 +320,9 @@ void quec_gnss_callback(char *data, int len)
|
||||
*===========================================================================*/
|
||||
void set_gnss_mode(gnss_mode_t mode)
|
||||
{
|
||||
#if !NFC_GNSS_BOARD_HAS_GNSS
|
||||
(void)mode;
|
||||
return; /* No GNSS task exists to leave FAST mode and allow sleep. */
|
||||
#else
|
||||
g_gnss_mode = mode;
|
||||
printf("[GNSSMode] Set to %s Mode\n",
|
||||
(mode == GNSS_MODE_FAST) ? "Fast (30s)" : "Slow (5min)");
|
||||
#endif
|
||||
}
|
||||
|
||||
gnss_mode_t get_gnss_mode(void)
|
||||
@@ -537,11 +531,6 @@ static void quec_gnss_test(void * argv)
|
||||
|
||||
void app_gnss_init(void)
|
||||
{
|
||||
#if !NFC_GNSS_BOARD_HAS_GNSS
|
||||
printf("[GNSS] Legacy board: positioning disabled\n");
|
||||
return;
|
||||
#else
|
||||
ql_task_t gnssTaskRef = NULL;
|
||||
ql_rtos_task_create(&gnssTaskRef, 1024*4, 100, "gnss_Task_Ref", quec_gnss_test, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ extern int fota_start;
|
||||
#define KEY_LONG_PRESS_1S 1000/5
|
||||
#define KEY_LONG_PRESS_1_5S 1500/5
|
||||
#define KEY_LONG_PRESS_3S 3000/5
|
||||
#define PWRKEY_SOFT_SHUTDOWN_TEST 8000/5
|
||||
#define KEY_LONG_PRESS_5S 5000/5
|
||||
#define KEY_LONG_PRESS_10S 10000/5
|
||||
|
||||
@@ -114,7 +115,7 @@ static void key_thread_entry(void *parameter)
|
||||
if(level!=0){ //up
|
||||
key_press_mic_status = 0;
|
||||
|
||||
if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S){
|
||||
if(ql_rtos_get_systicks() - key_press_mic_time > PWRKEY_SOFT_SHUTDOWN_TEST){
|
||||
//app_play_tips_file(10);
|
||||
// power_down_status = 1;
|
||||
ql_rtos_task_sleep_s(3);
|
||||
@@ -126,7 +127,12 @@ static void key_thread_entry(void *parameter)
|
||||
app_set_app_operation(1);
|
||||
}
|
||||
|
||||
if(app_get_data_call_net_status()&&get_mqtt_connect_status()==1){
|
||||
int mic_pdp = app_get_data_call_net_status();
|
||||
int mic_mqtt = get_mqtt_connect_status();
|
||||
printf("[NET-GATE] mic pdp=%d mqtt=%d action=%s\r\n",
|
||||
mic_pdp, mic_mqtt,
|
||||
!mic_pdp ? "blocked_no_pdp" : (mic_mqtt != 1 ? "blocked_mqtt_offline" : "start_voice"));
|
||||
if(mic_pdp && mic_mqtt == 1){
|
||||
if(tts_play_interrupt_func()==-2){
|
||||
app_play_tips_file(2);
|
||||
}
|
||||
@@ -143,7 +149,7 @@ static void key_thread_entry(void *parameter)
|
||||
key_press_mic_status = 1;//表示已经按下了
|
||||
}
|
||||
|
||||
if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S && power_down_status==0){
|
||||
if(ql_rtos_get_systicks() - key_press_mic_time > PWRKEY_SOFT_SHUTDOWN_TEST && power_down_status==0){
|
||||
power_down_status = 1;
|
||||
app_play_tips_file(10);
|
||||
power_down_status = 2;
|
||||
|
||||
@@ -36,7 +36,7 @@ const char *mp3_file[] ={
|
||||
"ai_active_zh.mp3",//18
|
||||
};
|
||||
|
||||
//http://175.24.73.253/assets/roles/zhuli/zh/tts_error.mp3
|
||||
//http://banban.api.talkingq.com:8080/assets/roles/banban/tts_error.mp3
|
||||
|
||||
//#define PCM_FILE "http://47.113.99.138:7050/output_16k.pcm"
|
||||
|
||||
@@ -194,7 +194,7 @@ void app_file_check_download(void)
|
||||
if(ql_access(filename_buff, 0)!=0){
|
||||
printf("downing mp3 file %d,%s\r\n", index,filename_buff);
|
||||
down_loop:
|
||||
sprintf(url_buff, "http://101.35.224.118:8080/assets/roles/banban/%s", mp3_file[index]);
|
||||
sprintf(url_buff, "http://banban.api.talkingq.com:8080/assets/roles/banban/%s", mp3_file[index]);
|
||||
|
||||
ret = http_file_download(url_buff);
|
||||
if(ret!=0&&cnt++<3) goto down_loop;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef TALKINGQ_MQTT_CONNECT_DIAG_H
|
||||
#define TALKINGQ_MQTT_CONNECT_DIAG_H
|
||||
|
||||
#include "MQTTClient.h"
|
||||
|
||||
/* Called by the single MQTT connection worker, before MQTTStartTask(). */
|
||||
int talkingq_mqtt_connect_diagnosed(MQTTClient *client, MQTTPacket_connectData *options);
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
=================================================================*/
|
||||
|
||||
#include "MQTTClient.h"
|
||||
#include "mqtt_connect_diag.h"
|
||||
#include "ql_data_call.h"
|
||||
#include "ql_application.h"
|
||||
#include "sockets.h"
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
#define PROFILE_IDX 1
|
||||
//#define DEFAULT_SERVER_DOMAIN "175.24.73.253"
|
||||
#define DEFAULT_SERVER_DOMAIN "101.35.224.118"
|
||||
#define DEFAULT_SERVER_DOMAIN "banban.api.talkingq.com"
|
||||
#define DEFAULT_SERVER_CLIENT_USER "talkingq"
|
||||
#define DEFAULT_SERVER_CLIENT_PASS "talkingq@2026"
|
||||
#define DEFAULT_SERVER_CLIENT_ID "9376265c059e474e92c2e46208ae1dc5"
|
||||
@@ -367,7 +368,7 @@ int parse_event_response(const char *json_str, response_t *resp)
|
||||
}
|
||||
else {
|
||||
// ===== 原有逻辑: NFC事件 - 动态查找 url_x 字段 =====
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
char key[16];
|
||||
snprintf(key, sizeof(key), "url_%d", i);
|
||||
cJSON *url = cJSON_GetObjectItem(params, key);
|
||||
@@ -390,11 +391,12 @@ int parse_event_response(const char *json_str, response_t *resp)
|
||||
|
||||
|
||||
/* [FIX] 安全处理 topic 名称,避免越界访问 */
|
||||
static void messageArrived(MessageData* data)
|
||||
{
|
||||
int ret;
|
||||
uint32 queue_count = 0;
|
||||
app_work_item *work_item;
|
||||
static void messageArrived(MessageData* data)
|
||||
{
|
||||
int ret;
|
||||
int payload_log_len;
|
||||
uint32 queue_count = 0;
|
||||
app_work_item *work_item;
|
||||
|
||||
// 安全获取 topic 字符串(复制到本地缓冲区)
|
||||
char topic_buf[128] = {0};
|
||||
@@ -402,10 +404,16 @@ static void messageArrived(MessageData* data)
|
||||
if (topic_len >= sizeof(topic_buf)) {
|
||||
topic_len = sizeof(topic_buf) - 1;
|
||||
}
|
||||
memcpy(topic_buf, data->topicName->lenstring.data, topic_len);
|
||||
topic_buf[topic_len] = '\0';
|
||||
|
||||
// 比较 topic 类型
|
||||
memcpy(topic_buf, data->topicName->lenstring.data, topic_len);
|
||||
topic_buf[topic_len] = '\0';
|
||||
|
||||
payload_log_len = data->message->payloadlen > 512 ? 512 : (int)data->message->payloadlen;
|
||||
printf("[MQTT-RX] topic=%s len=%d payload=%.*s%s\r\n",
|
||||
topic_buf, (int)data->message->payloadlen, payload_log_len,
|
||||
(const char *)data->message->payload,
|
||||
data->message->payloadlen > (unsigned int)payload_log_len ? "..." : "");
|
||||
|
||||
// 比较 topic 类型
|
||||
int is_command = (strstr(topic_buf, "command") != NULL);
|
||||
int is_event_resp = (strstr(topic_buf, "event_resp") != NULL) || (strstr(topic_buf, imei_buf) != NULL);
|
||||
|
||||
@@ -448,6 +456,8 @@ int app_mqtt_connect()
|
||||
|
||||
MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
|
||||
int mqtt_server_port=DEFAULT_SERVER_PORT;
|
||||
unsigned int tcp_started;
|
||||
int tcp_errno;
|
||||
|
||||
MQTT_CONN_LOCK();
|
||||
if(mqtt_connect==1){
|
||||
@@ -462,7 +472,14 @@ int app_mqtt_connect()
|
||||
NetworkInit(&network, NULL, PROFILE_IDX);
|
||||
MQTTClientInit(&client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf));
|
||||
char* address = DEFAULT_SERVER_DOMAIN;
|
||||
if ((rc = NetworkConnect(&network, address, mqtt_server_port)) != 0)
|
||||
printf("[MQTT-DIAG] TCP begin host=%s port=%d pdp=%d\r\n",
|
||||
address, mqtt_server_port, app_get_data_call_net_status());
|
||||
tcp_started = ql_rtos_get_systicks();
|
||||
rc = NetworkConnect(&network, address, mqtt_server_port);
|
||||
tcp_errno = rc != 0 ? ql_get_soc_errno() : 0;
|
||||
printf("[MQTT-DIAG] TCP end rc=%d socket=%d elapsed_ms=%u errno_snapshot=%d\r\n",
|
||||
rc, network.my_socket, (unsigned int)(ql_rtos_get_systicks() - tcp_started) * 5U, tcp_errno);
|
||||
if (rc != 0)
|
||||
{
|
||||
RLOGE("Return code from network connect is %d", rc);
|
||||
MQTTClientDeinit(&client);
|
||||
@@ -486,7 +503,8 @@ int app_mqtt_connect()
|
||||
connectData.cleansession = 0;
|
||||
connectData.keepAliveInterval = 60;
|
||||
|
||||
if ((rc = MQTTConnect(&client, &connectData)) != 0)
|
||||
printf("[MQTT-DIAG] saved_device_id=%d (registration needed when 0)\r\n", ret == 0);
|
||||
if ((rc = talkingq_mqtt_connect_diagnosed(&client, &connectData)) != 0)
|
||||
{
|
||||
RLOGE("Return code from MQTT connect is %d", rc);
|
||||
NetworkDisconnect(&network);
|
||||
@@ -607,15 +625,33 @@ sub_exit:
|
||||
//0:代表respone command
|
||||
//1:代表send event
|
||||
/* [FIX] 将连接状态检查和发送放在同一锁保护区内,避免竞争 */
|
||||
int app_mqtt_publish(char *buf, int len, int type)
|
||||
{
|
||||
static uint32_t mqtt_pub_cnt_err=0;
|
||||
int rc = -1;
|
||||
MQTTMessage message;
|
||||
int cnt = 0;
|
||||
static uint8_t publish_error = 0;
|
||||
|
||||
// 锁保护:检查连接状态并发送
|
||||
int app_mqtt_publish(char *buf, int len, int type)
|
||||
{
|
||||
static uint32_t mqtt_pub_cnt_err=0;
|
||||
int rc = -1;
|
||||
int payload_log_len;
|
||||
MQTTMessage message;
|
||||
int cnt = 0;
|
||||
static uint8_t publish_error = 0;
|
||||
const char *publish_topic = NULL;
|
||||
|
||||
if (type == 0) {
|
||||
publish_topic = respone_topicName;
|
||||
} else if (type == 1) {
|
||||
publish_topic = event_topicName;
|
||||
} else if (type == 2) {
|
||||
publish_topic = event_register;
|
||||
} else {
|
||||
RLOGE("invalid MQTT publish type=%d", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
payload_log_len = len > 512 ? 512 : len;
|
||||
printf("[MQTT-TX] topic=%s len=%d payload=%.*s%s\r\n",
|
||||
publish_topic, len, payload_log_len, buf,
|
||||
len > payload_log_len ? "..." : "");
|
||||
|
||||
// 锁保护:检查连接状态并发送
|
||||
int lock_ret = ql_rtos_mutex_lock(g_mqtt_public_mutex, 5000);
|
||||
if (lock_ret != 0) {
|
||||
RLOGE("MQTT mutex lock timeout");
|
||||
@@ -632,18 +668,13 @@ int app_mqtt_publish(char *buf, int len, int type)
|
||||
message.payload = buf;
|
||||
message.payloadlen = len;
|
||||
|
||||
while (cnt++ < 3) {
|
||||
u32 start = ql_rtos_get_systicks();
|
||||
if (type == 0) {
|
||||
rc = MQTTPublish(&client, respone_topicName, &message);
|
||||
} else if (type == 1) {
|
||||
rc = MQTTPublish(&client, event_topicName, &message);
|
||||
} else if (type == 2) {
|
||||
rc = MQTTPublish(&client, event_register, &message);
|
||||
}
|
||||
|
||||
RLOGD("Pulish time:%d len: %d\n", (ql_rtos_get_systicks()-start)*5, len);
|
||||
if (rc != 0) {
|
||||
while (cnt++ < 3) {
|
||||
u32 start = ql_rtos_get_systicks();
|
||||
rc = MQTTPublish(&client, publish_topic, &message);
|
||||
|
||||
RLOGD("Pulish time:%d len: %d\n", (ql_rtos_get_systicks()-start)*5, len);
|
||||
printf("[MQTT-TX] topic=%s attempt=%d rc=%d\r\n", publish_topic, cnt, rc);
|
||||
if (rc != 0) {
|
||||
mqtt_pub_cnt_err++;
|
||||
mqtt_public_error = 1;
|
||||
RLOGE("ERROR Return code from MQTT publish is %d, cnt %d", rc, mqtt_pub_cnt_err);
|
||||
@@ -1239,23 +1270,34 @@ void handle_nfc_trigger(const char *uuid)
|
||||
free(json_str);
|
||||
}
|
||||
|
||||
void handle_nfc_bind(const char *uuid)
|
||||
{
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON *data = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(root, "msg_id", "006");
|
||||
cJSON_AddStringToObject(root, "status", "success");
|
||||
|
||||
cJSON_AddStringToObject(data, "uuid", uuid);
|
||||
cJSON_AddItemToObject(root, "data", data);
|
||||
|
||||
char *json_str = cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
app_mqtt_publish(json_str, strlen(json_str), 0);
|
||||
free(json_str);
|
||||
}
|
||||
void handle_nfc_bind(const char *uuid)
|
||||
{
|
||||
char iccid[QL_SIM_ICCID_LEN * 2 + 1] = {0};
|
||||
QL_SIM_ERROR_CODE sim_ret;
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON *data = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(root, "msg_id", "006");
|
||||
cJSON_AddStringToObject(root, "status", "success");
|
||||
|
||||
cJSON_AddStringToObject(data, "uuid", uuid);
|
||||
|
||||
sim_ret = ql_sim_get_iccid(iccid, sizeof(iccid));
|
||||
if (sim_ret == QL_SIM_SUCCESS && iccid[0] != '\0') {
|
||||
printf("NFC bind ICCID:%s\r\n", iccid);
|
||||
cJSON_AddStringToObject(data, "iccid", iccid);
|
||||
} else {
|
||||
printf("NFC bind get ICCID failed, ret:%d\r\n", sim_ret);
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(root, "data", data);
|
||||
|
||||
char *json_str = cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
app_mqtt_publish(json_str, strlen(json_str), 0);
|
||||
free(json_str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mqtt_connect_diag.h"
|
||||
#include "sockets.h"
|
||||
|
||||
/* Only installed during synchronous CONNECT. Never dump the CONNECT payload:
|
||||
* it contains credentials. Keep only the first four incoming CONNACK bytes. */
|
||||
static struct {
|
||||
int (*read)(Network *, unsigned char *, int, int);
|
||||
int (*write)(Network *, unsigned char *, int, int);
|
||||
unsigned int read_calls, write_calls, received, sent;
|
||||
unsigned char prefix[4];
|
||||
unsigned int prefix_size;
|
||||
} mqtt_diag;
|
||||
|
||||
static unsigned int mqtt_diag_elapsed(unsigned int start)
|
||||
{
|
||||
return (unsigned int)(ql_rtos_get_systicks() - start) * 5U;
|
||||
}
|
||||
|
||||
static int mqtt_diag_read(Network *network, unsigned char *buffer, int size, int timeout)
|
||||
{
|
||||
unsigned int start = ql_rtos_get_systicks();
|
||||
int result = mqtt_diag.read(network, buffer, size, timeout);
|
||||
int socket_error = result <= 0 ? ql_get_soc_errno() : 0;
|
||||
int i;
|
||||
++mqtt_diag.read_calls;
|
||||
if (result > 0) {
|
||||
mqtt_diag.received += (unsigned int)result;
|
||||
for (i = 0; i < result && i < size && mqtt_diag.prefix_size < sizeof(mqtt_diag.prefix); ++i)
|
||||
mqtt_diag.prefix[mqtt_diag.prefix_size++] = buffer[i];
|
||||
}
|
||||
printf("[MQTT-DIAG] read request=%d rc=%d timeout_ms=%d elapsed_ms=%u errno_snapshot=%d\r\n",
|
||||
size, result, timeout, mqtt_diag_elapsed(start), socket_error);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int mqtt_diag_write(Network *network, unsigned char *buffer, int size, int timeout)
|
||||
{
|
||||
unsigned int start = ql_rtos_get_systicks();
|
||||
int result = mqtt_diag.write(network, buffer, size, timeout);
|
||||
int socket_error = result <= 0 ? ql_get_soc_errno() : 0;
|
||||
++mqtt_diag.write_calls;
|
||||
if (result > 0) mqtt_diag.sent += (unsigned int)result;
|
||||
printf("[MQTT-DIAG] write request=%d rc=%d timeout_ms=%d elapsed_ms=%u errno_snapshot=%d\r\n",
|
||||
size, result, timeout, mqtt_diag_elapsed(start), socket_error);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *mqtt_diag_connack_reason(unsigned char code)
|
||||
{
|
||||
switch (code) {
|
||||
case 0: return "accepted";
|
||||
case 1: return "protocol_version_rejected";
|
||||
case 2: return "client_id_rejected";
|
||||
case 3: return "server_unavailable";
|
||||
case 4: return "bad_username_or_password";
|
||||
case 5: return "not_authorized";
|
||||
default: return "reserved_code";
|
||||
}
|
||||
}
|
||||
|
||||
int talkingq_mqtt_connect_diagnosed(MQTTClient *client, MQTTPacket_connectData *options)
|
||||
{
|
||||
Network *network = client->ipstack;
|
||||
MQTTConnackData connack = {255, 255};
|
||||
unsigned int start;
|
||||
int result;
|
||||
int valid_connack;
|
||||
memset(&mqtt_diag, 0, sizeof(mqtt_diag));
|
||||
mqtt_diag.read = network->mqttread;
|
||||
mqtt_diag.write = network->mqttwrite;
|
||||
if (!mqtt_diag.read || !mqtt_diag.write) {
|
||||
printf("[MQTT-DIAG] missing transport callbacks; calling SDK unchanged\r\n");
|
||||
return MQTTConnectWithResults(client, options, &connack);
|
||||
}
|
||||
printf("[MQTT-DIAG] CONNECT begin version=%u clean=%u keepalive_s=%u timeout_ms=%u already_connected=%d\r\n",
|
||||
(unsigned int)options->MQTTVersion, (unsigned int)options->cleansession,
|
||||
(unsigned int)options->keepAliveInterval, client->command_timeout_ms, client->isconnected);
|
||||
network->mqttread = mqtt_diag_read;
|
||||
network->mqttwrite = mqtt_diag_write;
|
||||
start = ql_rtos_get_systicks();
|
||||
result = MQTTConnectWithResults(client, options, &connack);
|
||||
network->mqttread = mqtt_diag.read;
|
||||
network->mqttwrite = mqtt_diag.write;
|
||||
printf("[MQTT-DIAG] CONNECT end rc=%d elapsed_ms=%u write_calls=%u tx_bytes=%u read_calls=%u rx_bytes=%u\r\n",
|
||||
result, mqtt_diag_elapsed(start), mqtt_diag.write_calls, mqtt_diag.sent,
|
||||
mqtt_diag.read_calls, mqtt_diag.received);
|
||||
valid_connack = mqtt_diag.prefix_size == 4 && mqtt_diag.prefix[0] == 0x20 &&
|
||||
mqtt_diag.prefix[1] == 2 && (mqtt_diag.prefix[2] & 0xfe) == 0 &&
|
||||
mqtt_diag.prefix[3] <= 5 &&
|
||||
(mqtt_diag.prefix[3] == 0 || mqtt_diag.prefix[2] == 0);
|
||||
if (valid_connack) {
|
||||
printf("[MQTT-DIAG] CONNACK code=%u reason=%s session_present=%u\r\n",
|
||||
(unsigned int)mqtt_diag.prefix[3], mqtt_diag_connack_reason(mqtt_diag.prefix[3]),
|
||||
(unsigned int)mqtt_diag.prefix[2]);
|
||||
} else if (mqtt_diag.received) {
|
||||
printf("[MQTT-DIAG] no valid initial CONNACK: received_prefix_bytes=%u\r\n", mqtt_diag.prefix_size);
|
||||
} else {
|
||||
printf("[MQTT-DIAG] no response bytes returned by SDK read\r\n");
|
||||
}
|
||||
if (result != 0 && !mqtt_diag.write_calls)
|
||||
printf("[MQTT-DIAG] failed before transport write; inspect client state/CONNECT serialization\r\n");
|
||||
/* SDK read maps both EOF and some socket errors to -1. The errno snapshot
|
||||
* can be stale; do not claim a broker rejection without a valid CONNACK. */
|
||||
return result;
|
||||
}
|
||||
@@ -327,14 +327,14 @@ void vad_audio_process(void) {
|
||||
ql_audio_record_read(record_hd, mic_buf, &record_len);
|
||||
|
||||
//如果检测到声音再去传输
|
||||
if(first_sound_detected){
|
||||
//实际上每次编码需要输入1152字节的PCM数据
|
||||
if(hal_os_rb_write(ring_sender, (uint8*)mic_buf, record_len, 25)>0){
|
||||
// if(first_sound_detected){
|
||||
//实际上每次编码需要输入1152字节的PCM数据
|
||||
if(hal_os_rb_write(ring_sender, (uint8*)mic_buf, record_len, 25)>0){
|
||||
|
||||
//quec_usbcdc_write((uint8*)mic_buf, record_len);
|
||||
ql_rtos_semaphore_release(sender_sem); //告诉线程去获取录音数据
|
||||
}
|
||||
//quec_usbcdc_write((uint8*)mic_buf, record_len);
|
||||
ql_rtos_semaphore_release(sender_sem); //告诉线程去获取录音数据
|
||||
}
|
||||
// }
|
||||
#if 1
|
||||
for(index=0; index<320; index++)
|
||||
{
|
||||
@@ -354,12 +354,14 @@ void vad_audio_process(void) {
|
||||
// 连续达到阈值才确认检测到声音
|
||||
if (speech_detect_count >= SPEECH_DETECT_THRESHOLD) {
|
||||
|
||||
#if 0
|
||||
//实际上每次编码需要输入1152字节的PCM数据
|
||||
if(hal_os_rb_write(ring_sender, (uint8*)mic_buf, record_len, 25)>0){
|
||||
|
||||
//quec_usbcdc_write((uint8*)mic_buf, record_len);
|
||||
ql_rtos_semaphore_release(sender_sem); //告诉线程去获取录音数据
|
||||
}
|
||||
#endif
|
||||
|
||||
first_sound_detected = true;
|
||||
set_state(STATE_RECORDING_ACTIVE);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef NFC_GNSS_BOARD_FEATURES_H
|
||||
#define NFC_GNSS_BOARD_FEATURES_H
|
||||
|
||||
/* Legacy board has no GNSS. Set to 1 and rebuild kernel + app for GNSS boards. */
|
||||
#define NFC_GNSS_BOARD_HAS_GNSS 0
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,6 @@
|
||||
============================================================================*/
|
||||
|
||||
#include "gps_app.h"
|
||||
#include "../../../../ql-config/config/board_features.h"
|
||||
#include <string.h>
|
||||
#include "gps_debug.h"
|
||||
#include "quec_hx_agps.h"
|
||||
@@ -841,10 +840,6 @@ void quec_get_ocname_by_gnss_task(void * argv)
|
||||
|
||||
void quec_get_gnssid_task(void)
|
||||
{
|
||||
#if !NFC_GNSS_BOARD_HAS_GNSS
|
||||
RTI_LOG("[GNSS] Legacy board: skip GNSS ID detection");
|
||||
return;
|
||||
#else
|
||||
QuecOSStatus err = kNoErr;
|
||||
quec_task_t quec_ocname_get = NULL;
|
||||
err = quec_rtos_task_create(&quec_ocname_get, 2048, QUEC_APP_TASK_PRIORITY,"q_gocg", quec_get_ocname_by_gnss_task, NULL);
|
||||
@@ -854,7 +849,6 @@ void quec_get_gnssid_task(void)
|
||||
RTI_LOG("quec_get_ocname_by_gnss_task create failed!");
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3741,6 +3741,10 @@ extern void chargeManagePhase2Init(void);
|
||||
void PMIC_Phase2Init(void)
|
||||
{
|
||||
INTC_ReturnCode intcStatus;
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
UINT8 longkey_e3;
|
||||
UINT8 longkey_e4;
|
||||
#endif
|
||||
|
||||
PMIC_UART_DEBUG("PMIC_Phase2Init");
|
||||
|
||||
@@ -3780,6 +3784,30 @@ void PMIC_Phase2Init(void)
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
case PMIC_807:
|
||||
GuilinLite3ClkInit();
|
||||
longkey_e3 = PMIC_READ_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG);
|
||||
longkey_e4 = PMIC_READ_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG);
|
||||
RTI_LOG("PM807 LONGKEY before: E3=0x%x time=%ds E4=0x%x en1=%d en2=%d",
|
||||
longkey_e3, (((longkey_e3 >> 4) & 0x0f) + 1), longkey_e4,
|
||||
!!(longkey_e4 & GUILIN_LITE3_LONGKEY_EN1),
|
||||
!!(longkey_e4 & GUILIN_LITE3_LONGKEY_EN2));
|
||||
|
||||
PM812_SET_LONKEY_PRESS_TIME(2);
|
||||
PM812_LONKEY_ENABLE_SET(GUILIN_LITE3_LONGKEY_1, TRUE);
|
||||
PM812_LONKEY_ENABLE_SET(GUILIN_LITE3_LONGKEY_2, TRUE);
|
||||
|
||||
longkey_e3 = PMIC_READ_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG);
|
||||
longkey_e4 = PMIC_READ_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG);
|
||||
RTI_LOG("PM807 LONGKEY after: E3=0x%x time=%ds E4=0x%x en1=%d en2=%d",
|
||||
longkey_e3, (((longkey_e3 >> 4) & 0x0f) + 1), longkey_e4,
|
||||
!!(longkey_e4 & GUILIN_LITE3_LONGKEY_EN1),
|
||||
!!(longkey_e4 & GUILIN_LITE3_LONGKEY_EN2));
|
||||
if ((((longkey_e3 >> 4) & 0x0f) != 1) ||
|
||||
((longkey_e4 & (GUILIN_LITE3_LONGKEY_EN1 | GUILIN_LITE3_LONGKEY_EN2)) !=
|
||||
(GUILIN_LITE3_LONGKEY_EN1 | GUILIN_LITE3_LONGKEY_EN2)))
|
||||
{
|
||||
RTI_LOG("PM807 LONGKEY configure failed: E3=0x%x E4=0x%x",
|
||||
longkey_e3, longkey_e4);
|
||||
}
|
||||
// GuilinLite3_VBUCK1_Set_FPWM();
|
||||
break;
|
||||
#endif
|
||||
@@ -4231,6 +4259,13 @@ UINT8 PM812_GET_LONKEY_PRESS_TIME(void)
|
||||
return (((tmp >> 4) & 0x0f) + 1);
|
||||
}
|
||||
#endif
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
else if(PMIC_IS_PM807())
|
||||
{
|
||||
tmp = PMIC_READ_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG);
|
||||
return (((tmp >> 4) & 0x0f) + 1);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return tmp;
|
||||
@@ -4241,6 +4276,10 @@ UINT8 PM812_GET_LONKEY_PRESS_TIME(void)
|
||||
void PM812_SET_LONKEY_PRESS_TIME(UINT8 sec)
|
||||
{
|
||||
UINT8 tmp;
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
UINT8 target;
|
||||
UINT8 bit;
|
||||
#endif
|
||||
|
||||
#if !defined(NOT_SUPPORT_PM802)
|
||||
if (PMIC_IS_PM802()||PMIC_IS_PM802S())
|
||||
@@ -4268,6 +4307,30 @@ void PM812_SET_LONKEY_PRESS_TIME(UINT8 sec)
|
||||
PMIC_WRITE_REG_BASE(NINGBO_RTC_MISC_3_REG,(tmp|sec));
|
||||
}
|
||||
#endif
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
else if(PMIC_IS_PM807())
|
||||
{
|
||||
if ((sec < 1) || (sec > 16))
|
||||
{
|
||||
RTI_LOG("PM807 invalid LONGKEY time: %d", sec);
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = PMIC_READ_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG);
|
||||
target = (tmp & 0x0f) | ((sec - 1) << 4);
|
||||
|
||||
/* RTC_MISC_3 may only accept one changed bit per write. */
|
||||
for (bit = 4; bit < 8; bit++)
|
||||
{
|
||||
if ((tmp ^ target) & (1 << bit))
|
||||
{
|
||||
tmp = (tmp & ~(1 << bit)) | (target & (1 << bit));
|
||||
PMIC_WRITE_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG, tmp);
|
||||
tmp = PMIC_READ_REG_BASE(GUILIN_LITE3_RTC_MISC_3_REG);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PM812_LONKEY_ENABLE_SET(UINT8 LONGKEY_NUM,BOOL enable)
|
||||
@@ -4324,6 +4387,22 @@ void PM812_LONKEY_ENABLE_SET(UINT8 LONGKEY_NUM,BOOL enable)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
else if(PMIC_IS_PM807())
|
||||
{
|
||||
tmp = PMIC_READ_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG);
|
||||
if(LONGKEY_NUM == GUILIN_LITE3_LONGKEY_1)
|
||||
{
|
||||
enable ? (tmp |= GUILIN_LITE3_LONGKEY_EN1) : (tmp &= (~GUILIN_LITE3_LONGKEY_EN1));
|
||||
PMIC_WRITE_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG, tmp);
|
||||
}
|
||||
else if(LONGKEY_NUM == GUILIN_LITE3_LONGKEY_2)
|
||||
{
|
||||
enable ? (tmp |= GUILIN_LITE3_LONGKEY_EN2) : (tmp &= (~GUILIN_LITE3_LONGKEY_EN2));
|
||||
PMIC_WRITE_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG, tmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//LONGKEY_NUM: 1/2
|
||||
@@ -4352,6 +4431,13 @@ BOOL PM812_LONKEY_ENABLE_GET(UINT8 LONGKEY_NUM)
|
||||
((LONGKEY_NUM==NINGBO_LONGKEY_1)?NINGBO_LONGKEY_EN1:NINGBO_LONGKEY_EN2));
|
||||
}
|
||||
#endif
|
||||
#if !defined(NOT_SUPPORT_PM807)
|
||||
else if(PMIC_IS_PM807())
|
||||
{
|
||||
return (PMIC_READ_REG_BASE(GUILIN_LITE3_CLK_32K_SEL_REG) &
|
||||
((LONGKEY_NUM == GUILIN_LITE3_LONGKEY_1) ? GUILIN_LITE3_LONGKEY_EN1 : GUILIN_LITE3_LONGKEY_EN2));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
PMIC_UART_DEBUG("PM812_LONKEY_ENABLE_GET: it shouldn't reach here, NUM=%d",LONGKEY_NUM);
|
||||
|
||||
@@ -6,7 +6,7 @@ import struct
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
output = root / 'artifacts/wss/ecc-fix'
|
||||
output = root / 'artifacts/wss/new-board'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
toolchain = root / 'ql-cross-tool/win32/owtoolchain'
|
||||
gcc = toolchain / 'gcc-arm-none-eabi/bin/arm-none-eabi-gcc.exe'
|
||||
|
||||
@@ -11,7 +11,7 @@ parser.add_argument('chain', nargs='?', default=str(root / 'artifacts/wss/retest
|
||||
parser.add_argument('--compare-nist', action='store_true')
|
||||
parser.add_argument('--compare-windows', action='store_true')
|
||||
args = parser.parse_args()
|
||||
output = root / 'artifacts/wss/tls-speed/host-cert'
|
||||
output = root / 'artifacts/wss/new-board/host-cert'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
chain = Path(args.chain).resolve()
|
||||
sources = '''asn1parse asn1write bignum base64 pem oid pk pkparse pk_wrap rsa rsa_internal
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
"""Exercise actual MQTT diagnostic callbacks without a broker or credentials."""
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
output = root / 'artifacts/wss/new-board/mqtt-diag/tests'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
(output / 'MQTTClient.h').write_text(r'''
|
||||
#ifndef TEST_MQTT_CLIENT_H
|
||||
#define TEST_MQTT_CLIENT_H
|
||||
typedef struct Network Network;
|
||||
struct Network {
|
||||
int (*mqttread)(Network *, unsigned char *, int, int);
|
||||
int (*mqttwrite)(Network *, unsigned char *, int, int);
|
||||
};
|
||||
typedef struct { Network *ipstack; unsigned int command_timeout_ms; int isconnected; } MQTTClient;
|
||||
typedef struct { unsigned char MQTTVersion, cleansession; unsigned short keepAliveInterval; } MQTTPacket_connectData;
|
||||
typedef struct { unsigned char rc, sessionPresent; } MQTTConnackData;
|
||||
int MQTTConnectWithResults(MQTTClient *, MQTTPacket_connectData *, MQTTConnackData *);
|
||||
unsigned int ql_rtos_get_systicks(void);
|
||||
#endif
|
||||
''')
|
||||
(output / 'sockets.h').write_text('int ql_get_soc_errno(void);\n')
|
||||
harness = r'''
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mqtt_connect_diag.h"
|
||||
static unsigned int ticks;
|
||||
static int mode, offset, writes, reads;
|
||||
unsigned int ql_rtos_get_systicks(void) { return ticks; }
|
||||
int ql_get_soc_errno(void) { return 104; }
|
||||
static int fake_write(Network *n, unsigned char *buf, int size, int timeout) {
|
||||
(void)n;
|
||||
assert(timeout == 30000 && size == 19);
|
||||
assert(memcmp(buf, "PRIVATE_TEST_SECRET", 19) == 0);
|
||||
++writes; ticks += 2;
|
||||
return mode == 2 ? -1 : size;
|
||||
}
|
||||
static int fake_read(Network *n, unsigned char *buf, int size, int timeout) {
|
||||
unsigned char response[] = {0x20, 2, 0, 0};
|
||||
(void)n;
|
||||
assert(timeout == 30000 && (size == 1 || size == 2));
|
||||
++reads; ticks += 3;
|
||||
if (mode == 3) return -1;
|
||||
if (mode == 4) return 0;
|
||||
if (mode == 1) response[3] = 5;
|
||||
if (mode == 5) response[0] = 0x30;
|
||||
if (mode == 7) { response[2] = 1; response[3] = 5; }
|
||||
memcpy(buf, response + offset, size); offset += size;
|
||||
return size;
|
||||
}
|
||||
int MQTTConnectWithResults(MQTTClient *client, MQTTPacket_connectData *options, MQTTConnackData *ack) {
|
||||
unsigned char packet[] = "PRIVATE_TEST_SECRET";
|
||||
unsigned char response[4] = {0};
|
||||
int result;
|
||||
assert(options->MQTTVersion == 3);
|
||||
assert(ack->rc == 255);
|
||||
if (mode == 6) return -1;
|
||||
result = client->ipstack->mqttwrite(client->ipstack, packet, 19, 30000);
|
||||
if (result != 19) { assert(result == -1); return -1; }
|
||||
/* SDK reads fixed header, remaining length, then the two-byte body. */
|
||||
result = client->ipstack->mqttread(client->ipstack, response, 1, 30000);
|
||||
if (mode == 3 || mode == 4) { assert(result == (mode == 3 ? -1 : 0)); return -1; }
|
||||
assert(result == 1);
|
||||
assert(client->ipstack->mqttread(client->ipstack, response + 1, 1, 30000) == 1);
|
||||
assert(client->ipstack->mqttread(client->ipstack, response + 2, 2, 30000) == 2);
|
||||
assert(response[1] == 2);
|
||||
return mode == 0 ? 0 : (mode == 1 ? 5 : -1);
|
||||
}
|
||||
int main(void) {
|
||||
Network network = {fake_read, fake_write};
|
||||
MQTTClient client = {&network, 30000, 0};
|
||||
MQTTPacket_connectData options = {3, 0, 60};
|
||||
for (mode = 0; mode < 8; ++mode) {
|
||||
int expected = mode == 0 ? 0 : (mode == 1 ? 5 : -1);
|
||||
ticks = mode == 0 ? 0xfffffffeU : 0; offset = writes = reads = 0;
|
||||
printf("CASE %d\n", mode);
|
||||
assert(talkingq_mqtt_connect_diagnosed(&client, &options) == expected);
|
||||
assert(network.mqttread == fake_read && network.mqttwrite == fake_write);
|
||||
assert(writes == (mode == 6 ? 0 : 1));
|
||||
if (mode == 6 || mode == 2) assert(reads == 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
(output / 'test.c').write_text(harness)
|
||||
include = root / 'ql-application/threadx/interface/custom_app/inc'
|
||||
source = root / 'ql-application/threadx/interface/custom_app/mqtt_connect_diag.c'
|
||||
subprocess.run(['cl', '/nologo', '/W4', '/WX', '/TC', '/I' + str(output), '/I' + str(include),
|
||||
str(source), str(output / 'test.c'), '/Fe' + str(output / 'test.exe')], cwd=output, check=True)
|
||||
result = subprocess.check_output([str(output / 'test.exe')], text=True)
|
||||
assert 'PRIVATE_TEST_SECRET' not in result
|
||||
cases = [part for part in result.split('CASE ')[1:]]
|
||||
assert len(cases) == 8
|
||||
assert 'CONNACK code=0 reason=accepted' in cases[0] and 'elapsed_ms=55' in cases[0]
|
||||
assert 'CONNACK code=5 reason=not_authorized' in cases[1]
|
||||
assert 'write request=19 rc=-1' in cases[2]
|
||||
assert 'read request=1 rc=-1' in cases[3]
|
||||
assert 'read request=1 rc=0' in cases[4]
|
||||
assert 'no valid initial CONNACK' in cases[5]
|
||||
assert 'failed before transport write' in cases[6]
|
||||
assert 'no valid initial CONNACK' in cases[7]
|
||||
for case in cases[2:]:
|
||||
assert '[MQTT-DIAG] CONNACK code=' not in case
|
||||
(output / 'test-output.log').write_text(result)
|
||||
print('PASS: transport arguments/return values, callback restoration, split CONNACK, rejection, invalid response, errors, no-I/O failure, tick wrap and credential redaction')
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Verify the WSS flash package against the current legacy-board build."""
|
||||
"""Verify the new-board WSS package, including enabled GNSS task entry points."""
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
@@ -8,7 +8,7 @@ import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
package = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/full-handshake/EG800AKCN_11LG-legacy-wss-x25519.zip'
|
||||
package = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/new-board/EG800AKCN_11LG-new-board-wss-x25519.zip'
|
||||
output = package.parent
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
objdump = root / 'ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi/bin/arm-none-eabi-objdump.exe'
|
||||
@@ -33,8 +33,9 @@ clock_body = subprocess.check_output([str(objdump), '-d', '--disassemble=x509_ge
|
||||
assert '<mbedtls_platform_gmtime_r>' in clock_body and '<GetCurrentCompTime>' not in clock_body
|
||||
(output / 'x509-clock.disasm.txt').write_text(clock_body)
|
||||
report = {'package': package.name, 'sha256': hashlib.sha256(package.read_bytes()).hexdigest(),
|
||||
'board': 'new board with GNSS enabled',
|
||||
'linked_symbols': required, 'kernel_symbols': kernel_required,
|
||||
'hardware_test': '2026-09-16 14:38 device log: NIST TLS handshake 1820 ms and HTTP 101 passed; X25519 preference awaits device test',
|
||||
'hardware_test': 'New-board package awaits device testing; legacy board verified X25519 full handshake at 1455 ms on 2026-09-16',
|
||||
'backend': '2026-09-16 11:32 CST: WSS 443 /ws HTTP 101; 8080 plaintext WS'}
|
||||
with zipfile.ZipFile(package) as archive:
|
||||
assert archive.testzip() is None, 'ZIP CRC failure'
|
||||
@@ -46,16 +47,21 @@ with zipfile.ZipFile(package) as archive:
|
||||
assert b'wss://banban.api.talkingq.com:443/ws' in archive.read('customer_app.bin')
|
||||
assert b'WSS TLS handshake total=' in archive.read('customer_app.bin')
|
||||
assert b'WSS TLS full handshake: prefer X25519' in archive.read('customer_app.bin')
|
||||
assert b'Legacy board:' not in archive.read('customer_app.bin')
|
||||
assert b'Legacy board:' not in archive.read('cp.bin')
|
||||
assert b'gnss_Task_Ref' in archive.read('customer_app.bin')
|
||||
report['download_manifest'] = json.loads(archive.read('download.json'))
|
||||
printf_address = int(re.search(r'^([0-9a-fA-F]+) T printf$', symbols, re.M).group(1), 16)
|
||||
task_create_address = int(re.search(r'^([0-9a-fA-F]+) T ql_rtos_task_create$', symbols, re.M).group(1), 16)
|
||||
for symbol, binary, expected in [
|
||||
('quec_get_gnssid_task', root / 'ql-kernel/threadx/build/kernel.axf', '<RTI_LOG>'),
|
||||
('app_gnss_init', app, '0x%08x' % (printf_address | 1)),
|
||||
('set_gnss_mode', app, 'bx\tlr')]:
|
||||
('quec_get_gnssid_task', root / 'ql-kernel/threadx/build/kernel.axf', '<quec_rtos_task_create>'),
|
||||
('app_gnss_init', app, '0x%08x' % (task_create_address | 1)),
|
||||
('set_gnss_mode', app, 'strb')]:
|
||||
body = subprocess.check_output([str(objdump), '-d', '--disassemble=' + symbol, str(binary)], text=True)
|
||||
assert '<' + symbol + '>:' in body and expected in body and 'task_create' not in body
|
||||
assert '<' + symbol + '>:' in body and expected in body, 'GNSS entry point disabled or unexpected code: ' + symbol
|
||||
(output / (symbol + '.disasm.txt')).write_text(body)
|
||||
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, GNSS bypass, WSS URL, ECDSA/GCM/RTC/NIST kernel symbols and handshake timing logs'
|
||||
for symbol, table in [('quec_get_ocname_by_gnss_task', kernel_symbols), ('quec_gnss_test', symbols)]:
|
||||
assert re.search(r'\b' + symbol + r'$', table, re.M), 'Missing GNSS worker: ' + symbol
|
||||
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, GNSS task creation, WSS URL, ECDSA/GCM/RTC/NIST kernel symbols and handshake timing logs'
|
||||
(output / 'verification.json').write_text(json.dumps(report, indent=2))
|
||||
print(report['verification'])
|
||||
print('SHA256:', report['sha256'])
|
||||
|
||||
Reference in New Issue
Block a user