跳转到主要内容

简单的BLE服务,用于通过BLE读取和写入文件

项目描述

简介

Documentation Status Discord Build Status Code Style: Black

这是一个简单的BLE服务,用于通过BLE读取和写入文件。该BLE服务针对向运行该服务的设备传输文件而设计。协议的核心部分是空闲空间响应,这样服务器就可以是一个内存有限的设备。空闲空间响应允许使用小的缓冲区大小,不会因客户端而超负荷。

依赖项

此驱动程序依赖于

请确保所有依赖项都可在CircuitPython文件系统中使用。这可以通过下载Adafruit库和驱动程序捆绑包或使用circup安装单个库来实现。

从PyPI安装

在支持GNU/Linux系统(如Raspberry Pi)上,您可以从PyPI本地安装驱动程序。要为当前用户安装

pip3 install adafruit-circuitpython-ble-file-transfer

要全局安装(在某些情况下可能需要)

sudo pip3 install adafruit-circuitpython-ble-file-transfer

在当前项目中的虚拟环境中安装

mkdir project-name && cd project-name
python3 -m venv .venv
source .venv/bin/activate
pip3 install adafruit-circuitpython-ble-file-transfer

使用示例

请参阅examples/ble_file_transfer_simpletest.py以获取客户端示例。占位符服务器实现位于examples/ble_file_transfer_stub_server.py

协议

文件传输协议旨在简单且易于实现。它使用可用空间计数作为限制文件内容数据传输速率的方式。所有多字节数字都是使用最低有效字节首先编码的(在CPython的struct模块中为“<”)。

GATT 服务

该服务的UUID为 0xfebb,是Adafruit的16位服务UUID。

在特性中使用的基UUID是 ADAFxxxx-4669-6C65-5472-616E73666572。下面的16位数字将替换到 xxxx 部分。

该服务有两个特性

  • 版本(0x0100)- 简单的无符号32位整数版本号。可能是1-4。

  • 原始传输(0x0200)- 带有自定义协议的双向链路。客户端将 WRITE_NO_RESPONSE 发送到特性,然后服务器通过 NOTIFY 进行回复。(这类似于Nordic UART服务,但仅在单个特性上,而不是两个。)传输特性上的命令是无操作性和无状态的。命令期间的断开将重置状态。

时间分辨率

时间分辨率根据文件系统类型而变化。FATFS在1980年之后只能降低到2秒的界限。Littlefs可以在1970年1月1日之后进行64位纳秒。

为了解决这个问题,协议使用1970年1月1日之后的64位纳秒来表示时间。然而,服务器将响应一个可能被截断的版本,该版本是存储的值。

此外,请注意,提供文件传输协议的设备可能没有自己的时钟,因此不要依赖时间顺序。任何内部写入都可能设置时间不正确。因此,我们只建议将其用作缓存键。

命令

命令始终以一个固定的头开始。第一个条目总是命令编号本身,编码在一个字节中。头部的后续条目数量将根据命令而变化。整个头部必须作为一个单位发送,因此将特性设置为完整的头部数据包。只要整个头部在数据包中,就可以将多个命令组合成一个写入。

路径使用 / 作为分隔符,完整路径必须以 / 开始。

所有数字都是无符号的。

所有值都相对于数据包的开始对齐。

状态字节是 0x01 表示正常,0x02 表示错误。除 0x01 之外的所有值都是错误。 0x00 不应用于特定错误,但仍被视为错误。 0x05 是尝试修改只读文件系统的错误。

0x10 - 读取文件

给定完整路径,返回文件的全部内容。

头部有四个固定条目和一个可变长度的路径

  • 命令:单字节。总是 0x10

  • 1 字节保留用于填充。

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 块偏移:32位数字,表示文件中第一个块的偏移。

  • 块大小:32位数字,表示客户端在第一个回复中可以处理的数据量。

  • 路径:UTF-8编码的字符串,不是空终止的。(我们发送长度。)

服务器将响应

  • 命令:单字节。总是 0x11

  • 状态:单字节。

  • 2 字节保留用于填充。

  • 块偏移:32位数字,表示此块在文件中的偏移。

  • 总长度:32位数字,表示总文件长度。

  • 块长度:32位数字,表示读取数据长度,直到提供的块大小。

  • 从当前位置开始的文件块长度内容。

如果块长度小于总长度,则客户端将通过发送

  • 命令:单字节。始终为0x12

  • 状态:单字节。目前始终为OK。

  • 2 字节保留用于填充。

  • 块偏移量:32位数字,表示文件中下一个块开始的偏移量。

  • 块大小:32位数字,表示要读取的字节数。可能不同于原始大小。不需要受总大小的限制。

在服务器回复所有数据后,事务完成。(客户端不需要确认。)

0x20 - 写入文件

将内容写入给定的完整路径。如果文件存在,则将其覆盖。内容可能按接收方式写入,因此中断的传输可能导致文件截断。

大于现有文件大小的偏移量将在间隙中引入零。

头部有四个固定条目和一个可变长度的路径

  • 命令:单字节。始终为0x20

  • 1 字节保留用于填充。

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 偏移量:32位数字,表示写入的起始偏移量。

  • 当前时间:64位数字,表示自1970年1月1日以来的纳秒数。用作文件修改时间。不是所有系统都支持完整的分辨率。请使用截断的时间响应值进行缓存。

  • 总大小:32位数字,表示文件内容的总长度。

  • 路径:UTF-8编码的字符串,不是空终止的。(我们发送长度。)

