###### tags: `F'` `Flight software` `tm` `master` # Creating new component - Quick guide To create a `[name]` component in a `App` topology ### Create component - Create component directory `App/[name]` - Create `App/[name]/ComponentAi.xml` description file ```xml= <?xml version="1.0" encoding="UTF-8"?> <?xml-model href="../../Autocoders/schema/ISF/component_schema.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?> <!-- [name] component : [description] --> <component name="[name]" kind="[active/passive/queued]" namespace="App" modeler="true"> <!-- Import command ports --> <import_port_type>Fw/Cmd/CmdPortAi.xml</import_port_type> <import_port_type>Fw/Cmd/CmdRegPortAi.xml</import_port_type> <import_port_type>Fw/Cmd/CmdResponsePortAi.xml</import_port_type> <!-- Import event ports --> <import_port_type>Fw/Log/LogPortAi.xml</import_port_type> <import_port_type>Fw/Log/LogTextPortAi.xml</import_port_type> <!-- Import telemetry ports --> <import_port_type>Fw/Tlm/TlmPortAi.xml</import_port_type> <ports> <!-- Command port definitions: command input receives commands, command reg out, and response out are ports used to register with the command dispatcher, and return responses to it --> <port name="cmdDisp" data_type="Fw::Cmd" kind="input" role="Cmd" max_number="1"> </port> <port name="cmdRegOut" data_type="Fw::CmdReg" kind="output" role="CmdRegistration" max_number="1"> </port> <port name="cmdResponseOut" data_type="Fw::CmdResponse" kind="output" role="CmdResponse" max_number="1"> </port> <!-- Event ports: send events, and text formated events --> <port name="eventOut" data_type="Fw::Log" kind="output" role="LogEvent" max_number="1"> </port> <port name="textEventOut" data_type="Fw::LogText" kind="output" role="LogTextEvent" max_number="1"> </port> <!-- Telemetry ports --> <port name="tlmOut" data_type="Fw::Tlm" kind="output" role="Telemetry" max_number="1"> </port> <!-- Custom ports --> </port> </ports> <commands> <command kind="async" opcode="0" mnemonic="EVAC_RUN"> <comment>Run component</comment> </command> </commands> <events> <event id="0" name="[abr]_EVENT" severity="ACTIVITY_HI" format_string="Event : %s"> <comment>An event occured</comment> <args> <arg name="arg1" type="string" size="40"> <comment>Event arg</comment> </arg> </args> </event> </events> </component> ``` - Create `App/[name]/CMakeLists.txt` ```cmake= #### # : App/[name]/CMakeLists.txt # # SOURCE_FILES: combined list of source and autocoding files # MOD_DEPS: (optional) module dependencies # # This file will setup the build for the [name] component. This is done by defining the SOURCE_FILES variable and then # registering the component as an F prime module. This allows autocoding and more! #### set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/[name]Ai.xml" ) register_fprime_module() ``` - Update `CMakeLists.txt` in `App` directory ```cmake=33 ## # Section 3: Components and Topology # # This section includes deployment specific directories. This allows use of non- core components in the topology, # which is also added here. ## # Add component subdirectories add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/[name]/") ``` ### Build component - Generate build directory ``` cd App fprime-util purge --force fprime-util generate ``` - Generate implementation files and code implemetation ``` cd App/[name] fprime-util impl mv [name]ComponentImpl.cpp-template [name]ComponentImpl.cpp mv [name]ComponentImpl.hpp-template [name]ComponentImpl.hpp ``` - Add component implementation in `[name]/CMakeLists.txt` ```=10 set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/[name]Ai.xml" "${CMAKE_CURRENT_LIST_DIR}/[name]ComponentImpl.cpp" ) register_fprime_module() ``` - Build component ``` cd App fprime-util build ``` ### Add component to the toplogy #### Update `App/AppTopologyAppAi.xml` - Import component type ```xml <import_component_type>App/[name]/[name]ComponentAi.xml</import_component_type> ``` - Declare component instance ```xml <instance namespace="App" name="[instanceName]" type="[name]" base_id="xxxx" base_id_window="20" /> ``` - List connections ```xml <connection name = "[name]Connection"> <source component = "[name]" port = "cmdRegOut" type = "CmdReg" num = "0"/> <target component = "cmdDisp" port = "compCmdReg" type = "CmdReg" num = "15"/> </connection> ``` #### Import component in `App/Top/Components.hpp` - Import header file ```cpp=30 #include <App/[name]/[name]ComponentImpl.hpp> ``` - Add extern component variable ```cpp=30 extern App::[name]ComponentImpl [instanceName]; ``` #### Complete `App/Top/Topology.cpp` - Create component instance ```cpp=103 App::[name]ComponentImpl [instanceName](FW_OPTIONAL_NAME("[instanceName]")); ``` - Fill `constructApp()` method : *Init component* ```cpp=171 [name].init(10, 0); ``` *Register component* ```cpp=200 [name].regCommands(); ``` *readParamFile(), loadParameters() and register PingEntry if need(), see [Math tutorial](https://nasa.github.io/fprime/Tutorials/MathComponent/Tutorial.html)* *For active component, start thread* ```cpp=250 [name].start(0, 100, 10*1024); ``` - Fill `exitTasks()` method: ```cpp [name].exit(); (void) [name].ActiveComponentBase::join(NULL); ```