YouDuck.ai

配置一块开发板

最后更新

开发板信任团队的 dev 密钥,所以它会安装团队里任何人构建的东西。零售机器人的配置方式不同,并且会刻意拒绝这些构建。

这一页的所有内容都假设你面对的是开发板,不是零售机器人。

安全性并没有放宽

这一点值得说清楚,因为容易误解:dev 构建走的是同样的签名与哈希校验、同样的健康门禁、同样的自动回滚。唯一的区别是由哪把密钥签名。

而这正是这些构建进不了零售机器人的原因——零售机器人从两个层面拒绝 dev 密钥:

  1. allow_dev_keys = false
  2. 一把受信任的密钥只有在文件名以 .dev.pub 结尾时才算 dev 密钥。

下面整个配置流程存在的意义,就是把这两项翻过来。

刷系统

Armbian imager,选 Radxa Zero 3,然后 Armbian 26.2.1 Minimal。

写入前先把 imager 的 profile 填好——wifi 名称和密码、你想要的用户名和密码。在这里填能省掉后面接串口控制台的麻烦:板子首次开机就会连上你的网络,可以直接 ssh。

然后把 ssh 公钥送上去,provisioning 重启板子后需要靠它重连:

ssh-copy-id [email protected]

开始前需要准备

  • 板子的 IP 地址。 这个镜像上的 mDNS 不可靠,.local 名字能不能解析全看心情。duckctl ip 通过蓝牙问机器人要地址,不需要你自己有网络,也不需要读 DHCP 租约;板子还没开始广播时,退回去查路由器的租约表。
  • ssh 密钥访问(上一步)。provisioning 会重启板子并自行重连,密码提示是活不过重启的。
  • 一个 GitHub token,在这个仓库还是私有的期间——它的 release 资产没有 token 拿不到。仓库公开后 token 变成可选,只用来提高 API 速率限制。
  • 一份仓库克隆。 需要的 dev 公钥已经提交在 deploy/dev-key/team.dev.pub,不用向任何人索要。

安装

在自己机器上的克隆里,两条命令:

export DUCK_TOKEN=github_pat_replace_with_your_token
./scripts/provision-board.sh --pause-btd-on-pair --name <MY_COOL_ROBOT_NAME> [email protected]

它会送上你的 dev 密钥、启动 provisioning、等过重启、流式输出日志,最后停在 robotctl health

日志输出只是个查看器,不是干活的那个东西。 provisioning 装了一个 systemd unit 在开机时续跑,所以不管你还在不在看,板子都会自己走完。Ctrl-C 不会有任何损失,之后随时接回日志:

ssh -t [email protected] 'sudo tail -f /var/lib/robot/provision.log'

为什么默认带 --pause-btd-on-pair

在 aic8800 无线芯片上,btd 正在广播时手柄无法建立新的绑定。这个参数留下一个标记,让 robotctl pad pair 在配对窗口内停掉 btd 并给适配器断电重启,之后再启动它。

已有的绑定不受影响——配好的手柄在整套服务运行时照样连接和驱动——所以代价只是一个守护进程在配对期间短暂下线。

它成为默认值的原因很实际:一块需要它却没带这个参数配置的板子,表现出来就是“手柄配不上”,而你第一时间去查的每一个可能原因都在别处。

三种蓝牙配置,以及怎么判断你是哪一种

这里有两个互相独立的故障,所以有两个参数。先配一次手柄,读它的失败方式,然后对照:

你看到的现象 这块板子需要
手柄能绑定、能驱动 什么都不需要——不带参数配置
手柄绑不上,最后一步 SMP 永远不完成 --pause-btd-on-pair
暂停 btd 也绑不上 --weird-ble(隐含暂停,并加上 Privacy = device
手柄能绑上,然后反复掉线——PIN or Key Missing (0x06),创建不出输入设备 --weird-ble 对这块板子是错的:去掉它,保留暂停

最后一行是要特别留意的那个。

在只需要暂停的板子上设 Privacy = device,会产生一个“绑上之后立刻不工作”的状态——这比一个干脆配不上的手柄更难诊断。官方在 50:37:CD:16:1D:90 这块板子上实测过:off 加暂停能绑定并保持稳定,而 device 在 45 秒内掉线 46 次。

因此 --weird-ble 已经不再是默认值。

在两种配置之间移动

--weird-ble 退回只用暂停(保留标记):

sudo sed -i 's/^Privacy = device/Privacy = off/' /etc/bluetooth/main.conf && sudo reboot

反方向,用 provisioning 在板子上留下的脚本副本:

sudo DUCK_WEIRD_BLE=1 /usr/local/sbin/robot-setup-board && sudo reboot

验证一块板子两个都不需要——去掉之后配一次手柄:

sudo rm /var/lib/robot/weird-ble
sudo sed -i '/^Privacy = /d' /etc/bluetooth/main.conf && sudo reboot

改完 Privacy 必须重新配对。它会改变已存储密钥所派生的地址,所以已有的绑定不再匹配,会一直以 PIN or Key Missing 反复掉线,直到重新配对。

这一整套都是对 aic8800 无线芯片的绕行方案,不是设计本身的性质——换掉这个芯片它就消失了。详见配对手柄

从分支配置

./scripts/provision-board.sh --ref BRANCH [email protected]

--ref BRANCH 用某个分支来配置:跑它的脚本做 bring-up,并在上面装它构建的守护进程。

这里有个设计取舍值得理解:golden 始终保持稳定发布版——它是开机恢复网的兜底,而用分支构建当 golden 等于给一个坏分支配一个坏兜底——current 才是分支。

配置会失败,如果那个构建装不上,或者装上后被健康门禁回滚了。这是刻意的:

一块被要求装分支、却安静地跑着稳定版的开发板,是最难排查的失败——看起来一切都装好了,而被测试的代码根本不在上面。

配置前给 CI 一两分钟。如果卡住,用 gh run list --branch BRANCH 查。

其它有用的参数

  • --name Ducky —— 给机器人命名,而不是留着它从序列号推出来的 duck-7f3a。之后 robotctl system set-name 也能改,所以这只是省一条命令。
  • --local —— 发送这份克隆里的 provision.sh 而不是去拉取。这是在不合并的前提下测试 provisioning 脚本改动的方法。
  • --no-dev-key —— 做出一块只接受正式发布版的板子。

确认真的成功了

robotctl health

板子只有在密钥真的装上时才算开发板,而这是一件可以查证的事,不用靠记忆:

grep -c 'DEV BOARD' /var/lib/robot/provision.log

1 表示是。0 表示密钥没落地——之后 --ref 会被拒绝,而报错信息读起来像是发布版损坏。这个检查存在的意义就是提前抓住这个失败。

下一步