服务器将重复响应,直到总长度已通过以下方式传输

  • 命令:单字节。始终为0x21

  • 状态:单字节。如果OK,则为0x01。如果文件系统为只读,则为0x05。如果任何父目录不存在或为文件,则为0x02

  • 2 字节保留用于填充。

  • 偏移量:32位数字,表示写入的起始偏移量。(应与之前的0x20或0x22消息中的偏移量匹配)

  • 截断时间:64位数字,表示自1970年1月1日以来由文件系统存储的纳秒数。分辨率可能低于协议。它被发送回去以在主机端进行缓存。

  • 可用空间:32位数字,表示客户端可以发送的数据量。

客户端将重复响应,直到总长度已通过以下方式传输

  • 命令:单字节。始终为0x22

  • 状态:单字节。始终为0x01

  • 2 字节保留用于填充。

  • 偏移量:32位数字,表示写入的偏移量。

  • 数据大小:32位数字,表示客户端发送的数据量。

  • 数据

在服务器接收所有数据并回复状态为0可用空间且偏移量设置为内容长度后,事务完成。

注意:当前时间是在版本3中添加的。其余的包保持不变。

0x30 - 删除文件或目录

删除给定完整路径上的文件或目录。非空目录的内容也将被删除。

头部是两个固定条目和一个可变长度路径

  • 命令:单字节。始终为0x30

  • 1 字节保留用于填充。

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 路径:UTF-8编码的字符串,不是空终止的。(我们发送长度。)

服务器将回复

  • 命令:单字节。始终为0x31

  • 状态:单字节。如果文件或目录被删除,则为0x01。如果文件系统为只读,则为0x05。如果路径不存在,则为0x02

注意:在版本2中,此命令现在还删除目录的内容。它不会出错。

0x40 - 创建目录

在给定的完整路径上创建新的目录。如果父目录不存在,则也将创建它。如果任何名称与现有文件冲突,则将返回错误。

头部是两个固定条目和一个可变长度路径

  • 命令:单字节。总是 0x40

  • 1 字节保留用于填充。

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 4字节用于填充。

  • 当前时间:64位数字,表示自1970年1月1日以来的纳秒数。用作文件修改时间。不是所有系统都支持完整的分辨率。请使用截断的时间响应值进行缓存。

  • 路径:UTF-8编码的字符串,不是空终止的。(我们发送长度。)

服务器将回复

  • 命令:单字节。总是 0x41

  • 状态:单字节。如果目录创建成功则为 0x01,如果文件系统为只读则为 0x05,如果路径的任何父目录是现有文件则为 0x02

  • 6字节用于填充。

  • 截断时间:64位数字,表示自1970年1月1日以来由文件系统存储的纳秒数。分辨率可能低于协议。它被发送回去以在主机端进行缓存。

0x50 - 列出目录

列出给定完整路径下的目录中所有内容。返回的路径与给定路径 相对,以减少重复。

头部是两个固定条目和一个可变长度路径

  • 命令:单字节。总是 0x50

  • 1 字节保留用于填充。

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 路径:UTF-8编码的字符串,不是空终止的。(我们发送长度。)

对于有n个文件的目录,服务器将回复n+1个条目

  • 命令:单字节。总是 0x51

  • 状态:单字节。如果目录存在则为 0x01,如果不存在则为 0x02

  • 路径长度:16位数字,表示路径字符串的编码长度。

  • 条目编号:32位数字表示条目编号。

  • 总条目数:32位数字表示总条目数。

  • 标志:32位数字表示关于条目的数据。

    • 位0:当条目是目录时设置

    • 位1-7:保留

  • 修改时间:自1970年1月1日起的纳秒数。 然而,文件修改者可能没有准确的时钟,因此不要假设它是正确的。相反,仅用它来确定缓存性与本地副本。

  • 文件大小:32位数字表示文件的大小。对于目录忽略。值可能更改。

  • 路径:UTF-8编码的字符串,不包含空终止符。(我们发送长度。)这些路径是相对的,因此不会包含 /

当服务器从服务器发送最后一个条目时,事务完成。它将具有条目编号等于总条目数,标志、文件大小和路径长度为零。

0x60 - 移动文件或目录

将给定路径的文件或目录移动到不同的路径。也可以用于重命名。两个路径由一个字节分开,以便服务器可以自己空终止字符串。客户端可以发送任何内容。

头部是两个固定条目和一个可变长度路径

  • 命令:单字节。总是 0x60

  • 1 字节保留用于填充。

  • 旧路径长度:16位数字表示路径字符串的编码长度。

  • 新路径长度:16位数字表示路径字符串的编码长度。

  • 旧路径:UTF-8编码的字符串,不包含空终止符。(我们发送长度。)

  • 一个填充字节。这可以用来空终止旧路径字符串。

  • 新路径:UTF-8编码的字符串,不包含空终止符。(我们发送长度。)

服务器将回复

  • 命令:单字节。总是 0x61

  • 状态:单字节。成功时为 0x01,只读时为 0x05,其他错误时为 0x02

注意:这是在版本4中添加的。

版本

版本2

  • 将删除改为自动删除非空目录的内容。

版本3

  • 添加修改时间。* 将当前时间添加到文件写入命令。* 将当前时间添加到创建目录命令。* 将修改时间添加到目录列表条目。

版本4

  • 添加移动命令。

  • 添加0x05错误,用于只读文件系统。这通常是USB正在编辑相同的文件系统。

  • 删除目录路径必须以/结尾的要求。

贡献

欢迎贡献!在为该项目做出贡献之前,请阅读我们的行为准则,以帮助保持项目的友好氛围。

文档

有关构建库文档的信息,请参阅本指南

项目详情


下载文件

下载您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

构建分发

由以下机构支持