新闻详情

新闻详情

首页 / 资讯中心 / 详情

F´(F Prime)GDS 插件开发实战指南:从 SELECTION 到 FEATURE 插件的完整实现

发布时间:2026/9/15 15:55:28来源:尧图网络
F´(F Prime)GDS 插件开发实战指南:从 SELECTION 到 FEATURE 插件的完整实现
F´F PrimeGDS 插件开发实战指南从 SELECTION 到 FEATURE 插件的完整实现【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprimeF´F Prime地面数据系统GDS通过一套基于 pluggy 的插件机制允许开发者以两种方式扩展功能SELECTION插件为关键功能提供新实现选项如自定义帧格式、自定义通信适配器和FEATURE插件为 GDS 追加全新功能如独立运行的应用、数据处理与启动钩子。本文以官方 How-To 文档 develop-gds-plugins.md 为骨架完整演示如何开发一个framing选择型插件与一个带命令行参数的gds-app功能型插件并结合仓库内 GDS 插件参考文档 与源码说明插件注册、参数校验、打包测试与分发的全流程。读完本文你将能够独立编写、安装并分发自己的 F´ GDS 插件。插件系统设计F´ GDS 插件构建在 Python 插件框架 pluggy 之上。这意味着每个 GDS 插件实现者都必须定义一个功能函数并用实现装饰器gds_plugin标记同时所有 GDS 插件都必须定义一个注册函数为给定的插件类别返回一个实现类。插件类别总览GDS 定义了若干可供用户实现的插件类别下表汇总了每个类别及其插件类型类别类型描述参考文档framingSELECTION实现一对 framer/deframer 来处理串行化数据Framing Plugin ReferencecommunicationSELECTION实现与飞行软件通信的通信适配器Communication Plugin Referencedata-handlerFEATURE实现自定义数据项处理遥测、事件等Data Handler Plugingds-appFEATURE实现隔离在独立进程中的新 GDS 应用Gds Application Plugingds-functionFEATURE高级实现可控制进程的新 GDS 功能Gds Function Plugin两种插件类型的本质区别SELECTION 插件同一类别只运行一个实现由用户通过 CLI 显式选择。典型如framing帧/解帧协议与communication字节级收发适配器二者分别运行在 GDS 通信线程与通信进程中因此官方参考文档特别提示性能不佳或阻塞的实现会拖慢全部通信。FEATURE 插件默认全部运行除非用户单独禁用。典型如data-handler在独立的CustomDataHandler进程中消费已解码数据、gds-app独立进程中的应用、gds-function在主 GDS 进程中启动时执行一次。注册函数约定插件应定义一个名为register_category_plugin的函数返回上表中该类别实现基类的一个具体子类。这些具体类还可以额外定义get_arguments、get_name和check_arguments函数供插件系统向 CLI 提供并校验参数。TIP使用装饰器gds_plugin(BaseClass)例如gds_plugin(FramerDeframer)有助于定义插件。它会检查传入的基类是否为合法的插件基类添加相应的注册函数确保被装饰的类是正确的子类确保所有虚拟函数均已实现。开发一个 FramingSELECTION插件开发framing插件的第一步是确定必须实现的函数和必须派生的类。对于framing类别必须定义register_framing_plugin函数并返回FramerDeframer的具体子类。从 Framing 插件参考文档 可以看到FramerDeframer的虚拟函数包括两个核心方法frame(self, data: bytes) - bytes为待发送的数据包添加帧头、校验和或转义序列等准备用于传输deframe(self, data: bytes, no_copyFalse) - Tuple[bytes, bytes, bytes]把收到的字节流解析为完整数据包返回三元组(1) 提取出的数据包不完整时为None(2) 尚未消费的剩余字节(3) 被丢弃的数据。deframe的三元组返回值是 GDS 通信管线识别完整包 / 待续数据 / 垃圾字节的契约任何实现都必须严格遵循这一签名。基础插件骨架GDS 插件定义了一个继承自实现基类、并实现全部虚拟函数的类。这些类还定义一个经过正确装饰的注册函数类方法并可以定义用于 CLI 交互的其他类方法。一个基础的 framing 插件骨架如下src/my_plugin.py:from fprime_gds.common.communication.framing import FramerDeframer from fprime_gds.plugin.definitions import gds_plugin gds_plugin(FramerDeframer) class MyPlugin(FramerDeframer): # TODO: implement virtual functions classmethod def get_name(cls): Name of this implementation provided to CLI return my-plugin classmethod def get_arguments(cls): Arguments to request from the CLI return {} classmethod def check_arguments(cls): Check arguments from the CLI passTIP插件可以放在任意位置但典型做法是放在plugins/src目录下使插件与 F´ C 代码保持分离。实现虚拟函数每个插件实现基类如FramerDeframer都有一组实现者必须实现的虚拟方法。这些函数被标记为abc.abstractmethod可以在虚拟类定义中找到。FramerDeframer的虚拟函数由frame和deframe组成。下面这个frame函数在每个帧的开头加上字节MY-PLUGIN并在deframe时从帧头去掉同样的字节——这是一个极简的起始字start word示例src/my_plugin.py:from fprime_gds.common.communication.framing import FramerDeframer from fprime_gds.plugin.definitions import gds_plugin gds_plugin(FramerDeframer) class MyPlugin(FramerDeframer): START_TOKEN bMY-PLUGIN def frame(self, data): Frames data with MY-PLUGIN start token return self.START_TOKEN data def deframe(self, data, no_copyFalse): Deframe data with MY-PLUGIN start token discarded b data data if no_copy else b data # Copy data if no_copy # Deframing can deframe until data length isnt enough to provide start token while len(data) len(self.START_TOKEN): # Starts with start word and a second start word found if data[:len(self.START_TOKEN)] self.START_TOKEN and self.START_TOKEN in data[1:]: data data[len(self.START_TOKEN):] # Remove initial start token # Return packet (data to next start token), unconsumed data, and discarded data return data[:data.index(self.START_TOKEN)], data[data.index(self.START_TOKEN):], discarded # Starts with start token, but beginning of next packet was not found elif data[:len(self.START_TOKEN)] self.START_TOKEN: # Wait for new data break # Does not start with requested token throw away one byte and continue else: discarded data[1] data[1:] continue # No packet found, all data unconsumed, and discarded return None, data, discarded classmethod def get_name(cls): Name of this implementation provided to CLI return my-plugin classmethod def get_arguments(cls): Arguments to request from the CLI return {} classmethod def check_arguments(cls): Check arguments from the CLI pass这段deframe逻辑值得仔细阅读当缓冲区以START_TOKEN开头、且其后还能找到第二个START_TOKEN时认为第一个完整数据包已到达返回(data[:data.index(START_TOKEN)], 剩余数据, discarded)当缓冲区以起始字开头、但未发现下一个包的起始字时break跳出循环等待更多数据返回None表示当前无完整包当缓冲区不以起始字开头时逐个字节丢弃垃圾数据直到重新对齐起始字。这样实现了对字节流中起始字的滑动搜索与对齐正是流式传输如 TCP、UART场景下解帧的典型做法。更精简的无操作实现可参考 framing.md 中的NullFramerframe原样返回数据deframe直接返回(data, b, b)不添加任何帧结构。与飞行软件侧自定义帧协议的呼应如果你同时需要为 F´ 飞行软件侧实现自定义帧协议custom-framing.md 给出了完整的配套思路飞行软件侧需要实现 Framer 组件、Deframer 组件以及可选的FrameDetector而 GDS 侧正是通过本指南所述的FramerDeframer插件来对接同一套帧格式。两侧只需遵循同一协议约定起始字、帧头、长度字段等即可用fprime-gds --framing-selection MyCustomProtocol选择自定义插件完成地面段集成。开发一个 GDS AppFEATURE插件与framing示例插件不同应用插件是在 GDS 之外额外运行的。这类插件可用于启动连接更大 GDS 网络的新服务。本文将用应用插件演示如何从命令行获取参数。我们的插件将运行 Python 打印一条由参数提供的消息。这等价于执行下面这行命令python -c print(Hello World)应用插件骨架gds-app插件的基本结构如下它打印 Hello World。gds-app插件必须实现get_process_invocation函数返回将使用subprocess模块作为独立进程运行的命令行参数。src/my_app.py:import sys from fprime_gds.executables.apps import GdsApp from fprime_gds.plugin.definitions import gds_plugin gds_plugin(GdsApp) class MyApp(GdsApp): An app for the GDS def get_process_invocation(self): Process invocation return [sys.executable, -c, print(Hello World)] classmethod def get_name(cls): Get name return my-appTIPGdsApp插件可以启动任意进程不限于 Python 进程get_process_invocation返回的是subprocess.Popen风格的可执行命令行列表。高级用法GdsStandardApp参考文档 gds-app.md 指出GdsApp基类给予实现者完全控制权但不会自动与 GDS 数据网络建立任何通信。如果你的应用需要消费 GDS 的标准数据管线遥测、事件等应改用便捷子类GdsStandardApp它自动处理搭建标准 GDS 数据管线解析并转发常见 CLI 参数在正确的运行时环境中调用应用的start()方法。使用GdsStandardApp时你必须实现start(self, pipeline: StandardPipeline) - NoneGDS 初始化并连接后调用传入StandardPipeline并可选实现init(self)在管线创建前调用适合设置内部状态和get_additional_arguments(self)返回额外 CLI 参数注入 GDS CLI 解析器格式为参数标志元组 →argparse.add_argument关键字参数的映射。参考文档中的示例通过pipeline.send_command(cmdDisp.CMD_NO_OP, [])周期发送空操作命令。不需要、也不应自行实现get_process_invocation——它由框架自动处理。插件参数所有类型的插件都可以使用下文所述的模式从命令行获取参数。这里以应用插件展示。现在给插件加入参数。这个插件将接收一个--message参数并把它注入到打印的消息中。为此通过get_arguments类方法返回该参数。把下面代码加入MyApp类classmethod def get_arguments(cls): Get arguments return { (--message, ): { type: str, help: Message to print, required: True } }get_arguments是一个类方法返回一个字典键是包含标志位flags的元组值是要传给argparse.add_argument的关键字参数字典。因此支持argparse的一切能力type类型转换、help帮助文本、required是否必填、default默认值、choices可选值列表等。参数在插件实例化时以关键字参数形式提供给插件。向MyApp类添加如下内容def __init__(self, message): Constructor super().__init__() self.message message修改get_process_invocation以使用新的成员变量def get_process_invocation(self): Process invocation # Inject message into command line to print return [sys.executable, -c, fprint(f{self.message})]参数校验与安全性细心的安全开发者会注意到上面的代码存在注入漏洞。可以通过check_arguments类方法进行检查。当参数值格式错误时该方法应抛出ValueError或TypeError。把下面函数加入MyApp以修复注入问题classmethod def check_arguments(cls, message): Check arguments if in message or \n in message: raise ValueError(--message must not include nor a newline)由于消息被直接拼接进print(f{self.message})的代码字符串若消息中含有单引号或换行符\n就可能在子进程 Python 解释器中逃逸出字符串字面量、注入任意代码。check_arguments在 CLI 解析阶段即拦截非法输入避免其进入subprocess。完整插件现在插件可以运行了。用户运行fprime-gds --help时GDS 会自动征集message参数。完整的插件代码如下src/my_app.py:import sys from fprime_gds.plugin.definitions import gds_plugin from fprime_gds.executables.apps import GdsApp gds_plugin(GdsApp) class MyApp(GdsApp): An app for the GDS def __init__(self, message): Constructor super().__init__() self.message message def get_process_invocation(self): Process invocation # Inject message into command line to print return [sys.executable, -c, fprint(f{self.message})] classmethod def get_name(cls): Get name return my-app classmethod def get_arguments(cls): Get arguments return { (--message, ): { type: str, help: Message to print, required: True } } classmethod def check_arguments(cls, message): Check arguments if in message or \n in message: raise ValueError(--message must not include nor a newline)打包与测试插件插件以 Python 包的形式提供并使用入口点entrypoint加载插件。在包根目录需要配置一个基本的 Python 包包含两个文件代表包的pyproject.toml以及用于向后兼容的setup.py。项目结构如下plugins/src/my_plugin.py plugins/pyproject.toml plugins/setup.py一份示例pyproject.toml如下[build-system] requires [setuptools, wheel] build-backend setuptools.build_meta [project] name fprime-gds-my-plugin version 0.1.0 dependencies [ pluggy1.3.0, fprime-gds3.4.4 ] [project.entry-points.fprime_gds] my_plugin my_plugin:MyPlugin [tool.setuptools_scm]示例setup.py如下from setuptools import setup # Configuration is in pyproject.toml setup()[project.entry-points.fprime_gds]是插件被发现的关键机制每个条目形如名称 模块:类GDS 通过 pluggy 扫描该入口点组加载插件。上例中my_plugin my_plugin:MyPlugin指向my_plugin.py中装饰了gds_plugin的MyPlugin类。依赖中声明pluggy1.3.0与fprime-gds3.4.4保证插件运行所需的插件框架与 GDS 基础版本。用下面这行追加到project.entry-points.fprime_gds段即可加入我们的应用插件my_app my_app:MyApp文件写好后可以用下面的命令将插件本地安装以进行测试cd /path/to/plugin/directory pip install -e .WARNING用户必须处于已安装fprime-gds包的同一虚拟环境中。-eeditable 模式允许本地修改无需重装即可生效。通过 --help 验证插件加载测试插件的第一个步骤是运行fprime-gds --help。它应显示与你的插件关联的参数。这里实现的插件将产生如下输出usage: fprime-gds ... ... Framing Plugin Options: --framing-selection {fprime,my-plugin} Select framing implementer. (default: fprime) ... Gds_App Plugin my-app Options: --disable-my-app Disable the gds_app plugin my-app (default: False) --message MESSAGE Message to print (default: None)从输出可见插件系统的几个关键点--framing-selection的可选值自动扩展为{fprime,my-plugin}其中fprime是默认实现my-plugin来自get_name()的返回值每个gds-app插件自动获得一个--disable-name开关FEATURE 插件默认运行可单独禁用--message来自get_arguments()声明(default: None)表明该参数当前按非必填处理——注意这与示例中required: True的写法有关实际必填性以你的声明为准。WARNING此步骤可能暴露语法错误、缩进错误等异常。解决这些错误后帮助信息才能正常显示。运行测试测试 SELECTION 插件请在正常 GDS 运行时选择它fprime-gds --framing-selection my-pluginWARNING记得提供你的插件所需的任何参数应用插件在启动时自动运行。测试这类插件只需提供所需参数fprime-gds --message Hello Plugin若--message传入含或换行符的值check_arguments会抛出ValueError插件在启动前即被拒绝验证了安全校验生效。分发插件插件作为 Python 包实现因此可以通过以下方式分发源码分发Source Distribution把源码发送给用户按上文所示用pip install .安装二进制分发Binary Distribution把打包好的 wheel 发给用户用pip install /path/to/wheel安装PyPI通过 PyPI 分发你的 wheel。完整的 Python 打包教程包括构建 wheel 并上传到 PyPI可以参考 packaging.python.org 的打包项目教程。对于有固定依赖的插件如fprime-gds3.4.4在pyproject.toml的dependencies中声明版本约束可确保用户安装时自动拉取兼容的 GDS 版本。结论本文围绕 develop-gds-plugins.md 的核心脉络完整覆盖了 F´ GDS 插件的开发流程、设计原理以及 SELECTION 与 FEATURE 插件的区别插件系统设计基于 pluggygds_plugin装饰器 注册函数五类插件及各自基类详见 插件参考索引SELECTION 插件通过framing插件实例掌握FramerDeframer.frame/deframe的字节流处理与三元组返回契约FEATURE 插件通过gds-app插件实例掌握GdsApp/GdsStandardApp的进程启动模式与 CLI 参数交互参数机制get_arguments声明参数、check_arguments校验安全打包测试与分发入口点配置、pip install -e .本地测试、--help/--framing-selection/--message验证以及源码包、wheel、PyPI 三种分发途径。你现在应该能够编写自己的插件并处理参数了。若需要为其他类别编写插件如data-handler数据处理、communication通信适配、gds-function启动钩子可以分别查阅 contenteditable="false">【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置 2026/9/15 16:37:35

LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置

LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置 【免费下载链接】langchain4j LangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a un…

阅读更多 →
ai-memory 单写者 SQLite Actor:并发写入是如何做到零冲突的 2026/9/15 16:37:35

ai-memory 单写者 SQLite Actor:并发写入是如何做到零冲突的

ai-memory 单写者 SQLite Actor:并发写入是如何做到零冲突的 【免费下载链接】ai-memory Solution for long term memory for agent coding CLIs and to facilitate handoff between different agent vendors 项目地址: https://gitcode.com/GitHub_Trending/ai/a…

阅读更多 →
Cloudflare TURN 实战指南:WebRTC 长通话不掉线的 5 个关键设计 2026/9/15 16:37:35

Cloudflare TURN 实战指南:WebRTC 长通话不掉线的 5 个关键设计

Cloudflare TURN 实战指南:WebRTC 长通话不掉线的 5 个关键设计 【免费下载链接】skills Skills Catalog for Codex 项目地址: https://gitcode.com/GitHub_Trending/skills4/skills 想象这样一个场景:用户开了一场 WebRTC 视频会议,前…

阅读更多 →
deck.gl × Google Maps 集成指南:使用 GoogleMapsOverlay 构建自定义叠加层 2026/9/15 16:37:35

deck.gl × Google Maps 集成指南:使用 GoogleMapsOverlay 构建自定义叠加层

