"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[1392],{5528:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var i=t(1085),s=t(1184);const a={sidebar_position:1,title:"File Format"},r=void 0,o={id:"configuration/format",title:"File Format",description:"COSMOS configuration files are just text files. They can (and should) be checked into your configuration management system and thus can be easily diffed throughout their history. They support ERB syntax, partials, and various line continuations which make them extremely flexible.",source:"@site/docs/configuration/format.md",sourceDirName:"configuration",slug:"/configuration/format",permalink:"/tools/staticdocs/docs/configuration/format",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/format.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1,title:"File Format"},sidebar:"defaultSidebar",previous:{title:"Configuration",permalink:"/tools/staticdocs/docs/configuration"},next:{title:"Plugins",permalink:"/tools/staticdocs/docs/configuration/plugins"}},l={},d=[{value:"Keyword / Parameters",id:"keyword--parameters",level:2},{value:"ERB",id:"erb",level:2},{value:"render",id:"render",level:3},{value:"Line Continuation",id:"line-continuation",level:2},{value:"String Concatenation",id:"string-concatenation",level:2}];function c(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"COSMOS configuration files are just text files. They can (and should) be checked into your configuration management system and thus can be easily diffed throughout their history. They support ERB syntax, partials, and various line continuations which make them extremely flexible."}),"\n",(0,i.jsx)(n.h2,{id:"keyword--parameters",children:"Keyword / Parameters"}),"\n",(0,i.jsx)(n.p,{children:"Each line of a COSMOS configuration file contains a single keyword followed by parameters. For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'COMMAND TARGET COLLECT BIG_ENDIAN "Collect command"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["The keyword is ",(0,i.jsx)(n.code,{children:"COMMAND"})," and the parameters are ",(0,i.jsx)(n.code,{children:"TARGET"}),", ",(0,i.jsx)(n.code,{children:"COLLECT"}),", ",(0,i.jsx)(n.code,{children:"BIG_ENDIAN"}),", and ",(0,i.jsx)(n.code,{children:'"Collect command"'}),". Keywords are parsed by COSMOS and parameters are checked for validity. Parameters can be required or optional although required parameters always come first. Some parameters have a limited set of valid values. For example, the ",(0,i.jsx)(n.code,{children:"COMMAND"})," keyword above has the following documentation:"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"PARAMETER"}),(0,i.jsx)(n.th,{children:"DESCRIPTION"}),(0,i.jsx)(n.th,{children:"REQUIRED"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Target"}),(0,i.jsx)(n.td,{children:"Name of the target this command is associated with"}),(0,i.jsx)(n.td,{children:"True"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Command"}),(0,i.jsx)(n.td,{children:"Name of this command. Also referred to as its mnemonic. Must be unique to commands to this target. Ideally will be as short and clear as possible."}),(0,i.jsx)(n.td,{children:"True"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Endianness"}),(0,i.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)(n.code,{children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,i.jsx)(n.td,{children:"True"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Description"}),(0,i.jsx)(n.td,{children:"Description of this command which must be enclosed with quotes"}),(0,i.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["The Target and Command parameters can be any string and are required. The Endianness parameter is required and must be ",(0,i.jsx)(n.code,{children:"BIG_ENDIAN"})," or ",(0,i.jsx)(n.code,{children:"LITTLE_ENDIAN"}),". Other values will cause an error when parsed. The Description parameter must be enclosed in quotes and is optional. All the COSMOS configuration files document their keyword and parameters in this fashion. In addition, Example Usage is provided similar to the example given above."]}),"\n",(0,i.jsx)(n.h2,{id:"erb",children:"ERB"}),"\n",(0,i.jsxs)(n.p,{children:["ERB stands for Embedded Ruby. ",(0,i.jsx)(n.a,{href:"https://github.com/ruby/erb",children:"ERB"})," is a templating system for Ruby which allows you to use Ruby logic and variables to generate text files. There are two basic forms of ERB:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erb",children:"<% Ruby code -- no output %>\n<%= Ruby expression -- insert result %>\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In a COSMOS ",(0,i.jsx)(n.a,{href:"/tools/staticdocs/docs/configuration/telemetry",children:"Telemetry"})," configuration file we could write the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erb",children:'<% (1..5).each do |i| %>\n APPEND_ITEM VALUE<%= i %> 16 UINT "Value <%= i %> setting"\n<% end %>\n'})}),"\n",(0,i.jsxs)(n.p,{children:["The first line is Ruby code which iterates from 1 up to and including 5 and places the value in the variable i. The code inside the block will be output to the file every time the iteration runs. The APPEND_ITEM line uses the value of i and directly outputs it to the file by using the ",(0,i.jsx)(n.code,{children:"<%="})," syntax. The result of the parsing will look like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'APPEND_ITEM VALUE1 16 UINT "Value 1 setting"\nAPPEND_ITEM VALUE2 16 UINT "Value 2 setting"\nAPPEND_ITEM VALUE3 16 UINT "Value 3 setting"\nAPPEND_ITEM VALUE4 16 UINT "Value 4 setting"\nAPPEND_ITEM VALUE5 16 UINT "Value 5 setting"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["COSMOS uses ERB syntax extensively in a Plugin's ",(0,i.jsx)(n.a,{href:"/tools/staticdocs/docs/configuration/plugins#plugintxt-configuration-file",children:"plugin.txt"})," configuration file."]}),"\n",(0,i.jsx)(n.h3,{id:"render",children:"render"}),"\n",(0,i.jsxs)(n.p,{children:["COSMOS provides a method used inside ERB called ",(0,i.jsx)(n.code,{children:"render"})," which renders a configuration file into another configuration file. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status"\n <%= render "_ccsds_apid.txt", locals: {apid: 1} %>\n APPEND_ITEM COLLECTS 16 UINT "Number of collects"\n ...\n'})}),"\n",(0,i.jsx)(n.p,{children:"The render method takes a parameter which is the name of the configuration file to inject into the top level file. This file is required to start with underscore to avoid being processed as a regular configuration file. This file is called a partial since it's part of a larger file. For example, _ccsds_apid.txt is defined as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:' APPEND_ID_ITEM CCSDSAPID 11 UINT <%= apid %> "CCSDS application process id"\n'})}),"\n",(0,i.jsx)(n.p,{children:"This would result in output as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status"\n APPEND_ID_ITEM CCSDSAPID 11 UINT 1 "CCSDS application process id"\n APPEND_ITEM COLLECTS 16 UINT "Number of collects"\n ...\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Note the variable ",(0,i.jsx)(n.code,{children:"apid"})," was set to 1 using the ",(0,i.jsx)(n.code,{children:"locals:"})," syntax. This is a very powerful way to add common headers and footer to every packet definition. See the INST target's cmd_tlm definitions in the ",(0,i.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos/tree/main/openc3-cosmos-init/plugins/packages/openc3-cosmos-demo/targets/INST/cmd_tlm",children:"Demo"})," for a more comprehensive example."]}),"\n",(0,i.jsx)(n.h2,{id:"line-continuation",children:"Line Continuation"}),"\n",(0,i.jsxs)(n.p,{children:["COSMOS supports a line continuation character in configuration files. For a simple line continuation use the ampersand character: ",(0,i.jsx)(n.code,{children:"&"}),". For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN &\n "Health and status"\n'})}),"\n",(0,i.jsx)(n.p,{children:"This will strip the ampersand character and merge the two lines to result in:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status"\n'})}),"\n",(0,i.jsx)(n.p,{children:"Spaces around the second line are stripped so indentation does not matter."}),"\n",(0,i.jsx)(n.h2,{id:"string-concatenation",children:"String Concatenation"}),"\n",(0,i.jsxs)(n.p,{children:["COSMOS supports two different string concatenation characters in configuration files. To concatenate strings with a newline use the plus character: ",(0,i.jsx)(n.code,{children:"+"}),". For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status" +\n "Additional description"\n'})}),"\n",(0,i.jsx)(n.p,{children:"The strings will be merged with a newline to result in:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status\\nAdditional description"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To concatenate strings without a newline use the backslash character: ",(0,i.jsx)(n.code,{children:"\\"}),". For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"TELEMETRY INST HEALTH_STATUS BIG_ENDIAN 'Health and status' \\\n 'Additional description'\n"})}),"\n",(0,i.jsx)(n.p,{children:"The strings will be merged without a newline to result in:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"TELEMETRY INST HEALTH_STATUS BIG_ENDIAN 'Health and statusAdditional description'\n"})}),"\n",(0,i.jsx)(n.p,{children:"The string continuation characters work with both single or double quoted strings but note that both lines MUST use the same syntax. You can not concatenate a single quoted string with a double quoted string or vice versa. Also note the indentation of the second line does not matter as whitespace is stripped."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1184:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var i=t(4041);const s={},a=i.createContext(s);function r(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);