lager drivers install 安装到 Box 上,之后每位用户都可以用标准 CLI 操作它的 Net。驱动代码只保存在 Box 上。
驱动包结构
pyserial、pyusb 和 hidapi)以及 lager 包。如需其他包,请参见下文的“Python 包”一节。
清单文件
清单文件给出驱动的类型、Net 设置和操作。CLI 根据它生成lager <type> 命令,Box 按它校验每次调用。
每个 param 和 arg 都有一个
type:str、int、float、bool 或 choice。param 还可以是 net,表示另一个指定 role 的已保存 Net;驱动通过该 Net 访问硬件。字段还可以带有 required、default、min 和 max(仅限数字)、choices(用于 choice)以及 help。action、param 和 arg 的名称由 1 到 32 个小写字母、数字和 _ 组成,并以字母开头。不允许使用 -;CLI 将 hold_time 显示为 --hold-time。以下 arg 名称已被 CLI 占用,因此保留:box、json、as_json、help、netname、action、role、quiet、http_timeout、ctx、box_addr、params。
驱动代码
- 只有标记了
@action的方法可以被调用,并且每个方法都必须在清单文件中列出。方法以关键字参数接收操作的参数,类型与清单文件一致。 setup()在操作之前运行,teardown()在操作之后运行,即使操作抛出异常也会运行。- 返回字典、单个值或
None。字典中的message由 CLI 输出,其他键显示在其下方,--json输出完整结果。 - 异常会作为错误返回给用户,包含其类型和消息。
print()的输出和self.log写入 Box 日志,不会显示给用户。
Python 包
驱动可以使用 Box 上没有的包。将它们列在 requirements 文件中,并在清单文件中指定该文件:lager drivers install 时安装这些包,因此调用时无需等待安装。它们与驱动一起保存在 /etc/lager/drivers/ 中,因此 lager update 之后仍然保留。如果某个包无法安装,驱动不会被安装,之前安装的版本继续工作。
该文件必须将每个包(包括这些包所依赖的包)固定到一个版本并附带哈希值。pip-compile 可以生成这样的文件:
- 只允许精确版本加哈希值。 每一行为
name==version,并至少带一个--hash。不允许使用-r、-e、--index-url等选项。 - 只安装 wheel。 Box 不会从源码构建包。每个包必须有适用于 Box 的 Python(3.12)和 CPU 的 wheel。Box 可能是
x86_64或aarch64(ARM),因此请选择两种平台都有 wheel 的包,或纯 Python 的 wheel。pip-compile --generate-hashes会列出所有平台的哈希值。 - Box 自带的包优先。 驱动不能替换 Box 已有的包。如果固定了 Box 已有的包,版本必须与 Box 上的相同,否则安装会被拒绝。请不要列出这类包。
- 每个驱动有自己的包。 两个驱动可以使用同一个包的不同版本。
- 限制。 安装最长 5 分钟,安装后的包最多占用 200 MB。
无法联网的 Box
将 wheel 文件放在驱动包的wheels/ 文件夹中。Box 会先使用这些文件,再到网络上查找。它们计入 5 MB 的驱动包上限。下载适用于 Box CPU 的 wheel:
x86_64 的 Box 请使用 manylinux_2_36_x86_64。在 Box 上运行 uname -m 可以查看是哪一种。纯 Python 的 wheel 两种都适用。
更新之后
如果lager update 改变了 Box 的 Python 版本,lager drivers list 会将该驱动显示为 error,Deps 显示为 stale。使用以下命令重新安装这些包:
调用的运行方式
每次调用都会在 Box 上的新进程中运行驱动。驱动崩溃或挂起都不会使 Box 停止工作。Box 会在调用之前加载 Lager,因此进程启动很快。每次调用都会重新加载driver.py,因此安装的更新在下一次调用时生效。同一 Net 上的两次调用按顺序依次运行。如果某个 lager uart 会话占用了驱动所用的 UART Net,调用会被拒绝,直到该会话关闭。
在脚本中使用驱动
lager python 脚本可以直接使用自定义 Net:
open_driver() 在脚本自身的进程中加载驱动。它在进入时运行 setup(),在退出时运行 teardown()。当该 Net 不是自定义 Net,或某个 net 类型的 param 指向不存在的 Net 或角色不符的 Net 时,它会引发 ManifestError。当驱动无法导入或没有该 action 时,它会引发 DriverFailed。lager.drivers 还导出 DriverBusy、DriverTimeout 和 DriverUnavailable,Box 的 HTTP API 用它们表示 Net 忙、超时以及驱动未安装。
安装和使用
lager python 脚本相同。它不会出现在公开的 Lager 代码中,但能够连接到 Box 的人可以读取它。