deck.gl Google Maps 集成指南:使用 GoogleMapsOverlay 构建自定义叠加层 【免费下载链接】deck.gl WebGL2 powered visualization framework 项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl 本文以 deck.gl 仓库中的 deck.gl/google-maps 模块…

阅读更多 →
QMK 固件中的 1upkeyboards pi60_hse 键盘支持:基于 RP2040 的 60% 热插拔 PCB 配置与刷写实战 2026/9/15 16:37:35

QMK 固件中的 1upkeyboards pi60_hse 键盘支持:基于 RP2040 的 60% 热插拔 PCB 配置与刷写实战

QMK 固件中的 1upkeyboards pi60_hse 键盘支持:基于 RP2040 的 60% 热插拔 PCB 配置与刷写实战 【免费下载链接】qmk_firmware Open-source keyboard firmware for Atmel AVR and Arm USB families 项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmwar…

阅读更多 →
2026年9月流量卡选购指南:看懂套餐真实成本避坑 2026/9/15 16:34:35

2026年9月流量卡选购指南:看懂套餐真实成本避坑

每年9月都是运营商调整套餐政策的高峰期。2026年这波调整,比往年更值得关注——因为市场上能打的短期“神卡”基本绝迹了,取而代之的是一批挂着“长期”名头、看似划算、实则暗藏各种附加条件的合约套餐。我这两周集中测了市面上二十多个省市的线上办卡渠…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