Flipper Zero JavaScript SDK 开发指南:基于 @flipperdevices/fz-sdk 构建与运行 Flipper Zero JS 应用

发布时间:2026/9/14 2:07:17
Flipper Zero JavaScript SDK 开发指南:基于 @flipperdevices/fz-sdk 构建与运行 Flipper Zero JS 应用 Flipper Zero JavaScript SDK 开发指南基于 flipperdevices/fz-sdk 构建与运行 Flipper Zero JS 应用【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware导读本文以 Flipper Zero 固件仓库中的官方 JS SDK 开发包flipperdevices/fz-sdk为线索系统讲解如何用交互式脚手架创建 Flipper Zero JavaScript 应用、理解其构建上传流水线与配置文件并掌握 SDK 版本兼容检查机制和内置 API。读完本文你将能够独立完成一个 Flipper Zero JS 应用的初始化、编译、烧录运行与兼容性验证并理解其底层实现原理。一、flipperdevices/fz-sdk 是什么flipperdevices/fz-sdk是 Flipper Zero 官方为 JavaScript 应用开发提供的工具与类型声明包Type declarations and documentation for native JS modules available on Flipper Zero。它位于仓库的 applications/system/js_app/packages/fz-sdk 目录下主要包含三部分能力TypeScript 类型声明typings以*.d.ts文件形式描述 Flipper Zero 固件内置nativeJS 模块的完整 API 表面供开发者在 PC 上获得代码补全与类型检查CLI 工具sdk.js提供build与upload两个命令负责把 TypeScript 源码编译为 Flipper Zero 上 mJS 引擎可执行的脚本并通过串口上传到设备文档生成配置基于 TypeDoc 将类型声明中的 JSDoc 注释渲染为 API 文档。从 package.json 可以看到该包依赖esbuild打包压缩、esbuild-plugin-tscTypeScript 编译、typedoc文档生成、serialport串口上传等工具链组件版本为1.0.0License 为 GPL-3.0-only。它对应的解释器实现位于仓库固件侧applications/system/js_app目录下的js_app.c、js_thread.c以及modules/中各原生模块js_gui.c、js_gpio.c、js_storage.c等这些 C 模块就是 JS API 在固件端的实际落地实现。二、快速开始交互式脚手架与一键运行2.1 创建应用官方推荐的起步方式是使用交互式向导创建应用骨架npx flipperdevices/create-fz-applatest运行后向导会在当前目录生成一个 Flipper Zero JS 应用工程默认目录名如my-flip-app。脚手架的模板文件位于仓库 applications/system/js_app/packages/create-fz-app/template 下包含index.ts应用入口源码演示了事件循环 GUI 视图的基本用法package.json定义build/start脚本与依赖tsconfig.jsonTypeScript 编译配置fz-sdk.config.json5SDK 构建与上传配置。2.2 构建并运行cd my-flip-app npm startnpm start会依次执行模板 package.json 中定义的两条脚本build: tsc node node_modules/flipperdevices/fz-sdk/sdk.js build, start: npm run build node node_modules/flipperdevices/fz-sdk/sdk.js upload即先用tsc把 TypeScript 编译到dist/再调用sdk.js的build命令完成 mJS 兼容转译最后通过sdk.js upload将产物经串口上传到 Flipper Zero 并立即运行。官方文档同时说明你完全可以使用pnpm或yarn替代npm流程不变。2.3 向导生成的入口模板解读模板 index.ts 本身就是一个最小可运行的 Flipper Zero JS 应用值得逐段拆解// 注意导入顺序eventLoop 必须先于 gui 导入gui 必须先于任何 gui 子模块导入 import * as eventLoop from flipperdevices/fz-sdk/event_loop; import * as gui from flipperdevices/fz-sdk/gui; import * as dialog from flipperdevices/fz-sdk/gui/dialog; const views { dialog: dialog.makeWith({ header: Hello from app_name, text: Check out index.ts and\nchange something :), center: Gonna do that!, }), }; // 按下中间键退出应用 eventLoop.subscribe(views.dialog.input, (_sub, button, eventLoop) { if (button center) eventLoop.stop(); }, eventLoop); // 按下返回键退出应用 eventLoop.subscribe(gui.viewDispatcher.navigation, (_sub, _item, eventLoop) { eventLoop.stop(); }, eventLoop); // 切换到对话框视图并启动事件循环 gui.viewDispatcher.switchTo(views.dialog); eventLoop.run();这段代码集中体现了 Flipper Zero JS 编程的三个核心概念事件循环event_loop、视图工厂makeWith与视图调度器viewDispatcher其 API 语义在类型声明 event_loop/index.d.ts 与 gui/index.d.ts 中有完整定义。三、sdk.js 构建与上传流水线原理sdk.js是 SDK 包的命令行入口shebang#!/usr/bin/env node支持build与upload两个子命令从源码 sdk.js 可以还原其完整工作流程。3.1 build转译为 mJS 兼容子集Flipper Zero 上的 mJS 引擎并不支持完整的现代 JavaScript 语法因此build命令借助 esbuild 的supported选项显式禁用了一批语法特性将其转译为 mJS 可执行的兼容代码。被禁用的特性包括节选supported: { array-spread: false, arrow: false, async-await: false, class: false, destructuring: false, optional-chain: false, template-literal: false, for-of: false, // ... 完整清单见 sdk.js }同时flipperdevices/fz-sdk/*被声明为external意味着源码中的import * as gui from flipperdevices/fz-sdk/gui会保留为运行时的require(gui)调用与固件内建模块一一对应。构建产物默认写入dist/index.js由config.output决定并会在文件头部拼接let exports {};前缀以适配 mJS 的执行模型。3.2 upload串口自动发现与命令行协议upload命令实现了从 PC 到设备的完整烧录运行链路设备发现通过SerialPort.list()枚举串口优先匹配serialNumber以flip_开头的设备若为空部分 Windows 驱动不报告序列号则回退为按 STM32 VCP 的 VID:PID0483:5740过滤。多台设备时会弹出交互选择串口连接以230400波特率打开串口CLI 协议交互依次向 Flipper Zero 的 CLI 发送storage remove output删除旧文件、storage write_chunk output size分块写入脚本、js output启动脚本执行并以: 、Ready、Running、Script done!等输出标记同步状态退出清理进程退出时发送\x03中断脚本。也就是说npm start的上传即运行本质上是驱动了设备端 CLI 的存储与 JS 命令相关 CLI 实现在固件侧可对应到applications/services/cli与applications/system/js_app/js_app.c。四、fz-sdk.config.json5 配置详解构建与上传的行为由工程根目录下的fz-sdk.config.json5控制。模板默认配置如下完整模板{ build: { // 编译产物路径 output: dist/app_name.js, // 是否压缩代码以可读性和错误信息清晰度为代价减小体积 minify: false, // 设为 false 可关闭自动插入的 SDK 版本检查见下文第五、六节 enforceSdkVersion: true, }, upload: { // 上传源文件若无额外后处理应与 build.output 一致 input: dist/app_name.js, // 设备端存放路径默认是脚本应用目录 output: /ext/apps/Scripts/app_name.js, }, }各配置项说明配置项作用注意事项build.output编译产物输出路径通常放在dist/下build.minify是否启用 esbuild 压缩开启后体积更小但报错信息更难读build.enforceSdkVersion是否自动插入checkSdkCompatibility调用默认true关闭需自行做版本检查upload.input上传的源文件无后处理时应等于build.outputupload.output设备端保存路径默认/ext/apps/Scripts/目录与设备上脚本应用的浏览入口一致五、版本兼容机制SDK 版本与额外特性集这是 SDK 设计中最关键的部分原文档README 的 Versioning 一节给出了明确的版本语义版本对齐flipperdevices/fz-sdk每个发布版本的主版本号major和次版本号minor与它面向的 Flipper Zero JS SDK 版本一致并遵循 semver 语义。例如用 SDK 版本0.1.0编译的应用与0.1…1.0不含1.0之间的 JS SDK 版本兼容。破坏性变更规则major 版本在引入破坏性变更时递增即需要开发者修改应用的变更minor 版本在引入新的非破坏性特性时递增。由于官方已采用 TypeScript 类型声明是否属于破坏性变更依据 semver-ts 标准判定其核心是no new red squiggles编译期不产生新的类型错误。每个 API 的版本史类型声明中每个 API 的 JSDoc 注释都记录了其引入/修改的版本例如 global.d.ts 中大量出现version Added in JS SDK 0.1、version Added in JS SDK 0.2, extra feature gui-widget、version Baseline since JS SDK 1.0等标记。此外SDK 定义了额外特性集extra feature set概念每个 major 版本对应一组在部分固件发行版中存在、但并未进入上游的额外特性。各发行版之间可以互相移植这些特性当某个特性被移植进上游固件后在下一次 JS SDK major 版本发布时它会被声明为基线特性baseline feature不再被视为额外特性。当前仓库中的 JS SDK 即为 v1.0global.d.ts的 JSDoc 中明确标注 Youre looking at JS SDK v1.0。结论是在使用任何特性之前必须先检查运行脚本的解释器是否支持它否则应用的跨固件可移植性将大打折扣。六、兼容性检查 API 详解针对不同的使用场景global.d.ts 提供了五个兼容性检查函数均为全局可用无需导入函数签名用途sdkCompatibilityStatus(expectedMajor, expectedMinor) compatible \| firmwareTooOld \| firmwareTooNew需要详细的兼容性状态时使用isSdkCompatible(expectedMajor, expectedMinor) boolean需要布尔形式判断时使用checkSdkCompatibility(expectedMajor, expectedMinor) void \| never脚本绝对无法在不兼容的解释器上运行时使用不兼容时会询问用户是否继续doesSdkSupport(features: string[]) boolean查询指定额外特性是否被支持布尔形式checkSdkFeatures(features: string[]) void \| never同上但不支持时询问用户是否继续运行其中sdkCompatibilityStatus的三态语义为compatible脚本与固件 JS SDK 兼容firmwareTooOld期望的 major 大于固件版本或期望的 minor 大于固件版本firmwareTooNew期望的 major 低于固件版本。doesSdkSupport/checkSdkFeatures有一个易踩的坑类型声明中以warning明确标注如果被查询的特性如今已被认定为基线特性函数会返回false或视为未实现。因此查询时应只针对额外特性列表基线特性无需也不能通过它们检查。自动版本强制在enforceSdkVersion: true默认时build过程会在产物开头自动插入一行checkSdkCompatibility(major, minor);见 sdk.js其中 major/minor 取自flipperdevices/fz-sdk包自身的package.json版本。如果你已通读文档、确定能用上文的手动检查 API 获得更好控制可在fz-sdk.config.json5中将该选项设为false。补充说明原 README 的 Versioning 一节提到可组合使用sdkCompatibilityStatus、isSdkCompatible与assertSdkCompatibility三个函数而在当前仓库的类型声明中第三个函数的实际名称为checkSdkCompatibility语义一致检查失败时询问用户是否继续并以doesSdkSupport/checkSdkFeatures补充了特性级检查。使用时应以 global.d.ts 的实际声明为准。七、全局内置 APIglobal.d.ts 一览SDK 除模块化 API 外还提供了一批全局可用的内置函数与类型均在 global.d.ts 中声明基础函数delay(ms)暂停执行、print(...args)输出到 GUI 控制台视图、parseInt(text, base?)转数字base 支持 2…16默认 10、chr(n)ASCII 码转单字符越界返回null、require(module)加载原生模块、load(path, scope?)加载并执行另一个 JS 文件结果按会话缓存、die(message)携带错误信息退出环境变量__dirname当前脚本所在目录、__filename当前脚本文件路径控制台console.log / debug / warn / error分别输出到 UART 日志的[I]/[D]/[W]/[E]级别二进制类型ArrayBuffer含getPtr、byteLength、slice、RawPointer不透明指针类型JS 侧只能持有并原样回传、Uint8Array/Int8Array/Uint16Array/Int16Array/Uint32Array/Int32Array及ElementType联合类型内建对象子集Arraysplice/push/length、StringcharCodeAt/at/indexOf/slice/toUpperCase/toLowerCase、Number.toString(base)等。标准库的大部分特性尚未实现该模块只声明了确实实现的部分JSDoc 中明确说明 Standard library features are mostly unimplemented。编写代码时请以本文件声明为唯一依据不要依赖未声明的 ECMAScript 标准库行为。八、原生模块与 TypeScript 类型声明flipperdevices/fz-sdk的*.d.ts覆盖了固件侧全部原生 JS 模块与applications/system/js_app/modules/下的 C 实现一一对应SDK 模块类型声明目录固件侧 C 实现event_loopjs_event_loop.cgui及 15 个子模块dialog、submenu、widget、text_input、number_input、byte_input、file_picker、loading、menu、popup、empty_screen、button_menu、button_panel、vi_list、text_box、iconjs_gui.c 及各视图 C 文件gpiojs_gpio.cstoragejs_storage.cserialjs_serial.cmathjs_math.cnotificationjs_notification.cbadusbjs_badusb.cflipperjs_flipper.ctestsjs_tests.c在仓库自带的示例脚本 applications/system/js_app/examples/apps/Scripts 中gui.js、storage.js、gpio.js、event_loop.js、uart_echo.js、notify.js、math.js、badusb_demo.js等可以看到这些模块在真实脚本中的用法。8.1 GUI 体系View、ViewFactory 与 ViewDispatchergui/index.d.ts 系统性地描述了 Flipper Zero 的 GUI 抽象层次Canvas纯绘图区域没有抽象层Viewport指向画布矩形区域的窗口应用总是通过 viewport 访问画布View占据整个 viewport 并接管所有输入事件的全屏设计元素即 Flipper 术语中的视图。JS 适配器已覆盖button_menu、button_panel、byte_input、dialog对应dialog_ex、empty_screen、file_picker对应file_browser、loading、menu、number_input、popup、submenu、text_box、text_input、vi_list对应variable_item_list、widget共 15 种视图ViewDispatcher持有应用所需的所有视图并在请求间切换提供switchTo、sendCustom、sendTo以及navigation/custom事件源SceneManager视图调度器的可选附加组件用于复杂导航流程管理当前版本在 JS 中不可用。每种视图通过ViewFactory提供make()默认属性创建与makeWith(props)自定义初始属性创建两个工厂方法且属性可在创建后用view.set(name, value)修改。GUI 依赖event_loop模块因此必须先导入event_loop再导入gui再导入gui子模块——这一约束在模板index.ts的注释和类型声明中均有明确说明。8.2 事件循环模型event_loop/index.d.ts 说明了一个重要事实Flipper Zero 的 mJS 子系统不支持闭包因此subscribe(callback, ...extraArgs)允许把外部值作为额外参数传给回调若回调返回一个与额外参数个数相同的数组则下次触发时使用新值。示例定时器let timer eventLoop.timer(periodic, 1000); eventLoop.subscribe(timer, function(_sub, _item, counter, eventLoop) { print(Counter is at:, counter); if(counter 10) eventLoop.stop(); return [counter 1, eventLoop]; // 修改下次回调收到的额外参数 }, 0, eventLoop);回调的前两个参数固定为订阅管理器可cancel()和事件项无数据的定时器事件为undefined。8.3 存储 API 要点storage/index.d.ts 提供了File/FileInfo/FsInfo等类以及两组重要枚举访问模式AccessModer只读、w只写、rw读写创建模式OpenModeopen_existing不存在即失败、open_always不存在则创建空文件、open_append打开并把读写指针置到文件末尾不存在则创建、create_new已存在即失败、create_always截断并打开不存在则创建空文件。FileInfo返回pathstat返回完整路径readDirectory返回文件名、isDirectory、size与accessTimeUNIX 时间戳。九、开发工作流与最佳实践综合以上内容一个完整的 Flipper Zero JS 应用开发周期是初始化npx flipperdevices/create-fz-applatest生成工程骨架编码在index.ts或按需拆分的多个 TS 文件中编写逻辑依赖tsc的类型检查模板 tsconfig.json 开启checkJs、noLib并显式包含global.d.ts以保证全局 API 可用构建npm run build调用tsc与sdk.js build产出 mJS 兼容的压缩脚本运行npm start自动执行构建 串口上传 启动在设备上观察输出Running…Script done!标记兼容性保持默认的enforceSdkVersion: true或按第六节手动调用sdkCompatibilityStatus/isSdkCompatible/doesSdkSupport做精细控制关注每个 API JSDoc 中的version历史以决定脚本可运行的固件范围。最佳实践要点在脚本无法运行于不兼容解释器时使用checkSdkCompatibility/checkSdkFeatures自动询问用户在脚本能利用多版本能力时使用isSdkCompatible/doesSdkSupport需要详细状态时使用sdkCompatibilityStatus。谨记先检查、再使用的原则这能确保你的应用在各类 Flipper Zero 固件发行版之间保持可移植性。【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考