AirTerminal 在 1.2 版本中增加了两个新功能:
- XMODEM 文件传输: 通过 XMODEM 协议,可以方便地在 iOS 设备和 BLE 设备中之间传输文件
- 自定义终端工作模式: 除了标准的终端,还可以设置将终端设置为本地回显或行模式,以兼容没有实现完整 shell 的设备
新版 AirTerminal 已提交至 App Store,欢迎下载或更新。本文将详细介绍这两个功能的工作原理和使用方法。
XMODEM 协议
什么是 XMODEM
XMODEM 是一种文件传输协议,能够将文件按照固定字节数的 packet 进行传输,同时提供了校验码和重传等机制,增强文件传输的可靠性。
XMODEM 常用于通过串口进行文件传输,例如为嵌入式设备更新固件和 bootloader。另外,在之前学习 CS140e 的时候,我也使用 Rust 实现过基本的的 XMODEM 协议。
XMODEM 协议的三个版本
1. 原始的 XMODEM 协议
原始的 XMODEM 协议将文件按照 128 字节的 packet 进行传输。同时,每个 packet 中包含一个单字节的校验和,如果接收者接收 packet 后,校验和检查成功,就会通知发送者发送下一个 packet,如果检查失败,则通知发送者重新发送当前 packet。
XMODEM 的传输由接收者启动,接收者会定期向发送者发送 NAK
字节,当发送者收到来自接收者的 NAK
后,则启动传输。
协议的具体细节可参考如下文章:Understanding The X-Modem File Transfer Protocol
2. 使用 16 位 CRC 校验码的 XMODEM 协议
原始的 XMODEM 协议使用了比较简单的校验和,容易出现数据传输错误,但校验成功的情况(例如数据中的两个字节交换位置)。所以,后续的 XMODEM-CRC 协议,对原始 XMODEM 进行了扩充,使用 16 位的 CRC 校验码代替原始的校验和。
为了与原始的 XMODEM 保持兼容,XMODEM-CRC 接收者使用 ASCII 字符 "C"
代替 NAK
字节来启动传输,发送者可根据这一字节来确定是否以 CRC 的方式进行传输。如果发送者不支持 CRC,接收者将会在多次重试失败后,向发送者发送 NAK
字节,回退到非 CRC 的方式来传输。
对于 XMODEM-CRC 的工作原理,可参考如下文章:XModem Protocol with CRC
3. XMODEM-1K
对于原始的 XMODEM 和 XMODEM-CRC 协议,每个 packet 包含 128 字节的数据。XMODEM-1K 在 XMODEM-CRC 的基础上,将每个 packet 中的字节数修改为 1024 字节,以减少发送者和接收者之间的交互次数,增大数据传输速率。
对于是否使用 XMODEM-1K,由发送者进行确定。如果使用 XMODEM-1K,发送者发送的每个 packet 中,以 STX
做为起始字节,否则使用 SOH
做为起始字节。
如果想进一步了解 XMODEM,可参考如下链接:
- XMODEM 的 Wikipedia 词条
- kelvinlawson/xmodem-1k: 一个简单的 XMODEM C 语言实现
目前,AirTerminal 已兼容这三个版本的 XMODEM。发送文件时能够手动选择使用 XMODEM 或者 XMODEM-1K,并能自动确定是否启用 CRC. 接收文件时,默认启动 CRC 通知发送者,7 次通知失败后,则该用非 CRC 的模式来接收。后续可能会增加对更多文件传输协议的支持,例如 YMODEM、ZMODEM,以及传输程序到 Arduino 等功能。
AirTerminal 中的 XMODEM 实现
1. BLE MTU 的选择
对于串口,数据的传输是以字节为单位的。对于 BLE,数据的传输以报文为单位,每个报文中可包含多个字节。
AirTerminal 和 BLE 串口透传模块,实际上是将串口数据封装在 BLE 报文中进行传输。在 AirTerminal 支持 XMODEM 之前,数据的发送均以字节为单位,即每在键盘上敲下一个字符,AirTerminal 就将这单个字符封装在一个报文进行发送。
支持 XMODEM 后,为了提高文件传输速率,可以将连续的数据放在一个 BLE 报文中进行传输。BLE 默认的 ATT_MTU 为 23,去除留做其他用处的 3 字节后,即每个报文默认能携带 20 字节的数据。设备间也可以协商使用更大的 MTU 进行传输。
由于各个厂商的 BLE 串口模块,在实现上不一定相同,怀疑可能有一些模块不支持最大 20 字节的 MTU。所以我查阅了目前比较流行的几个 BLE 串口模块的资料:
- 周立功 ZLG9021P0-1-TC: 文档中已确认每个报文最大支持 20 字节的数据
- 有人物联网 USR-BLE100: 每个报文最大支持 20 字节数据,同型号模块间传输,最大支持每报文 100 字节数据
- DFRobot Bluno Link: 文档中未说明
- MLT-BT05: 文档中未说明,实测每报文最大支持 20 字节数据
考虑到传输速率和兼容性,AirTerminal 在使用 XMODEM 发送数据时,MTU 固定为 10,即每报文携带 10 个字节的数据;在使用 XMODEM-1K 发送数据时,MTU 固定为 20. 后续可能会考虑增加设置选项,用户可自由设置数据发送时的 MTU.
2. Write 与 Write without response
BLE 的 characteristic 支持 write 和 write without response 两种属性,在通过 write without response 进行写操作时,由于忽略了回应,可以大幅度提高写操作的速率。
但经过实际测试,使用 write without response 连续发送数据时,丢包现象比较严重,即使加上 XMODEM 的校验重传机制,也不一定能够将数据发送成功。所以,在 AirTerminal 中,发送数据优先采用 write,如果不能使用 write,才会使用 write without response.
使用举例:通过 lrzsz
实现与 Linux 主机之间的文件传输
lrzsz 工具能够通过 XMODEM、YMODEM、ZMODEM 等协议进行文件传输,在 Linux 或者 macOS 等操作系统上,都可以使用系统自带的包管理工具进行安装。下文将介绍使用 lrzsz
在 Linux 主机和 AirTerminal 之间传输文件的方法。(在 Windows 系统上,也有不少终端工具内置了 XMODEM 支持,例如 ExtraPuTTY 等)
首先安装 lrzsz
,对于 Ubuntu 等系统,可以使用如下命令安装:
sudo apt install lrzsz
对于 macOS,可通过 Homebrew 安装:
brew install lrzsz
安装完毕后,即可使用 rz
和 sz
命令进行文件的传输了。如果需要将文件从主机发送至 AirTerminal,可使用 sz
命令,等屏幕中出现 Give your local XMODEM receive command now
后,即可在 AirTerminal 中选择接收文件,启动文件传输:
$ sz -X <要发送的文件路径>
Give your local XMODEM receive command now.
如果需要将文件从 AirTerminal 发送到主机,可使用 rz
命令,执行之后直接在 AirTerminal 中选择发送文件即可。
$ rz -X <本地保存的文件名>
rz waiting to receive xxx.
也可以通过指定 rz
或 sz
的参数,选择使用 XMODEM-CRC 或者 XMODEM-1K 模式进行传输。具体可参考 sz --help
或 rz --help
中的帮助信息。
终端工作模式的支持
1. 标准终端
在之前的版本中,AirTerminal 假设对端设备实现了一个完整的 shell:键盘上按下的每一个字符,都会发送到对端设备;正常情况下,对端设备收到发送过来的字符后,也会通过串口将字符发送回终端,从而 AirTerminal 能够显示键盘上按下的字符。
但是,对于一些简单的设备,尤其是自己的 DIY 作品,不一定有必要实现完成的 shell,所以可能会仅仅有一个简单的串口数据收发功能。所以,在一位用户的建议下,AirTerminal 又增加了本地回显和行模式这两种终端工作模式。
2. 本地回显
如果在键盘上敲击字符,AirTerminal 将字符发送给对端后,对端无法将收到的字符通过重新发送回 AirTerminal,则可以使用本地回显模式。在该模式下,输入的每一个字符,在通过蓝牙发送给对端设备的同时,也会在 AirTerminal 中直接显示到终端。
3. 行模式
对于需要快速读取一行字符串的对端设备,可以使用行模式。在行模式下,只有用户输入回车之后,AirTerminal 才会将此前输入的内容批量发送给对端。这种模式下,AirTerminal 更像是传统的串口助手软件,用户主动确认后,内容才会发送出去。
目前在行模式下,每行输入的内容将在一个报文中一次性发送,所以每行内容不能超过 20 个字节。且目前无法编辑已输入内容,无法通过退格键删除已输入内容。下个版本将会解决这些问题。
更多
此外,AirTerminal 在本次更新中还有如下修改:
- 支持 iPhone XR、iPhone XS Max 和新款 iPad Pro
- Peripheral 模式下,支持对端通过 write without response 发送数据,从而增强与部分 BLE 模块的兼容性
- 其他 bug 修改
留言
大神您好,想請問一下是否支援樹莓派4呢?如果有,需要在樹莓派上做出什麼設定才能使用?還是原生支援直接連接就好?謝謝
BLE 原生不支持串口,AirTerminal 需要配合 BLE 转串口的透传模块才能使用。对于树莓派自带的蓝牙,应该需要再写一个辅助程序,运行在树莓派上,才可以支持。