docs/search-doc-1727995151675.json
{"searchDocs":[{"title":"Introduction","type":0,"sectionRef":"#","url":"/docs","content":"","keywords":"","version":"Next"},{"title":"So what is COSMOS, exactly?","type":1,"pageTitle":"Introduction","url":"/docs#so-what-is-cosmos-exactly","content":" COSMOS is a suite of applications that can be used to control a set of embedded systems. These systems can be anything from test equipment (power supplies, oscilloscopes, switched power strips, UPS devices, etc), to development boards (Arduinos, Raspberry Pi, Beaglebone, etc), to satellites. ","version":"Next","tagName":"h2"},{"title":"COSMOS Architecture","type":1,"pageTitle":"Introduction","url":"/docs#cosmos-architecture","content":" COSMOS 5 is a cloud native, containerized, microservice oriented command and control system. All the COSMOS microservices are docker containers which is why Docker is shown containing the entire COSMOS system. The green boxes on the left represent external embedded systems (Targets) which COSMOS connects to. The Redis data store contains the configuration for all the microservices, the current value table, as well as data streams containing decommutated data. The Minio data store contains plugins, targets, configuration data, text logs as well as binary logs of all the raw, decommutated, and reduced data. Users interact with COSMOS from a web browser which routes through the internal Traefik load balancer. Keep reading for an in-depth discussion of each of the COSMOS Tools. ","version":"Next","tagName":"h3"},{"title":"Helpful Hints","type":1,"pageTitle":"Introduction","url":"/docs#helpful-hints","content":" Throughout this guide there are a number of small-but-handy pieces of information that can make using COSMOS easier, more interesting, and less hazardous. Here's what to look out for. ProTips™ help you get more from COSMOS These are tips and tricks that will help you be a COSMOS wizard! Notes are handy pieces of information These are for the extra tidbits sometimes necessary to understand COSMOS. Warnings help you not blow things up Be aware of these messages if you wish to avoid certain death. Find a problem in the documentation or in COSMOS itself? Both using and hacking on COSMOS should be fun, simple, and easy, so if for some reason you find it's a pain, please create an issue on GitHub describing your experience so we can make it better. ","version":"Next","tagName":"h2"},{"title":"target.txt Keywords","type":0,"sectionRef":"#","url":"/docs/configuration/target","content":"","keywords":"","version":"Next"},{"title":"LANGUAGE","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#language","content":" (Since 5.11.1) Programming language of the target interfaces and microservices The target language must be either Ruby or Python. The language determines how the target's interfaces and microservices are run. Note that both Ruby and Python still use ERB to perform templating. Parameter\tDescription\tRequired\tRuby or Python Valid Values: ruby, python\tTrue Example Usage: LANGUAGE python ","version":"Next","tagName":"h2"},{"title":"REQUIRE","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#require","content":" Requires a Ruby file List the Ruby files required to explicitly declare dependencies. This is now completely optional. Parameter\tDescription\tRequiredFilename\tFilename to require. For files in the target's lib directory simply supply the filename, e.g. "REQUIRE my_file". Files in the base OpenC3 lib directory also should just list the filename. If a file is in a folder under the lib directory then you must specify the folder name, e.g. "REQUIRE folder/my_file". Note the ".rb" extension is optional when specifying the filename.\tTrue Example Usage: REQUIRE limits_response.rb ","version":"Next","tagName":"h2"},{"title":"IGNORE_PARAMETER","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#ignore_parameter","content":" Ignore the given command parameter Hint to other OpenC3 tools to hide or ignore this command parameter when processing the command. For example, Command Sender and Command Sequence will not display the parameter (by default) when showing the command and Script Runner code completion will not display the parameter. Parameter\tDescription\tRequiredParameter Name\tThe name of a command parameter. Note that this parameter will be ignored in ALL the commands it appears in.\tTrue Example Usage: IGNORE_PARAMETER CCSDS_VERSION ","version":"Next","tagName":"h2"},{"title":"IGNORE_ITEM","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#ignore_item","content":" Ignore the given telemetry item Hint to other OpenC3 tools to hide or ignore this telemetry item when processing the telemetry. For example, Packet Viewer will not display the item (by default) when showing the packet. Parameter\tDescription\tRequiredItem name\tThe name of a telemetry item. Note that this item will be ignored in ALL the telemetry it appears in.\tTrue Example Usage: IGNORE_ITEM CCSDS_VERSION ","version":"Next","tagName":"h2"},{"title":"COMMANDS","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#commands","content":" Process the given command definition file This keyword is used to explicitly add the command definition file to the list of command and telemetry files to process. warning Usage of this keyword overrides automatic command and telemetry file discovery. If this keyword is used, you must also use the TELEMETRY keyword to specify the telemetry files to process. Parameter\tDescription\tRequiredFilename\tName of a command definition file in the target's cmd_tlm directory, e.g. "cmd.txt".\tTrue Example Usage: COMMANDS inst_cmds_v2.txt TELEMETRY inst_tlm_v2.txt ","version":"Next","tagName":"h2"},{"title":"TELEMETRY","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#telemetry","content":" Process the given telemetry definition file This keyword is used to explicitly add the telemetry definition file to the list of command and telemetry files to process. warning Usage of this keyword overrides automatic command and telemetry file discovery. If this keyword is used, you must also use the COMMAND keyword to specify the command files to process. Parameter\tDescription\tRequiredFilename\tName of a telemetry definition file in the target's cmd_tlm directory, e.g. "tlm.txt".\tTrue Example Usage: COMMANDS inst_cmds_v2.txt TELEMETRY inst_tlm_v2.txt ","version":"Next","tagName":"h2"},{"title":"CMD_UNIQUE_ID_MODE","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#cmd_unique_id_mode","content":" (Since 4.4.0) Command packet identifiers don't all share the same bit offset, size, and type Ideally all commands for a target are identified using the exact same bit offset, size, and type field in each command. If ANY command identifiers differ then this flag must be set to force a brute force identification method. warning Using this mode significantly slows packet identification ","version":"Next","tagName":"h2"},{"title":"TLM_UNIQUE_ID_MODE","type":1,"pageTitle":"target.txt Keywords","url":"/docs/configuration/target#tlm_unique_id_mode","content":" (Since 4.4.0) Telemetry packets identifiers don't all share the same bit offset, size, and type Ideally all telemetry for a target are identified using the exact same bit offset, size, and type field in each packet. If ANY telemetry identifiers differ then this flag must be set to force a brute force identification method. warning Using this mode significantly slows packet identification ","version":"Next","tagName":"h2"},{"title":"File Format","type":0,"sectionRef":"#","url":"/docs/configuration/format","content":"","keywords":"","version":"Next"},{"title":"Keyword / Parameters","type":1,"pageTitle":"File Format","url":"/docs/configuration/format#keyword--parameters","content":" Each line of a COSMOS configuration file contains a single keyword followed by parameters. For example: COMMAND TARGET COLLECT BIG_ENDIAN "Collect command" The keyword is COMMAND and the parameters are TARGET, COLLECT, BIG_ENDIAN, and "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 COMMAND keyword above has the following documentation: PARAMETER\tDESCRIPTION\tREQUIREDTarget\tName of the target this command is associated with\tTrue Command\tName 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.\tTrue Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tTrue Description\tDescription of this command which must be enclosed with quotes\tFalse The Target and Command parameters can be any string and are required. The Endianness parameter is required and must be BIG_ENDIAN or 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. ","version":"Next","tagName":"h2"},{"title":"ERB","type":1,"pageTitle":"File Format","url":"/docs/configuration/format#erb","content":" ERB stands for Embedded Ruby. 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: <% Ruby code -- no output %> <%= Ruby expression -- insert result %> In a COSMOS Telemetry configuration file we could write the following: <% (1..5).each do |i| %> APPEND_ITEM VALUE<%= i %> 16 UINT "Value <%= i %> setting" <% end %> 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 <%= syntax. The result of the parsing will look like the following: APPEND_ITEM VALUE1 16 UINT "Value 1 setting" APPEND_ITEM VALUE2 16 UINT "Value 2 setting" APPEND_ITEM VALUE3 16 UINT "Value 3 setting" APPEND_ITEM VALUE4 16 UINT "Value 4 setting" APPEND_ITEM VALUE5 16 UINT "Value 5 setting" COSMOS uses ERB syntax extensively in a Plugin's plugin.txt configuration file. ","version":"Next","tagName":"h2"},{"title":"render","type":1,"pageTitle":"File Format","url":"/docs/configuration/format#render","content":" COSMOS provides a method used inside ERB called render which renders a configuration file into another configuration file. For example: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status" <%= render "_ccsds_apid.txt", locals: {apid: 1} %> APPEND_ITEM COLLECTS 16 UINT "Number of collects" ... 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: APPEND_ID_ITEM CCSDSAPID 11 UINT <%= apid %> "CCSDS application process id" This would result in output as follows: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status" APPEND_ID_ITEM CCSDSAPID 11 UINT 1 "CCSDS application process id" APPEND_ITEM COLLECTS 16 UINT "Number of collects" ... Note the variable apid was set to 1 using the 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 Demo for a more comprehensive example. ","version":"Next","tagName":"h3"},{"title":"Line Continuation","type":1,"pageTitle":"File Format","url":"/docs/configuration/format#line-continuation","content":" COSMOS supports a line continuation character in configuration files. For a simple line continuation use the ampersand character: &. For example: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN & "Health and status" This will strip the ampersand character and merge the two lines to result in: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status" Spaces around the second line are stripped so indentation does not matter. ","version":"Next","tagName":"h2"},{"title":"String Concatenation","type":1,"pageTitle":"File Format","url":"/docs/configuration/format#string-concatenation","content":" COSMOS supports two different string concatenation characters in configuration files. To concatenate strings with a newline use the plus character: +. For example: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status" + "Additional description" The strings will be merged with a newline to result in: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status\\nAdditional description" To concatenate strings without a newline use the backslash character: \\. For example: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN 'Health and status' \\ 'Additional description' The strings will be merged without a newline to result in: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN 'Health and statusAdditional description' 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. ","version":"Next","tagName":"h2"},{"title":"Host Install","type":0,"sectionRef":"#","url":"/docs/development/host-install","content":"","keywords":"","version":"Next"},{"title":"Installing COSMOS Directly onto a Host (No Containers)","type":1,"pageTitle":"Host Install","url":"/docs/development/host-install#installing-cosmos-directly-onto-a-host-no-containers","content":" Note: THIS IS NOT A RECOMMENDED CONFIGURATION. COSMOS 5 is released as containers and intended to be run as containers. However, for various reasons someone might want to run COSMOS directly on a host. These instructions will walk through getting COSMOS 5 installed and running directly on RHEL 7 or Centos 7. This configuration will create a working install, but falls short of the ideal in that it does not setup the COSMOS processes as proper services on the host OS (that restart themselves on boot, and maintain themselves running in case of errors). Contributions that add that functionality are welcome. Let's get started. The starting assumption is that you have a fresh install of either RHEL 7 or Centos 7. You are running as a normal user that has sudo permissions, and has git installed. Start by downloading the latest working version of COSMOS from Github cd ~ git clone https://github.com/openc3/cosmos.git Run the COSMOS installation script If you are feeling brave, you can run the one large installer script that installs everything in one step: cd cosmos/examples/hostinstall/centos7 ./openc3_install.sh Or, you may want to break it down to the same steps that are in that script, and make sure each individual step is successful: cd cosmos/examples/hostinstall/centos7 ./openc3_install_packages.sh ./openc3_install_ruby.sh ./openc3_install_redis.sh ./openc3_install_minio.sh ./openc3_install_traefik.sh ./openc3_install_openc3.sh ./openc3_start_services.sh ./openc3_first_init.sh If all was successful, you should be able to open Firefox, and goto: http://localhost:2900. Congrats you have COSMOS running directly on a host. As stated at the beginning, this is not currently a supported configuration. Contributions that help to improve it are welcome. ","version":"Next","tagName":"h2"},{"title":"SSL-TLS","type":0,"sectionRef":"#","url":"/docs/configuration/ssl-tls","content":"","keywords":"","version":"Next"},{"title":"Generate the certificate","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#generate-the-certificate","content":" Note: Self-signed certificates are considered insecure for the Internet. Firefox will treat the site as having an invalid certificate, while Chrome will act as if the connection was plain HTTP. To create a new Self-Signed SSL Certificate, use the openssl req command (run on linux from the cosmos-project root): openssl req -newkey rsa:4096 \\ -x509 \\ -sha256 \\ -days 3650 \\ -nodes \\ -out ./openc3-traefik/cert.crt \\ -keyout ./openc3-traefik/cert.key Country Name (2 letter code) [XX]:. State or Province Name (full name) []:. Locality Name (eg, city) [Default City]:. Organization Name (eg, company) [Default Company Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (eg, your name or your server hostname) []: <!-- UPDATE WITH YOUR HOSTNAME HERE --> Email Address []: Let's breakdown the command and understand what each option means: newkey rsa:4096 - Creates a new certificate request and 4096 bit RSA key. The default one is 2048 bits.x509 - Creates a X.509 Certificate.sha256 - Use 265-bit SHA (Secure Hash Algorithm).days 3650 - The number of days to certify the certificate for. 3650 is ten years. You can use any positive integer.nodes - Creates a key without a passphrase.out ./openc3-traefik/cert.crt - Specifies the filename to write the newly created certificate to. You can specify any file name.keyout ./openc3-traefik/cert.key - Specifies the filename to write the newly created private key to. You can specify any file name. For more information about the openssl req command options, visit the OpenSSL req documentation page. ","version":"Next","tagName":"h3"},{"title":"Updating the openc3-traefik Dockerfile","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#updating-the-openc3-traefik-dockerfile","content":" Add the new cert to the traefik Docker container. --- a/openc3-traefik/Dockerfile +++ b/openc3-traefik/Dockerfile @@ -1,3 +1,4 @@ FROM traefik:2.4 COPY ./traefik.yaml /etc/traefik/traefik.yaml +COPY ./cert.crt ./cert.key /etc/certs/ EXPOSE 80 ","version":"Next","tagName":"h3"},{"title":"Updating the Traefik config","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#updating-the-traefik-config","content":" Configure Traefik to use the new cert file. openc3-traefik/traefik.yaml --- a/openc3-traefik/traefik.yaml +++ b/openc3-traefik/traefik.yaml @@ -3,6 +3,17 @@ +tls: + certificates: + - certFile: "/etc/certs/cert.crt" + keyFile: "/etc/certs/cert.key" # Listen for everything coming in on the standard HTTP port entrypoints: web: address: ":2900" + http: + redirections: + entryPoint: + to: websecure + scheme: https + websecure: + address: ":2943" + http: + tls: + domains: + - main: "<!-- UPDATE WITH YOUR HOSTNAME HERE -->" ","version":"Next","tagName":"h3"},{"title":"Update docker-compose.yaml","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#update-docker-composeyaml","content":" Update traefik to use secure port 443 instead of port 80. --- a/compose.yaml +++ b/compose.yaml services: openc3-minio: @@ -70,7 +70,7 @@ services: openc3-traefik: image: "ballaerospace/openc3-traefik:${OPENC3_TAG}" ports: - - "80:2900" + - "443:2943" restart: "unless-stopped" depends_on: Now you can run ./openc3.sh start to rebuild the Traefik container and it should include your new cert file. ","version":"Next","tagName":"h3"},{"title":"Let's Encrypt","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#lets-encrypt","content":" KEY privkey.pem is the "key" file Sometimes it is named as cert.key or example.com.key. CRT fullchain.pem is your "crt" file. Sometimes it is named as example.com.crt. CRT/KEY Bundle bundle.pem would be made like so: cat fullchain.pem privkey.pem > bundle.pem HAProxy is the only server that I know of that uses bundle.pem. cert.pem cert.pem contains ONLY your certificate, which can only be used by itself if the browser already has the certificate which signed it, which may work in testing (which makes it seem like it may be the right file), but will actually fail for many of your users in production with a security error of untrusted certificate. However, you don't generally use the cert.pem by itself. It's almost always coupled with chain.pem as fullchain.pem. chain.pem chain.pem is the intermediary signed authority, signed by the root authority - which is what all browsers are guaranteed to have in their pre-built cache. ","version":"Next","tagName":"h2"},{"title":"Checking certs","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#checking-certs","content":" You can inspect the cert like so: openssl x509 -in cert.pem -text -noout ","version":"Next","tagName":"h3"},{"title":"Extracting the certificate and keys from a .pfx file","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#extracting-the-certificate-and-keys-from-a-pfx-file","content":" The .pfx file, which is in a PKCS#12 format, contains the SSL certificate (public keys) and the corresponding private keys. You might have to import the certificate and private keys separately in an unencrypted plain text format to use it on another system. This topic provides instructions on how to convert the .pfx file to .crt and .key files. ","version":"Next","tagName":"h2"},{"title":"Extract .crt and .key files from .pfx file","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#extract-crt-and-key-files-from-pfx-file","content":" PREREQUISITE: Ensure OpenSSL is installed in the server that contains the SSL certificate. Start OpenSSL from the OpenSSL\\bin folder. Open the command prompt and go to the folder that contains your .pfx file. Run the following command to extract the private key: openssl pkcs12 -in [yourfile.pfx] -nocerts -out [drlive.key] You will be prompted to type the import password. Type the password that you used to protect your keypair when you created the .pfx file. You will be prompted again to provide a new password to protect the .key file that you are creating. Store the password to your key file in a secure place to avoid misuse. Run the following command to extract the certificate: openssl pkcs12 -in [yourfile.pfx] -clcerts -nokeys -out [drlive.crt] Run the following command to decrypt the private key: openssl rsa -in [drlive.key] -out [drlive-decrypted.key] Type the password that you created to protect the private key file in the previous step. The .crt file and the decrypted and encrypted .key files are available in the path, where you started OpenSSL. ","version":"Next","tagName":"h3"},{"title":"Convert .pfx file to .pem format","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#convert-pfx-file-to-pem-format","content":" There might be instances where you might have to convert the .pfx file into .pem format. Run the following command to convert it into PEM format. openssl rsa -in [keyfile-encrypted.key] -outform PEM -out [keyfile-encrypted-pem.key] ","version":"Next","tagName":"h3"},{"title":"TLS1.2 INADEQUATE_SECURITY Errors","type":1,"pageTitle":"SSL-TLS","url":"/docs/configuration/ssl-tls#tls12-inadequate_security-errors","content":" https://doc.traefik.io/traefik/https/tls/#cipher-suiteshttps://pkg.go.dev/crypto/tls#pkg-constants tls: options: default: cipherSuites: - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ","version":"Next","tagName":"h2"},{"title":"Developing COSMOS","type":0,"sectionRef":"#","url":"/docs/development/developing","content":"","keywords":"","version":"Next"},{"title":"Development Tools","type":1,"pageTitle":"Developing COSMOS","url":"/docs/development/developing#development-tools","content":" The core COSMOS team develops with the Visual Studio Code editor and we highly recommend it. We also utilize a number of extensions including docker, kubernetes, gitlens, prettier, eslint, python, vetur, and ruby. We commit our openc3.code-workspace configuration for VSCode to help configure these plugins. You also need Docker Desktop which you should already have as it is a requirement to run COSMOS. You'll also need NodeJS and yarn installed. Building COSMOS Note: We primarily develop COSMOS in MacOS so the commands here will reference bash scripts but the same files exist in Windows as batch scripts. Build COSMOS using the openc3.sh script: % ./openc3.sh build This will pull all the COSMOS container dependencies and build our local containers. Note: This can take a long time especially for your first build! Once the build completes you can see the built images with the following command: % docker image ls | grep "openc3" openc3inc/openc3-cosmos-init latest 4cac7a3ea9d3 29 hours ago 446MB openc3inc/openc3-cosmos-script-runner-api latest 4aacbaf49f7a 29 hours ago 431MB openc3inc/openc3-cosmos-cmd-tlm-api latest 9a8806bd4be3 3 days ago 432MB openc3inc/openc3-operator latest 223e98129fe9 3 days ago 405MB openc3inc/openc3-base latest 98df5c0378c2 3 days ago 405MB openc3inc/openc3-redis latest 5a3003a49199 8 days ago 111MB openc3inc/openc3-traefik latest ec13a8d16a2f 8 days ago 104MB openc3inc/openc3-minio latest 787f6e3fc0be 8 days ago 238MB openc3inc/openc3-node latest b3ee86d3620a 8 days ago 372MB openc3inc/openc3-ruby latest aa158bbb9539 8 days ago 326MB Offline Building If you're building in a offline environment or want to use a private Rubygems, NPM or APK server (e.g. Nexus), you can update the following environment variables: RUBYGEMS_URL, NPM_URL, APK_URL, and more in the .env file. Example values: ALPINE_VERSION=3.18 ALPINE_BUILD=9 RUBYGEMS_URL=https://rubygems.org NPM_URL=https://registry.npmjs.org APK_URL=http://dl-cdn.alpinelinux.org Running COSMOS Running COSMOS in development mode enables localhost access to internal API ports as well as sets RAILS_ENV=development in the cmd-tlm-api and script-runner-api Rails servers. To run in development mode: % ./openc3.sh dev You can now see the running containers (I removed CONTAINER ID, CREATED and STATUS to save space): % docker ps IMAGE COMMAND PORTS NAMES openc3/openc3-cmd-tlm-api:latest "/sbin/tini -- rails…" 127.0.0.1:2901->2901/tcp cosmos-openc3-cmd-tlm-api-1 openc3/openc3-script-runner-api:latest "/sbin/tini -- rails…" 127.0.0.1:2902->2902/tcp cosmos-openc3-script-runner-api-1 openc3/openc3-traefik:latest "/entrypoint.sh trae…" 0.0.0.0:2900->80/tcp cosmos-openc3-traefik-1 openc3/openc3-operator:latest "/sbin/tini -- ruby …" cosmos-openc3-operator-1 openc3/openc3-minio:latest "/usr/bin/docker-ent…" 127.0.0.1:9000->9000/tcp cosmos-openc3-minio-1 openc3/openc3-redis:latest "docker-entrypoint.s…" 127.0.0.1:6379->6379/tcp cosmos-openc3-redis-1 If you go to localhost:2900 you should see COSMOS up and running! ","version":"Next","tagName":"h2"},{"title":"Running a Frontend Application","type":1,"pageTitle":"Developing COSMOS","url":"/docs/development/developing#running-a-frontend-application","content":" So now that you have COSMOS up and running how do you develop an individual COSMOS application? Bootstrap the frontend with yarn openc3-init % yarn Serve a local COSMOS application (CmdTlmServer, ScriptRunner, etc) openc3-init % cd plugins/packages/openc3-tool-scriptrunner openc3-tool-scriptrunner % yarn serve DONE Compiled successfully in 128722ms App running at: - Local: http://localhost:2914/tools/scriptrunner/ - Network: http://localhost:2914/tools/scriptrunner/ Note that the development build is not optimized. To create a production build, run npm run build. Set the single SPA override for the application Visit localhost:2900 and Right-click 'Inspect' In the console paste: localStorage.setItem("devtools", true); Refresh and you should see {...} in the bottom right Click the Default button next to the application (@openc3/tool-scriptrunner) Paste in the development path which is dependent on the port returned by the local yarn serve and the tool name (scriptrunner) http://localhost:2914/tools/scriptrunner/js/app.js Refresh the page and you should see your local copy of the application (Script Runner in this example). If you dynamically add code (like console.log) the yarn window should re-compile and the browser should refresh displaying your new code. It is highly recommended to get familiar with your browser's development tools if you plan to do frontend development. ","version":"Next","tagName":"h2"},{"title":"Running a Backend Server","type":1,"pageTitle":"Developing COSMOS","url":"/docs/development/developing#running-a-backend-server","content":" If the code you want to develop is the cmd-tlm-api or script-runner-api backend servers there are several steps to enable access to a development copy. Run a development version of traefik. COSMOS uses traefik to direct API requests to the correct locations. % cd openc3-traefik openc3-traefik % docker ps # Look for the container with name including traefik openc3-traefik % docker stop cosmos-openc3-traefik-1 openc3-traefik % docker build --build-arg TRAEFIK_CONFIG=traefik-dev.yaml -t openc3-traefik-dev . openc3-traefik % docker run --network=openc3-cosmos-network -p 2900:2900 -it --rm openc3-traefik-dev Run a local copy of the cmd-tlm-api or script-runner-api % cd openc3-cosmos-cmd-tlm-api openc3-cosmos-cmd-tlm-api % docker ps # Look for the container with name including cmd-tlm-api openc3-cosmos-cmd-tlm-api % docker stop cosmos-openc3-cosmos-cmd-tlm-api-1 # Run the following on Windows: openc3-cosmos-cmd-tlm-api> dev_server.bat # In Linux, set all the environment variables in the .env file, but override REDIS to be local openc3-cosmos-cmd-tlm-api % set -a; source ../.env; set +a openc3-cosmos-cmd-tlm-api % export OPENC3_REDIS_HOSTNAME=127.0.0.1 openc3-cosmos-cmd-tlm-api % export OPENC3_REDIS_EPHEMERAL_HOSTNAME=127.0.0.1 openc3-cosmos-cmd-tlm-api % bundle install openc3-cosmos-cmd-tlm-api % bundle exec rails s Once the bundle exec rails s command returns you should see API requests coming from interactions in the frontend code. If you add code (like Ruby debugging statements) to the cmd-tlm-api code you need to stop the server (CTRL-C) and restart it to see the effect. ","version":"Next","tagName":"h2"},{"title":"Testing with Curl","type":0,"sectionRef":"#","url":"/docs/development/curl","content":"","keywords":"","version":"Next"},{"title":"Curl Example with OpenC3 COSMOS Open Source","type":1,"pageTitle":"Testing with Curl","url":"/docs/development/curl#curl-example-with-openc3-cosmos-open-source","content":" OpenC3 COSMOS Open Source just has a single user account, so all you need to do is pass the single password as the token with your requests like this. Request: curl -i -H "Content-Type: application/json-rpc" -H "Authorization: password" -d '{"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "keyword_params": {"scope": "DEFAULT"}, "id": 8}' -X POST http://127.0.0.1:2900/openc3-api/api Response: HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Content-Length: 51 Content-Type: application/json-rpc Etag: W/"e806aacfdbed0b325e7a5928e3bb5cf4" Vary: Origin X-Request-Id: bbad6c6b-6d22-4374-a86f-b5b0b95e6939 X-Runtime: 0.059044 Date: Sat, 04 Nov 2023 21:34:47 GMT {"jsonrpc":"2.0","id":8,"result":53.26555000000001} ","version":"Next","tagName":"h2"},{"title":"Curl Example with OpenC3 COSMOS Enterprise","type":1,"pageTitle":"Testing with Curl","url":"/docs/development/curl#curl-example-with-openc3-cosmos-enterprise","content":" OpenC3 COSMOS Enterprise uses the Keycloak Single Sign-on system, so you must first request a token from Keycloak using a username and password pair, before you make requests. By default this token will expire in 5 minutes, and will need to be refreshed if it expires before your next request. Keycloak Request: # Get tokens from Keycloak - You will need to update the username and password with your account curl -i -H "Content-Type: application/x-www-form-urlencoded" -d 'username=operator&password=operator&client_id=api&grant_type=password&scope=openid' -X POST http://127.0.0.1:2900/auth/realms/openc3/protocol/openid-connect/token Keycloak Response: HTTP/1.1 200 OK Cache-Control: no-store Content-Length: 3207 Content-Type: application/json Pragma: no-cache Referrer-Policy: no-referrer Set-Cookie: KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/openc3/; HttpOnly Set-Cookie: KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/openc3/; HttpOnly Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Xss-Protection: 1; mode=block Date: Wed, 10 May 2023 00:40:40 GMT {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiZmVlOTQwYWYtZDY3Ny00MWUyLWIzNWYtZDI5ODhiM2RhZGQ2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsInN1YiI6ImFjZTFlNmExLTkzMTktNDc2ZS1iZjQzLTZmM2NhYjllZTJkZSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaSIsInNlc3Npb25fc3RhdGUiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtb3BlbmMzIiwiQUxMU0NPUEVTX19vcGVyYXRvciIsIm9mZmxpbmVfYWNjZXNzIiwiQUxMU0NPUEVTX192aWV3ZXIiXX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUaGUgT3BlcmF0b3IiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJvcGVyYXRvciIsImdpdmVuX25hbWUiOiJUaGUiLCJmYW1pbHlfbmFtZSI6Ik9wZXJhdG9yIn0.eSqSeZrmCTahwltz5jsu5r3w6W15T5h0BvIdqKWQBDcnxAcxKuT-Nwziw_ewySSgHeC172CIWJUpHVp8ACDQG-dfW4KkvA6AcGfSF_f8TBH_rZrVQwlvwwzdA_egGKzhZWcnAC8TDjXRxuaWmnOgWT0aaHZAoW8EvwmKp-1IVz2l0B-hqzfC7dkjMrCI1udLfDvDBza9OtuR-FnKGt8h4nYnRzr8pO2jwebPFyZlR00gVsyK-b411XqprpT-qpRObYZwH5womA-8xIiwRZj9dsfQ1TaHGFkp1LNzxcj_r6pfwVO263bohbeU7ImezQdbvGLJ9NHaglzVNroTui4BXA","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5NjNlMjJiMS0wZmYwLTRmZjktYTg0Zi1hOGI4MzcxOWFiMDEifQ.eyJleHAiOjE2ODM2ODEwNDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiMmQyYjIyNmItNjJkOS00YjRjLWI3YTYtMGEwYjk4MGQyMjMwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MjkwMC9hdXRoL3JlYWxtcy9vcGVuYzMiLCJzdWIiOiJhY2UxZTZhMS05MzE5LTQ3NmUtYmY0My02ZjNjYWI5ZWUyZGUiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYXBpIiwic2Vzc2lvbl9zdGF0ZSI6ImYzNzg1OTY3LTJhNDYtNGMxMi1hZDBjLWNmZjdmYzQ3N2RmOSIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkifQ.1HlKdxQkaL5tYuHTXsOceLZFmNNLl9BjoA4oUl70x9M","token_type":"Bearer","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwiYXV0aF90aW1lIjowLCJqdGkiOiJhNDJkOTY1ZS1lMzU0LTRiM2QtOTIyYS1hOWE0ZDgwZWYxMTkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjI5MDAvYXV0aC9yZWFsbXMvb3BlbmMzIiwiYXVkIjoiYXBpIiwic3ViIjoiYWNlMWU2YTEtOTMxOS00NzZlLWJmNDMtNmYzY2FiOWVlMmRlIiwidHlwIjoiSUQiLCJhenAiOiJhcGkiLCJzZXNzaW9uX3N0YXRlIjoiZjM3ODU5NjctMmE0Ni00YzEyLWFkMGMtY2ZmN2ZjNDc3ZGY5IiwiYXRfaGFzaCI6IjNBWE9ISkFKYzFPVldLd2Y0a0Q4TkEiLCJhY3IiOiIxIiwic2lkIjoiZjM3ODU5NjctMmE0Ni00YzEyLWFkMGMtY2ZmN2ZjNDc3ZGY5IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiVGhlIE9wZXJhdG9yIiwicHJlZmVycmVkX3VzZXJuYW1lIjoib3BlcmF0b3IiLCJnaXZlbl9uYW1lIjoiVGhlIiwiZmFtaWx5X25hbWUiOiJPcGVyYXRvciJ9.gdLl6KOKIIAdl6jYEuAXQrGCNvuwLQb3RDnwrHJdqyFXshiwofBiLMFreRsIE-33xXWNBU6pnSLQHPVlQU5Vmzlk0IOfk-b4yNq0dNa1TV1kmnxRl8w1ulTQYVZjdsN-oyLNwe0v3aJcYtbvIA3DP8rgO6bVv0ogkjWtlda6MbkyZN-har8x3raUVSlUPRP2Basy1xSMNNA1jvB-nEM-aubrUZE6r0PjI6PE1hbLPmuPbcX3uuIwXu2-UoXepkB8H7omUuMm-S98aHpRarwszC0mmHD5b_wiXusMVw4xYw8eavFue4zfw-T2IKuTVtxbMTygXIah6iqi4gkpL8Mx1w","not-before-policy":0,"session_state":"f3785967-2a46-4c12-ad0c-cff7fc477df9","scope":"openid profile email"} COSMOS Request: # COSMOS Request now looks like this: curl -i -H "Content-Type: application/json-rpc" -H "Authorization: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiZmVlOTQwYWYtZDY3Ny00MWUyLWIzNWYtZDI5ODhiM2RhZGQ2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsInN1YiI6ImFjZTFlNmExLTkzMTktNDc2ZS1iZjQzLTZmM2NhYjllZTJkZSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaSIsInNlc3Npb25fc3RhdGUiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtb3BlbmMzIiwiQUxMU0NPUEVTX19vcGVyYXRvciIsIm9mZmxpbmVfYWNjZXNzIiwiQUxMU0NPUEVTX192aWV3ZXIiXX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUaGUgT3BlcmF0b3IiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJvcGVyYXRvciIsImdpdmVuX25hbWUiOiJUaGUiLCJmYW1pbHlfbmFtZSI6Ik9wZXJhdG9yIn0.eSqSeZrmCTahwltz5jsu5r3w6W15T5h0BvIdqKWQBDcnxAcxKuT-Nwziw_ewySSgHeC172CIWJUpHVp8ACDQG-dfW4KkvA6AcGfSF_f8TBH_rZrVQwlvwwzdA_egGKzhZWcnAC8TDjXRxuaWmnOgWT0aaHZAoW8EvwmKp-1IVz2l0B-hqzfC7dkjMrCI1udLfDvDBza9OtuR-FnKGt8h4nYnRzr8pO2jwebPFyZlR00gVsyK-b411XqprpT-qpRObYZwH5womA-8xIiwRZj9dsfQ1TaHGFkp1LNzxcj_r6pfwVO263bohbeU7ImezQdbvGLJ9NHaglzVNroTui4BXA" -d '{"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "keyword_params": {"scope": "DEFAULT"}, "id": 8}' -X POST http://127.0.0.1:2900/openc3-api/api COSMOS Response: HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Content-Type: application/json-rpc Etag: W/"1e44c0878528687014e1e60a1cbebdae" Vary: Origin X-Request-Id: 47a8dd26-1348-4693-8df1-5375f60abc6c X-Runtime: 0.046477 Date: Wed, 10 May 2023 00:41:33 GMT Transfer-Encoding: chunked {"jsonrpc":"2.0","id":8,"result":29.204100000000007} ","version":"Next","tagName":"h2"},{"title":"Suite Runner Example","type":1,"pageTitle":"Testing with Curl","url":"/docs/development/curl#suite-runner-example","content":" It can be very useful to run the a suite or script remotely from a continuous testing server. COSMOS' REST API allows for this. To figure out what is required to run a certain task on the web GUI you can open up your browser's developer tools to monitor the network traffic. You will see all the requests and responses required to run a command and you can reformat them yourself to suit your own purposes. Below is an example of running a test script from a Chromium-based browser: You can see that there are 5 transactions total. To investigate just right-click on the network transaction and click "copy as curl" (depends on the browser). Here is an example of the second one: curl 'http://localhost:2900/script-api/scripts/TARGET/procedures/cmd_tlm_test.rb/lock?scope=DEFAULT' \\ -X 'POST' \\ -H 'Accept: application/json' \\ -H 'Accept-Language: en-US,en;q=0.9' \\ -H 'Authorization: pass' \\ -H 'Connection: keep-alive' \\ -H 'Content-Length: 0' \\ -H 'Origin: http://ascportal:2900' \\ -H 'Referer: http://localhost:2900/tools/scriptrunner/?file=TARGET%2Fprocedures%2Fcmd_tlm_test.rb' \\ -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0' \\ --insecure Many of the browser-specific headers are not required. The important thing to notice here is the URL and the request (in this case POST). If we inspect all of these we'll find out what each one does: Set the script contents this updates any local changes)Note that this is a different request to GET the script contents. This is done on the page load. Lock the script (so other users can't edit it during execution)Run script (this takes a JSON with options)Open Websocket for logsRequest Result (this URL is a little different because the results are saved in redis) Below is a bash script which does all the above given some options. It requires curl for the web requests and jq for JSON parsing and formatting. It locks and runs the script, continually checks its status, then requests the result. #!/bin/bash set -e TARGET=${1:-'TARGET'} SCRIPT=${2:-'procedures/cmd_tlm_test.rb'} SUITE=${3:-'TestSuite'} COSMOS_HOST='http://localhost:2900' SCRIPT_API="$COSMOS_HOST/script-api" SCRIPT_PATH="scripts/$TARGET/$SCRIPT" CURL_ARGS=( -H 'Accept: application/json' -H 'Authorization: password' -H 'Accept-Language: en-US,en;q=0.9' -H 'Connection: keep-alive' -H 'Content-Type: application/json' --insecure --silent ) # Lock script # curl "$SCRIPT_API/$SCRIPT_PATH/lock?scope=DEFAULT" -X "POST" "${CURL_ARGS[@]}" # Run script # RUN_OPTS=$(cat <<-json { "environment": [], "suiteRunner": { "method": "start", "suite": "$SUITE", "options": [ "continueAfterError" ] } } json ) RUN_OPTS=$(<<<"$RUN_OPTS" jq -rc .) ID=$(curl "$SCRIPT_API/$SCRIPT_PATH/run?scope=DEFAULT" --data-raw "$RUN_OPTS" "${CURL_ARGS[@]}") echo "Starting Script '$SCRIPT_PATH' at $(date) (may take up to 15 minutes)" > /dev/stderr echo "You can monitor it in Script Runner here: $COSMOS_HOST/tools/scriptrunner/$ID" > /dev/stderr # Loop while Script ID is still running # while true; do SCRIPT_STATUS="$(curl "$SCRIPT_API/running-script?scope=DEFAULT" "${CURL_ARGS[@]}" | jq ".[]|select(.id==$ID)")" if [[ -z $SCRIPT_STATUS ]]; then break; fi sleep 2 done # Request results # BUCKET_FILE_URI="$(curl "$SCRIPT_API/completed-scripts?scope=DEFAULT" "${CURL_ARGS[@]}" |\\ jq '[.[]|select(.name | test("'"${SCRIPT_PATH#scripts/}"' "))][0] | .log | @uri' -r)" URL="$(curl "$COSMOS_HOST/openc3-api/storage/download/$BUCKET_FILE_URI?bucket=OPENC3_LOGS_BUCKET&scope=DEFAULT" "${CURL_ARGS[@]}" |jq .url -r)" curl "$COSMOS_HOST$URL" "${CURL_ARGS[@]}" ","version":"Next","tagName":"h2"},{"title":"Log Structure","type":0,"sectionRef":"#","url":"/docs/development/log-structure","content":"","keywords":"","version":"Next"},{"title":"Packet Log File Format","type":1,"pageTitle":"Log Structure","url":"/docs/development/log-structure#packet-log-file-format","content":" Packet logs in OpenC3 COSMOS 5 are used to store raw binary packets as received from various targets, as well as decommutated packets stored as JSON structures. ","version":"Next","tagName":"h2"},{"title":"File Header","type":1,"pageTitle":"Log Structure","url":"/docs/development/log-structure#file-header","content":" COSMOS 5 Packet log files start with the 8-character sequence "COSMOS5_". This can be used to identify the type of file independent of filename and differentiate them from newer and older versions. ","version":"Next","tagName":"h3"},{"title":"Entry Types","type":1,"pageTitle":"Log Structure","url":"/docs/development/log-structure#entry-types","content":" Packet log files have 6 different entry types with room for future expansion. All entry headers are big endian binary data. Common Entry Format This common format is used for all packet log entries: Field\tData Type\tDescriptionLength\t32-bit Unsigned Integer\tTotal length of the entry in bytes not including the length field. Max entry size is therefore 4GiB. Entry Type\t4-bit Unsigned Integer\tEntry Type: 1 = Target Declaration 2 = Packet Declaraction 3 = Raw Packet 4 = JSON/CBOR Packet 5 = Offset Marker 6 = Key Map Cmd/Tlm Flag\t1-bit Unsigned Integer\t1 = Command 0 = Telemetry Stored Flag\t1-bit Unsigned Integer\t1 = Stored Data 0 = Realtime Data Id Flag\t1-bit Unsigned Integer\t1 = ID present 0 = ID not present CBOR Flag\t1-bit Unsigned Integer\tOnly Valid for "JSON/CBOR Packets" 1 = CBOR Data 0 = JSON Data Extra Flag\t1-bit Unsigned Integer\t1 = Extra present 0 = Extra Not Present (Added COSMOS 5.11) Received Time Flag\t1-bit Unsigned Integer\t1 = Received Time Present 0 = No Received Time (Added COSMOS 5.11.0) Reserved\t6-bit Unsigned Integer\tReserved for Future expansion. Should be set to 0 if unused. Entry Data\tVariable\tUnique data based on entry type. See Entry Types Below Id (Optional)\t32-byte Binary Hash\tIf the ID field is set, this is a binary 256-bit SHA-256 hash uniquely identifying a target configuration or packet configuration Target Declaration Entry Declares the name of a target the first time it is seen when writing the log file. Field\tData Type\tDescriptionTarget Name\tVariable-Length ASCII String\tTarget Name Packet Declaration Entry Declares the name of a packet the first time it is seen when writing the log file. References the associated target name by index. Field\tData Type\tDescriptionTarget Index\t16-bit Unsigned Integer\tIndex into a dynamically built table of target names, generated from the order of the target declarations in the file. The first target declaration gets index 0, the second target declaration gets index 1, etc. Packet Name\tVariable-Length ASCII String\tPacket Name Raw Packet and JSON Packet Entries Holds the main data for a packet. Raw packets are the data before the COSMOS decommutation phase. "JSON" packets are the data after decommutation. Note that "JSON" packets are now generally stored as CBOR rather than JSON to reduce storage size. Field\tData Type\tDescriptionPacket Index\t16-bit Unsigned Integer\tIndex into a dynamically built table of cmd_or_tlm/target name/packet name tuples, generated from the order of the packet declarations in the file. The first packet declaration gets index 0, the second packet declaration gets index 1, etc. This limits the max number of unique packet types in a single file to 65536. Packet Timestamp\t64-bit Unsigned Integer\tPacket timestamp in nanoseconds from the unix epoch (Jan 1st, 1970, midnight). This field contains the “packet time” for both Raw and JSON packet entries (which are used to store decommutated date). For JSON packet entries, the packet received time can also be extracted from the JSON data if needed. Received Timestamp (Optional)\t64-bit Unsigned Integer\tOnly present if Received Time Flag is Set (Only currently in Raw log files). Received timestamp in nanoseconds from the unix epoch (Jan 1st, 1970, midnight). This field contains the received time” for both Raw packet entries (which are used to store decommutated date). For JSON packet entries, the packet received time can be extracted from the JSON data if needed. Extra Length (Optional)\t32-bit Unsigned Integer\tOnly Present if Extra Flag is Set. Length of extra data in bytes not including itself. Extra Data (Optional)\tVariable-Length Block Data\tOnly Present if Extra Flag is Set. CBOR or JSON encoded object of extra data. Packet Data\tVariable-Length Block Data\tThe Raw binary packet data for Raw Packet entries, and ASCII JSON data (or CBOR if flag set) for JSON packet entries. Note the Common Entry Format Id field is not supported with either type of packet entry. Offset Marker Entry This contains the Redis stream offset for the last packet stored in this log file. This entry allows for a seamless transition from log files to Redis streams holding the most recent data received by COSMOS. Field\tData Type\tDescriptionOffset Marker\tVariable-Length ASCII String\tRedis Offset Marker Key Map Entry The key map entry is used to further reduce log file sizes by reducing the size of the names of the decommutated values. Each value is given a numeric name counting up from 0 which drastically reduces decommutated data size. Note: This could be further enhanced in the future by changing to a denser encoding similar to base64. The key map is generated on the first reception of a packet. If future packets have different keys, then the names are used as-is and no reduction is gained. Typically packet keys don't change within a file. Field\tData Type\tDescriptionPacket Index\t16-bit Unsigned Integer\tIndex into a dynamically built table of packet names, generated from the order of the packet declarations in the file. The first packet declaration gets index 0, the second packet declaration gets index 1, etc. Key Map\tVariable-Length ASCII String\tKey Map Data with Mapping from numeric key to actual packet item name ","version":"Next","tagName":"h3"},{"title":"Roadmap","type":0,"sectionRef":"#","url":"/docs/development/roadmap","content":"","keywords":"","version":"Next"},{"title":"Key Features Still to Come in OpenC3 COSMOS 5.x:","type":1,"pageTitle":"Roadmap","url":"/docs/development/roadmap#key-features-still-to-come-in-openc3-cosmos-5x","content":" Command Authority (Enterprise) Standardized Mission Planning Interface (aka Command Load Generator (CLG)) Protocol buffer support Critical Commanding (Two Operators - Enterprise) Log Message Extractor Tool (Enterprise) System Health Tool (Enterprise) ","version":"Next","tagName":"h2"},{"title":"OpenC3 COSMOS 6.0 (Late 2024)","type":1,"pageTitle":"Roadmap","url":"/docs/development/roadmap#openc3-cosmos-60-late-2024","content":" Core Features: Python Support Upgrade Tools to Vue 3 / Vuetify 3 Plugin App Store Functionality For 6.1+: Telemetry Viewer screen playback of historical data libCSP Interface (Cubesat Space Protocol) Standardized Interfaces for common message buses (ZeroMQ, ActiveMQ, etc) COSMOS Notebooks (similar to Jupyter Notebooks) COSMOS Dashboards (configurable iFrames for Common Operating Picture) Integration with ground networks (Atlas, RBC Signals) Integration with mission planning (Orbit Logic, Cognitive Space) Integration with flight dynamics (Kayhan, SEE, Exotrail) ","version":"Next","tagName":"h2"},{"title":"OpenC3 COSMOS 7.0","type":1,"pageTitle":"Roadmap","url":"/docs/development/roadmap#openc3-cosmos-70","content":" Core Features: Super Bridge - This will enable SaaS COSMOS and provide a secure method to communicate from a cloud server to an intranet for hardware control ","version":"Next","tagName":"h2"},{"title":"Near-term Planning","type":1,"pageTitle":"Roadmap","url":"/docs/development/roadmap#near-term-planning","content":" Our near-term planning linking to specific tickets is on our Github Planning Project. If you would like to commit feature ideas for COSMOS, please do so with normal Github issues at the main repo. ","version":"Next","tagName":"h2"},{"title":"Streaming API","type":0,"sectionRef":"#","url":"/docs/development/streaming-api","content":"Streaming API This documentation is for COSMOS Developers This information is just generally used behind the scenes in COSMOS tools The COSMOS 5 Streaming Api is the primary interface to receive a stream of the telemetry packets and/or command packets that have passed through the COSMOS system, both logged and continuously in realtime. Either raw binary packets or decommutated JSON packets can be requested. This API is implemented over Websockets using the Rails ActionCable framework. Actioncable client libraries are known to exist for at least Javascript, Ruby, and Python. Other languages may exist or could be created. Websockets allow for easy interaction with the new COSMOS 5 Javascript based frontend. The following interactions are all shown in Javascript, but would be very similar in any language. Connecting to this API begins by initiating an ActionCable connection. cable = ActionCable.createConsumer('/openc3-api/cable') This call opens the HTTP connection to the given URL and upgrades it to a websocket connection. This connection can then be shared with multiple “subscriptions”. A subscription describes a set of data that you want the API to stream to you. Creating a subscription looks like this: subscription = cable.subscriptions.create( { channel: "StreamingChannel", scope: "DEFAULT", token: token, }, { received: (data) => { // Handle received data }, connected: () => { // First chance to add what you want to stream here }, disconnected: () => { // Handle the subscription being disconnected }, rejected: () => { // Handle the subscription being rejected }, } ); Subscribing to the StreamingApi requires passing a channel name set to “StreamingChannel”, a scope which is typically “DEFAULT”, and an access token (a password in OpenSource COSMOS). In Javascript you also pass a set of callback functions that run at various lifecycle points in the subscription. The most important of these are connected and received. connected runs when the subscription is accepted by the StreamApi. This callback is the first opportunity to request specific data that you would like streamed. Data can also be added or removed at any time while the subscription is open. Data can be added to the stream by requesting individual items from a packet or by requesting the entire packet. Adding items to stream is done as follows: var items = [ ["DECOM__TLM__INST__ADCS__Q1__RAW", "0"], ["DECOM__CMD__INST__COLLECT__DURATION__WITH_UNITS", "1"], ]; OpenC3Auth.updateToken(OpenC3Auth.defaultMinValidity).then(() => { this.subscription.perform("add", { scope: window.openc3Scope, token: localStorage.openc3Token, items: items, start_time: this.startDateTime, end_time: this.endDateTime, }); }); The values in the item name are separated by double underscores, e.g. <MODE>__<CMD or TLM>__<TARGET NAME>__<PACKET NAME>__<ITEM NAME>__<VALUE TYPE>__<REDUCED TYPE>. Mode is either RAW, DECOM, REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY. The next parameter is CMD or TLM followed by the target, packet and item names. The Value Type is one of RAW, CONVERTED, FORMATTED, or WITH_UNITS. The last parameter is optional if you want to use the reduced data types. Reduced Type is one of SAMPLE, MIN, MAX, AVG, or STDDEV. Adding packets to stream is done as follows: var packets = [ ["RAW__TLM__INST__ADCS", "0"], ["DECOM__TLM__INST__HEALTH_STATUS__FORMATTED", "1"], ]; OpenC3Auth.updateToken(OpenC3Auth.defaultMinValidity).then(() => { this.subscription.perform("add", { scope: window.openc3Scope, token: localStorage.openc3Token, packets: packets, start_time: this.startDateTime, end_time: this.endDateTime, }); }); The values in the packet name are separated by double underscores, e.g. <MODE>__<CMD or TLM>__<TARGET NAME>__<PACKET NAME>__<VALUE TYPE>. Mode is either RAW or DECOM. The next parameter is CMD or TLM followed by the target and packet names. The Value Type is one of RAW, CONVERTED, FORMATTED, or WITH_UNITS. For Raw mode, VALUE TYPE should be set to RAW or omitted (e.g. TLM__INST__ADCS__RAW or TLM__INST__ADCS). start_time and end_time are standard COSMOS 64-bit integer timestamps in nanoseconds since the Unix Epoch (midnight January 1st, 1970). If start_time is null, that indicates to start streaming from the current time in realtime, indefinitely until items are removed, or the subscription is unsubscribed. end_time is ignored if start_time is null. If start_time is given and end_time is null, that indicates to playback from the given starttime and then continue indefinitely in realtime. If both start_time and end_time are given, then that indicates a temporary playback of historical data. Data returned by the streaming API is handled by the received callback in Javascript. Data is returned as a JSON Array, with a JSON object in the array for each packet returned. Results are batched, and the current implementation will return up to 100 packets in each batch (the array will have 100 entries). 100 packets per batch is not guaranteed, and batches may take on varying sizes based on the size of the data returned, or other factors. An empty array indicates that all data has been sent for a purely historical query and can be used as an end of data indicator. For decommutated items, each packet is represented as a JSON object with a 'time' field holding the COSMOS nanosecond timestamp of the packet, and then each of the requested item keys with their corresponding value from the packet. [ { "time": 1234657585858, "TLM__INST__ADCS__Q1__RAW": 50.0, "TLM__INST__ADCS__Q2__RAW": 100.0 }, { "time": 1234657585859, "TLM__INST__ADCS__Q1__RAW": 60.0, "TLM__INST__ADCS__Q2__RAW": 110.0 } ] For raw packets, each packet is represented as a JSON object with a time field holding the COSMOS nanosecond timestamp of the packet, a packet field holding the topic the packet was read from in the form of SCOPE__TELEMETRY__TARGETNAME__PACKETNAME, and a buffer field holding a BASE64 encoded copy of the packet data. [ { "time": 1234657585858, "packet": "DEFAULT__TELEMETRY__INST__ADCS", "buffer": "SkdfjGodkdfjdfoekfsg" }, { "time": 1234657585859, "packet": "DEFAULT__TELEMETRY__INST__ADCS", "buffer": "3i5n49dmnfg9fl32k3" } ] ","keywords":"","version":"Next"},{"title":"Tables","type":0,"sectionRef":"#","url":"/docs/configuration/table","content":"","keywords":"","version":"Next"},{"title":"Table Definition Files","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#table-definition-files","content":" Table definition files define the binary tables that can be displayed in COSMOS Table Manager. Table definitions are defined in the target's tables/config directory and are typically named after the table such as PPSSelectionTable_def.txt. The _def.txt extension helps to identify the file as a table definition. Table definitions can be combined using the TABLEFILE keyword. This allows you to build individual table components into a larger binary. The Table definition files share a lot of similarity with the Command Configuration. You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. Table Keywords ","version":"Next","tagName":"h2"},{"title":"TABLEFILE","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#tablefile","content":" Specify another file to open and process for table definitions Parameter\tDescription\tRequiredFile Name\tName of the file. The file will be looked for in the directory of the current definition file.\tTrue ","version":"Next","tagName":"h2"},{"title":"TABLE","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#table","content":" Start a new table definition Parameter\tDescription\tRequiredName\tName of the table in quotes. The name will appear on the GUI tab.\tTrue Endianness\tIndicates if the data in this table is in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tTrue Display\tIndicates the table contains KEY_VALUE rows (e.g. each row is unique), or a ROW_COLUMN table with identical rows containing different values. Valid Values: KEY_VALUE, ROW_COLUMN\tFalse When Display is KEY_VALUE the remaining parameters are: Parameter\tDescription\tRequiredDescription\tDescription of the table in quotes. The description is used in mouseover popups and status line information.\tFalse When Display is ROW_COLUMN the remaining parameters are: Parameter\tDescription\tRequiredRows\tThe number of rows in the table\tFalse Description\tDescription of the table in quotes. The description is used in mouseover popups and status line information.\tFalse ","version":"Next","tagName":"h2"},{"title":"TABLE Modifiers","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#table-modifiers","content":" The following keywords must follow a TABLE keyword. ","version":"Next","tagName":"h2"},{"title":"PARAMETER","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#parameter","content":" Defines a parameter in the current table Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the table.\tTrue Bit Offset\tBit offset into the table of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the table. Always use a bit offset of 0 for derived parameters.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue Default Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse ","version":"Next","tagName":"h3"},{"title":"PARAMETER Modifiers","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#parameter-modifiers","content":" The following keywords must follow a PARAMETER keyword. FORMAT_STRING Adds printf style formatting Parameter\tDescription\tRequiredFormat\tHow to format using printf syntax. For example, '0x%0X' will display the value in hex.\tTrue Example Usage: FORMAT_STRING "0x%0X" UNITS Add displayed units Parameter\tDescription\tRequiredFull Name\tFull name of the units type, e.g. Celsius\tTrue Abbreviated\tAbbreviation for the units, e.g. C\tTrue Example Usage: UNITS Celsius C UNITS Kilometers KM DESCRIPTION Override the defined description Parameter\tDescription\tRequiredValue\tThe new description\tTrue META Stores custom user metadata Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files. Parameter\tDescription\tRequiredMeta Name\tName of the metadata to store\tTrue Meta Values\tOne or more values to be stored for this Meta Name\tFalse Example Usage: META TEST "This parameter is for test purposes only" OVERLAP (Since 4.4.1) This item is allowed to overlap other items in the packet If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message. KEY (Since 5.0.10) Defines the key used to access this raw value in the packet. Keys are often JsonPath or XPath strings Parameter\tDescription\tRequiredKey string\tThe key to access this item\tTrue Example Usage: KEY $.book.title VARIABLE_BIT_SIZE (Since 5.18.0) Marks an item as having its bit size defined by another length item Parameter\tDescription\tRequiredLength Item Name\tThe name of the associated length item\tTrue Length Bits Per Count\tBits per count of the length item. Defaults to 8\tFalse Length Value Bit Offset\tOffset in Bits to Apply to Length Field Value. Defaults to 0\tFalse REQUIRED Parameter is required to be populated in scripts When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition. MINIMUM_VALUE Override the defined minimum value Parameter\tDescription\tRequiredValue\tThe new minimum value for the parameter\tTrue MAXIMUM_VALUE Override the defined maximum value Parameter\tDescription\tRequiredValue\tThe new maximum value for the parameter\tTrue DEFAULT_VALUE Override the defined default value Parameter\tDescription\tRequiredValue\tThe new default value for the parameter\tTrue STATE Defines a key/value pair for the current command parameter Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error. Parameter\tDescription\tRequiredKey\tThe string state name\tTrue Value\tThe numerical state value\tTrue Hazardous / Disable Messages\tIndicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state. Valid Values: HAZARDOUS\tFalse Hazardous Description\tString describing why this state is hazardous\tFalse Example Usage: APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting" STATE FALSE 0 STATE TRUE 1 APPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter" STATE "NOOP" "NOOP" DISABLE_MESSAGES STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard" STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!" WRITE_CONVERSION Applies a conversion when writing the current command parameter Conversions are implemented in a custom Ruby or Python file which should be located in the target's lib folder. The class must inherit from Conversion. It must implement the initialize (Ruby) or __init__ (Python) method if it takes extra parameters and must always implement the call method. The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Multiple write conversions on command parameters When a command is built, each item gets written (and write conversions are run) to set the default value. Then items are written (again write conversions are run) with user provided values. Thus write conversions can be run twice. Also there are no guarantees which parameters have already been written. The packet itself has a given_values() method which can be used to retrieve a hash of the user provided values to the command. That can be used to check parameter values passed in. Parameter\tDescription\tRequiredClass Filename\tThe filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'.\tTrue Parameter\tAdditional parameter values for the conversion which are passed to the class constructor.\tFalse Ruby Example: WRITE_CONVERSION the_great_conversion.rb 1000 Defined in the_great_conversion.rb: require 'openc3/conversions/conversion' module OpenC3 class TheGreatConversion < Conversion def initialize(multiplier) super() @multiplier = multiplier.to_f end def call(value, packet, buffer) return value * multiplier end end end Python Example: WRITE_CONVERSION the_great_conversion.py 1000 Defined in the_great_conversion.py: from openc3.conversions.conversion import Conversion class TheGreatConversion(Conversion): def __init__(self, multiplier): super().__init__() self.multiplier = float(multiplier) def call(self, value, packet, buffer): return value * multiplier POLY_WRITE_CONVERSION Adds a polynomial conversion factor to the current command parameter The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Parameter\tDescription\tRequiredC0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: POLY_WRITE_CONVERSION 10 0.5 0.25 SEG_POLY_WRITE_CONVERSION Adds a segmented polynomial conversion factor to the current command parameter This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Parameter\tDescription\tRequiredLower Bound\tDefines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound.\tTrue C0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50 SEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100 SEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100 GENERIC_WRITE_CONVERSION_START Start a generic write conversion Adds a generic conversion function to the current command parameter. This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. The conversion is specified as Ruby or Python code that receives two implied parameters. 'value' which is the raw value being written and 'packet' which is a reference to the command packet class (Note, referencing the packet as 'myself' is still supported for backwards compatibility). The last line of code should return the converted value. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of code for the conversion have been given. Multiple write conversions on command parameters When a command is built, each item gets written (and write conversions are run) to set the default value. Then items are written (again write conversions are run) with user provided values. Thus write conversions can be run twice. Also there are no guarantees which parameters have already been written. The packet itself has a given_values() method which can be used to retrieve a hash of the user provided values to the command. That can be used to check parameter values passed in. warning Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance. Ruby Example: APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0 GENERIC_WRITE_CONVERSION_START return (value * 1.5).to_i # Convert the value by a scale factor GENERIC_WRITE_CONVERSION_END Python Example: APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0 GENERIC_WRITE_CONVERSION_START return int(value * 1.5) # Convert the value by a scale factor GENERIC_WRITE_CONVERSION_END GENERIC_WRITE_CONVERSION_END Complete a generic write conversion OVERFLOW Set the behavior when writing a value overflows the type By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value. Parameter\tDescription\tRequiredBehavior\tHow OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types. Valid Values: ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE\tTrue Example Usage: OVERFLOW TRUNCATE HIDDEN Indicates that the parameter should not be shown to the user in the Table Manager GUI Hidden parameters still exist and will be saved to the resulting binary. This is useful for padding and other essential but non-user editable fields. UNEDITABLE Indicates that the parameter should be shown to the user but not editable. Uneditable parameters are useful for control fields which the user may be interested in but should not be able to edit. ","version":"Next","tagName":"h3"},{"title":"APPEND_PARAMETER","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#append_parameter","content":" Defines a parameter in the current table Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the table.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue Default Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse ","version":"Next","tagName":"h3"},{"title":"SELECT_TABLE","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#select_table","content":" Select an existing table for editing, typically done to override an existing definition Parameter\tDescription\tRequiredTable\tThe name of the existing table\tTrue ","version":"Next","tagName":"h2"},{"title":"DEFAULT","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#default","content":" Specify default values for a SINGLE row in a multi-column table If you have multiple rows you need a DEFAULT line for each row. If all your rows are identical consider using ERB as shown in the OpenC3 demo. Parameter\tDescription\tRequiredDefault values\tA STATE value or data value corresponding to the data type\tFalse ","version":"Next","tagName":"h2"},{"title":"Example File","type":1,"pageTitle":"Tables","url":"/docs/configuration/table#example-file","content":" Example File: TARGET/tables/config/MCConfigurationTable_def.txt TABLE "MC_Configuration" BIG_ENDIAN KEY_VALUE "Memory Control Configuration Table" APPEND_PARAMETER "Scrub_Region_1_Start_Addr" 32 UINT 0 0x03FFFFFB 0 FORMAT_STRING "0x%0X" APPEND_PARAMETER "Scrub_Region_1_End_Addr" 32 UINT 0 0x03FFFFFF 0x03FFFFFF FORMAT_STRING "0x%0X" APPEND_PARAMETER "Scrub_Region_2_Start_Addr" 32 UINT 0 0x03FFFFB 0 FORMAT_STRING "0x%0X" APPEND_PARAMETER "Scrub_Region_2_End_Addr" 32 UINT 0 0x03FFFFF 0x03FFFFF FORMAT_STRING "0x%0X" APPEND_PARAMETER "Dump_Packet_Throttle_(sec)" 32 UINT 0 0x0FFFFFFFF 2 "Number of seconds to wait between dumping large packets" APPEND_PARAMETER "Memory_Scrubbing" 8 UINT 0 1 1 STATE DISABLE 0 STATE ENABLE 1 APPEND_PARAMETER "SIOC_Memory_Config" 8 UINT 1 3 3 APPEND_PARAMETER "Uneditable_Text" 32 UINT MIN MAX 0xDEADBEEF "Uneditable field" FORMAT_STRING "0x%0X" UNEDITABLE APPEND_PARAMETER "Uneditable_State" 16 UINT MIN MAX 0 "Uneditable field" STATE DISABLE 0 STATE ENABLE 1 UNEDITABLE APPEND_PARAMETER "Uneditable_Check" 16 UINT MIN MAX 1 "Uneditable field" STATE UNCHECKED 0 STATE CHECKED 1 UNEDITABLE APPEND_PARAMETER "Binary" 32 STRING 0xDEADBEEF "Binary string" APPEND_PARAMETER "Pad" 16 UINT 0 0 0 HIDDEN ","version":"Next","tagName":"h2"},{"title":"JSON API","type":0,"sectionRef":"#","url":"/docs/development/json-api","content":"","keywords":"","version":"Next"},{"title":"Authorization","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#authorization","content":" The HTTP Authorization request header contains the credentials to authenticate a user agent with a server, usually, but not necessarily, after the server has responded with a 401 Unauthorized status and the WWW-Authenticate header. Authorization: <token/password> ","version":"Next","tagName":"h2"},{"title":"JSON-RPC 2.0","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#json-rpc-20","content":" The COSMOS API implements a relaxed version of the JSON-RPC 2.0 Specification. Requests with an "id" of NULL are not supported. Numbers can contain special non-string literal's such as NaN, and +/-inf. Request params must be specified by-position, by-name is not supported. Section 6 of the spec, Batch Operations, is not supported. The COSMOS scope must be specified in a "keyword_params" object. ","version":"Next","tagName":"h2"},{"title":"Socket Connections","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#socket-connections","content":" The COSMOS Command and Telemetry Server listens for connections to the COSMOS API on an HTTP server (default port of 7777). COSMOS listens for HTTP API requests at the default 2900 port at the /openc3-api/api endpoint. ","version":"Next","tagName":"h2"},{"title":"Supported Methods","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#supported-methods","content":" The list of methods supported by the COSMOS API may be found in the api source code on Github. The @api_whitelist variable is initialized with an array of all methods accepted by the CTS. This page will not show the full argument list for every method in the API, but it should be noted that the JSON API methods correspond to the COSMOS scripting API methods documented in the Scripting Writing Guide. This page will show a few example JSON requests and responses, and the scripting guide can be used as a reference to extrapolate how to build requests and parse responses for methods not explicitly documented here. ","version":"Next","tagName":"h2"},{"title":"Existing Implementations","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#existing-implementations","content":" The COSMOS JSON API has been implemented in the following languages: Ruby, Python and Javascript. ","version":"Next","tagName":"h2"},{"title":"Example Usage","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#example-usage","content":" ","version":"Next","tagName":"h2"},{"title":"Sending Commands","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#sending-commands","content":" The following methods are used to send commands: cmd, cmd_no_range_check, cmd_no_hazardous_check, cmd_no_checks The cmd method sends a command to a COSMOS target in the system. The cmd_no_range_check method does the same but ignores parameter range errors. The cmd_no_hazardous_check method does the same, but allows hazardous commands to be sent. The cmd_no_checks method does the same but allows hazardous commands to be sent, and ignores range errors. Two parameter syntaxes are supported. The first is a single string of the form "TARGET_NAME COMMAND_NAME with PARAMETER_NAME_1 PARAMETER_VALUE_1, PARAMETER_NAME_2 PARAMETER_VALUE_2, ..." The "with ..." portion of the string is optional. Any unspecified parameters will be given default values. Parameter\tData Type\tDescriptioncommand_string\tstring\tA single string containing all required information for the command The second is two or three parameters with the first parameter being a string denoting the target name, the second being a string with the command name, and an optional third being a hash of parameter names/values. This format should be used if the command contains parameters that take binary data that is not capable of being expressed as ASCII text. The cmd and cmd_no_range_check methods will fail on all attempts to send a command that has been marked hazardous. To send hazardous commands, the cmd_no_hazardous_check, or cmd_no_checks methods must be used. Parameter\tData Type\tDescriptiontarget_name\tString\tName of the target to send the command to command_name\tString\tThe name of the command command_params\tHash\tOptional hash of command parameters Example Usage: --> {"jsonrpc": "2.0", "method": "cmd", "params": ["INST COLLECT with DURATION 1.0, TEMP 0.0, TYPE 'NORMAL'"], "id": 1, "keyword_params":{"scope":"DEFAULT"}} <-- {"jsonrpc": "2.0", "result": ["INST", "COLLECT", {"DURATION": 1.0, "TEMP": 0.0, "TYPE": "NORMAL"}], "id": 1} --> {"jsonrpc": "2.0", "method": "cmd", "params": ["INST", "COLLECT", {"DURATION": 1.0, "TEMP": 0.0, "TYPE": "NORMAL"}], "id": 1, "keyword_params":{"scope":"DEFAULT"}} <-- {"jsonrpc": "2.0", "result": ["INST", "COLLECT", {"DURATION": 1.0, "TEMP": 0.0, "TYPE": "NORMAL"}], "id": 1} ","version":"Next","tagName":"h3"},{"title":"Getting Telemetry","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#getting-telemetry","content":" The following methods are used to get telemetry: tlm, tlm_raw, tlm_formatted, tlm_with_units The tlm method returns the current converted value of a telemetry point. The tlm_raw method returns the current raw value of a telemetry point. The tlm_formatted method returns the current formatted value of a telemetry point. The tlm_with_units method returns the current formatted value of a telemetry point with its units appended to the end. Two parameter syntaxes are supported. The first is a single string of the form "TARGET_NAME PACKET_NAME ITEM_NAME" Parameter\tData Type\tDescriptiontlm_string\tString\tA single string containing all required information for the telemetry item The second is three parameters with the first parameter being a string denoting the target name, the second being a string with the packet name, and the third being a string with the item name. Parameter\tData Type\tDescriptiontarget_name\tString\tName of the target to get the telemetry value from packet_name\tString\tName of the packet to get the telemetry value from item_name\tString\tName of the telemetry item Example Usage: --> {"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "id": 2, "keyword_params":{"scope":"DEFAULT"}} <-- {"jsonrpc": "2.0", "result": 94.9438, "id": 2} --> {"jsonrpc": "2.0", "method": "tlm", "params": ["INST", "HEALTH_STATUS", "TEMP1"], "id": 2, "keyword_params":{"scope":"DEFAULT"}} <-- {"jsonrpc": "2.0", "result": 94.9438, "id": 2} ","version":"Next","tagName":"h3"},{"title":"Further Debugging","type":1,"pageTitle":"JSON API","url":"/docs/development/json-api#further-debugging","content":" If developing an interface for the JSON API from another language, the best way to debug is to send the same messages from the supported Ruby interface first, like the following. By enabling the debug mode, you can see the exact request and response sent from the Ruby Implementation. Launch COSMOSOpen Command SenderOpen browser developer tools (right-click->Inspect in Chrome)Click "Network" tab (may need to add it with + button)Send a command with the GUIView the request in the developer tool. Click the "Payload" sub-tab to view the JSON You can also try sending these raw commands from the terminal with a program like curl: curl -d '{"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "id": 2, "keyword_params":{"type":"WITH_UNITS","scope":"DEFAULT"}}' http://localhost:2900/openc3-api/api -H "Authorization: password" ","version":"Next","tagName":"h2"},{"title":"Testing COSMOS","type":0,"sectionRef":"#","url":"/docs/development/testing","content":"","keywords":"","version":"Next"},{"title":"Playwright","type":1,"pageTitle":"Testing COSMOS","url":"/docs/development/testing#playwright","content":" ","version":"Next","tagName":"h2"},{"title":"Prerequesits","type":1,"pageTitle":"Testing COSMOS","url":"/docs/development/testing#prerequesits","content":" Install Yarn npm install --global yarn Clone the COSMOS Playwright repo git clone https://github.com/OpenC3/cosmos-playwright Install Playwright and dependencies cosmos-playwright % yarn install ","version":"Next","tagName":"h3"},{"title":"Playwright Testing","type":1,"pageTitle":"Testing COSMOS","url":"/docs/development/testing#playwright-testing","content":" Start COSMOS cosmos % openc3.sh start Open COSMOS in your browser. At the login screen, set the password to "password". Run tests (Note the --headed option visually displays tests, leave it off to run in the background) cosmos-playwright % yarn playwright test --project=chromium --headed [Optional] Fix istanbul/nyc coverage source lookups (use fixwindows if not on Linux). Tests will run successfully without this step and you will get coverage statistics, but line-by-line coverage won't work. cosmos-playwright % yarn fixlinux Generate code coverage cosmos-playwright % yarn coverage Code coverage reports can be viewed at openc3-playwright/coverage/index.html ","version":"Next","tagName":"h3"},{"title":"Unit Tests","type":1,"pageTitle":"Testing COSMOS","url":"/docs/development/testing#unit-tests","content":" Navigate to cosmos/openc3 folder. Run the command: cosmos/openc3 % rake build cosmos/openc3 % bundle exec rspec Code coverage reports can be found at cosmos/openc3/coverage/index.html ","version":"Next","tagName":"h2"},{"title":"Installation","type":0,"sectionRef":"#","url":"/docs/getting-started/installation","content":"","keywords":"","version":"Next"},{"title":"Installing OpenC3 COSMOS","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#installing-openc3-cosmos","content":" The following sections describe how to get OpenC3 COSMOS installed on various operating systems. This document should help you setup you host machine to allow you to have a running version of COSMOS in no time. ","version":"Next","tagName":"h2"},{"title":"Installing OpenC3 COSMOS on Host Machines","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#installing-openc3-cosmos-on-host-machines","content":" ","version":"Next","tagName":"h2"},{"title":"PREREQUISITES","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#prerequisites","content":" Install Docker and install Docker Compose. Minimum Resources allocated to Docker: 8GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk Docker on Windows with WSL2: WSL2 consumes 50% of total memory on Windows or 8GB, whichever is less. However, on Windows builds before 20175 (use winver to check) it consumes 80% of your total memory. This can have a negative effect on Windows performance! On Windows builds < 20175 or for more fine grained control, create C:\\Users\\<username>\\.wslconfig. Suggested contents on a 32GB machine: [wsl2] memory=16GB swap=0 Important: Modify Docker Connection Timeouts Docker by default will break idle (no data) connections after a period of 5 minutes. This "feature" will eventually cause you problems if you don't adjust the Docker settings. This may manifest as idle connections dropping or simply failing to resume after data should have started flowing again. Find the file at C:\\Users\\username\\AppData\\Roaming\\Docker\\settings.json on Windows or ~/Library/Group Containers/group.com.docker/settings.json on MacOS. Modify the value vpnKitMaxPortIdleTime to change the timeout (recommend setting to 0). Note: 0 means no timeout (idle connections not dropped) Note: As of December 2021 the COSMOS Docker containers are based on the Alpine Docker image. ","version":"Next","tagName":"h3"},{"title":"CLONE PROJECT","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#clone-project","content":" Since the COSMOS 5.0.9 release we recommend using the project template to get started. git clone https://github.com/OpenC3/cosmos-project.git git clone https://github.com/OpenC3/cosmos-enterprise-project.git Offline Installation If you need to install in an offline environment you should first see if you're able to directly use the COSMOS containers. If so you can first save the containers: ./openc3.sh util save docker.io openc3inc 5.16.2 This will download the COSMOS containers from the docker.io repo using the openc3inc namespace and version 5.16.2. The repo, namespace and version are all configurable. Tar files are created in the 'tmp' directory which you can transfer to your offline environment. Transfer the tar files to your offline environment's project 'tmp' dir and import them with: ./openc3.sh util load 5.16.2 Note the version specified in save needs to match the version in load. ","version":"Next","tagName":"h3"},{"title":"CERTIFICATES","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#certificates","content":" The COSMOS containers are designed to work and be built in the presence of an SSL Decryption device. To support this a cacert.pem file can be placed at the base of the COSMOS 5 project that includes any certificates needed by your organization. Note: If you set the path to the ssl file in the SSL_CERT_FILE environment variables the openc3 setup script will copy it and place it for the docker container to load. SSL Issues Increasingly organizations are using some sort of SSL decryptor device which can cause curl and other command line tools like git to have SSL certificate problems. If installation fails with messages that involve "certificate", "SSL", "self-signed", or "secure" this is the problem. IT typically sets up browsers to work correctly but not command line applications. Note that the file extension might not be .pem, it could be .pem, crt, .ca-bundle, .cer, .p7b, .p7s, or potentially something else. The workaround is to get a proper local certificate file from your IT department that can be used by tools like curl (for example C:\\Shared\\Ball.pem). Doesn't matter just somewhere with no spaces. Then set the following environment variables to that path (ie. C:\\Shared\\Ball.pem) SSL_CERT_FILE CURL_CA_BUNDLE REQUESTS_CA_BUNDLE Here are some directions on environment variables in Windows: Windows Environment Variables You will need to create new ones with the names above and set their value to the full path to the certificate file. ","version":"Next","tagName":"h3"},{"title":"RUN","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#run","content":" Add the locally cloned project directory to your path so you can directly use the batch file or shell script. In Windows this would be adding "C:\\openc3-project" to the PATH. In Linux you would edit your shell's rc file and export the PATH. For example, on a Mac add the following to ~/.zshrc: export PATH=~/cosmos-project:$PATH. Run openc3.bat run (Windows), or ./openc3.sh run (linux/Mac). Note, you can edit the .env file and change OPENC3_TAG to a specific release (e.g. 5.0.9) rather than 'latest'. If you see an error indicating docker daemon is not running ensure Docker and Docker compose is installed and running. If it errors please try to run docker --version or docker-compose --version and try to run the start command again. If the error continues please include the version in your issue if you choose to create one. Running docker ps can help show the running containers. openc3.* takes multiple arguments. Run with no arguments for help. An example run of openc3.sh with no arguments will show a usage guide. ./openc3.sh Usage: ./openc3.sh [cli, cliroot, start, stop, cleanup, run, util] * cli: run a cli command as the default user ('cli help' for more info) * cliroot: run a cli command as the root user ('cli help' for more info) * start: start the docker-compose openc3 * stop: stop the running dockers for openc3 * cleanup: cleanup network and volumes for openc3 * run: run the prebuilt containers for openc3 * util: various helper commands ","version":"Next","tagName":"h3"},{"title":"CONNECT","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#connect","content":" Connect a web browser to http://localhost:2900. Set the password to whatever you want. ","version":"Next","tagName":"h3"},{"title":"NEXT STEPS","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#next-steps","content":" Continue to Getting Started. ","version":"Next","tagName":"h3"},{"title":"Feedback","type":1,"pageTitle":"Installation","url":"/docs/getting-started/installation#feedback","content":" Find a problem in the documentation? Please create an issue on GitHub describing what we can do to make it better. ","version":"Next","tagName":"h3"},{"title":"Podman","type":0,"sectionRef":"#","url":"/docs/getting-started/podman","content":"","keywords":"","version":"Next"},{"title":"OpenC3 COSMOS Using Rootless Podman and Docker-Compose","type":1,"pageTitle":"Podman","url":"/docs/getting-started/podman#openc3-cosmos-using-rootless-podman-and-docker-compose","content":" Optional Installation Option These directions are for installing and running COSMOS using Podman instead of Docker. If you have Docker available, that is a simpler method. Podman is an alternative container technology to Docker that is actively promoted by RedHat. The key benefit is that Podman can run without a root-level daemon service, making it significantly more secure by design, over standard Docker. However, it is a little more complicated to use. These directions will get you up and running with Podman. The following directions have been tested against RHEL 8.8, and RHEL 9.2, but should be similar on other operating systems. Rootless Podman Does Not Work (Directly) with NFS Home Directories NFS does not work for holding container storage due to issues with user ids and group ids. There are workarounds available but they all involve moving container storage to another location: either a different partition on the host local disk, or into a special mounted disk image. See: [https://www.redhat.com/sysadmin/rootless-podman-nfs]https://www.redhat.com/sysadmin/rootless-podman-nfs). Note that there is also a newish Podman setting that allows you to more easily change where the storage location is in /etc/containers/storage.conf called rootless_storage_path. See https://www.redhat.com/sysadmin/nfs-rootless-podman Redhat 8.8 and 9.2 Instructions Install Prerequisite Packages Note: This downloads and installs docker-compose from the latest 2.x release on Github. If your operating system has a docker-compose package, it will be easier to install using that instead. RHEL8 does not have a docker-compose package. sudo yum update sudo yum install git podman-docker netavark curl -SL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 -o docker-compose sudo mv docker-compose /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose Configure Host OS for Redis sudo su echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag sysctl -w vm.max_map_count=262144 exit Configure Podman to use Netavark for DNS sudo cp /usr/share/containers/containers.conf /etc/containers/. sudo vi /etc/containers/containers.conf Then edit the network_backend line to be "netavark" instead of "cni" Start rootless podman socket service systemctl enable --now --user podman.socket Put the following into your .bashrc file (or .bash_profile or whatever) export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock" Source the profile file for your current terminal source .bashrc Get COSMOS - A release or the current main branch (main branch shown) git clone https://github.com/OpenC3/cosmos.git Optional - Set Default Container Registry If you don't want podman to keep querying you for which registry to use, you can create a $HOME/.config/containers/registries.conf and modify to just have the main docker registry (or modify the /etc/containers/registries.conf file directly) mkdir -p $HOME/.config/containers cp /etc/containers/registries.conf $HOME/.config/containers/. vi $HOME/.config/containers/registries.conf Then edit the unqualified-search-registries = line to just have the registry you care about (probably docker.io) Edit cosmos/compose.yaml cd cosmos vi compose.yaml Edit compose.yaml and uncomment the user: 0:0 lines and comment the user: "${OPENC3_USER_ID}:${OPENC3_GROUP_ID}" lines. You may also want to update the traefik configuration to allow access from the internet by removing 127.0.0.1 and probably switching to either an SSL config file, or the allow http one. Also make sure your firewall allows whatever port you choose to use in. Rootless podman will need to use a higher numbered port (not 1-1023). Run COSMOS ./openc3.sh run Wait until everything is built and running and then goto http://localhost:2900 in your browser Podman on MacOS Podman can also be used on MacOS, though we still generally recommend Docker Desktop ","version":"Next","tagName":"h3"},{"title":"MacOS Instructions","type":1,"pageTitle":"Podman","url":"/docs/getting-started/podman#macos-instructions","content":" Install podman brew install podman Start the podman virtual machine podman machine init podman machine start # Note: update to your username in the next line or copy paste from what 'podman machine start' says export DOCKER_HOST='unix:///Users/ryanmelt/.local/share/containers/podman/machine/qemu/podman.sock' Install docker-compose brew install docker-compose # Optional if you already have Docker Desktop Edit cosmos/compose.yaml Edit compose.yaml and uncomment the user: 0:0 lines and comment the user: "${OPENC3_USER_ID}:${OPENC3_GROUP_ID}" lines. Important: on MacOS you must also remove all :z from the volume mount lines You may also want to update the traefik configuration to allow access from the internet. Run COSMOS cd cosmos ./openc3.sh run ","version":"Next","tagName":"h2"},{"title":"Upgrading","type":0,"sectionRef":"#","url":"/docs/getting-started/upgrading","content":"","keywords":"","version":"Next"},{"title":"COSMOS Upgrades","type":1,"pageTitle":"Upgrading","url":"/docs/getting-started/upgrading#cosmos-upgrades","content":" COSMOS is released as Docker containers. Since we're using Docker containers and volumes we can simply stop the existing COSMOS application, then download and run the new release. This example assumes an existing COSMOS project at C:\\cosmos-project. Stop the current COSMOS application C:\\cosmos-project> openc3.bat stop Change the release in the .env file to the desired release OPENC3_TAG=5.1.1 Run the new COSMOS application C:\\cosmos-project> openc3.bat run ","version":"Next","tagName":"h3"},{"title":"Migrating From COSMOS 4 to COSMOS 5","type":1,"pageTitle":"Upgrading","url":"/docs/getting-started/upgrading#migrating-from-cosmos-4-to-cosmos-5","content":" COSMOS 5 is a new architecture and treats targets as independent plugins. Thus the primary effort in porting from COSMOS 4 to COSMOS 5 is converting targets to plugins. We recommend creating plugins for each independent target (with its own interface) but targets which share an interface will need to be part of the same plugin. The reason for independent plugins is it allows the plugin to be versioned separately and more easily shared outside your specific project. If you have very project specific targets (e.g. custom hardware) those can potentially be combined for ease of deployment. COSMOS 5 includes a migration tool for converting an existing COSMOS 4 configuration into a COSMOS 5 plugin. This example assumes an existing COSMOS 4 configuration at C:\\COSMOS and a new COSMOS 5 installation at C:\\cosmos-project. Linux users can adjust paths and change from .bat to .sh to follow along. Change to the existing COSMOS 4 configuration directory. You should see the config, lib, procedures, outputs directory. You can then run the migration tool by specifying the absolute path to the COSMOS 5 installation. C:\\COSMOS> C:\\cosmos-project\\openc3.bat cli migrate -a demo This creates a new COSMOS 5 plugin called openc3-cosmos-demo with a target named DEMO containing the existing lib and procedures files as well as all the existing targets. C:\\COSMOS> C:\\cosmos-project\\openc3.bat cli migrate demo-part INST This would create a new COSMOS 5 plugin called openc3-cosmos-demo-part with a target named DEMO_PART containing the existing lib and procedures files as well as the INST target (but no others). Open the new COSMOS 5 plugin and ensure the plugin.txt file is correctly configured. The migration tool doesn't create VARIABLEs or MICROSERVICEs or handle target substitution so those features will have to added manually. Follow the building your plugin part of the Getting Started tutorial to build your new plugin and upload it to COSMOS 5. ","version":"Next","tagName":"h3"},{"title":"OpenC3 COSMOS Key Concepts","type":0,"sectionRef":"#","url":"/docs/getting-started/key_concepts","content":"","keywords":"","version":"Next"},{"title":"Projects","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#projects","content":" The main COSMOS repo contains all the source code used to build and run COSMOS. However, users (not developers) of COSMOS should use the COSMOS project to launch COSMOS. The project consists of the openc3.sh and openc3.bat files for starting and stopping COSMOS, the compose.yaml for configuring the COSMOS containers, and the .env file for setting runtime variables. Additionally, the COSMOS project contains user modifiable config files for both Redis and Traefik. ","version":"Next","tagName":"h2"},{"title":"Containerization","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#containerization","content":" ","version":"Next","tagName":"h2"},{"title":"Images","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#images","content":" Per Docker, "An image is a read-only template with instructions for creating a Docker container." The base operating system COSMOS uses is called Alpine Linux. It is a simple and compact image with a full package system that allows us to install our dependencies. Starting with Alpine, we create a Dockerfile to add Ruby and Python and a few other packages to create our own docker image. We further build upon that image to create a NodeJS image to support our frontend and additional images to support our backend. ","version":"Next","tagName":"h3"},{"title":"Containers","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#containers","content":" Per Docker, "a container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another." Also per Docker, "A container is an isolated environment for your code. This means that a container has no knowledge of your operating system, or your files. It runs on the environment provided to you by Docker Desktop. Containers have everything that your code needs in order to run, down to a base operating system." COSMOS utilizes containers to provide a consistent runtime environment. Containers make it easy to deploy to local on-prem servers, cloud environments, or air-gapped networks. The COSMOS Open Source containers consist of the following: Name\tDescriptioncosmos-openc3-cosmos-init-1\tCopies files to Minio and configures COSMOS then exits cosmos-openc3-operator-1\tMain COSMOS container that runs the interfaces and target microservices cosmos-openc3-cosmos-cmd-tlm-api-1\tRails server that provides all the COSMOS API endpoints cosmos-openc3-cosmos-script-runner-api-1\tRails server that provides the Script API endpoints cosmos-openc3-redis-1\tServes the static target configuration cosmos-openc3-redis-ephemeral-1\tServes the streams containing the raw and decomutated data cosmos-openc3-minio-1\tProvides a S3 like bucket storage interface and also serves as a static webserver for the tool files cosmos-openc3-traefik-1\tProvides a reverse proxy and load balancer with routes to the COSMOS endpoints The container list for Enterprise COSMOS consists of the following: Name\tDescriptioncosmos-enterprise-openc3-metrics-1\tRails server that provides metrics on COSMOS performance cosmos-enterprise-openc3-keycloak-1\tSingle-Sign On service for authentication cosmos-enterprise-openc3-postgresql-1\tSQL Database for use by Keycloak openc3-nfs *\tNetwork File System pod only for use in Kubernetes to share code libraries between containers ","version":"Next","tagName":"h3"},{"title":"Docker Compose","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#docker-compose","content":" Per Docker, "Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services. Then, with a single command, you create and start all the services from your configuration." OpenC3 uses compose files to both build and run COSMOS. The compose.yaml is where ports are exposed and environment variables are used. ","version":"Next","tagName":"h3"},{"title":"Environment File","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#environment-file","content":" COSMOS uses an environment file along with Docker Compose to pass environment variables into the COSMOS runtime. This .env file consists of simple key value pairs that contain the version of COSMOS deployed, usernames and passwords, and much more. ","version":"Next","tagName":"h3"},{"title":"Kubernetes","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#kubernetes","content":" Per Kubernetes.io, "Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications. It groups containers that make up an application into logical units for easy management and discovery." COSMOS Enterprise provides Helm charts for easy deployment to Kubernetes in various cloud environments. COSMOS Enterprise also provides Terraform scripts to deploy COSMOS infrastructure on various cloud environments. ","version":"Next","tagName":"h3"},{"title":"Frontend","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#frontend","content":" ","version":"Next","tagName":"h2"},{"title":"Vue.js","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#vuejs","content":" The COSMOS frontend is fully browser native and is implemented in the Vue.js framework. Per Vue.js, "Vue is a JavaScript framework for building user interfaces. It builds on top of standard HTML, CSS, and JavaScript and provides a declarative and component-based programming model that helps you efficiently develop user interfaces, be they simple or complex." COSMOS utilizes Vue.js and the Vuetify Component Framework UI library to build all the COSMOS tools which run in the browser of your choice. ","version":"Next","tagName":"h3"},{"title":"Single-Spa","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#single-spa","content":" While COSMOS itself is written in Vue.js, we utilize a technology called single-spa to allow COSMOS developers to create applications in any javascript framework they choose. Single-spa is a micro frontend framework and acts as a top level router to render the application being requested. COSMOS provides sample applications ready to plug into single-spa in Angular, React, Svelte, and Vue. ","version":"Next","tagName":"h3"},{"title":"Astro UX","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#astro-ux","content":" Per AstroUXDS, "The Astro Space UX Design System enables developers and designers to build rich space app experiences with established interaction patterns and best practices." COSMOS utilizes the Astro design guidelines for color, typograpy, and iconograpy. In some cases, e.g. Astro Clock, COSMOS directly incorporates Astro components. ","version":"Next","tagName":"h3"},{"title":"Backend","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#backend","content":" ","version":"Next","tagName":"h2"},{"title":"Redis","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#redis","content":" Redis is an in-memory data store with support for strings, hashes, lists, sets, sorted sets, streams, and more. COSMOS uses Redis to store both our configuration and data. If you look back at our container list you'll notice two redis containers: cosmos-openc3-redis-1 and cosmos-openc3-redis-ephemeral-1. The ephemeral container contains all the real-time data pushed into Redis streams. The other redis container contains COSMOS configuration that is meant to persist. COSMOS Enterprise provides helm charts that setup Redis Cluster to perform horizontal scaling where data is shared across multiple Redis nodes. ","version":"Next","tagName":"h3"},{"title":"MinIO","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#minio","content":" MinIO is a high-performance, S3 compatible object store. COSMOS uses this storage technology to host both the COSMOS tools themselves and the long term log files. COSMOS Enterprise deployed in a cloud environment uses the available cloud native bucket storage technology, e.g. AWS S3, GCP Buckets, and Azure Blob Storage. Using bucket storage allows COSMOS to directly serve the tools as a static website and thus we don't need to deploy Tomcat or Nginx for example. ","version":"Next","tagName":"h3"},{"title":"Ruby on Rails","type":1,"pageTitle":"OpenC3 COSMOS Key Concepts","url":"/docs/getting-started/key_concepts#ruby-on-rails","content":" The COSMOS API and Script Runner backends are powered by Ruby on Rails. Rails is a web application development framework written in the Ruby programming language. Rails (and our familiarity with Ruby) allows us to write less code while accomplishing more than many other languages and frameworks. ","version":"Next","tagName":"h3"},{"title":"Protocols","type":0,"sectionRef":"#","url":"/docs/configuration/protocols","content":"","keywords":"","version":"Next"},{"title":"Packet Delineation Protocols","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#packet-delineation-protocols","content":" COSMOS provides the following packet delineation protocols: COBS, SLIP, Burst, Fixed, Length, Template (deprecated), Terminated and Preidentified. Each of these protocols has the primary purpose of separating out packets from a byte stream. Note that all protocols take a final parameter called "Allow Empty Data". This indicates whether the protocol will allow an empty string to be passed down to later Protocols (instead of returning :STOP). Can be true, false, or nil, where nil is interpreted as true unless the Protocol is the last Protocol of the chain. End users of a protocol will almost always simply leave off this parameter. For more information read the Custom Protocols documentation. ","version":"Next","tagName":"h2"},{"title":"COBS Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#cobs-protocol","content":" The Consistent Overhead Byte Stuffing (COBS) Protocol is an algorithm for encoding data bytes that results in efficient, reliable, unambiguous packet framing regardless of packet content, thus making it easy for receiving applications to recover from malformed packets. It employs the zero byte value to serve as a packet delimiter (a special value that indicates the boundary between packets). The algorithm replaces each zero data byte with a non-zero value so that no zero data bytes will appear in the packet and thus be misinterpreted as packet boundaries (See https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing for more). ","version":"Next","tagName":"h3"},{"title":"SLIP Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#slip-protocol","content":" The Serial Line IP (SLIP) Protocol defines a sequence of characters that frame IP packets on a serial line. It defines two special characters: END and ESC. END is 0xC0 and ESC is 0xDB. To send a packet, a SLIP host simply starts sending the data in the packet. If a data byte is the same code as END character, a two byte sequence of ESC and 0xDC is sent instead. If a data bytes is the same as an ESC character, an two byte sequence of ESC and 0xDD is sent instead. When the last byte in the packet has been sent, an END character is then transmitted (See https://datatracker.ietf.org/doc/html/rfc1055 for more). Parameter\tDescription\tRequired\tDefaultStart Char\tCharacter to place at the start of frames\tNo\tnil (no character) Read Strip Characters\tStrip off start_char and end_char from reads\tNo\ttrue Read Enable Escaping\tWhether to enable character escaping on reads\tNo\ttrue Write Enable Escaping\tWhether to enable character escaping on writes\tNo\ttrue End Char\tCharacter to place at the end of frames\tNo\t0xC0 Esc Char\tEscape character\tNo\t0xDB Escape End Char\tCharacter to escape End character\tNo\t0xDC Escape Esc Char\tCharacter to escape Esc character\tNo\t0xDD ","version":"Next","tagName":"h3"},{"title":"Burst Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#burst-protocol","content":" The Burst Protocol simply reads as much data as it can from the interface before returning the data as a COSMOS Packet (It returns a packet for each burst of data read). This Protocol relies on regular bursts of data delimited by time and thus is not very robust. However, it can utilize a sync pattern which does allow it to re-sync if necessary. It can also discard bytes from the incoming data to remove the sync pattern. Finally, it can add sync patterns to data being written out of the Interface. Parameter\tDescription\tRequired\tDefaultDiscard Leading Bytes\tThe number of bytes to discard from the binary data after reading. Note that this applies to bytes starting with the sync pattern if the sync pattern is being used.\tNo\t0 (do not discard bytes) Sync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found including the sync pattern will be returned\tNo\tnil (no sync pattern) Fill Fields\tWhether to fill in the sync pattern on outgoing packets\tNo\tfalse ","version":"Next","tagName":"h3"},{"title":"Fixed Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#fixed-protocol","content":" The Fixed Protocol reads a preset minimum amount of data which is necessary to properly identify all the defined packets using the interface. It then identifies the packet and proceeds to read as much data from the interface as necessary to create the packet which it then returns. This protocol relies on all the packets on the interface being fixed in length. For example, all the packets using the interface are a fixed size and contain a simple header with a 32-bit sync pattern followed by a 16 bit ID. The Fixed Protocol would elegantly handle this case with a minimum read size of 6 bytes. The Fixed Protocol also supports a sync pattern, discarding leading bytes, and filling the sync pattern similar to the Burst Protocol. Parameter\tDescription\tRequired\tDefaultMinimum ID Size\tThe minimum number of bytes needed to identify a packet. All the packet definitions must declare their ID_ITEM(s) within this given number of bytes.\tYes Discard Leading Bytes\tThe number of bytes to discard from the binary data after reading. Note that this applies to bytes starting with the sync pattern if the sync pattern is being used.\tNo\t0 (do not discard bytes) Sync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found including the sync pattern will be returned.\tNo\tnil (no sync pattern) Telemetry\tWhether the data is telemetry\tNo\ttrue (false means command) Fill Fields\tWhether to fill in the sync pattern on outgoing packets\tNo\tfalse Unknown Raise\tWhether to raise an exception for an unknown packet\tNo\tfalse ","version":"Next","tagName":"h3"},{"title":"Length Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#length-protocol","content":" The Length Protocol depends on a length field at a fixed location in the defined packets using the interface. It then reads enough data to grab the length field, decodes it, and reads the remaining length of the packet. For example, all the packets using the interface contain a CCSDS header with a length field. The Length Protocol can be set up to handle the length field and even the length offset CCSDS uses. The Length Protocol also supports a sync pattern, discarding leading bytes, and filling the length and sync pattern similar to the Burst Protocol. Parameter\tDescription\tRequired\tDefaultLength Bit Offset\tThe bit offset from the start of the packet to the length field. Every packet using this interface must have the same structure such that the length field is the same size at the same location. Be sure to account for the length of the Sync Pattern in this value (if present).\tNo\t0 bits Length Bit Size\tThe size in bits of the length field\tNo\t16 bits Length Value Offset\tThe offset to apply to the length field value. The actual value of the length field plus this offset should equal the exact number of bytes required to read all data for the packet (including the length field itself, sync pattern, etc). For example, if the length field indicates packet length minus one, this value should be one. Be sure to account for the length of the Sync Pattern in this value (if present).\tNo\t0 Bytes per Count\tThe number of bytes per each length field 'count'. This is used if the units of the length field is something other than bytes, e.g. if the length field count is in words.\tNo\t1 byte Length Endianness\tThe endianness of the length field. Must be either 'BIG_ENDIAN' or 'LITTLE_ENDIAN'.\tNo\t'BIG_ENDIAN' Discard Leading Bytes\tThe number of bytes to discard from the binary data after reading. Note that this applies to bytes including the sync pattern if the sync pattern is being used. Discarding is one of the very last steps so any size and offsets above need to account for all the data before discarding.\tNo\t0 (do not discard bytes) Sync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found including the sync pattern will be returned.\tNo\tnil (no sync pattern) Max Length\tThe maximum allowed value in the length field\tNo\tnil (no maximum length) Fill Length and Sync Pattern\tSetting this flag to true causes the length field and sync pattern (if present) to be filled automatically on outgoing packets.\tNo\tfalse The most confusing aspect of the Length Protocol is calculating the Length Value Offset. This is especially true in the commonly used CCSDS Space Packet Protocol. The best way to illustrate this is with an example. Suppose you have CCSDS Space Packets prepended with a Sync Pattern of 0x1ACFFC1D. This would look like the following: Sync (4 bytes)\tHeader (4 bytes)\tLength (2 bytes)\tData (4 bytes)0x1ACFFC1D\t0x0001CADB\t0x0003\t0xDEADBEEF In this case the total length of the packet is 14 bytes: 4 + 4 + 2 + 4 = 14. With 4 bytes of data, the length field is 3 because in CCSDS the length field is calculated as (data length - 1). So how would we calculate the Length Value Offset? COSMOS reads all the bytes in the packet (including the Sync Pattern) so the total length is 14 bytes. The length field is 3 so the Length Value Offset (offset to apply to the length field value) should be 11 (3 + 11 = 14). ","version":"Next","tagName":"h3"},{"title":"Terminated Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#terminated-protocol","content":" The Terminated Protocol delineates packets using termination characters found at the end of every packet. It continuously reads data until the termination characters are found at which point it returns the packet data. For example, all the packets using the interface are followed by 0xABCD. This data can either be a part of each packet that is kept or something which is known only by the Terminated Protocol and simply thrown away. Parameter\tDescription\tRequired\tDefaultWrite Termination Characters\tThe data to write after writing a command packet. Given as a hex string such as 0xABCD.\tYes Read Termination Characters\tThe characters which delineate the end of a telemetry packet. Given as a hex string such as 0xABCD.\tYes Strip Read Termination\tWhether to remove the read termination characters before returning the telemetry packet\tNo\ttrue Discard Leading Bytes\tThe number of bytes to discard from the binary data after reading. Note that this applies to bytes including the sync pattern if the sync pattern is being used.\tNo\t0 (do not discard bytes) Sync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found including the sync pattern will be returned.\tNo\tnil (no sync pattern) Fill Fields\tWhether to fill in the sync pattern on outgoing packets\tNo\tfalse ","version":"Next","tagName":"h3"},{"title":"Template Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#template-protocol","content":" Deprecated This protocol is now deprecated because it is not able to capture the original SCPI messages in COSMOS raw logging. Please use the TemplateAccessor with the CmdResponseProtocol instead. The Template Protocol works much like the Terminated Protocol except it is designed for text-based command and response type interfaces such as SCPI (Standard Commands for Programmable Instruments). It delineates packets in the same way as the Terminated Protocol except each packet is referred to as a line (because each usually contains a line of text). For outgoing packets, a CMD_TEMPLATE field is expected to exist in the packet. This field contains a template string with items to be filled in delineated within HTML tag style brackets "<EXAMPLE>". The Template Protocol will read the named items from within the packet and fill in the CMD_TEMPLATE. This filled in string is then sent out rather than the originally passed in packet. Correspondingly, if a response is expected the outgoing packet should include a RSP_TEMPLATE and RSP_PACKET field. The RSP_TEMPLATE is used to extract data from the response string and build a corresponding RSP_PACKET. See the TEMPLATE target within the COSMOS Demo configuration for an example of usage. Parameter\tDescription\tRequired\tDefaultWrite Termination Characters\tThe data to write after writing a command packet. Given as a hex string such as 0xABCD.\tYes Read Termination Characters\tThe characters which delineate the end of a telemetry packet. Given as a hex string such as 0xABCD.\tYes Ignore Lines\tNumber of response lines to ignore (completely drop)\tNo\t0 lines Initial Read Delay\tAn initial delay after connecting after which the interface will be read till empty and data dropped. Useful for discarding connect headers and initial prompts.\tNo\tnil (no initial read) Response Lines\tThe number of lines that make up expected responses\tNo\t1 line Strip Read Termination\tWhether to remove the read termination characters before returning the telemetry packet\tNo\ttrue Discard Leading Bytes\tThe number of bytes to discard from the binary data after reading. Note that this applies to bytes including the sync pattern if the sync pattern is being used.\tNo\t0 (do not discard bytes) Sync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found including the sync pattern will be returned.\tNo\tnil (no sync pattern) Fill Fields\tWhether to fill in the sync pattern on outgoing packets\tNo\tfalse Response Timeout\tNumber of seconds to wait for a response before timing out\tNo\t5.0 Response Polling Period\tNumber of seconds to wait between polling for a response\tNo\t0.02 Raise Exceptions\tWhether to raise exceptions when errors occur like timeouts or unexpected responses\tNo\tfalse ","version":"Next","tagName":"h3"},{"title":"Preidentified Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#preidentified-protocol","content":" The Preidentified Protocol delineates packets using a custom COSMOS header. This Protocol is created to allow tools to connect and receive the entire packet stream. It can also be used to chain COSMOS instances together although that should rarely be needed with the new web native implementation. Parameter\tDescription\tRequired\tDefaultSync Pattern\tHex string representing a byte pattern that will be searched for in the raw data. This pattern represents a packet delimiter and all data found AFTER the sync pattern will be returned. The sync pattern itself is discarded.\tNo\tnil (no sync pattern) Max Length\tThe maximum allowed value in the length field\tNo\tnil (no maximum length) Mode\tThe Version of the preidentified protocol to support (2 or 4).3\tNo\t4 ","version":"Next","tagName":"h3"},{"title":"Helper Protocols","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#helper-protocols","content":" COSMOS provides the following helper protocols: CmdResponse, Crc and Ignore. These protocols provide helper functionality to Interfaces. ","version":"Next","tagName":"h2"},{"title":"CmdResponse Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#cmdresponse-protocol","content":" The CmdResponse Protocol waits for a response for any commands with a defined response packet (TODO: More documentation and examples). Parameter\tDescription\tRequired\tDefaultResponse Timeout\tNumber of seconds to wait before timing out when waiting for a response\tNo\t5 Response Polling Period\tNumber of seconds to wait between polling for a response\tNo\t0.02 Raise Exceptions\tWhether to raise exceptions when errors occur in the protocol like unexpected responses or response timeouts\tNo\tfalse ","version":"Next","tagName":"h3"},{"title":"CRC Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#crc-protocol","content":" The CRC protocol can add CRCs to outgoing commands and verify CRCs on incoming telemetry packets. Parameter\tDescription\tRequired\tDefaultWrite Item Name\tItem to fill with calculated CRC value for outgoing packets (nil = don't fill)\tNo\tnil Strip CRC\tWhether to remove the CRC from incoming packets\tNo\tfalse Bad Strategy\tHow to handle CRC errors on incoming packets. ERROR = Just log the error, DISCONNECT = Disconnect interface\tNo\t"ERROR" Bit Offset\tBit offset of the CRC in the data. Can be negative to indicate distance from end of packet\tNo\t-32 Bit Size\tBit size of the CRC - Must be 16, 32, or 64\tNo\t32 Endianness\tEndianness of the CRC (BIG_ENDIAN/LITTLE_ENDIAN)\tNo\t"BIG_ENDIAN" Poly\tPolynomial to use when calculating the CRC expressed as an integer\tNo\tnil (use default polynomial - 16-bit=0x1021, 32-bit=0x04C11DB7, 64-bit=0x42F0E1EBA9EA3693) Seed\tSeed value to start the calculation\tNo\tnil (use default seed - 16-bit=0xFFFF, 32-bit=0xFFFFFFFF, 64-bit=0xFFFFFFFFFFFFFFFF) Xor\tWhether to XOR the CRC result with 0xFFFF\tNo\tnil (use default value - 16-bit=false, 32-bit=true, 64-bit=true) Reflect\tWhether to bit reverse each byte of data before calculating the CRC\tNo\tnil (use default value - 16-bit=false, 32-bit=true, 64-bit=true) ","version":"Next","tagName":"h3"},{"title":"Ignore Packet Protocol","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#ignore-packet-protocol","content":" The Ignore Packet protocol drops specified command packets sent by COSMOS or drops incoming telemetry packets. Parameter\tDescription\tRequired\tDefaultTarget Name\tTarget name of the packet to ignore\tYes\tnil Packet Name\tPacket name of the packet to ignore\tYes\tnil ","version":"Next","tagName":"h3"},{"title":"Custom Protocols","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#custom-protocols","content":" Creating a custom protocol is easy and should be the default solution for customizing COSMOS Interfaces (rather than creating a new Interface class). However, creating custom Interfaces is still useful for defaulting parameters to values that always are fixed for your target and for including the necessary Protocols. The base COSMOS Interfaces take a lot of parameters that can be confusing to your end users. Thus you may want to create a custom Interface just to hard coded these values and cut the available parameters down to something like the hostname and port to connect to. All custom Protocols should derive from the Protocol class openc3/interfaces/protocols/protocol.rb (Ruby) and openc3/interfaces/protocols/protocol.py (Python). This class defines the 9 methods that are relevant to writing your own protocol. The base class implementation for each method is included below as well as a discussion as to how the methods should be overridden and used in your own Protocols. Ruby Protocol APIs Protocols should not require 'openc3/script' since they are part of a COSMOS interface. They should use the COSMOS library code directly like System, Packet, Bucket, BinaryAccessor, etc. When in doubt, consult the existing COSMOS protocol classes. Python Protocol APIs Protocols should not from openc3.script import * since they are part of a COSMOS interface. They should use the COSMOS library code directly like System, Packet, Bucket, BinaryAccessor, etc. When in doubt, consult the existing COSMOS protocol classes. To really understand how Protocols work, you first must understand the logic within the base Interface class read and write methods. Let's first discuss the read method. Ruby Symbols, Python Strings In the following discussions an all caps word is a symbol in Ruby and a string in Python. So a reference to STOP means :STOP in Ruby and "STOP" in Python. On every call to read, an empty string "" is first passed down to each of the read Protocol's read_data() method before new raw data is attempted to be read using the Interface's read_interface() method. This is a signal to Protocols that have cached up more than one packet worth of data to output those cached packets before any new data is read from the Interface. Typically no data will be cached up and one of the Protocols read_data() methods will return STOP in response to the empty string, indicating that more data is required to generate a packet. Each Protocol's read_data() method can return one of three things: data that will be passed down to any additional Protocols or turned into a Packet, STOP which means more data is required from the Interface for the Protocol to continue, or DISCONNECT which means that something has happened that requires disconnecting the Interface (and by default trying to reconnect). Each Protocol's read_data() method is passed the data that will eventually be turned into a packet and returns a possibly modified set of data. If the data passes through all Protocol's read_data() methods it is then converted into a COSMOS packet using the Interface's convert_data_to_packet() method. This packet is then run in a similar fashion through each Read Protocol's read_packet() method. This method has essentially the same return possibilities: a Packet (instead of data as in read_data()), STOP, or DISCONNECT. If the Packet makes it through all read_packet() methods then the Interface packet read counter is incremented and the Packet is returned to the Interface. The Interface write() method works very similarly to read. (It should be mentioned that by default write protocols run in the reverse order of read protocols. This makes sense because when reading you're typically stripping layers of data and when writing you're typically adding on layers in reverse order.) First, the packet write counter is incremented. Then each write Protocol is given a chance to modify the packet by its write_packet() method being called. This method can either return a potentially modified packet, STOP, or DISCONNECT. If a write Protocol returns STOP no data will be written out the Interface and it is assumed that more packets are necessary before a final packet can be output. DISCONNECT will disconnect the Interface. If the packet makes it through all the write Protocol's write_packet() methods, then it is converted to binary data using the Interface's convert_packet_to_data() method. Next the write_data() method is called for each write Protocol giving it a chance to modify the lower level data. The same return options are available except a Ruby string of data is returned instead of a COSMOS packet. If the data makes it through all write_data() methods, then it is written out on the Interface using the write_interface() method. Afterwards, each Protocol's post_write_interface() method is called with both the final modified Packet, and the actual data written out to the Interface. This method allows follow-up such as waiting for a response after writing out a message. ","version":"Next","tagName":"h2"},{"title":"Method discussions","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#method-discussions","content":" ","version":"Next","tagName":"h2"},{"title":"initialize or init","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#initialize-or-init","content":" This is the constructor for your custom Protocol. It should always call super(allow_empty_data) to initialize the base Protocol class. Base class Ruby implementation: # @param allow_empty_data [true/false] Whether STOP should be returned on empty data def initialize(allow_empty_data = false) @interface = nil @allow_empty_data = ConfigParser.handle_true_false(allow_empty_data) reset() end Base class Python implementation: def __init__(self, allow_empty_data=None): self.interface = None self.allow_empty_data = ConfigParser.handle_true_false_none(allow_empty_data) self.reset() As you can see, every Protocol maintains state on at least two items. The interface variable holds the Interface class instance that the protocol is associated with. This is sometimes necessary to introspect details that only the Interface knows. allow_empty_data is a flag used by the read_data(data) method that is discussed later in this document. ","version":"Next","tagName":"h3"},{"title":"reset","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#reset","content":" The reset method is used to reset internal protocol state when the Interface is connected and/or disconnected. This method should be used for common resetting logic. Connect and Disconnect specific logic are handled in the next two methods. Base class Ruby implementation: def reset end Base class Python implementation: def reset(self): pass As you can see, the base class reset implementation doesn't do anything. ","version":"Next","tagName":"h3"},{"title":"connect_reset","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#connect_reset","content":" The connect_reset method is used to reset internal Protocol state each time the Interface is connected. Base class Ruby implementation: def connect_reset reset() end Base class Python implementation: def connect_reset(self): self.reset() The base class connect_reset implementation just calls the reset method to ensure common reset logic is run. ","version":"Next","tagName":"h3"},{"title":"disconnect_reset","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#disconnect_reset","content":" The disconnect_reset method is used to reset internal Protocol state each time the Interface is disconnected. Base class Ruby implementation: def disconnect_reset reset() end Base class Python implementation: def disconnect_reset(self): self.reset() The base class disconnect_reset implementation just calls the reset method to ensure common reset logic is run. ","version":"Next","tagName":"h3"},{"title":"read_data","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#read_data","content":" The read_data method is used to analyze and potentially modify any raw data read by an Interface. It takes one parameter as the current state of the data to be analyzed. It can return either a string of data, STOP, or DISCONNECT. If it returns a string, then it believes that data may be ready to be a full packet, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes it needs more data to complete a full packet. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected). Base class Ruby implementation: def read_data(data) if (data.length <= 0) if @allow_empty_data.nil? if @interface and @interface.read_protocols[-1] == self # Last read interface in chain with auto @allow_empty_data return :STOP end elsif !@allow_empty_data # Don't @allow_empty_data means STOP return :STOP end end data end Base class Python implementation: def read_data(self, data, extra=None): if len(data) <= 0: if self.allow_empty_data is None: if self.interface and self.interface.read_protocols[-1] == self: # Last read interface in chain with auto self.allow_empty_data return ("STOP", extra) elif self.allow_empty_data: # Don't self.allow_empty_data means STOP return ("STOP", extra) return (data, extra) The base class implementation does nothing except return the data it was given. The only exception to this is when handling an empty string. If the allow_empty_data flag is false / False or if it is nil / None and the Protocol is the last in the chain, then the base implementation will return STOP to indicate that it is time to call the Interface read_interface() method to get more data. Blank strings are used to signal Protocols that they have an opportunity to return a cached packet. ","version":"Next","tagName":"h3"},{"title":"read_packet","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#read_packet","content":" The read_packet method is used to analyze and potentially modify a COSMOS packet before it is returned by the Interface. It takes one parameter as the current state of the packet to be analyzed. It can return either a COSMOS packet, STOP, or DISCONNECT. If it returns a COSMOS packet, then it believes that the packet is valid, should be returned, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes the packet should be silently dropped. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected). This method is where a Protocol would set the stored flag on a packet if it determines that the packet is stored telemetry instead of real-time telemetry. Base class Ruby implementation: def read_packet(packet) return packet end Base class Python implementation: def read_packet(self, packet): return packet The base class always just returns the packet given. ","version":"Next","tagName":"h3"},{"title":"write_packet","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#write_packet","content":" The write_packet method is used to analyze and potentially modify a COSMOS packet before it is output by the Interface. It takes one parameter as the current state of the packet to be analyzed. It can return either a COSMOS packet, STOP, or DISCONNECT. If it returns a COSMOS packet, then it believes that the packet is valid, should be written out the Interface, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes the packet should be silently dropped. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected). Base class Ruby implementation: def write_packet(packet) return packet end Base class Python implementation: def write_packet(self, packet): return packet The base class always just returns the packet given. ","version":"Next","tagName":"h3"},{"title":"write_data","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#write_data","content":" The write_data method is used to analyze and potentially modify data before it is written out by the Interface. It takes one parameter as the current state of the data to be analyzed and sent. It can return either a string of data, STOP, or DISCONNECT. If it returns a string of data, then it believes that the data is valid, should be written out the Interface, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes the data should be silently dropped. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected). Base class Ruby implementation: def write_data(data) return data end Base class Python implementation: def write_data(self, data, extra=None): return (data, extra) The base class always just returns the data given. ","version":"Next","tagName":"h3"},{"title":"post_write_interface","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#post_write_interface","content":" The post_write_interface method is called after data has been written out the Interface. The typical use of this method is to provide a hook to implement command/response type interfaces where a response is always immediately expected in response to a command. It takes two parameters, the packet after all modifications by write_packet() and the data that was actually written out the Interface. It can return either the same pair of packet/data, STOP, or DISCONNECT. If it returns a packet/data pair then they are passed on to any other Protocols. If STOP is returned then the Interface write() call completes and no further Protocols post_write_interface() methods are called. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected). Note that only the first parameter "packet", is checked to be STOP, or DISCONNECT on the return. Base class Ruby implementation: def post_write_interface(packet, data) return packet, data end Base class Python implementation: def post_write_interface(self, packet, data, extra=None): return (packet, data, extra) The base class always just returns the packet/data given. ","version":"Next","tagName":"h3"},{"title":"protocol_cmd","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#protocol_cmd","content":" The protocol_cmd method is used to send commands to the protocol itself. This is useful to change protocol behavior during runtime. See interface_protocol_cmd for more information. Base class Ruby implementation: def protocol_cmd(cmd_name, *cmd_args) # Default do nothing - Implemented by subclasses return false end Base class Python implementation: def protocol_cmd(self, cmd_name, *cmd_args): # Default do nothing - Implemented by subclasses return False The base class does nothing as this is special functionality implemented by subclasses. ","version":"Next","tagName":"h3"},{"title":"Examples","type":1,"pageTitle":"Protocols","url":"/docs/configuration/protocols#examples","content":" Please see the linked Ruby Protocol and Python Protocol code for examples of the above methods in action. ","version":"Next","tagName":"h2"},{"title":"Getting Started","type":0,"sectionRef":"#","url":"/docs/getting-started/gettingstarted","content":"","keywords":"","version":"Next"},{"title":"Interfacing with Your Hardware","type":1,"pageTitle":"Getting Started","url":"/docs/getting-started/gettingstarted#interfacing-with-your-hardware","content":" Playing with the COSMOS Demo is fun and all, but now you want to talk to your own real hardware? Let's do it! Install and Platform This guide assumes we're on Windows and COSMOS is installed in C:\\COSMOS. Adjust scripts and paths as necessary to match your platform and COSMOS installation directory. Before creating your own configuration you should uninstall the COSMOS Demo so you're working with a clean COSMOS system. Click the Admin button and the PLUGINS tab. Then click the Trash can icon next to openc3-cosmos-demo to delete it. When you go back to the Command and Telemetry Server you should have a blank table with no interfaces. If you followed the Installation Guide you should already be inside a cloned openc3-project which is in your PATH (necessary for openc3.bat / openc3.sh to be resolved). Inside this project it's recommended to edit the README.md (Markdown) to describe your program / project. Now we need to create a plugin. Plugins are how we add targets and microservices to COSMOS. Our plugin will contain a single target which contains all the information defining the packets (command and telemetry) that are needed to communicate with the target. Use the COSMOS plugin generator to create the correct structure: C:\\openc3-project> openc3.bat cli generate plugin BOB This should create a new directory called "openc3-cosmos-bob" with a bunch of files in it. The full description of all the files is explained by the Plugin Structure page. Run as the Root user The cli runs as the default COSMOS container user which is the recommended practice. If you're having issues running as that user you can run as the root user (effectively docker run --user=root ) by running cliroot instead of cli in any of the examples. Starting with COSMOS v5.5.0, the plugin generator creates just the plugin framework (previously it would also create a target). From within the newly created plugin directory, we generate a target. C:\\openc3-project> cd openc3-cosmos-bob openc3-cosmos-bob> openc3.bat cli generate target BOB Generators There are a number of generators available. Run openc3.bat cli generate to see all the available options. The target generator creates a single target named BOB. Best practice is to create a single target per plugin to make it easier to share targets and upgrade them individually. Lets see what the target generator created for us. Open the openc3-cosmos-bob/targets/BOB/cmd_tlm/cmd.txt: COMMAND BOB EXAMPLE BIG_ENDIAN "Packet description" # Keyword Name BitSize Type Min Max Default Description APPEND_ID_PARAMETER ID 16 INT 1 1 1 "Identifier" APPEND_PARAMETER VALUE 32 FLOAT 0 10.5 2.5 "Value" APPEND_PARAMETER BOOL 8 UINT MIN MAX 0 "Boolean" STATE FALSE 0 STATE TRUE 1 APPEND_PARAMETER LABEL 0 STRING "OpenC3" "The label to apply" What does this all mean? We created a COMMAND for target BOB named EXAMPLE.The command is made up of BIG_ENDIAN parameters and is described by "Packet description". Here we are using the append flavor of defining parameters which stacks them back to back as it builds up the packet and you don't have to worry about defining the bit offset into the packet.First we APPEND_ID_PARAMETER a parameter that is used to identify the packet called ID that is an 16-bit signed integer (INT) with a minimum value of 1, a maximum value of 1, and a default value of 1, that is described as the "Identifier".Next we APPEND_PARAMETER a parameter called VALUE that is a 32-bit float (FLOAT) that has a minimum value of 0, a maximum value of 10.5, and a default value of 2.5.Then we APPEND_PARAMETER a third parameter called BOOL which is a 8-bit unsigned integer (UINT) with a minimum value of MIN (meaning the smallest value a UINT supports, e.g 0), a maximum value of MAX (largest value a UINT supports, e.g. 255), and a default value of 0. BOOL has two states which are just a fancy way of giving meaning to the integer values 0 and 1. The STATE FALSE has a value of 0 and the STATE TRUE has a value of 1.Finally we APPEND_PARAMETER called LABEL which is a 0-bit (meaning it takes up all the remaining space in the packet) string (STRING) with a default value of "OpenC3". Strings don't have minimum or maximum values as that doesn't make sense for STRING types. Check out the full Command documentation for more. Now open the openc3-cosmos-bob/targets/BOB/cmd_tlm/tlm.txt: TELEMETRY BOB STATUS BIG_ENDIAN "Telemetry description" # Keyword Name BitSize Type ID Description APPEND_ID_ITEM ID 16 INT 1 "Identifier" APPEND_ITEM VALUE 32 FLOAT "Value" APPEND_ITEM BOOL 8 UINT "Boolean" STATE FALSE 0 STATE TRUE 1 APPEND_ITEM LABEL 0 STRING "The label to apply" This time we created a TELEMETRY packet for target BOB called STATUS that contains BIG_ENDIAN items and is described as "Telemetry description".We start by defininig an ID_ITEM called ID that is a 16-bit signed integer (INT) with an id value of 1 and described as "Identifier". Id items are used to take unidentified blobs of bytes and determine which packet they are. In this case if a blob comes in with a value of 1, at bit offset 0 (since we APPEND this item first), interpreted as a 16-bit integer, then this packet will be "identified" as STATUS. Note the first packet defined without any ID_ITEMS is a "catch-all" packet that matches all incoming data (even if the data lengths don't match).Next we define three items similar to the command definition above. Check out the full Telemetry documentation for more. COSMOS has defined an example command and telemetry packet for our target. Most targets will obviously have more than one command and telemetry packet. To add more simply create additional COMMAND and TELEMETRY lines in your text files. Actual packets should match the structure of your command and telemetry. Be sure to add at least one unique ID_PARAMETER and ID_ITEM so your packets can be distinguished from each other. Now we need to tell COSMOS how to connect to our BOB target. Open the openc3-cosmos-bob/plugin.txt file: # Set VARIABLEs here to allow variation in your plugin # See [Plugins](../configuration/plugins.md) for more information VARIABLE bob_target_name BOB # Modify this according to your actual target connection # See [Interfaces](../configuration/interfaces.md) for more information TARGET BOB <%= bob_target_name %> INTERFACE <%= bob_target_name %>_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST MAP_TARGET <%= bob_target_name %> This configures the plugin with a VARIABLE called bob_target_name with a default of "BOB". When you install this plugin you will have the option to change the name of this target to something other than "BOB". This is useful to avoid name conflicts and allows you to have multiple copies of the BOB target in your COSMOS system.The TARGET line declares the new BOB target using the name from the variable. The <%= %> syntax is called ERB (embedded Ruby) and allows us to put variables into our text files, in this case referencing our bob_target_name.The last line declares a new INTERFACE called (by default) BOB_INT that will connect as a TCP/IP client using the code in tcpip_client_interface.rb to address host.docker.internal (This adds an /etc/hosts entry to the correct IP address for the host's gateway) using port 8080 for writing and 8081 for reading. It also has a write timeout of 10 seconds and reads will never timeout (nil). The TCP/IP stream will be interpreted using the COSMOS BURST protocol which means it will read as much data as it can from the interface. For all the details on how to configure COSMOS interfaces please see the Interface Guide. The MAP_TARGET line tells COSMOS that it will receive telemetry from and send commands to the BOB target using the BOB_INT interface. Variables Support Reusability In a plugin that you plan to reuse you should make things like hostnames and ports variables ","version":"Next","tagName":"h2"},{"title":"Building Your Plugin","type":1,"pageTitle":"Getting Started","url":"/docs/getting-started/gettingstarted#building-your-plugin","content":" Now we need to build our plugin and upload it to COSMOS. C:\\cosmos-project> cd openc3-cosmos-bob C:\\cosmos-project\\openc3-cosmos-bob> ..\\openc3.bat cli rake build VERSION=1.0.0 Successfully built RubyGem Name: openc3-cosmos-bob Version: 1.0.0.20210618174517 File: openc3-cosmos-bob-1.0.0.20210618174517.gem Note that the VERSION is required to specify the version to build. We recommend semantic versioning when building your plugin so people using your plugin (including you) know when there are breaking changes. Once our plugin is built we need to upload it to COSMOS. Go back to the Admin page and click the Plugins Tab. Click on "Click to install plugin" and select the openc3-cosmos-bob-1.0.0.20210618174517.gem file. Then click Upload. Go back to the CmdTlmServer and you should see the plugin being deployed at which point the BOB_INT interface should appear and try to connect. Go ahead and click 'Cancel' because unless you really have something listening on port 8080 this will never connect. At this point you can explore the other CmdTlmServer tabs and other tools to see your newly defined BOB target. Let's modify our BOB target and then update the copy in COSMOS. If you open Command Sender in COSMOS to BOB EXAMPLE you should see the VALUE parameter has value 2.5. Open the openc3-cosmos-bob/targets/BOB/cmd_tlm/cmd.txt and change the Default value for VALUE to 5 and the description to "New Value". COMMAND BOB EXAMPLE BIG_ENDIAN "Packet description" # Keyword Name BitSize Type Min Max Default Description APPEND_ID_PARAMETER ID 16 INT 1 1 1 "Identifier" APPEND_PARAMETER VALUE 32 FLOAT 0 10.5 5 "New Value" APPEND_PARAMETER BOOL 8 UINT MIN MAX 0 "Boolean" STATE FALSE 0 STATE TRUE 1 APPEND_PARAMETER LABEL 0 STRING "OpenC3" "The label to apply" Rebuild the plugin with a new VERSION number. Since we didn't make any breaking changes we simply bump the patch release number: C:\\cosmos-project\\openc3-cosmos-bob> ..\\openc3.bat cli rake build VERSION=1.0.1 Successfully built RubyGem Name: openc3-cosmos-bob Version: 1.0.1.20210618202504 File: openc3-cosmos-bob-1.0.1.20210618202504.gem Go back to the Admin page and click the Plugins Tab. This time click the clock icon next to openc3-cosmos-bob-1.0.0 to Upgrade the plugin. Browse to the newly built plugin gem and select it. This will re-prompt for the plugin variables (bob_target_name) so don't change the name and just click OK. You should see a message about the plugin being installed at which point the plugins list will change to openc3-cosmos-bob-1.0.1.20210618202504.gem. Go back to Command Sender and you should see the new Default value for VALUE is 5 and the description is "New Value". We have upgraded our plugin! At this point you can create a new plugin named after your real target and start modifying the interface and command and telemetry definitions to enable COSMOS to connect to and drive your target. If you run into trouble look for solutions on our Github Issues page. If you would like to enquire about support contracts or professional COSMOS development please contact us at support@openc3.com. ","version":"Next","tagName":"h2"},{"title":"Custom Widgets","type":0,"sectionRef":"#","url":"/docs/guides/custom-widgets","content":"","keywords":"","version":"Next"},{"title":"Custom Widgets","type":1,"pageTitle":"Custom Widgets","url":"/docs/guides/custom-widgets#custom-widgets","content":" We're basically going to follow the COSMOS Demo and explain how that custom widget was created. If you look at the bottom of the Demo's plugin.txt file you'll see we declare the widgets: WIDGET BIG WIDGET HELLOWORLD When the plugin is deployed this causes COSMOS to look for the as-built widgets. For the BIG widget it will look for the widget at tools/widgets/BigWidget/BigWidget.umd.min.js. Similarly it looks for HELLOWORLD at tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. These directories and file names may seem mysterious but it's all about how the widgets get built. ","version":"Next","tagName":"h2"},{"title":"Helloworld Widget","type":1,"pageTitle":"Custom Widgets","url":"/docs/guides/custom-widgets#helloworld-widget","content":" The Helloworld Widget source code is found in the plugin's src directory and is called HelloworldWidget.vue. The basic structure is as follows: <template> <!-- Implement widget here --> </template> <script> import Widget from "@openc3/tool-common/src/components/widgets/Widget"; export default { mixins: [Widget], data() { return { // Reactive data items }; }, }; </script> <style scoped> /* widget specific style */ </style> Vue & Vuetify For more information about how the COSMOS frontend is built (including all the Widgets) please check out Vue.js and Vuetify. To build this custom widget we changed the Demo Rakefile to call yarn run build when the plugin is built. yarn run XXX looks for 'scripts' to run in the package.json file. If we open package.json we find the following: "scripts": { "build": "vue-cli-service build --target lib --dest tools/widgets/HelloworldWidget --formats umd-min src/HelloworldWidget.vue --name HelloworldWidget && vue-cli-service build --target lib --dest tools/widgets/BigWidget --formats umd-min src/BigWidget.vue --name BigWidget" }, This uses the vue-cli-service to build the code found at src/HelloworldWidget.vue and formats as umd-min and puts it in the tools/widgets/HelloworldWidget directory. So this is why the plugin looks for the plugin at tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. Click here for the vue-cli-service build documentation. If you look at the Demo plugin's simple.txt screen you'll see we're using the widgets: SCREEN AUTO AUTO 0.5 LABELVALUE <%= target_name %> HEALTH_STATUS CCSDSSEQCNT HELLOWORLD BIG <%= target_name %> HEALTH_STATUS TEMP1 Opening this screen in Telemetry Viewer results in the following: While this is a simple example the possibilities with custom widgets are limitless! ","version":"Next","tagName":"h3"},{"title":"Code Generators","type":0,"sectionRef":"#","url":"/docs/getting-started/generators","content":"","keywords":"","version":"Next"},{"title":"Plugin Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#plugin-generator","content":" The plugin generator creates the scaffolding for a new COSMOS Plugin. It requires a plugin name and will create a new directory called openc3-cosmos-<name>. For example: % openc3.sh cli generate plugin Usage: cli generate plugin <NAME> % openc3.sh cli generate plugin GSE Plugin openc3-cosmos-gse successfully generated! This creates the following files: Name\tDescription.gitignore\tTells git to ignore any node_modules directory (for tool development) LICENSE.txt\tLicense for the plugin. COSMOS Plugins should be licensed in a manner compatible with the AGPLv3, unless they are designed only for use with COSMOS Enterprise Edition. openc3-cosmos-gse.gemspec\tGemspec file which should be edited to add user specific information like description, authors, emails, homepage, etc. The name of this file is used in compiling the plugin contents into the final corresponding gem file: e.g. openc3-cosmos-gse-1.0.0.gem. COSMOS plugins should always begin with the openc3-cosmos prefix to make them easily identifiable in the Rubygems repository. The file is formatted as documented at: https://guides.rubygems.org/specification-reference/ plugin.txt\tCOSMOS specific file for Plugin creation. Learn more here. Rakefile\tRuby Rakefile configured to support building the plugin by running "openc3.sh cli rake build VERSION=X.X.X" where X.X.X is the plugin version number README.md\tMarkdown file used to document the plugin While this structure is required, it is not very useful by itself. The plugin generator just creates the framework for other generators to use. ","version":"Next","tagName":"h2"},{"title":"Target Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#target-generator","content":" The target generator creates the scaffolding for a new COSMOS Target. It must operate inside an existing COSMOS plugin and requires a target name. For example: openc3-cosmos-gse % openc3.sh cli generate target Usage: cli generate target <NAME> (--ruby or --python) openc3-cosmos-gse % openc3.sh cli generate target GSE Target GSE successfully generated! This creates the following files and directories: Name\tDescriptiontargets/GSE\tContains the configuration for the GSE target. The target name is always defined in all caps. This is typically the default name of the target, but well-designed targets will allow themselves to be renamed at installation. targets/GSE/cmd_tlm\tContains the command and telemetry definition files for the GSE target. These files capture the format of the commands that can be sent to the target, and the telemetry packets that are expected to be received by COSMOS from the target. Note that the files in this folder are processed in alphabetical order by default. That can matter if you reference a packet in another file (it must already have been defined). targets/GSE/cmd_tlm/cmd.txt\tExample command configuration. Will need to be edited for the target specific commands. targets/GSE/cmd_tlm/tlm.txt\tExample telemetry configuration. Will need to be edited for the target specific telemetry. targets/GSE/lib\tContains any custom code required by the target. Good examples of custom code are library files, custom interface classes and protocols. targets/GSE/lib/gse.rb\tExample library file which can be expanded as the target is developed. COSMOS recommends building up library methods to avoid code duplication and ease reuse. targets/GSE/procedures\tThis folder contains target specific procedures and helper methods which exercise functionality of the target. These procedures should be kept simple and only use the command and telemetry definitions associated with this target. See the Scripting Guide for more information. targets/GSE/procedures/procedure.rb\tProcedure with an example of sending a command and checking telemetry targets/GSE/public\tPut image files here for use in Telemetry Viewer Canvas Image widgets such as CANVASIMAGE and CANVASIMAGEVALUE targets/GSE/screens\tContains telemetry screens for the target targets/GSE/screens/status.txt\tExample screen to display telemetry values targets/GSE/target.txt\tTarget configuration such as ignoring command and telemetry items and how to process the cmd/tlm files It also updates the plugin.txt file to add the new target: VARIABLE gse_target_name GSE TARGET GSE <%= gse_target_name %> INTERFACE <%= gse_target_name %>_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST MAP_TARGET <%= gse_target_name %> ","version":"Next","tagName":"h2"},{"title":"Microservice Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#microservice-generator","content":" The microservice generator creates the scaffolding for a new COSMOS Microservice. It must operate inside an existing COSMOS plugin and requires a target name. For example: openc3-cosmos-gse % openc3.sh cli generate microservice Usage: cli generate microservice <NAME> (--ruby or --python) openc3-cosmos-gse % openc3.sh cli generate microservice background Microservice BACKGROUND successfully generated! This creates the following files and directories: Name\tDescriptionmicroservices/BACKGROUND\tContains the code and any necessary configuration for the BACKGROUND microservice. The name is always defined in all caps. This is typically the default name of the microservice, but well-designed microservices will allow themselves to be renamed at installation. microservices/BACKGROUND/background.rb\tFully functional microservice which will run every minute and log a message. Edit to implement any custom logic that you want to run in the background. Potential uses are safety microservices which can check and autonomously respond to complex events and take action (NOTE: Simple actions might just require a Limits Response). It also updates the plugin.txt file to add the new microservice: MICROSERVICE BACKGROUND background-microservice CMD ruby background.rb ","version":"Next","tagName":"h2"},{"title":"Conversion Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#conversion-generator","content":" The conversion generator creates the scaffolding for a new COSMOS Conversion. It must operate inside an existing COSMOS plugin and requires both a target name and conversion name. For example: openc3-cosmos-gse % openc3.sh cli generate conversion Usage: cli generate conversion <TARGET> <NAME> (--ruby or --python) openc3-cosmos-gse % openc3.sh cli generate limits_response GSE double Conversion targets/GSE/lib/double_conversion.rb successfully generated! To use the conversion add the following to a telemetry item: READ_CONVERSION double_conversion.rb This creates the following files and directories: Name\tDescriptiontargets/GSE/lib/double_conversion.rb\tFully functional Conversion which has an example implementation of the call() method to convert any existing COSMOS values. As the generator states, to use this conversion code you must add it to a telemetry item. For example: TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description" # Keyword Name BitSize Type ID Description APPEND_ID_ITEM ID 16 INT 1 "Identifier" APPEND_ITEM VALUE 32 FLOAT "Value" READ_CONVERSION double_conversion.rb APPEND_ITEM BOOL 8 UINT "Boolean" STATE FALSE 0 STATE TRUE 1 APPEND_ITEM LABEL 0 STRING "The label to apply" ","version":"Next","tagName":"h2"},{"title":"Limits Response Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#limits-response-generator","content":" The limits_response generator creates the scaffolding for a new COSMOS Limits Response. It must operate inside an existing COSMOS plugin and requires both a target name and limits response name. For example: openc3-cosmos-gse % openc3.sh cli generate limits_response Usage: cli generate limits_response <TARGET> <NAME> (--ruby or --python) openc3-cosmos-gse % openc3.sh cli generate limits_response GSE safe Limits response targets/GSE/lib/safe_limits_response.rb successfully generated! To use the limits response add the following to a telemetry item: LIMITS_RESPONSE safe_limits_response.rb This creates the following files and directories: Name\tDescriptiontargets/GSE/lib/safe_limits_response.rb\tFully functional Limits Response which has an example implementation of the call() method and taking action based on the current limits state of the particular item As the generator states, to use this limits code you must add it to a telemetry item which has limits defined. In the generated GSE target, none of the items have limits defined so you first need to add limits and then add the response. TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description" # Keyword Name BitSize Type ID Description APPEND_ID_ITEM ID 16 INT 1 "Identifier" APPEND_ITEM VALUE 32 FLOAT "Value" LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0 LIMITS_RESPONSE safe_limits_response.rb APPEND_ITEM BOOL 8 UINT "Boolean" STATE FALSE 0 STATE TRUE 1 APPEND_ITEM LABEL 0 STRING "The label to apply" ","version":"Next","tagName":"h2"},{"title":"Widget Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#widget-generator","content":" The conversion generator creates the scaffolding for a new COSMOS Widget for use in Telemetry Viewer Screens. For more information see the Custom Widget guide. It must operate inside an existing COSMOS plugin and requires a widget name. For example: openc3-cosmos-gse % openc3.sh cli generate widget Usage: cli generate widget <SuperdataWidget> openc3-cosmos-gse % openc3.sh cli generate widget HelloworldWidget Widget HelloworldWidget successfully generated! Please be sure HelloworldWidget does not overlap an existing widget: https://docs.openc3.com/docs/configuration/telemetry-screens This creates the following files and directories: Name\tDescriptionsrc/HelloworldWidget.vue\tFully functional widget which displays a simple value. This can be expanded using existing COSMOS Vue.js code to create any data visualization imaginable. It also updates the plugin.txt file to add the new widget: WIDGET Helloworld ","version":"Next","tagName":"h2"},{"title":"Tool Generator","type":1,"pageTitle":"Code Generators","url":"/docs/getting-started/generators#tool-generator","content":" The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelte. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see Running a Frontend Application. openc3-cosmos-gse % openc3.sh cli generate tool Usage: cli generate tool 'Tool Name' openc3-cosmos-gse % openc3.sh cli generate widget DataVis Tool datavis successfully generated! Please be sure datavis does not conflict with any other tools This creates the following files and directories: Name\tDescriptionsrc/App.vue\tBasic Vue template to render the application. src/main.js\tEntry point for the new tool which loads Vue, Vuetify, and other libraries. src/router.js\tVue component router. src/tools/datavis\tContains all the files necessary to serve a web-based tool named datavis. The name is always defined in all lowercase. Due to technical limitations, the toolname must be unique and cannot be renamed at installation. src/tools/datavis/datavis.vue\tFully functional tool which displays a simple button. This can be expanded using existing COSMOS Vue.js code to create any tool imaginable. package.json\tBuild and dependency definition file. Used by npm or yarn to build the tool. vue.config.js\tVue configuration file used to serve the application in development and build the application. <dotfiles>\tVarious dotfiles which help configure formatters and tools for Javascript frontend development It also updates the plugin.txt file to add the new tool. The icon can be changed to any of the material design icons found here. TOOL datavis "DataVis" INLINE_URL js/app.js ICON mdi-file-cad-box ","version":"Next","tagName":"h2"},{"title":"Little Endian Bitfields","type":0,"sectionRef":"#","url":"/docs/guides/little-endian-bitfields","content":"Little Endian Bitfields Defining little endian bitfields is a little weird but is possible in COSMOS. However, note that APPEND does not work with little endian bitfields. Here are the rules on how COSMOS handles LITTLE_ENDIAN data: COSMOS bit offsets are always defined in BIG_ENDIAN terms. Bit 0 is always the most significant bit of the first byte in a packet, and increasing from there. All 8, 16, 32, and 64-bit byte-aligned LITTLE_ENDIAN data types define their bit_offset as the most significant bit of the first byte in the packet that contains part of the item. (This is exactly the same as BIG_ENDIAN). Note that for all except 8-bit LITTLE_ENDIAN items, this is the LEAST significant byte of the item. LITTLE_ENDIAN bit fields are defined as any LITTLE_ENDIAN INT or UINT item that is not 8, 16, 32, or 64-bit and byte aligned. LITTLE_ENDIAN bit fields must define their bit_offset as the location of the most significant bit of the bitfield in BIG_ENDIAN space as described in rule 1 above. So for example. The following C struct at the beginning of a packet would be defined like so: struct { unsigned short a:4; unsigned short b:8; unsigned short c:4; } ITEM A 4 4 UINT "struct item a" ITEM B 12 8 UINT "struct item b" ITEM C 8 4 UINT "struct item c" This is hard to visualize, but the structure above gets spread out in a byte array like the following after byte swapping: least significant 4 bits of b, 4-bits a, 4-bits c, most significant 4 bits of b. The best advice is to experiment and use the View Raw feature in the Command and Telemetry Service to inspect the bytes of the packet and adjust as necessary.","keywords":"","version":"Next"},{"title":"Bridges","type":0,"sectionRef":"#","url":"/docs/guides/bridges","content":"","keywords":"","version":"Next"},{"title":"Bridges are Generally Just an Interface and Router","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#bridges-are-generally-just-an-interface-and-router","content":" Bridges are generally made up of a COSMOS Interface class that pull data from a host connected device, and a Router that forwards that data to COSMOS over TCP/IP. In most cases, data can be safely sent to COSMOS using the BURST protocol, and let the COSMOS side use the correct packet delineation protocol like LENGTH. ","version":"Next","tagName":"h2"},{"title":"Host Requirements for Running Bridges","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#host-requirements-for-running-bridges","content":" Requires a host Ruby installation (Ruby 3)Install the OpenC3 gem gem install openc3 Make sure the Ruby gem executable path is in your PATH environment variable You can find this path by running gem environment and looking for EXECUTABLE DIRECTORY If successful, you should be able to run openc3cli from a terminal ","version":"Next","tagName":"h2"},{"title":"Bridge Configuration: bridge.txt","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#bridge-configuration-bridgetxt","content":" Bridges are run using an configuration file named bridge.txt. This file is a subset of the plugin.txt configuration syntax supporting VARIABLE, INTERFACE, ROUTER, and associated modifier keywords. However, BRIDGES HAVE NO KNOWLEDGE OF TARGETS. So instead of MAP_TARGETS, the INTERFACE is associated with the ROUTER using the ROUTE keyword. The following is the default bridge.txt that is generated by running openc3cli bridgesetup # Write serial port name VARIABLE write_port_name COM1 # Read serial port name VARIABLE read_port_name COM1 # Baud Rate VARIABLE baud_rate 115200 # Parity - NONE, ODD, or EVEN VARIABLE parity NONE # Stop bits - 0, 1, or 2 VARIABLE stop_bits 1 # Write Timeout VARIABLE write_timeout 10.0 # Read Timeout VARIABLE read_timeout nil # Flow Control - NONE, or RTSCTS VARIABLE flow_control NONE # Data bits per word - Typically 8 VARIABLE data_bits 8 # Port to listen for connections from COSMOS - Plugin must match VARIABLE router_port 2950 # Port to listen on for connections from COSMOS. Defaults to localhost for security. Will need to be opened # if COSMOS is on another machine. VARIABLE router_listen_address 127.0.0.1 INTERFACE SERIAL_INT serial_interface.rb <%= write_port_name %> <%= read_port_name %> <%= baud_rate %> <%= parity %> <%= stop_bits %> <%= write_timeout %> <%= read_timeout %> OPTION FLOW_CONTROL <%= flow_control %> OPTION DATA_BITS <%= data_bits %> ROUTER SERIAL_ROUTER tcpip_server_interface.rb <%= router_port %> <%= router_port %> 10.0 nil BURST ROUTE SERIAL_INT OPTION LISTEN_ADDRESS <%= router_listen_address %> VARIABLE provides default values to variables that can be changed when the bridge is started. This example shows an INTERFACE that is configured to use the serial_interface.rb class. It also includes a standard ROUTER using tcpip_server_interface.rb that COSMOS can connect to and get the data from the serial port. The LISTEN_ADDRESS is set to 127.0.0.1 in this example to prevent access from outside of the host system. Docker running on the same machine can access this server using the host.docker.internal hostname and the configured port (2950 in this example). ","version":"Next","tagName":"h2"},{"title":"Bridge Commands: openc3cli","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#bridge-commands-openc3cli","content":" openc3cli bridgesetup Generates a bridge.txt example file openc3cli bridge [filename] [variable1=value1] [variable2=value2] Runs a bridge from a given configuration file. Defaults to bridge.txt in the current directory. Variables can also be passed into to override VARIABLE defaults. openc3cli bridgegem [gem_name] [variable1=value1] [variable2=value2] Runs a bridge using the bridge.txt provided in a bridge gem. Variables can also be passed into to override VARIABLE defaults. ","version":"Next","tagName":"h2"},{"title":"Example Bridge Gems","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#example-bridge-gems","content":" Serial Port: openc3-cosmos-bridge-serialHost: openc3-cosmos-bridge-hostHIDAPI: openc3-cosmos-bridge-hidapiPS5 Dual Sense Controller: openc3-cosmos-bridge-dualsense ","version":"Next","tagName":"h2"},{"title":"Note on Serial Ports","type":1,"pageTitle":"Bridges","url":"/docs/guides/bridges#note-on-serial-ports","content":" Serial ports can be used directly without bridges on Linux Docker installations. Add the following to the operator service in compose.yaml: devices: - "/dev/ttyUSB0:/dev/ttyUSB0" Make sure the serial device has permissions for the user running Docker to access: sudo chmod 666 /dev/ttyUSB0 ","version":"Next","tagName":"h2"},{"title":"Interfaces","type":0,"sectionRef":"#","url":"/docs/configuration/interfaces","content":"","keywords":"","version":"Next"},{"title":"Provided Interfaces","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#provided-interfaces","content":" COSMOS provides the following interfaces for use: TCPIP Client, TCPIP Server, UDP, and Serial. The interface to use is defined by the INTERFACE and ROUTER keywords. ","version":"Next","tagName":"h2"},{"title":"TCPIP Client Interface","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#tcpip-client-interface","content":" The TCPIP client interface connects to a TCPIP socket to send commands and receive telemetry. This interface is used for targets which open a socket and wait for a connection. This is the most common type of interface. Parameter\tDescription\tRequiredHost\tMachine name to connect to\tYes Write Port\tPort to write commands to (can be the same as read port). Pass nil / None to make the interface read only.\tYes Read Port\tPort to read telemetry from (can be the same as write port). Pass nil / None to make the interface write only.\tYes Write Timeout\tNumber of seconds to wait before aborting the write\tYes Read Timeout\tNumber of seconds to wait before aborting the read. Pass nil / None to block on read.\tYes Protocol Type\tSee Protocols.\tNo Protocol Arguments\tSee Protocols for the arguments each stream protocol takes.\tNo plugin.txt Ruby Examples: INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil FIXED 6 0 nil true INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 10.0 # no built-in protocol plugin.txt Python Examples: INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 None LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None FIXED 6 0 None true INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 10.0 # no built-in protocol See INTERFACE for a description of the INTERFACE keyword. See Interface Modifiers for a description of the keywords which can follow the INTERFACE keyword. ","version":"Next","tagName":"h3"},{"title":"TCPIP Server Interface","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#tcpip-server-interface","content":" The TCPIP server interface creates a TCPIP server which listens for incoming connections and dynamically creates sockets which communicate with the target. This interface is used for targets which open a socket and try to connect to a server. Parameter\tDescription\tRequiredWrite Port\tPort to write commands to (can be the same as read port)\tYes Read Port\tPort to read telemetry from (can be the same as write port)\tYes Write Timeout\tNumber of seconds to wait before aborting the write\tYes Read Timeout\tNumber of seconds to wait before aborting the read. Pass nil / None to block on read.\tYes Protocol Type\tSee Protocols.\tNo Protocol Arguments\tSee Protocols for the arguments each stream protocol takes.\tNo plugin.txt Ruby Examples: INTERFACE INTERFACE_NAME tcpip_server_interface.rb 8080 8081 10.0 nil LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 INTERFACE INTERFACE_NAME tcpip_server_interface.rb 8080 8080 10.0 nil BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME tcpip_server_interface.rb 8080 8080 10.0 nil FIXED 6 0 nil true INTERFACE INTERFACE_NAME tcpip_server_interface.rb 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME tcpip_client_interface.rb 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME tcpip_server_interface.rb 8080 8080 10.0 nil PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME tcpip_client_interface.rb 8080 8080 10.0 10.0 # no built-in protocol plugin.txt Python Examples: INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_server_interface.py 8080 8081 10.0 None LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_server_interface.py 8080 8080 10.0 None BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_server_interface.py 8080 8080 10.0 None FIXED 6 0 None true INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_server_interface.py 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_server_interface.py 8080 8080 10.0 None PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py 8080 8080 10.0 10.0 # no built-in protocol See INTERFACE for a description of the INTERFACE keyword. See Interface Modifiers for a description of the keywords which can follow the INTERFACE keyword. Note, TcpipServerInterface processes the OPTION modifier. ","version":"Next","tagName":"h3"},{"title":"UDP Interface","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#udp-interface","content":" The UDP interface uses UDP packets to send and receive telemetry from the target. Parameter\tDescription\tRequired\tDefaultHost\tHost name or IP address of the machine to send and receive data with\tYes Write Dest Port\tPort on the remote machine to send commands to\tYes Read Port\tPort on the remote machine to read telemetry from\tYes Write Source Port\tPort on the local machine to send commands from\tNo\tnil (socket is not bound to an outgoing port) Interface Address\tIf the remote machine supports multicast the interface address is used to configure the outgoing multicast address\tNo\tnil (not used) TTL\tTime to Live. The number of intermediate routers allowed before dropping the packet.\tNo\t128 (Windows) Write Timeout\tNumber of seconds to wait before aborting the write\tNo\t10.0 Read Timeout\tNumber of seconds to wait before aborting the read\tNo\tnil (block on read) plugin.txt Ruby Example: INTERFACE INTERFACE_NAME udp_interface.rb host.docker.internal 8080 8081 8082 nil 128 10.0 nil plugin.txt Python Example: INTERFACE INTERFACE_NAME openc3/interfaces/udp_interface.py host.docker.internal 8080 8081 8082 None 128 10.0 None See INTERFACE for a description of the INTERFACE keyword. See Interface Modifiers for a description of the keywords which can follow the INTERFACE keyword. ","version":"Next","tagName":"h3"},{"title":"Serial Interface","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#serial-interface","content":" The serial interface connects to a target over a serial port. COSMOS provides drivers for both Windows and POSIX drivers for UNIX based systems. The Serial Interface is currently only implemented in Ruby. Parameter\tDescription\tRequiredWrite Port\tName of the serial port to write, e.g. 'COM1' or '/dev/ttyS0'. Pass nil / None to disable writing.\tYes Read Port\tName of the serial port to read, e.g. 'COM1' or '/dev/ttyS0'. Pass nil / None to disable reading.\tYes Baud Rate\tBaud rate to read and write\tYes Parity\tSerial port parity. Must be 'NONE', 'EVEN', or 'ODD'.\tYes Stop Bits\tNumber of stop bits, e.g. 1.\tYes Write Timeout\tNumber of seconds to wait before aborting the write\tYes Read Timeout\tNumber of seconds to wait before aborting the read. Pass nil / None to block on read.\tYes Protocol Type\tSee Protocols.\tNo Protocol Arguments\tSee Protocols for the arguments each stream protocol takes.\tNo plugin.txt Ruby Examples: INTERFACE INTERFACE_NAME serial_interface.rb COM1 COM1 9600 NONE 1 10.0 nil LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 INTERFACE INTERFACE_NAME serial_interface.rb /dev/ttyS1 /dev/ttyS1 38400 ODD 1 10.0 nil BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME serial_interface.rb COM2 COM2 19200 EVEN 1 10.0 nil FIXED 6 0 nil true INTERFACE INTERFACE_NAME serial_interface.rb COM4 COM4 115200 NONE 1 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME serial_interface.rb COM4 COM4 115200 NONE 1 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME serial_interface.rb /dev/ttyS0 /dev/ttyS0 57600 NONE 1 10.0 nil PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME serial_interface.rb COM4 COM4 115200 NONE 1 10.0 10.0 # no built-in protocol See INTERFACE for a description of the INTERFACE keyword. See Interface Modifiers for a description of the keywords which can follow the INTERFACE keyword. Note, SerialInterface processes the OPTION modifier. ","version":"Next","tagName":"h3"},{"title":"Streams","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#streams","content":" Streams are low level classes that implement read, read_nonblock, write, connect, connected? and disconnect methods. The built-in Stream classes are SerialStream, TcpipSocketStream and TcpipClientStream and they are automatically used when creating a Serial Interface, TCP/IP Server Interface, or TCP/IP Client Interface. ","version":"Next","tagName":"h2"},{"title":"Protocols","type":1,"pageTitle":"Interfaces","url":"/docs/configuration/interfaces#protocols","content":" Protocols define the behaviour of an Interface, including differentiating packet boundaries and modifying data as necessary. COSMOS defines the following built-in protocols which can be used with the above interfaces: Name\tDescriptionBurst\tReads as much data as possible from the interface Fixed\tProcesses fixed length packets with a known ID position Length\tProcesses a length field at a fixed location and then reads the remainder of the data Terminated\tDelineates packets uses termination characters at the end of each packet Template\tProcesses text based command / response data such as SCPI interfaces Preidentified\tInternal COSMOS protocol used by COSMOS tools These protocols are declared directly after the interface: INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil FIXED 6 0 nil true INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil LENGTH 0 16 0 1 BIG_ENDIAN 4 INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil PREIDENTIFIED 0xCAFEBABE INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None BURST 4 0xDEADBEEF INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None FIXED 6 0 None true INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 None LENGTH 0 16 0 1 BIG_ENDIAN 4 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 10.0 TERMINATED 0x0D0A 0x0D0A true 0 0xF005BA11 INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 10.0 TEMPLATE 0xA 0xA INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8080 10.0 None PREIDENTIFIED 0xCAFEBABE COSMOS also defines the following helper protocols: Name\tDescriptionCRC\tAdds CRCs to outgoing packets and verifies CRCs on incoming packets Ignore\tIgnores the specified packet by dropping it These protocols are declared after the INTERFACE: INTERFACE INTERFACE_NAME tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 nil BURST 4 0xDEADBEEF TARGET TGT PROTOCOL WRITE CrcProtocol CRC # See the documentation for parameters INTERFACE INTERFACE_NAME openc3/interfaces/tcpip_client_interface.rb host.docker.internal 8080 8080 10.0 None BURST 4 0xDEADBEEF TARGET TGT PROTOCOL WRITE CrcProtocol CRC # See the documentation for parameters Note the first parameter after the PROTOCOL keyword is how to apply the protocol: READ, WRITE, or READ_WRITE. Read applies the protocol on incoming packets (telemetry) and write on outgoing packets (commands). The next parameter is the protocol filename or class name. All other parameters are protocol specific. In addition, you can define your own protocols which are declared like the COSMOS helper protocols after your interface. See the Custom Protocols documentation for more information. Protocol Run Order Read protocols execute in the order specified (First specified runs first). Write protocols execute in the reverse order (Last specified executes first). ","version":"Next","tagName":"h2"},{"title":"Plugins","type":0,"sectionRef":"#","url":"/docs/configuration/plugins","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#introduction","content":" This document provides the information necessary to configure a COSMOS plugin. Plugins are how you configure and extend COSMOS. Plugins are where you define targets (and their corresponding command and telemetry packet definitions), where you configure the interfaces needed to talk to targets, where you can define routers to stream raw data out of COSMOS, how you can add new tools to the COSMOS user interface, and how you can run additional microservices to provide new functionality. Each plugin is built as a Ruby gem and thus has a plugin.gemspec file which builds it. Plugins have a plugin.txt file which declares all the variables used by the plugin and how to interface to the target(s) it contains. ","version":"Next","tagName":"h2"},{"title":"Concepts","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#concepts","content":" ","version":"Next","tagName":"h2"},{"title":"Target","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#target","content":" Targets are the external pieces of hardware and/or software that COSMOS communicates with. These are things like Front End Processors (FEPs), ground support equipment (GSE), custom software tools, and pieces of hardware like satellites themselves. A target is anything that COSMOS can send commands to and receive telemetry from. ","version":"Next","tagName":"h3"},{"title":"Interface","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#interface","content":" Interfaces implement the physical connection to one or more targets. They are typically ethernet connections implemented using TCP or UDP but can be other connections like serial ports. Interfaces send commands to targets and receive telemetry from targets. ","version":"Next","tagName":"h3"},{"title":"Router","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#router","content":" Routers flow streams of telemetry packets out of COSMOS and receive streams of commands into COSMOS. The commands are forwarded by COSMOS to associated interfaces. Telemetry comes from associated interfaces. ","version":"Next","tagName":"h3"},{"title":"Tool","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tool","content":" COSMOS Tools are web-based applications the communicate with the COSMOS APIs to perform takes like displaying telemetry, sending commands, and running scripts. ","version":"Next","tagName":"h3"},{"title":"Microservice","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#microservice","content":" Microservices are persistent running backend code that runs within the COSMOS environment. They can process data and perform other useful tasks. ","version":"Next","tagName":"h3"},{"title":"Plugin Directory Structure","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#plugin-directory-structure","content":" COSMOS plugins have a well-defined directory structure described in detail in the Code Generator documentation. ","version":"Next","tagName":"h2"},{"title":"plugin.txt Configuration File","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#plugintxt-configuration-file","content":" A plugin.txt configuration file is required for any COSMOS plugin. It declares the contents of the plugin and provides variables that allow the plugin to be configured at the time it is initially installed or upgraded. This file follows the standard COSMOS configuration file format of keywords followed by zero or more space separated parameters. The following keywords are supported by the plugin.txt config file: ","version":"Next","tagName":"h2"},{"title":"VARIABLE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#variable","content":" Define a configurable variable for the plugin The VARIABLE keyword defines a variable that will be requested for the user to enter during plugin installation. Variables can be used to handle details of targets that are user defined such as specific IP addresses and ports. Variables should also be used to allow users to rename targets to whatever name they want and support multiple installations of the same target with different names. Variables can be used later in plugin.txt or in any other configuration file included in a plugin using Ruby ERB syntax. The variables are assigned to accessible local variables in the file. At a high level, ERB allows you to run Ruby code in configuration files. Parameter\tDescription\tRequiredVariable Name\tThe name of the variable\tTrue Default Value\tDefault value of the variable\tTrue ","version":"Next","tagName":"h2"},{"title":"NEEDS_DEPENDENCIES","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#needs_dependencies","content":" (Since 5.5.0) Indicates the plugin needs dependencies and sets the GEM_HOME environment variable If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kubernetes pod. ","version":"Next","tagName":"h2"},{"title":"INTERFACE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#interface-1","content":" Defines a connection to a physical target Interfaces are what OpenC3 uses to talk to a particular piece of hardware. Interfaces require a Ruby or Python file which implements all the interface methods necessary to talk to the hardware. OpenC3 defines many built in interfaces or you can define your own as long as it implements the interface protocol. Parameter\tDescription\tRequiredInterface Name\tName of the interface. This name will appear in the Interfaces tab of the Server and is also referenced by other keywords. The OpenC3 convention is to name interfaces after their targets with '_INT' appended to the name, e.g. INST_INT for the INST target.\tTrue Filename\tRuby or Python file to use when instantiating the interface. Valid Values: tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface\tTrue Additional parameters are required. Please see the Interfaces documentation for more details. ","version":"Next","tagName":"h2"},{"title":"INTERFACE Modifiers","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#interface-modifiers","content":" The following keywords must follow a INTERFACE keyword. ","version":"Next","tagName":"h2"},{"title":"MAP_TARGET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#map_target","content":" Maps a target name to an interface Parameter\tDescription\tRequiredTarget Name\tTarget name to map to this interface\tTrue Ruby Example: INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST MAP_TARGET DATA Python Example: INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST MAP_TARGET DATA ","version":"Next","tagName":"h3"},{"title":"MAP_CMD_TARGET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#map_cmd_target","content":" (Since 5.2.0) Maps a target name to an interface for commands only Parameter\tDescription\tRequiredTarget Name\tCommand target name to map to this interface\tTrue Ruby Example: INTERFACE CMD_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface Python Example: INTERFACE CMD_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface ","version":"Next","tagName":"h3"},{"title":"MAP_TLM_TARGET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#map_tlm_target","content":" (Since 5.2.0) Maps a target name to an interface for telemetry only Parameter\tDescription\tRequiredTarget Name\tTelemetry target name to map to this interface\tTrue Ruby Example: INTERFACE TLM_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface Python Example: INTERFACE TLM_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface ","version":"Next","tagName":"h3"},{"title":"DONT_CONNECT","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#dont_connect","content":" Server will not automatically try to connect to the interface at startup ","version":"Next","tagName":"h3"},{"title":"DONT_RECONNECT","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#dont_reconnect","content":" Server will not try to reconnect to the interface if the connection is lost ","version":"Next","tagName":"h3"},{"title":"RECONNECT_DELAY","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reconnect_delay","content":" Reconnect delay in seconds If DONT_RECONNECT is not present the Server will try to reconnect to an interface if the connection is lost. Reconnect delay sets the interval in seconds between reconnect tries. Parameter\tDescription\tRequiredDelay\tDelay in seconds between reconnect attempts. The default is 15 seconds.\tTrue ","version":"Next","tagName":"h3"},{"title":"DISABLE_DISCONNECT","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#disable_disconnect","content":" Disable the Disconnect button on the Interfaces tab in the Server Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertently disconnect from a target. ","version":"Next","tagName":"h3"},{"title":"LOG_RAW","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#log_raw","content":" Deprecated, use LOG_STREAM ","version":"Next","tagName":"h3"},{"title":"LOG_STREAM","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#log_stream","content":" (Since 5.5.2) Log all data on the interface exactly as it is sent and received LOG_STREAM does not add any OpenC3 headers and thus can not be read by OpenC3 tools. It is primarily useful for low level debugging of an interface. You will have to manually parse these logs yourself using a hex editor or other application. Parameter\tDescription\tRequiredCycle Time\tAmount of time to wait before cycling the log file. Default is 10 min. If nil refer to Cycle Hour and Cycle Minute.\tFalse Cycle Size\tAmount of data to write before cycling the log file. Default is 50MB.\tFalse Cycle Hour\tThe time at which to cycle the log. Combined with Cycle Minute to cycle the log daily at the specified time. If nil, the log will be cycled hourly at the specified Cycle Minute. Only applies if Cycle Time is nil.\tFalse Cycle Minute\tSee Cycle Hour.\tFalse Example Usage: INTERFACE EXAMPLE example_interface.rb # Override the default log time of 600 LOG_STREAM 60 ","version":"Next","tagName":"h3"},{"title":"PROTOCOL","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#protocol","content":" (Since 4.0.0) Protocols modify the interface by processing the data Protocols can be either READ, WRITE, or READ_WRITE. READ protocols act on the data received by the interface while write acts on the data before it is sent out. READ_WRITE applies the protocol to both reading and writing. For information on creating your own custom protocol please see Protocols Parameter\tDescription\tRequiredType\tWhether to apply the protocol on incoming data, outgoing data, or both Valid Values: READ, WRITE, READ_WRITE\tTrue Protocol Filename or Classname\tRuby or Python filename or class name which implements the protocol\tTrue Protocol specific parameters\tAdditional parameters used by the protocol\tFalse Ruby Example: INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil nil MAP_TARGET DATA # Rather than defining the LENGTH protocol on the INTERFACE line we define it here PROTOCOL READ LengthProtocol 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11 Python Example: INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST MAP_TARGET DATA PROTOCOL READ IgnorePacketProtocol INST IMAGE # Drop all INST IMAGE packets ","version":"Next","tagName":"h3"},{"title":"OPTION","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#option","content":" Set a parameter on an interface When an option is set the interface class calls the set_option method. Custom interfaces can override set_option to handle any additional options they want. Parameter\tDescription\tRequiredName\tThe option to set. OpenC3 defines several options on the core provided interfaces. The SerialInterface defines FLOW_CONTROL which can be NONE (default) or RTSCTS and DATA_BITS which changes the data bits of the serial interface. The TcpipServerInterface and HttpServerInterface define LISTEN_ADDRESS which is the IP address to accept connections on (default 0.0.0.0).\tTrue Parameters\tParameters to pass to the option\tFalse Example Usage: INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil OPTION FLOW_CONTROL RTSCTS OPTION DATA_BITS 8 ROUTER SERIAL_ROUTER tcpip_server_interface.rb 2950 2950 10.0 nil BURST ROUTE SERIAL_INT OPTION LISTEN_ADDRESS 127.0.0.1 ","version":"Next","tagName":"h3"},{"title":"SECRET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#secret","content":" (Since 5.3.0) Define a secret needed by this interface Defines a secret for this interface and optionally assigns its value to an option Parameter\tDescription\tRequiredType\tENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file.\tTrue Secret Name\tThe name of the secret to retrieve\tTrue Environment Variable or File Path\tEnvironment variable name or file path to store secret\tTrue Option Name\tInterface option to pass the secret value\tFalse Secret Store Name\tName of the secret store for stores with multipart keys\tFalse Example Usage: SECRET ENV USERNAME ENV_USERNAME USERNAME SECRET FILE KEY "/tmp/DATA/cert" KEY ","version":"Next","tagName":"h3"},{"title":"ENV","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#env","content":" (Since 5.7.0) Sets an environment variable in the microservice. Parameter\tDescription\tRequiredKey\tEnvironment variable name\tTrue Value\tEnvironment variable value\tTrue Example Usage: ENV COMPANY OpenC3 ","version":"Next","tagName":"h3"},{"title":"WORK_DIR","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#work_dir","content":" (Since 5.7.0) Set the working directory Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in. Parameter\tDescription\tRequiredDirectory\tWorking directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.\tTrue Example Usage: WORK_DIR '/openc3/lib/openc3/microservices' ","version":"Next","tagName":"h3"},{"title":"PORT","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#port","content":" (Since 5.7.0) Open port for the microservice Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support Parameter\tDescription\tRequiredNumber\tPort number\tTrue Protocol\tPort protocol. Default is TCP.\tFalse Example Usage: PORT 7272 ","version":"Next","tagName":"h3"},{"title":"CMD","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd","content":" (Since 5.7.0) Command line to execute to run the microservice. Command line to execute to run the microservice. Parameter\tDescription\tRequiredArgs\tOne or more arguments to exec to run the microservice.\tTrue Ruby Example: CMD ruby interface_microservice.rb DEFAULT__INTERFACE__INT1 Python Example: CMD python interface_microservice.py DEFAULT__INTERFACE__INT1 ","version":"Next","tagName":"h3"},{"title":"CONTAINER","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#container","content":" (Since 5.7.0) Docker Container Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition. Parameter\tDescription\tRequiredArgs\tName of the container\tFalse ","version":"Next","tagName":"h3"},{"title":"ROUTE_PREFIX","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#route_prefix","content":" (Since 5.7.0) Prefix of route Prefix of route to the microservice to expose externally with Traefik Parameter\tDescription\tRequiredRoute Prefix\tRoute prefix. Must be unique across all scopes. Something like /myprefix\tTrue Example Usage: ROUTE_PREFIX /interface ","version":"Next","tagName":"h3"},{"title":"ROUTER","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#router-1","content":" Create router to receive commands and output telemetry packets from one or more interfaces Creates an router which receives command packets from their remote clients and sends them to associated interfaces. They receive telemetry packets from their interfaces and send them to their remote clients. This allows routers to be intermediaries between an external client and an actual device. Parameter\tDescription\tRequiredName\tName of the router\tTrue Filename\tRuby or Python file to use when instantiating the interface. Valid Values: tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface\tTrue Additional parameters are required. Please see the Interfaces documentation for more details. ","version":"Next","tagName":"h2"},{"title":"TARGET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#target-1","content":" Defines a new target Parameter\tDescription\tRequiredFolder Name\tThe target folder\tTrue Name\tThe target name. While this is almost always the same as Folder Name it can be different to create multiple targets based on the same target folder.\tTrue Example Usage: TARGET INST INST ","version":"Next","tagName":"h2"},{"title":"TARGET Modifiers","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#target-modifiers","content":" The following keywords must follow a TARGET keyword. ","version":"Next","tagName":"h2"},{"title":"CMD_BUFFER_DEPTH","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_buffer_depth","content":" (Since 5.2.0) Number of commands to buffer to ensure logged in order Parameter\tDescription\tRequiredBuffer Depth\tBuffer depth in packets (Default = 5)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_LOG_CYCLE_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_log_cycle_time","content":" Command binary logs can be cycled on a time interval. Parameter\tDescription\tRequiredTime\tMaximum time between files in seconds (default = 600)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_LOG_CYCLE_SIZE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_log_cycle_size","content":" Command binary logs can be cycled after a certain log file size is reached. Parameter\tDescription\tRequiredSize\tMaximum file size in bytes (default = 50_000_000)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_log_retain_time","content":" How long to keep raw command logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep raw command logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_DECOM_LOG_CYCLE_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_decom_log_cycle_time","content":" Command decommutation logs can be cycled on a time interval. Parameter\tDescription\tRequiredTime\tMaximum time between files in seconds (default = 600)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_DECOM_LOG_CYCLE_SIZE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_decom_log_cycle_size","content":" Command decommutation logs can be cycled after a certain log file size is reached. Parameter\tDescription\tRequiredSize\tMaximum file size in bytes (default = 50_000_000)\tTrue ","version":"Next","tagName":"h3"},{"title":"CMD_DECOM_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd_decom_log_retain_time","content":" How long to keep decom command logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep decom command logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_BUFFER_DEPTH","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_buffer_depth","content":" (Since 5.2.0) Number of telemetry packets to buffer to ensure logged in order Parameter\tDescription\tRequiredBuffer Depth\tBuffer depth in packets (Default = 60)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_LOG_CYCLE_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_log_cycle_time","content":" Telemetry binary logs can be cycled on a time interval. Parameter\tDescription\tRequiredTime\tMaximum time between files in seconds (default = 600)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_LOG_CYCLE_SIZE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_log_cycle_size","content":" Telemetry binary logs can be cycled after a certain log file size is reached. Parameter\tDescription\tRequiredSize\tMaximum file size in bytes (default = 50_000_000)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_log_retain_time","content":" How long to keep raw telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep raw telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_DECOM_LOG_CYCLE_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_decom_log_cycle_time","content":" Telemetry decommutation logs can be cycled on a time interval. Parameter\tDescription\tRequiredTime\tMaximum time between files in seconds (default = 600)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_DECOM_LOG_CYCLE_SIZE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_decom_log_cycle_size","content":" Telemetry decommutation logs can be cycled after a certain log file size is reached. Parameter\tDescription\tRequiredSize\tMaximum file size in bytes (default = 50_000_000)\tTrue ","version":"Next","tagName":"h3"},{"title":"TLM_DECOM_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tlm_decom_log_retain_time","content":" How long to keep decom telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep decom telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"REDUCED_MINUTE_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reduced_minute_log_retain_time","content":" How long to keep reduced minute telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep reduced minute telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"REDUCED_HOUR_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reduced_hour_log_retain_time","content":" How long to keep reduced hour telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep reduced hour telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"REDUCED_DAY_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reduced_day_log_retain_time","content":" How long to keep reduced day telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep reduced day telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#log_retain_time","content":" How long to keep all regular telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep all regular telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"REDUCED_LOG_RETAIN_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reduced_log_retain_time","content":" How long to keep all reduced telemetry logs in seconds. Parameter\tDescription\tRequiredTime\tNumber of seconds to keep all reduced telemetry logs (default = nil = Forever)\tTrue ","version":"Next","tagName":"h3"},{"title":"CLEANUP_POLL_TIME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cleanup_poll_time","content":" Period at which to run the cleanup process. Parameter\tDescription\tRequiredTime\tNumber of seconds between runs of the cleanup process (default = 900 = 15 minutes)\tTrue ","version":"Next","tagName":"h3"},{"title":"REDUCER_DISABLE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reducer_disable","content":" Disables the data reduction microservice for the target ","version":"Next","tagName":"h3"},{"title":"REDUCER_MAX_CPU_UTILIZATION","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#reducer_max_cpu_utilization","content":" Maximum amount of CPU utilization to apply to data reduction Parameter\tDescription\tRequiredPercentage\t0 to 100 percent (default = 30)\tTrue ","version":"Next","tagName":"h3"},{"title":"TARGET_MICROSERVICE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#target_microservice","content":" (Since 5.2.0) Breaks a target microservice out into its own process. Can be used to give more resources to processing that is falling behind. If defined multiple times for the same type, will create multiple processes. Each process can be given specific packets to process with the PACKET keyword. Parameter\tDescription\tRequiredType\tThe target microservice type. Must be one of DECOM, COMMANDLOG, DECOMCMDLOG, PACKETLOG, DECOMLOG, REDUCER, or CLEANUP\tTrue ","version":"Next","tagName":"h3"},{"title":"PACKET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#packet","content":" (Since 5.2.0) Packet Name to allocate to the current TARGET_MICROSERVICE. Parameter\tDescription\tRequiredPacket Name\tThe packet name. Does not apply to REDUCER or CLEANUP target microservice types.\tTrue ","version":"Next","tagName":"h3"},{"title":"DISABLE_ERB","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#disable_erb","content":" (Since 5.12.0) Disable ERB processing Disable ERB processing for the entire target or a set of regular expressions over its filenames Parameter\tDescription\tRequiredRegex\tRegex to match against filenames. If match, then no ERB processing\tFalse ","version":"Next","tagName":"h3"},{"title":"MICROSERVICE","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#microservice-1","content":" Defines a new microservice Defines a microservice that the plugin adds to the OpenC3 system. Microservices are background software processes that perform persistent processing. Parameter\tDescription\tRequiredMicroservice Folder Name\tThe exact name of the microservice folder in the plugin. ie. microservices/MicroserviceFolderName\tTrue Microservice Name\tThe specific name of this instance of the microservice in the OpenC3 system\tTrue Example Usage: MICROSERVICE EXAMPLE openc3-example ","version":"Next","tagName":"h2"},{"title":"MICROSERVICE Modifiers","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#microservice-modifiers","content":" The following keywords must follow a MICROSERVICE keyword. ","version":"Next","tagName":"h2"},{"title":"ENV","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#env-1","content":" Sets an environment variable in the microservice. Parameter\tDescription\tRequiredKey\tEnvironment variable name\tTrue Value\tEnvironment variable value\tTrue Example Usage: MICROSERVICE EXAMPLE openc3-example ENV COMPANY OpenC3 ","version":"Next","tagName":"h3"},{"title":"WORK_DIR","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#work_dir-1","content":" Set the working directory Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in. Parameter\tDescription\tRequiredDirectory\tWorking directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.\tTrue Example Usage: MICROSERVICE EXAMPLE openc3-example WORK_DIR . ","version":"Next","tagName":"h3"},{"title":"PORT","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#port-1","content":" (Since 5.0.10) Open port for the microservice Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support Parameter\tDescription\tRequiredNumber\tPort number\tTrue Protocol\tPort protocol. Default is TCP.\tFalse Example Usage: MICROSERVICE EXAMPLE openc3-example PORT 7272 ","version":"Next","tagName":"h3"},{"title":"TOPIC","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#topic","content":" Associate a Redis topic Redis topic to associate with this microservice. Standard OpenC3 microservices such as decom_microservice use this information to know what packet streams to subscribe to. The TOPIC keyword can be used as many times as necessary to associate all needed topics. Parameter\tDescription\tRequiredTopic Name\tRedis Topic to associate with the microservice\tTrue Example Usage: MICROSERVICE EXAMPLE openc3-example # Manually assigning topics is an advanced topic and requires # intimate knowledge of the internal COSMOS data structures. TOPIC DEFAULT__openc3_log_messages TOPIC DEFAULT__TELEMETRY__EXAMPLE__STATUS ","version":"Next","tagName":"h3"},{"title":"TARGET_NAME","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#target_name","content":" Associate a OpenC3 target OpenC3 target to associate with the microservice. For standard OpenC3 microservices such as decom_microservice this causes the target configuration to get loaded into the container for the microservice. Parameter\tDescription\tRequiredTarget Name\tOpenC3 target to associate with the microservice\tTrue Example Usage: MICROSERVICE EXAMPLE openc3-example TARGET_NAME EXAMPLE ","version":"Next","tagName":"h3"},{"title":"CMD","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#cmd-1","content":" Command line to execute to run the microservice. Command line to execute to run the microservice. Parameter\tDescription\tRequiredArgs\tOne or more arguments to exec to run the microservice.\tTrue Ruby Example: MICROSERVICE EXAMPLE openc3-example CMD ruby example_target.rb Python Example: MICROSERVICE EXAMPLE openc3-example CMD python example_target.py ","version":"Next","tagName":"h3"},{"title":"OPTION","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#option-1","content":" Pass an option to the microservice Generic key/value(s) options to pass to the microservice. These take the form of KEYWORD/PARAMS like a line in a OpenC3 configuration file. Multiple OPTION keywords can be used to pass multiple options to the microservice. Parameter\tDescription\tRequiredOption Name\tName of the option\tTrue Option Value(s)\tOne or more values to associate with the option\tTrue ","version":"Next","tagName":"h3"},{"title":"CONTAINER","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#container-1","content":" Docker Container Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition. Parameter\tDescription\tRequiredArgs\tName of the container\tFalse ","version":"Next","tagName":"h3"},{"title":"SECRET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#secret-1","content":" (Since 5.3.0) Define a secret needed by this microservice Defines a secret for this microservice Parameter\tDescription\tRequiredType\tENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file.\tTrue Secret Name\tThe name of the secret to retrieve\tTrue Environment Variable or File Path\tEnvironment variable name or file path to store secret\tTrue Secret Store Name\tName of the secret store for stores with multipart keys\tFalse Example Usage: SECRET ENV USERNAME ENV_USERNAME SECRET FILE KEY "/tmp/DATA/cert" ","version":"Next","tagName":"h3"},{"title":"ROUTE_PREFIX","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#route_prefix-1","content":" (Since 5.5.0) Prefix of route Prefix of route to the microservice to expose externally with Traefik Parameter\tDescription\tRequiredRoute Prefix\tRoute prefix. Must be unique across all scopes. Something like /myprefix\tTrue Example Usage: MICROSERVICE CFDP CFDP ROUTE_PREFIX /cfdp ","version":"Next","tagName":"h3"},{"title":"DISABLE_ERB","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#disable_erb-1","content":" (Since 5.12.0) Disable ERB processing Disable ERB processing for the entire microservice or a set of regular expressions over its filenames Parameter\tDescription\tRequiredRegex\tRegex to match against filenames. If match, then no ERB processing\tFalse ","version":"Next","tagName":"h3"},{"title":"TOOL","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tool-1","content":" Define a tool Defines a tool that the plugin adds to the OpenC3 system. Tools are web based applications that make use of the Single-SPA javascript library that allows them to by dynamically added to the running system as independent frontend microservices. Parameter\tDescription\tRequiredTool Folder Name\tThe exact name of the tool folder in the plugin. ie. tools/ToolFolderName\tTrue Tool Name\tName of the tool that is displayed in the OpenC3 Navigation menu\tTrue Example Usage: TOOL DEMO Demo ","version":"Next","tagName":"h2"},{"title":"TOOL Modifiers","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#tool-modifiers","content":" The following keywords must follow a TOOL keyword. ","version":"Next","tagName":"h2"},{"title":"URL","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#url","content":" Url used to access the tool The relative url used to access the tool. Defaults to "/tools/ToolFolderName". Parameter\tDescription\tRequiredUrl\tThe url. If not given defaults to tools/ToolFolderName. Generally should not be given unless linking to external tools.\tTrue ","version":"Next","tagName":"h3"},{"title":"INLINE_URL","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#inline_url","content":" Internal url to load a tool The url of the javascript file used to load the tool into single-SPA. Defaults to "js/app.js". Parameter\tDescription\tRequiredUrl\tThe inline url. If not given defaults to js/app.js. Generally should not be given unless using a non-standard filename.\tTrue ","version":"Next","tagName":"h3"},{"title":"WINDOW","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#window","content":" How to display the tool when navigated to The window mode used to display the tool. INLINE opens the tool internally without refreshing the page using the Single-SPA framework. IFRAME opens external tools in an Iframe within OpenC3. NEW opens the tool in a new TAB. Parameter\tDescription\tRequiredWindow Mode\tTool display mode Valid Values: INLINE, IFRAME, NEW\tTrue ","version":"Next","tagName":"h3"},{"title":"ICON","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#icon","content":" Set tool icon Icon shown next to the tool name in the OpenC3 navigation menu. Parameter\tDescription\tRequiredIcon Name\tIcon to display next to the tool name. Icons come from Font Awesome, Material Design (https://materialdesignicons.com/), and Astro.\tTrue ","version":"Next","tagName":"h3"},{"title":"CATEGORY","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#category","content":" Category for the tool Associates the tool with a category which becomes a submenu in the Navigation menu. Parameter\tDescription\tRequiredCategory Name\tCategory to associate the tool with\tTrue ","version":"Next","tagName":"h3"},{"title":"SHOWN","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#shown","content":" Show the tool or not Whether or not the tool is shown in the Navigation menu. Should generally be true, except for the openc3 base tool. Parameter\tDescription\tRequiredShown\tWhether or not the tool is shown. TRUE or FALSE Valid Values: true, false\tTrue ","version":"Next","tagName":"h3"},{"title":"POSITION","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#position","content":" (Since 5.0.8) Position of the tool in the nav bar Position of the tool starting at 2 (1 is reserved for Admin Console). Tools without a position are appended to the end as they are installed. All COSMOS open source tools have consecutive integer values for position. Parameter\tDescription\tRequiredPosition\tNumerical position\tTrue ","version":"Next","tagName":"h3"},{"title":"DISABLE_ERB","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#disable_erb-2","content":" (Since 5.12.0) Disable ERB processing Disable ERB processing for the entire tool or a set of regular expressions over its filenames Parameter\tDescription\tRequiredRegex\tRegex to match against filenames. If match, then no ERB processing\tFalse ","version":"Next","tagName":"h3"},{"title":"WIDGET","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#widget","content":" Define a custom widget Defines a custom widget that can be used in Telemetry Viewer screens. Parameter\tDescription\tRequiredWidget Name\tThe name of the widget will be used to build a path to the widget implementation. For example, WIDGET HELLOWORLD will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the Custom Widgets guide for more details.\tTrue Label\tThe label for the widget that will appear in the Data Viewer component drop down\tFalse Example Usage: WIDGET HELLOWORLD ","version":"Next","tagName":"h2"},{"title":"WIDGET Modifiers","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#widget-modifiers","content":" The following keywords must follow a WIDGET keyword. ","version":"Next","tagName":"h2"},{"title":"DISABLE_ERB","type":1,"pageTitle":"Plugins","url":"/docs/configuration/plugins#disable_erb-3","content":" (Since 5.12.0) Disable ERB processing Disable ERB processing for the entire widget or a set of regular expressions over its filenames Parameter\tDescription\tRequiredRegex\tRegex to match against filenames. If match, then no ERB processing\tFalse ","version":"Next","tagName":"h3"},{"title":"Local Mode","type":0,"sectionRef":"#","url":"/docs/guides/local-mode","content":"","keywords":"","version":"Next"},{"title":"Using Local Mode","type":1,"pageTitle":"Local Mode","url":"/docs/guides/local-mode#using-local-mode","content":" In this tutorial we will use the COSMOS Demo as configured by the Installation Guide. You should have cloned a cosmos-project and started it using openc3.sh run. If you check the project directory you should see a plugins/DEFAULT/openc3-cosmos-demo directory. This will contain both the gem that was installed and a plugin_instance.json file. The plugin_instance.json file captures the plugin.txt values when the plugin was installed. Note, all files in the plugins directory are meant to be configuration managed with the project. This ensures if you make local edits and check them in, another user can clone the project and get the exact same configuration. We will demonstrate this later. ","version":"Next","tagName":"h2"},{"title":"Editing scripts","type":1,"pageTitle":"Local Mode","url":"/docs/guides/local-mode#editing-scripts","content":" Visual Studio Code This tutorial will use VS Code which is the editor used by the COSMOS developers. The most common use case for Local Mode is script development. Launch Script Runner and open the INST/procedures/checks.rb file. If you run this script you'll notice that it has a few errors (by design) which prevent it from running to completion. Let's fix it! Comment out lines 7 & 9 and save the script. You should now notice that Local Mode has saved a copy of the script to plugins/targets_modified/INST/procedures/checks.rb. At this point Local Mode keeps these scripts in sync so we can edit in either place. Let's edit the local script by adding a simple comment at the top: # This is a script. Now if we go back to Script Runner the changes have not automatically appeared. However, there is a Reload button next to the filename that will refresh the file from the backend. Clicking this reloads the file which has been synced into COSMOS and now we see our comment. ","version":"Next","tagName":"h3"},{"title":"Disabling Local Mode","type":1,"pageTitle":"Local Mode","url":"/docs/guides/local-mode#disabling-local-mode","content":" If you want to disable Local Mode you can edit the .env file and delete the setting OPENC3_LOCAL_MODE=1. ","version":"Next","tagName":"h3"},{"title":"Configuration Management","type":1,"pageTitle":"Local Mode","url":"/docs/guides/local-mode#configuration-management","content":" It is recommended to configuration manage the entire project including the plugins directory. This will allow any user who starts COSMOS to launch an identical configuration. Plugins are created and updated with any modifications found in the targets_modified directory. At some point you will probably want to release your local changes back to the plugin they originated from. Simply copy the entire targets_modified/TARGET directory back to the original plugin. At that point you can rebuild the plugin using the CLI. openc3-cosmos-demo % ./openc3.sh cli rake build VERSION=1.0.1 Successfully built RubyGem Name: openc3-cosmos-demo Version: 1.0.1 File: openc3-cosmos-demo-1.0.1.gem Upgrade the plugin using the Admin Plugins tab and the Upgrade link. When you select your newly built plugin, COSMOS detects the existing changes and asks if you want to delete them. There is a stern warning attached because this will permanently remove these changes! Since we just moved over the changes and rebuilt the plugin we will check the box and INSTALL. When the new plugin is installed, the project's plugins directory gets updated with the new plugin and everything under the targets_modified directory is removed because there are no modifications on a new install. Local Mode is a powerful way to develop scripts and screens on the local file system and automatically have them sync to COSMOS. ","version":"Next","tagName":"h2"},{"title":"Logging","type":0,"sectionRef":"#","url":"/docs/guides/logging","content":"","keywords":"","version":"Next"},{"title":"decom_logs & raw_logs","type":1,"pageTitle":"Logging","url":"/docs/guides/logging#decom_logs--raw_logs","content":" The decom_logs and raw_logs folders contain the decommutated and raw command and telemetry data. Both are further broken down by target, packet, then date. For example, browsing into the DEFAULT/raw_logs/tlm/INST2/<YYYYMMDD>/ directory: Note the presence of the gzipped .bin files which contain the raw binary data. For more information about the structure of these files see the Log Structure developer documentation. The default settings for the Logging microservice is to start a new log file every 10 minutes or 50MB, which ever comes first. In the case of the low data rate demo, the 10 minute mark is hit first. To change the logging settings add the various CYCLE_TIME Target Modifiers under the declared TARGET name in your plugin.txt. ","version":"Next","tagName":"h3"},{"title":"text_logs","type":1,"pageTitle":"Logging","url":"/docs/guides/logging#text_logs","content":" The text_logs folder contains openc3_log_messages which contains text files that are again sorted by date and timestamped. These log messages come from the various microservices including the server and the target microservices. Thus these logs contain all the commands sent (in plain text) and telemetry checked. These log messages files are long term records of the messages in the CmdTlmServer Log Messages window: ","version":"Next","tagName":"h3"},{"title":"tool_logs","type":1,"pageTitle":"Logging","url":"/docs/guides/logging#tool_logs","content":" The tool_logs directory contains logs from the various COSMOS tools. Note that if you have not yet run any tools you may not see this directory as it is created on demand. Tool sub-directories are also created on demand. For example, after running a script in Script Runner a new 'sr' subdirectory appears which contains the script runner log resulting from running the script. In some cases logs in this directory may also be directly available from the tool itself. In the Script Runner case, the Script Messages pane below the script holds the output messages from the last script. Clicking the Download link allows you to download these messages as a file. ","version":"Next","tagName":"h3"},{"title":"Monitoring","type":0,"sectionRef":"#","url":"/docs/guides/monitoring","content":"","keywords":"","version":"Next"},{"title":"Monitoring and observability","type":1,"pageTitle":"Monitoring","url":"/docs/guides/monitoring#monitoring-and-observability","content":" With moving COSMOS to container based service, we needed a better way to monitor the internals of COSMOS. So here is some information on external services that you can use to monitor COSMOS. If you want to read more about Monitoring Distributed Systems ","version":"Next","tagName":"h3"},{"title":"Fluent/Fluentd","type":1,"pageTitle":"Monitoring","url":"/docs/guides/monitoring#fluentfluentd","content":" Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. Notes in_docker.conf <source> @type forward port 24224 bind 0.0.0.0 </source> <match *.metric> @type copy <store> @type elasticsearch host openc3-elasticsearch port 9200 logstash_format true logstash_prefix metric logstash_dateformat %Y%m%d include_tag_key true type_name access_log tag_key @log_name flush_interval 1s </store> <store> @type stdout </store> </match> <match *__openc3.log> @type copy <store> @type elasticsearch host openc3-elasticsearch port 9200 logstash_format true logstash_prefix openc3 logstash_dateformat %Y%m%d include_tag_key true type_name access_log tag_key @log_name flush_interval 1s </store> <store> @type stdout </store> </match> <match *.**> @type copy <store> @type elasticsearch host openc3-elasticsearch port 9200 logstash_format true logstash_prefix fluentd logstash_dateformat %Y%m%d include_tag_key true type_name access_log tag_key @log_name flush_interval 1s </store> <store> @type stdout </store> </match> Dockerfile FROM fluent/fluentd:v1.10.3-1.0 COPY ./in_docker.conf /fluentd/etc/fluent.conf USER root RUN gem install fluent-plugin-elasticsearch --no-document --version 4.0.7 \\ && gem install fluent-plugin-prometheus --no-document --version 1.8.5 USER fluent ","version":"Next","tagName":"h3"},{"title":"OpenDistro","type":1,"pageTitle":"Monitoring","url":"/docs/guides/monitoring#opendistro","content":" Open Distro for Elasticsearch provides a powerful, easy-to-use event monitoring and alerting system, enabling you to monitor your data and send notifications automatically to your stakeholders. With an intuitive Kibana interface and powerful API, it is easy to set up and manage alerts. Docker Notes When testing this I found that depending on how you ingest your logs into the opendistro I found I had to disable security. Here is an example of the docker file. Dockerfile FROM amazon/opendistro-for-elasticsearch:1.12.0 RUN /usr/share/elasticsearch/bin/elasticsearch-plugin remove opendistro_security ","version":"Next","tagName":"h3"},{"title":"Prometheus","type":1,"pageTitle":"Monitoring","url":"/docs/guides/monitoring#prometheus","content":" Prometheus scrapes metrics from instrumented jobs, either directly or via an intermediary push gateway for short-lived jobs. It stores all scraped samples locally and runs rules over this data to either aggregate and record new time series from existing data or generate alerts. Grafana or other API consumers can be used to visualize the collected data. Notes prometheus.yaml global: scrape_interval: 15s evaluation_interval: 15s rule_files: # - "first.rules" # - "second.rules" scrape_configs: - job_name: prometheus static_configs: - targets: ["localhost:9090"] - job_name: openc3-internal-metrics metrics_path: "/openc3-api/internal/metrics" static_configs: - targets: ["openc3-cmd-tlm-api:2901"] - job_name: openc3-cmd-tlm-api metrics_path: "/openc3-api/metrics" static_configs: - targets: ["openc3-cmd-tlm-api:2901"] - job_name: openc3-script-runner-api metrics_path: "/script-api/metrics" static_configs: - targets: ["openc3-script-runner-api:2902"] - job_name: minio-job metrics_path: /minio/v2/metrics/cluster scheme: http static_configs: - targets: ['openc3-minio:9000'] Dockerfile FROM prom/prometheus:v2.24.1 ADD prometheus.yaml /etc/prometheus/ ","version":"Next","tagName":"h3"},{"title":"Grafana","type":1,"pageTitle":"Monitoring","url":"/docs/guides/monitoring#grafana","content":" Grafana is a multi-platform open source analytics and interactive visualization web application. It provides charts, graphs, and alerts for the web when connected to supported data sources. Notes datasource.yaml apiVersion: 1 datasources: - name: Prometheus type: prometheus # Access mode - proxy (server in the UI) or direct (browser in the UI). access: proxy url: http://openc3-prometheus:9090 Dockerfile FROM grafana/grafana COPY datasource.yaml /etc/grafana/provisioning/datasources/ ","version":"Next","tagName":"h3"},{"title":"Telemetry","type":0,"sectionRef":"#","url":"/docs/configuration/telemetry","content":"","keywords":"","version":"Next"},{"title":"Telemetry Definition Files","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#telemetry-definition-files","content":" Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters. When defining telemetry items you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. Within COSMOS, the only difference between a STRING and BLOCK is when COSMOS reads a STRING type it stops reading when it encounters a null byte (0). This shows up when displaying the value in Packet Viewer or Tlm Viewer and in the output of Data Extractor. You should strive to store non-ASCII data inside BLOCK items and ASCII strings in STRING items. Printing Data Most data types can be printed in a COSMOS script simply by doing print(tlm("TGT PKT ITEM")). However, if the ITEM is a BLOCK data type and contains binary (non-ASCII) data then that won't work. COSMOS comes with a built-in method called formatted to help you view binary data. If ITEM is a BLOCK type containing binary try puts tlm("TGT PKT ITEM").formatted (Ruby) and print(formatted(tlm("TGT PKT ITEM"))) (Python) which will print the bytes out as hex. ","version":"Next","tagName":"h2"},{"title":"ID Items","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#id-items","content":" All packets require identification items so the incoming data can be matched to a packet structure. These items are defined using the ID_ITEM and APPEND_ID_ITEM. As data is read from the interface and refined by the protocol, the resulting packet is identified by matching all the ID fields. Note that ideally all packets in a particular target should use the exact same bit offset, bit size, and data type to identify. If this is not the case, you must set TLM_UNIQUE_ID_MODE in the target.txt file which incurs a performance penalty on every packet identification. ","version":"Next","tagName":"h3"},{"title":"Variable Sized Items","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#variable-sized-items","content":" COSMOS specifies a variable sized item with a bit size of 0. When a packet is identified, all other data that isn't explicitly defined will be put into the variable sized item. These items are typically used for packets containing memory dumps which vary in size depending on the number of bytes dumped. Note that there can only be one variable sized item per packet. ","version":"Next","tagName":"h3"},{"title":"Derived Items","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#derived-items","content":" COSMOS has a concept of a derived item which is a telemetry item that doesn't actually exist in the binary data. Derived items are typically computed based on other telemetry items. COSMOS derived items are very similar to real items except they use the special DERIVED data type. Here is how a derived item might look in a telemetry definition. ITEM TEMP_AVERAGE 0 0 DERIVED "Average of TEMP1, TEMP2, TEMP3, TEMP4" Note the bit offset and bit size of 0 and the data type of DERIVED. For this reason DERIVED items should be declared using ITEM rather than APPEND_ITEM. They can be defined anywhere in the packet definition but are typically placed at the end. The ITEM definition must be followed by a CONVERSION keyword, e.g. READ_CONVERSION, to generate the value. ","version":"Next","tagName":"h3"},{"title":"Received Time and Packet Time","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#received-time-and-packet-time","content":" COSMOS automatically creates several telemetry items on every packet: PACKET_TIMESECONDS, PACKET_TIMEFORMATTED, RECEIVED_COUNT, RECEIVED_TIMEFORMATTED, and RECEIVED_TIMESECONDS. RECEIVED_TIME is the time that COSMOS receives the packet. This is set by the interface which is connected to the target and is receiving the raw data. Once a packet has been created out of the raw data the time is set. PACKET_TIME defaults to RECEIVED_TIME, but can be set as a derived item with a time object in the telemetry configuration file. This helps support stored telemetry packets so that they can be more reasonably handled by other COSMOS tools such as Telemetry Grapher and Data Extractor. You can set the 'stored' flag in your interface and the current value table is unaffected. The _TIMEFORMATTED items returns the date and time in a YYYY/MM/DD HH:MM:SS.sss format and the _TIMESECONDS returns the Unix seconds of the time. Internally these are both stored as either a Ruby Time object or Python date object. Example COSMOS provides a Unix time conversion class which returns a Ruby Time object or Python date object based on the number of seconds and (optionally) microseconds since the Unix epoch. Note: This returns a native object and not a float or string! Ruby Example: ITEM PACKET_TIME 0 0 DERIVED "Ruby time based on TIMESEC and TIMEUS" READ_CONVERSION unix_time_conversion.rb TIMESEC TIMEUS Python Example: ITEM PACKET_TIME 0 0 DERIVED "Python time based on TIMESEC and TIMEUS" READ_CONVERSION openc3/conversions/unix_time_conversion.py TIMESEC TIMEUS Defining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet. Telemetry Keywords ","version":"Next","tagName":"h3"},{"title":"TELEMETRY","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#telemetry","content":" Defines a new telemetry packet Parameter\tDescription\tRequiredTarget\tName of the target this telemetry packet is associated with\tTrue Command\tName of this telemetry packet. Also referred to as its mnemonic. Must be unique to telemetry packets in this target. Ideally will be as short and clear as possible.\tTrue Endianness\tIndicates if the data in this packet is in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tTrue Description\tDescription of this telemetry packet which must be enclosed with quotes\tFalse Example Usage: TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Instrument health and status" ","version":"Next","tagName":"h2"},{"title":"TELEMETRY Modifiers","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#telemetry-modifiers","content":" The following keywords must follow a TELEMETRY keyword. ","version":"Next","tagName":"h2"},{"title":"ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#item","content":" Defines a telemetry item in the current telemetry packet Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Bit Offset\tBit offset into the telemetry packet of the Most Significant Bit of this item. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived item.\tTrue Bit Size\tBit size of this telemetry item. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this telemetry item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Description\tDescription for this telemetry item which must be enclosed with quotes\tFalse Endianness\tIndicates if the item is to be interpreted in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: ITEM PKTID 112 16 UINT "Packet ID" ITEM DATA 0 0 DERIVED "Derived data" ","version":"Next","tagName":"h3"},{"title":"ITEM Modifiers","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#item-modifiers","content":" The following keywords must follow a ITEM keyword. FORMAT_STRING Adds printf style formatting Parameter\tDescription\tRequiredFormat\tHow to format using printf syntax. For example, '0x%0X' will display the value in hex.\tTrue Example Usage: FORMAT_STRING "0x%0X" UNITS Add displayed units Parameter\tDescription\tRequiredFull Name\tFull name of the units type, e.g. Celsius\tTrue Abbreviated\tAbbreviation for the units, e.g. C\tTrue Example Usage: UNITS Celsius C UNITS Kilometers KM DESCRIPTION Override the defined description Parameter\tDescription\tRequiredValue\tThe new description\tTrue META Stores custom user metadata Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files. Parameter\tDescription\tRequiredMeta Name\tName of the metadata to store\tTrue Meta Values\tOne or more values to be stored for this Meta Name\tFalse Example Usage: META TEST "This parameter is for test purposes only" OVERLAP (Since 4.4.1) This item is allowed to overlap other items in the packet If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message. KEY (Since 5.0.10) Defines the key used to access this raw value in the packet. Keys are often JsonPath or XPath strings Parameter\tDescription\tRequiredKey string\tThe key to access this item\tTrue Example Usage: KEY $.book.title VARIABLE_BIT_SIZE (Since 5.18.0) Marks an item as having its bit size defined by another length item Parameter\tDescription\tRequiredLength Item Name\tThe name of the associated length item\tTrue Length Bits Per Count\tBits per count of the length item. Defaults to 8\tFalse Length Value Bit Offset\tOffset in Bits to Apply to Length Field Value. Defaults to 0\tFalse STATE Defines a key/value pair for the current item Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the telemetry item and allows for much greater clarity and less chance for user error. A catch all value of ANY applies to all other values not already defined as state values. Parameter\tDescription\tRequiredKey\tThe string state name\tTrue Value\tThe numerical state value or ANY to apply the state to all other values\tTrue Color\tThe color the state should be displayed as Valid Values: GREEN, YELLOW, RED\tFalse Example Usage: APPEND_ITEM ENABLE 32 UINT "Enable setting" STATE FALSE 0 STATE TRUE 1 STATE ERROR ANY # Match all other values to ERROR APPEND_ITEM STRING 1024 STRING "String" STATE "NOOP" "NOOP" GREEN STATE "ARM LASER" "ARM LASER" YELLOW STATE "FIRE LASER" "FIRE LASER" RED READ_CONVERSION Applies a conversion to the current telemetry item Conversions are implemented in a custom Ruby or Python file which should be located in the target's lib folder. The class must inherit from Conversion. It must implement the initialize (Ruby) or __init__ (Python) method if it takes extra parameters and must always implement the call method. The conversion factor is applied to the raw value in the telemetry packet before it is displayed to the user. The user still has the ability to see the raw unconverted value in a details dialog. Parameter\tDescription\tRequiredClass Filename\tThe filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'.\tTrue Parameter\tAdditional parameter values for the conversion which are passed to the class constructor.\tFalse Ruby Example: READ_CONVERSION the_great_conversion.rb 1000 Defined in the_great_conversion.rb: require 'openc3/conversions/conversion' module OpenC3 class TheGreatConversion < Conversion def initialize(multiplier) super() @multiplier = multiplier.to_f end def call(value, packet, buffer) return value * @multiplier end end end Python Example: READ_CONVERSION the_great_conversion.py 1000 Defined in the_great_conversion.py: from openc3.conversions.conversion import Conversion class TheGreatConversion(Conversion): def __init__(self, multiplier): super().__init__() self.multiplier = float(multiplier) def call(self, value, packet, buffer): return value * multiplier POLY_READ_CONVERSION Adds a polynomial conversion factor to the current telemetry item The conversion factor is applied to raw value in the telemetry packet before it is displayed to the user. The user still has the ability to see the raw unconverted value in a details dialog. Parameter\tDescription\tRequiredC0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: POLY_READ_CONVERSION 10 0.5 0.25 SEG_POLY_READ_CONVERSION Adds a segmented polynomial conversion factor to the current telemetry item This conversion factor is applied to the raw value in the telemetry packet before it is displayed to the user. The user still has the ability to see the raw unconverted value in a details dialog. Parameter\tDescription\tRequiredLower Bound\tDefines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound.\tTrue C0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: SEG_POLY_READ_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50 SEG_POLY_READ_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100 SEG_POLY_READ_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100 GENERIC_READ_CONVERSION_START Start a generic read conversion Adds a generic conversion function to the current telemetry item. This conversion factor is applied to the raw value in the telemetry packet before it is displayed to the user. The user still has the ability to see the raw unconverted value in a details dialog. The conversion is specified as Ruby or Python code that receives two implied parameters. 'value' which is the raw value being read and 'packet' which is a reference to the telemetry packet class (Note, referencing the packet as 'myself' is still supported for backwards compatibility). The last line of code should return the converted value. The GENERIC_READ_CONVERSION_END keyword specifies that all lines of code for the conversion have been given. warning Generic conversions are not a good long term solution. Consider creating a conversion class and using READ_CONVERSION instead. READ_CONVERSION is easier to debug and has higher performance. Parameter\tDescription\tRequiredConverted Type\tType of the converted value Valid Values: INT, UINT, FLOAT, STRING, BLOCK\tFalse Converted Bit Size\tBit size of converted value\tFalse Ruby Example: APPEND_ITEM ITEM1 32 UINT GENERIC_READ_CONVERSION_START return (value * 1.5).to_i # Convert the value by a scale factor GENERIC_READ_CONVERSION_END Python Example: APPEND_ITEM ITEM1 32 UINT GENERIC_READ_CONVERSION_START return int(value * 1.5) # Convert the value by a scale factor GENERIC_READ_CONVERSION_END GENERIC_READ_CONVERSION_END Complete a generic read conversion LIMITS Defines a set of limits for a telemetry item If limits are violated a message is printed in the Command and Telemetry Server to indicate an item went out of limits. Other tools also use this information to update displays with different colored telemetry items or other useful information. The concept of "limits sets" is defined to allow for different limits values in different environments. For example, you might want tighter or looser limits on telemetry if your environment changes such as during thermal vacuum testing. Parameter\tDescription\tRequiredLimits Set\tName of the limits set. If you have no unique limits sets use the keyword DEFAULT.\tTrue Persistence\tNumber of consecutive times the telemetry item must be within a different limits range before changing limits state.\tTrue Initial State\tWhether limits monitoring for this telemetry item is initially enabled or disabled. Note if you have multiple LIMITS items they should all have the same initial state. Valid Values: ENABLED, DISABLED\tTrue Red Low Limit\tIf the telemetry value is less than or equal to this value a Red Low condition will be detected\tTrue Yellow Low Limit\tIf the telemetry value is less than or equal to this value, but greater than the Red Low Limit, a Yellow Low condition will be detected\tTrue Yellow High Limit\tIf the telemetry value is greater than or equal to this value, but less than the Red High Limit, a Yellow High condition will be detected\tTrue Red High Limit\tIf the telemetry value is greater than or equal to this value a Red High condition will be detected\tTrue Green Low Limit\tSetting the Green Low and Green High limits defines an "operational limit" which is colored blue by OpenC3. This allows for a distinct desired operational range which is narrower than the green safety limit. If the telemetry value is greater than or equal to this value, but less than the Green High Limit, a Blue operational condition will be detected.\tFalse Green High Limit\tSetting the Green Low and Green High limits defines an "operational limit" which is colored blue by OpenC3. This allows for a distinct desired operational range which is narrower than the green safety limit. If the telemetry value is less than or equal to this value, but greater than the Green Low Limit, a Blue operational condition will be detected.\tFalse Example Usage: LIMITS DEFAULT 3 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0 LIMITS TVAC 3 ENABLED -80.0 -30.0 30.0 80.0 LIMITS_RESPONSE Defines a response class that is called when the limits state of the current item changes Parameter\tDescription\tRequiredResponse Class Filename\tName of the Ruby or Python file which implements the limits response. This file should be in the target's lib directory.\tTrue Response Specific Options\tVariable length number of options that will be passed to the class constructor\tFalse Ruby Example: LIMITS_RESPONSE example_limits_response.rb 10 Python Example: LIMITS_RESPONSE example_limits_response.py 10 ","version":"Next","tagName":"h3"},{"title":"APPEND_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#append_item","content":" Defines a telemetry item in the current telemetry packet Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Bit Size\tBit size of this telemetry item. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this telemetry item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Description\tDescription for this telemetry item which must be enclosed with quotes\tFalse Endianness\tIndicates if the item is to be interpreted in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_ITEM PKTID 16 UINT "Packet ID" ","version":"Next","tagName":"h3"},{"title":"ID_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#id_item","content":" Defines a telemetry item in the current telemetry packet. Note, packets defined without one or more ID_ITEMs are "catch-all" packets which will match all incoming data. Normally this is the job of the UNKNOWN packet. Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Bit Offset\tBit offset into the telemetry packet of the Most Significant Bit of this item. May be negative to indicate on offset from the end of the packet.\tTrue Bit Size\tBit size of this telemetry item. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value.\tTrue Data Type\tData Type of this telemetry item Valid Values: INT, UINT, FLOAT, STRING, BLOCK\tTrue ID Value\tThe value of this telemetry item that uniquely identifies this telemetry packet\tTrue Description\tDescription for this telemetry item which must be enclosed with quotes\tFalse Endianness\tIndicates if the item is to be interpreted in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: ID_ITEM PKTID 112 16 UINT 1 "Packet ID which must be 1" ","version":"Next","tagName":"h3"},{"title":"APPEND_ID_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#append_id_item","content":" Defines a telemetry item in the current telemetry packet Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Bit Size\tBit size of this telemetry item. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value.\tTrue Data Type\tData Type of this telemetry item Valid Values: INT, UINT, FLOAT, STRING, BLOCK\tTrue ID Value\tThe value of this telemetry item that uniquely identifies this telemetry packet\tTrue Description\tDescription for this telemetry item which must be enclosed with quotes\tFalse Endianness\tIndicates if the item is to be interpreted in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_ID_ITEM PKTID 16 UINT 1 "Packet ID which must be 1" ","version":"Next","tagName":"h3"},{"title":"ARRAY_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#array_item","content":" Defines a telemetry item in the current telemetry packet that is an array Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Bit Offset\tBit offset into the telemetry packet of the Most Significant Bit of this item. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived item.\tTrue Item Bit Size\tBit size of each array item\tTrue Item Data Type\tData Type of each array item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Array Bit Size\tTotal Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value.\tTrue Description\tDescription which must be enclosed with quotes\tFalse Endianness\tIndicates if the data is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: ARRAY_ITEM ARRAY 64 32 FLOAT 320 "Array of 10 floats" ","version":"Next","tagName":"h3"},{"title":"APPEND_ARRAY_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#append_array_item","content":" Defines a telemetry item in the current telemetry packet that is an array Parameter\tDescription\tRequiredName\tName of the telemety item. Must be unique within the packet.\tTrue Item Bit Size\tBit size of each array item\tTrue Item Data Type\tData Type of each array item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Array Bit Size\tTotal Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value.\tTrue Description\tDescription which must be enclosed with quotes\tFalse Endianness\tIndicates if the data is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_ARRAY_ITEM ARRAY 32 FLOAT 320 "Array of 10 floats" ","version":"Next","tagName":"h3"},{"title":"SELECT_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#select_item","content":" Selects an existing telemetry item for editing Must be used in conjunction with SELECT_TELEMETRY to first select the packet. Typically used to override generated values or make specific changes to telemetry that only affect a particular instance of a target used multiple times. Parameter\tDescription\tRequiredItem\tName of the item to select for modification\tTrue Example Usage: SELECT_TELEMETRY INST HEALTH_STATUS SELECT_ITEM TEMP1 # Define limits for this item, overrides or replaces any existing LIMITS DEFAULT 3 ENABLED -90.0 -80.0 80.0 90.0 -20.0 20.0 ","version":"Next","tagName":"h3"},{"title":"DELETE_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#delete_item","content":" (Since 4.4.1) Delete an existing telemetry item from the packet definition Deleting an item from the packet definition does not remove the defined space for that item. Thus unless you redefine a new item, there will be a "hole" in the packet where the data is not accessible. You can use SELECT_TELEMETRY and then ITEM to define a new item. Parameter\tDescription\tRequiredItem\tName of the item to delete\tTrue Example Usage: SELECT_TELEMETRY INST HEALTH_STATUS DELETE_ITEM TEMP4 ","version":"Next","tagName":"h3"},{"title":"META","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#meta-1","content":" Stores metadata for the current telemetry packet Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files. Parameter\tDescription\tRequiredMeta Name\tName of the metadata to store\tTrue Meta Values\tOne or more values to be stored for this Meta Name\tFalse Example Usage: META FSW_TYPE "struct tlm_packet" ","version":"Next","tagName":"h3"},{"title":"PROCESSOR","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#processor","content":" Defines a processor class that executes code every time a packet is received Parameter\tDescription\tRequiredProcessor Name\tThe name of the processor\tTrue Processor Class Filename\tName of the Ruby or Python file which implements the processor. This file should be in the target's lib directory.\tTrue Processor Specific Options\tVariable length number of options that will be passed to the class constructor.\tFalse Ruby Example: PROCESSOR TEMP1HIGH watermark_processor.rb TEMP1 Python Example: PROCESSOR TEMP1HIGH watermark_processor.py TEMP1 ","version":"Next","tagName":"h3"},{"title":"ALLOW_SHORT","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#allow_short","content":" Process telemetry packets which are less than their defined length Allows the telemetry packet to be received with a data portion that is smaller than the defined size without warnings. Any extra space in the packet will be filled in with zeros by OpenC3. ","version":"Next","tagName":"h3"},{"title":"HIDDEN","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#hidden","content":" Hides this telemetry packet from all the OpenC3 tools This packet will not appear in Packet Viewer, Telemetry Grapher and Handbook Creator. It also hides this telemetry from appearing in the Script Runner popup helper when writing scripts. The telemetry still exists in the system and can received and checked by scripts. ","version":"Next","tagName":"h3"},{"title":"ACCESSOR","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#accessor","content":" (Since 5.0.10) Defines the class used to read and write raw values from the packet Defines the class that is used too read raw values from the packet. Defaults to BinaryAccessor. Provided accessors also include JsonAccessor, CborAccessor, HtmlAccessor, and XmlAccessor. Parameter\tDescription\tRequiredAccessor Class Name\tThe name of the accessor class\tTrue ","version":"Next","tagName":"h3"},{"title":"IGNORE_OVERLAP","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#ignore_overlap","content":" (Since 5.16.0) Ignores any packet items which overlap Packet items which overlap normally generate a warning unless each individual item has the OVERLAP keyword. This ignores overlaps across the entire packet. ","version":"Next","tagName":"h3"},{"title":"VIRTUAL","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#virtual","content":" (Since 5.18.0) Marks this packet as virtual and not participating in identification Used for packet definitions that can be used as structures for items with a given packet. ","version":"Next","tagName":"h3"},{"title":"SELECT_TELEMETRY","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#select_telemetry","content":" Selects an existing telemetry packet for editing Typically used in a separate configuration file from where the original telemetry is defined to override or add to the existing telemetry definition. Must be used in conjunction with SELECT_ITEM to change an individual item. Parameter\tDescription\tRequiredTarget Name\tName of the target this telemetry packet is associated with\tTrue Packet Name\tName of the telemetry packet to select\tTrue Example Usage: SELECT_TELEMETRY INST HEALTH_STATUS SELECT_ITEM TEMP1 # Define limits for this item, overrides or replaces any existing LIMITS DEFAULT 3 ENABLED -90.0 -80.0 80.0 90.0 -20.0 20.0 ","version":"Next","tagName":"h2"},{"title":"LIMITS_GROUP","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#limits_group","content":" Defines a group of related limits Items Limits groups contain telemetry items that can be enabled and disabled together. It can be used to group related limits as a subsystem that can be enabled or disabled as that particular subsystem is powered (for example). To enable a group call the enable_limits_group("NAME") method in Script Runner. To disable a group call the disable_limits_group("NAME") in Script Runner. Items can belong to multiple groups but the last enabled or disabled group "wins". For example, if an item belongs to GROUP1 and GROUP2 and you first enable GROUP1 and then disable GROUP2 the item will be disabled. If you then enable GROUP1 again it will be enabled. Parameter\tDescription\tRequiredGroup Name\tName of the limits group\tTrue ","version":"Next","tagName":"h2"},{"title":"LIMITS_GROUP_ITEM","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#limits_group_item","content":" Adds the specified telemetry item to the last defined LIMITS_GROUP Limits group information is typically kept in a separate configuration file in the config/TARGET/cmd_tlm folder named limits_groups.txt. Parameter\tDescription\tRequiredTarget Name\tName of the target\tTrue Packet Name\tName of the packet\tTrue Item Name\tName of the telemetry item to add to the group\tTrue Example Usage: LIMITS_GROUP SUBSYSTEM LIMITS_GROUP_ITEM INST HEALTH_STATUS TEMP1 LIMITS_GROUP_ITEM INST HEALTH_STATUS TEMP2 LIMITS_GROUP_ITEM INST HEALTH_STATUS TEMP3 ","version":"Next","tagName":"h2"},{"title":"Example File","type":1,"pageTitle":"Telemetry","url":"/docs/configuration/telemetry#example-file","content":" Example File: TARGET/cmd_tlm/tlm.txt TELEMETRY TARGET HS BIG_ENDIAN "Health and Status for My Target" ITEM CCSDSVER 0 3 UINT "CCSDS PACKET VERSION NUMBER (SEE CCSDS 133.0-B-1)" ITEM CCSDSTYPE 3 1 UINT "CCSDS PACKET TYPE (COMMAND OR TELEMETRY)" STATE TLM 0 STATE CMD 1 ITEM CCSDSSHF 4 1 UINT "CCSDS SECONDARY HEADER FLAG" STATE FALSE 0 STATE TRUE 1 ID_ITEM CCSDSAPID 5 11 UINT 102 "CCSDS APPLICATION PROCESS ID" ITEM CCSDSSEQFLAGS 16 2 UINT "CCSDS SEQUENCE FLAGS" STATE FIRST 0 STATE CONT 1 STATE LAST 2 STATE NOGROUP 3 ITEM CCSDSSEQCNT 18 14 UINT "CCSDS PACKET SEQUENCE COUNT" ITEM CCSDSLENGTH 32 16 UINT "CCSDS PACKET DATA LENGTH" ITEM CCSDSDAY 48 16 UINT "DAYS SINCE EPOCH (JANUARY 1ST, 1958, MIDNIGHT)" ITEM CCSDSMSOD 64 32 UINT "MILLISECONDS OF DAY (0 - 86399999)" ITEM CCSDSUSOMS 96 16 UINT "MICROSECONDS OF MILLISECOND (0-999)" ITEM ANGLEDEG 112 16 INT "Instrument Angle in Degrees" POLY_READ_CONVERSION 0 57.295 ITEM MODE 128 8 UINT "Instrument Mode" STATE NORMAL 0 GREEN STATE DIAG 1 YELLOW ITEM TIMESECONDS 0 0 DERIVED "DERIVED TIME SINCE EPOCH IN SECONDS" GENERIC_READ_CONVERSION_START FLOAT 32 ((packet.read('ccsdsday') * 86400.0) + (packet.read('ccsdsmsod') / 1000.0) + (packet.read('ccsdsusoms') / 1000000.0) ) GENERIC_READ_CONVERSION_END ITEM TIMEFORMATTED 0 0 DERIVED "DERIVED TIME SINCE EPOCH AS A FORMATTED STRING" GENERIC_READ_CONVERSION_START STRING 216 time = Time.ccsds2mdy(packet.read('ccsdsday'), packet.read('ccsdsmsod'), packet.read('ccsdsusoms')) sprintf('%04u/%02u/%02u %02u:%02u:%02u.%06u', time[0], time[1], time[2], time[3], time[4], time[5], time[6]) GENERIC_READ_CONVERSION_END ","version":"Next","tagName":"h2"},{"title":"COSMOS Hardware Requirements","type":0,"sectionRef":"#","url":"/docs/guides/performance","content":"","keywords":"","version":"Next"},{"title":"Memory","type":1,"pageTitle":"COSMOS Hardware Requirements","url":"/docs/guides/performance#memory","content":" COSMOS can run on a Raspberry Pi up to a Kubernetes cluster in the cloud. On all platforms the key performance factor is the number and complexity of the targets and their defined packets. Targets can vary from simple targets taking 100 MB of RAM to complex targets taking 400 MB. The base COSMOS containers require about 800 MB of RAM. A good rule of thumb is to average about 300 MB of RAM for targets. As an example data point, the COSMOS Demo has 4 targets, two complex (INST & INST2) and two relatively simple (EXAMPLE & TEMPLATED), and requires 800 MB of RAM (on top of the 800 MB of base container RAM). Base RAM MB Calculator = 800 + (num targets) * 300 In addition, the Redis streams contain the last 10 min of both raw and decommutated data from all targets. Thus you must wait ~15min to truly see what the high water memory mark will be. In the COSMOS Demo the INST & INST2 targets are fairly simple with four 1Hz packet of ~15 items and one 10Hz packet with 20 items. This only causes 50 MiB of redis RAM usage according to docker stats. Installing the COSMOS LoadSim with 10 packets with 1000 items each at 10Hz pushed the redis memory usage to about 350 MiB. ","version":"Next","tagName":"h2"},{"title":"CPU","type":1,"pageTitle":"COSMOS Hardware Requirements","url":"/docs/guides/performance#cpu","content":" Another consideration is the CPU performance. In the Open Source Edition, by default COSMOS spawns off 2 microservices per target. One combines packet logging and decommutation of the data and the other performs data reduction. In COSMOS Enterprise Edition on Kubernetes, each process becomes an independent container that is deployed on the cluster allowing horizontal scaling. The COSMOS command and telemetry API and script running API servers should have a dedicated core while targets can generally share cores. It's hard to provide a general rule of thumb with the wide variety of architectures, clock speeds, and core counts. The best practice is to install COSMOS with the expected load and do some monitoring with htop to visualize the load on the various cores. Any time a single core gets overloaded (100%) this is a concern and system slowdown can occur. ","version":"Next","tagName":"h2"},{"title":"Performance Comparison","type":1,"pageTitle":"COSMOS Hardware Requirements","url":"/docs/guides/performance#performance-comparison","content":" Performance characterization was performed in Azure on a Standard D4s v5 (4 vcpus, 16 GiB memory) chosen to allow virtualization per Docker. COSMOS 5.9.1 Enterprise Edition was installed on both Windows 11 Pro 1 and Ubuntu 22. Note: Enterprise Edition was not utilizing Kubernetes, just Docker. Testing involved starting the COSMOS Demo, connecting all targets (EXAMPLE, INST, INST2, TEMPLATED), opening the following TlmViewer screens (ADCS, ARRAY, BLOCK, COMMANDING, HS, LATEST, LIMITS, OTHER, PARAMS, SIMPLE, TABS) and creating two TlmGrapher graphs consisting of INST HEALTH_STATUS TEMP[1-4] and INST ADCS POS[X,Y,Z] and INST ADCS VEL[X,Y,Z]. This was allowed to run for 1hr and results were collected using htop: Platform\tCore CPU %\tRAMWindows 11 Pro\t12% 12% 10% 10%\t3.9G / 7.7G Headless Ubuntu 22\t7% 7% 8% 6%\t3.2G / 15.6G Windows was only allocated 8 GB of RAM due to the .wslconfig settings.Since Ubuntu was running headless, the screens and graphs were brought up on another machine. docker stats was also run to show individual container cpu and memory usage: NAME\tWindows CPU %\tUbuntu CPU %\tWindows MEM\tUbuntu MEMcosmos-enterprise-project-openc3-traefik-1\t4.16%\t1.32%\t43.54MiB\t51.38MiB cosmos-enterprise-project-openc3-cosmos-cmd-tlm-api-1\t10.16%\t6.14%\t401.6MiB\t392MiB cosmos-enterprise-project-openc3-keycloak-1\t0.17%\t0.13%\t476.8MiB\t476.8MiB cosmos-enterprise-project-openc3-operator-1\t21.27%\t13.91%\t1.214GiB\t1.207GiB cosmos-enterprise-project-openc3-cosmos-script-runner-api-1\t0.01%\t0.01%\t127.4MiB\t117.1MiB cosmos-enterprise-project-openc3-metrics-1\t0.01%\t0.00%\t105.2MiB\t83.87MiB cosmos-enterprise-project-openc3-redis-ephemeral-1\t4.05%\t1.89%\t46.22MiB\t69.84MiB cosmos-enterprise-project-openc3-redis-1\t1.56%\t0.72%\t12.82MiB\t9.484MiB cosmos-enterprise-project-openc3-minio-1\t0.01%\t0.00%\t152.9MiB\t169.8MiB cosmos-enterprise-project-openc3-postgresql-1\t0.00%\t0.39%\t37.33MiB\t41.02MiB memory profiles are similar between the two platformsredis-ephemeral isn't using much memory on the base Demo with its small packets At this point the COSMOS LoadSim was installed with default settings which creates 10 packets with 1000 items each at 10Hz (110kB/s). After a 1 hr soak, htop now indicated: Platform\tCore CPU %\tRAMWindows 11 Pro\t40% 35% 39% 42%\t4.64G / 7.7G Headless Ubuntu 22\t17% 20% 16% 18%\t3.74G / 15.6G The larger packets and data rate of the LoadSim target caused both platforms to dramatically increase CPU utilization but the Linux machine stays quite performant. docker stats was also run to show individual container cpu and memory usage: NAME\tWindows CPU %\tUbuntu CPU %\tWindows MEM\tUbuntu MEMcosmos-enterprise-project-openc3-traefik-1\t4.09%\t0.01%\t44.3MiB\t0.34MiB cosmos-enterprise-project-openc3-cosmos-cmd-tlm-api-1\t17.78%\t6.18%\t407.9MiB\t405.8MiB cosmos-enterprise-project-openc3-keycloak-1\t0.20%\t0.12%\t480.2MiB\t481.5MiB cosmos-enterprise-project-openc3-operator-1\t221.15%\t66.72%\t1.6GiB\t1.512GiB cosmos-enterprise-project-openc3-cosmos-script-runner-api-1\t0.01%\t0.01%\t136.6MiB\t127.5MiB cosmos-enterprise-project-openc3-metrics-1\t0.01%\t0.01%\t106.3MiB\t84.87MiB cosmos-enterprise-project-openc3-redis-ephemeral-1\t19.63%\t3.91%\t333.8MiB\t370.8MiB cosmos-enterprise-project-openc3-redis-1\t7.42%\t1.49%\t15.87MiB\t11.81MiB cosmos-enterprise-project-openc3-minio-1\t0.10%\t0.02%\t167.8MiB\t179.2MiB cosmos-enterprise-project-openc3-postgresql-1\t0.00%\t0.00%\t35.4MiB\t42.93MiB memory profiles are similar between the two platformsredis-ephemeral is now using much more RAM as it is storing the large LoadSim packetsWindows is using much more CPU power running the operator, cmd-tlm, and redis Conclusions While it is easy to run COSMOS on any Docker platform, increasing the number and complexity of the targets requires choosing the correct hardware. Sizing can be approximated but the best solution is to install representative targets and use docker stats and htop to judge the CPU and memory pressure on the given hardware. COSMOS Enterprise Edition on Kubernetes helps to eliminate the hardware sizing issue by scaling the cluster to meet the needs of the system. Check out this recent talk Ryan gave at GSAW showing how we scaled to over 160 satellites on a 4 node kubernetes cluster on EKS. Footnotes Full specs of the Windows Platform: Windows 11 Pro Docker Desktop 4.22.0 WSL version: 1.2.5.0 Kernel version: 5.15.90.1 WSLg version: 1.0.51 MSRDC version: 1.2.3770 Direct3D version: 1.608.2-61064218 DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp Windows version: 10.0.22621.2134 ↩ ","version":"Next","tagName":"h2"},{"title":"Raspberry Pi","type":0,"sectionRef":"#","url":"/docs/guides/raspberrypi","content":"","keywords":"","version":"Next"},{"title":"COSMOS Running on Raspberry Pi 4","type":1,"pageTitle":"Raspberry Pi","url":"/docs/guides/raspberrypi#cosmos-running-on-raspberry-pi-4","content":" The Raspberry Pi 4 is a low-cost powerful ARM-based minicomputer that runs linux. And because it runs modern linux, it can also run COSMOS! These directions will get you up and running. What you'll need: Raspberry Pi 4 board (tested with 8GB RAM)A Pi Case but OptionalRaspbeerry Pi Power Supply32GB or Larger SD Card - Also faster the betterA Laptop with a way to write SD Cards Let's get started! Setup 64-bit Raspian OS Lite on the SD Card Make sure you have the Raspberry Pi Imager app from: https://www.raspberrypi.com/software/ Insert the SD Card into your computer (Note this process will erase all data on the SD card!)Open the Raspberry Pi Imager AppClick the "Choose Device" ButtonPick Your Raspberry Pi ModelClick the "Choose OS" ButtonSelect "Raspberry Pi OS (other)"Select "Raspberry Pi OS Lite (64-bit)"Click the "Choose Storage" ButtonSelect Your SD CardClick Edit SettingsIf prompted if you would like to prefill the Wifi information, select OKSet the hostname to: cosmos.localSet the username and password. The default username is your username, you should also set a password to make the system secureFill in your Wifi info, and set the country appropriately (ie. US)Set the correct time zoneGoto the Services Tab and Enable SSHYou can either use Password auth, or public-key only if your computer is already setup for passwordless SSHGoto the Options tab and make sure "Enable Telemetry" is not checkedClick "Save" when everything is filled outClick "Yes" to apply OS Customization Settings, Yes to Are You Sure, and Wait for it to complete Make sure the Raspberry Pi is NOT powered on Remove the SD Card from your computer and insert into the Raspberry Pi Apply power to the Raspberry Pi and wait approximately 1 minute for it to boot SSH to your raspberry Pi Open a terminal window and use ssh to connect to your Pi On Mac / Linux: ssh yourusername@cosmos.localOn Windows, use Putty to connect. You will probably have to install Bonjour for Windows for .local addresses to work as well. From SSH, Enter the following commands sudo sysctl -w vm.max_map_count=262144 sudo sysctl -w vm.overcommit_memory=1 sudo apt update sudo apt upgrade sudo apt install git -y curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER newgrp docker git clone https://github.com/OpenC3/cosmos-project.git cosmos cd cosmos # Edit compose.yaml and remove 127.0.0.1: from the ports section of the openc3-traefik service ./openc3.sh run After about 2 minutes, open a web browser on your computer, and goto: http://cosmos.local:2900 Congratulations! You now have COSMOS running on a Raspberry Pi! ","version":"Next","tagName":"h3"},{"title":"COSMOS and NASA cFS","type":0,"sectionRef":"#","url":"/docs/guides/cfs","content":"","keywords":"","version":"Next"},{"title":"Working configuration","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#working-configuration","content":" This tutorial has been tested using the following components: COSMOS v5 release 5.0.6cFS master-branch commit: 561b128 (June 1, 2022)Docker Desktop 4.9.0 on Windows Replace all <xxxxxx> with your matching paths and names. Example: <USERNAME>. ","version":"Next","tagName":"h2"},{"title":"Setting up COSMOS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#setting-up-cosmos","content":" Install COSMOS according to the official installation instructions. ","version":"Next","tagName":"h2"},{"title":"Configuring COSMOS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#configuring-cosmos","content":" Change the Docker configuration for the interoperability with NASA cFS. For subscribing to the telemetry, you have to append a port binding in the filecompose.yaml under the section openc3-operator. The port number has to match with the port number cFS is sending the telemetry on. openc3-operator: ports: - "1235:1235/udp" Run COSMOS, the first run takes a while (~15 min). openc3.sh start When started, connect with a browser to http://localhost:2900. For shutting down COSMOS: openc3.sh stop ","version":"Next","tagName":"h3"},{"title":"Setting up cFS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#setting-up-cfs","content":" To run NASA cFS as a Docker container do the following: ","version":"Next","tagName":"h2"},{"title":"Clone cFS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#clone-cfs","content":" git clone --recurse-submodules https://github.com/nasa/cFS.git ","version":"Next","tagName":"h3"},{"title":"Create Dockerfile in cFS dir","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#create-dockerfile-in-cfs-dir","content":" FROM ubuntu:22.10 AS builder ARG DEBIAN_FRONTEND=noninteractive ARG SIMULATION=native ENV SIMULATION=${SIMULATION} ARG BUILDTYPE=debug ENV BUILDTYPE=${BUILDTYPE} ARG OMIT_DEPRECATED=true ENV OMIT_DEPRECATED=${OMIT_DEPRECATED} RUN \\ apt-get update && \\ apt-get -y upgrade && \\ apt-get install -y build-essential git cmake && \\ rm -rf /var/lib/apt/lists/* WORKDIR /cFS COPY . . RUN git submodule init \\ && git submodule update \\ && cp cfe/cmake/Makefile.sample Makefile \\ && cp -r cfe/cmake/sample_defs . RUN make prep RUN make RUN make install FROM ubuntu:22.10 COPY --from=builder /cFS/build /cFS/build WORKDIR /cFS/build/exe/cpu1 ENTRYPOINT [ "./core-cpu1" ] ","version":"Next","tagName":"h3"},{"title":"Build and run cFS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#build-and-run-cfs","content":" Note we're connecting to the COSMOS network (docker network ls) and exposing the cFS ports. docker build -t cfs . docker run --cap-add CAP_SYS_RESOURCE --net=openc3-cosmos-network --name cfs -p1234:1234/udp -p1235:1235 cfs ","version":"Next","tagName":"h3"},{"title":"Creating a COSMOS plugin for TM/TC interface with cFS","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#creating-a-cosmos-plugin-for-tmtc-interface-with-cfs","content":" The detailed instructions how to create a plugin, can be foundhere, in the chapter "Interfacing with Your Hardware". Create a new plugin with the name CFS. CFS is the name of the plugin and must be in capital letters according to the COSMOS documentation. This command should create the plugin structure. Then cd into the plugin to create the target. # cd .. to the location of the cfs dir $PATH_TO_OPENC3/openc3.sh cli generate plugin CFS cd openc3-cosmos-cfs $PATH_TO_OPENC3/openc3.sh cli generate target CFS In this newly created plugin, change the plugin.txt file, so that the communication happens over UDP. port_tm is the port number on which cFS sends the telemetry messages. port_tc indicates the port on which cFS listens to the telecommands. VARIABLE ip 127.0.0.1 VARIABLE port_tm 1235 VARIABLE port_tc 1234 VARIABLE cfs_target_name CFS TARGET CFS <%= cfs_target_name %> # hostname write_dest_port read_port write_src_port interface_address ttl write_timeout read_timeout bind_address INTERFACE <%= cfs_target_name %>_INT udp_interface.rb <%= ip %> <%= port_tc %> <%= port_tm %> nil nil 128 nil nil MAP_TARGET <%= cfs_target_name %> Note that the two arguments to the TARGET parameter are: the physical target name that should match the name of the plugin, i.e. CFS. This name must match the folder name in the targets folder. Example: for theCFS plugin, the target specifications must be underopenc3-cfs/targets/CFS. If you don't follow this convention, the server will refuse to install your plugin at the following steps. the name of your target and how it is shown in the user interface. In this example, we keep both names to be CFS. ","version":"Next","tagName":"h2"},{"title":"Creating TM/TC definitions","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#creating-tmtc-definitions","content":" Change to the target folder and remove the existing files and create own files. cd openc3-cfs/targets/CFS/cmd_tlm rm * touch cfs_cmds.txt touch cfs_tlm.txt touch to_lab_cmds.txt Open these newly created files in a text editor and fill them with following content. to_lab_cmds.txt: COMMAND CFS TO_LAB_ENABLE BIG_ENDIAN "Enable telemetry" # NAME BITS TYPE min VAL max VAL init VAL DESCRIPTION APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1880 0x1880 0x1880 "Stream ID" FORMAT_STRING "0x%04X" APPEND_PARAMETER SEQUENCE 16 UINT 0xC000 MAX_UINT16 0xC000 "" FORMAT_STRING "0x%04X" APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0xFFFF 0x0012 "length of the packet" APPEND_PARAMETER CMD_ID 8 UINT 6 6 6 "" APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0x98 "" FORMAT_STRING "0x%2X" APPEND_PARAMETER DEST_IP 144 STRING "127.0.0.1" "Destination IP, i.e. 172.16.9.112, pc-57" Enabling Telemetry The command 0x1880 is needed to enable telemetry. When the cFS receives this command, it starts sending telemetry to the IP address provided via theDEST_IP field. cfs_cmds.txt: COMMAND CFS NOOP BIG_ENDIAN "NOOP Command" # cFS primary header APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification" FORMAT_STRING "0x%04X" APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "" FORMAT_STRING "0x%04X" APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length" # cFS CMD secondary header APPEND_PARAMETER CMD_ID 8 UINT 0 0 0 "" APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 "" COMMAND CFS RESET BIG_ENDIAN "Reset Counters Command" APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification" FORMAT_STRING "0x%04X" APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "" FORMAT_STRING "0x%04X" APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length" APPEND_PARAMETER CMD_ID 8 UINT 1 1 1 "" APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 "" COMMAND CFS PROCESS BIG_ENDIAN "Process Command" APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification" FORMAT_STRING "0x%04X" APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "" FORMAT_STRING "0x%04X" APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length" APPEND_PARAMETER CMD_ID 8 UINT 2 2 2 "" APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 "" cfs_tlm.txt: TELEMETRY CFS HK BIG_ENDIAN "housekeeping telemetry" # NAME BITS TYPE ID DESCRIPTION APPEND_ID_ITEM STREAM_ID 16 UINT 0x0883 "Stream ID" FORMAT_STRING "0x%04X" APPEND_ITEM SEQUENCE 16 UINT "Packet Sequence" FORMAT_STRING "0x%04X" APPEND_ITEM PKT_LEN 16 UINT "Length of the packet" # telemetry secondary header APPEND_ITEM SECONDS 32 UINT "" UNITS Seconds sec APPEND_ITEM SUBSECS 16 UINT "" UNITS Milliseconds ms # some bytes not known for what APPEND_ITEM SPARE2ALIGN 32 UINT "Spares" # payload APPEND_ITEM CMD_ERRS 8 UINT "Command Error Counter" APPEND_ITEM CMD_CNT 8 UINT "Command Counter" # spare / alignment APPEND_ITEM SPARE 16 UINT "Spares" Build the plugin from the base of your plugin folder: # cd openc3-cfs $PATH_TO_OPENC3/openc3.sh cli rake build VERSION=1.0.0 Plugin versioning Do not forget to change the version number with every build if you want to better distinguish between the versions of the plugin. When the version is seen in the plugin's .gem file name, it is easier to visualize the existing versions and the newly uploaded versions. Plugin parameters Multiple parameters are available for the plugin configuration. See the plugin page. ","version":"Next","tagName":"h2"},{"title":"Uploading the plugin","type":1,"pageTitle":"COSMOS and NASA cFS","url":"/docs/guides/cfs#uploading-the-plugin","content":" After the plugin has been built, you can import the plugin in the admin area of the page. Connect with a browser tohttp://localhost:2900/tools/admin. Click on the clip icon and navigate to where your plugin is stored and select the openc3-cosmos-cfs-1.0.0.gem file. Right of the selection line click on UPLOAD. Determine the IP address the cFS container and COSMOS operator container are running at: docker network ls NETWORK ID NAME DRIVER SCOPE d842f813f1c7 openc3-cosmos-network bridge local docker network inspect openc3-cosmos-network [ { "Name": "openc3-cosmos-network", ... "Containers": { "03cb6bf1b27c631fad1366e9342aeaa5b80f458a437195e4a95e674bb5f5983d": { "Name": "cfs", "IPv4Address": "172.20.0.9/16", }, "ceb9ea99b00849fd8867dcd1646838fef3471f7d64b69014703dbedbcc8147fc": { "Name": "openc3_openc3-operator_1", "IPv4Address": "172.20.0.8/16", } } ... } ] When using this plugin, make sure to change the ip variable during uploading to match where cFS is running. In the example above you would set it to 172.20.0.9.port_tm is the port number on which cFS is sending the telemetry messages.port_tc indicates the port on cFS is listening for telecommands. Under cfs_target_name you can change the target name of this plugin. This step is optional as long as you are fine with your plugin showing up as CFS. Port subscription The last uploaded plugin on COSMOS will subscribe to TM on port 1235. Other plugins will not receive any TM anymore. Typo errors Presence of typos in one of the plugin files can cause problems when uploading and installing the plugin's .gem file. Make sure your configuration is typo-free. In the example above, the operator image is running at 172.20.0.8. To enable telemetry, go to the browser and connect tohttp://localhost:2900/tools/cmdsender/CFS/TO_LAB_ENABLE. Change the DEST_IP to the IP address of the operator image (172.20.0.8) and send the command. Under http://localhost:2900/tools/cmdtlmserver/tlm-packets, you should see the incoming packets. Note in the CmdTlmServer you will also see CFS_INT UNKNOWN packets because we did not define the full cFS packet set. That exercise is left to the reader. ","version":"Next","tagName":"h2"},{"title":"Commands","type":0,"sectionRef":"#","url":"/docs/configuration/command","content":"","keywords":"","version":"Next"},{"title":"Command Definition Files","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#command-definition-files","content":" Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters. When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters. Command Keywords ","version":"Next","tagName":"h2"},{"title":"COMMAND","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#command","content":" Defines a new command packet Parameter\tDescription\tRequiredTarget\tName of the target this command is associated with\tTrue Command\tName 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.\tTrue Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tTrue Description\tDescription of this command which must be enclosed with quotes\tFalse Example Usage: COMMAND INST COLLECT BIG_ENDIAN "Start collect" ","version":"Next","tagName":"h2"},{"title":"COMMAND Modifiers","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#command-modifiers","content":" The following keywords must follow a COMMAND keyword. ","version":"Next","tagName":"h2"},{"title":"PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#parameter","content":" Defines a command parameter in the current command packet Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Bit Offset\tBit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue Default Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: PARAMETER SYNC 0 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern" PARAMETER DATA 32 32 INT MIN MAX 0 "Data value" PARAMETER VALUE 64 32 FLOAT 0 10.5 2.5 PARAMETER LABEL 96 96 STRING "OPENC3" "The label to apply" PARAMETER BLOCK 192 0 BLOCK 0x0 "Block of binary data" ","version":"Next","tagName":"h3"},{"title":"PARAMETER Modifiers","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#parameter-modifiers","content":" The following keywords must follow a PARAMETER keyword. FORMAT_STRING Adds printf style formatting Parameter\tDescription\tRequiredFormat\tHow to format using printf syntax. For example, '0x%0X' will display the value in hex.\tTrue Example Usage: FORMAT_STRING "0x%0X" UNITS Add displayed units Parameter\tDescription\tRequiredFull Name\tFull name of the units type, e.g. Celsius\tTrue Abbreviated\tAbbreviation for the units, e.g. C\tTrue Example Usage: UNITS Celsius C UNITS Kilometers KM DESCRIPTION Override the defined description Parameter\tDescription\tRequiredValue\tThe new description\tTrue META Stores custom user metadata Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files. Parameter\tDescription\tRequiredMeta Name\tName of the metadata to store\tTrue Meta Values\tOne or more values to be stored for this Meta Name\tFalse Example Usage: META TEST "This parameter is for test purposes only" OVERLAP (Since 4.4.1) This item is allowed to overlap other items in the packet If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message. KEY (Since 5.0.10) Defines the key used to access this raw value in the packet. Keys are often JsonPath or XPath strings Parameter\tDescription\tRequiredKey string\tThe key to access this item\tTrue Example Usage: KEY $.book.title VARIABLE_BIT_SIZE (Since 5.18.0) Marks an item as having its bit size defined by another length item Parameter\tDescription\tRequiredLength Item Name\tThe name of the associated length item\tTrue Length Bits Per Count\tBits per count of the length item. Defaults to 8\tFalse Length Value Bit Offset\tOffset in Bits to Apply to Length Field Value. Defaults to 0\tFalse REQUIRED Parameter is required to be populated in scripts When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition. MINIMUM_VALUE Override the defined minimum value Parameter\tDescription\tRequiredValue\tThe new minimum value for the parameter\tTrue MAXIMUM_VALUE Override the defined maximum value Parameter\tDescription\tRequiredValue\tThe new maximum value for the parameter\tTrue DEFAULT_VALUE Override the defined default value Parameter\tDescription\tRequiredValue\tThe new default value for the parameter\tTrue STATE Defines a key/value pair for the current command parameter Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error. Parameter\tDescription\tRequiredKey\tThe string state name\tTrue Value\tThe numerical state value\tTrue Hazardous / Disable Messages\tIndicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state. Valid Values: HAZARDOUS\tFalse Hazardous Description\tString describing why this state is hazardous\tFalse Example Usage: APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting" STATE FALSE 0 STATE TRUE 1 APPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter" STATE "NOOP" "NOOP" DISABLE_MESSAGES STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard" STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!" WRITE_CONVERSION Applies a conversion when writing the current command parameter Conversions are implemented in a custom Ruby or Python file which should be located in the target's lib folder. The class must inherit from Conversion. It must implement the initialize (Ruby) or __init__ (Python) method if it takes extra parameters and must always implement the call method. The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Multiple write conversions on command parameters When a command is built, each item gets written (and write conversions are run) to set the default value. Then items are written (again write conversions are run) with user provided values. Thus write conversions can be run twice. Also there are no guarantees which parameters have already been written. The packet itself has a given_values() method which can be used to retrieve a hash of the user provided values to the command. That can be used to check parameter values passed in. Parameter\tDescription\tRequiredClass Filename\tThe filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'.\tTrue Parameter\tAdditional parameter values for the conversion which are passed to the class constructor.\tFalse Ruby Example: WRITE_CONVERSION the_great_conversion.rb 1000 Defined in the_great_conversion.rb: require 'openc3/conversions/conversion' module OpenC3 class TheGreatConversion < Conversion def initialize(multiplier) super() @multiplier = multiplier.to_f end def call(value, packet, buffer) return value * multiplier end end end Python Example: WRITE_CONVERSION the_great_conversion.py 1000 Defined in the_great_conversion.py: from openc3.conversions.conversion import Conversion class TheGreatConversion(Conversion): def __init__(self, multiplier): super().__init__() self.multiplier = float(multiplier) def call(self, value, packet, buffer): return value * multiplier POLY_WRITE_CONVERSION Adds a polynomial conversion factor to the current command parameter The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Parameter\tDescription\tRequiredC0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: POLY_WRITE_CONVERSION 10 0.5 0.25 SEG_POLY_WRITE_CONVERSION Adds a segmented polynomial conversion factor to the current command parameter This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. Parameter\tDescription\tRequiredLower Bound\tDefines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound.\tTrue C0\tCoefficient\tTrue Cx\tAdditional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate.\tFalse Example Usage: SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50 SEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100 SEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100 GENERIC_WRITE_CONVERSION_START Start a generic write conversion Adds a generic conversion function to the current command parameter. This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent. The conversion is specified as Ruby or Python code that receives two implied parameters. 'value' which is the raw value being written and 'packet' which is a reference to the command packet class (Note, referencing the packet as 'myself' is still supported for backwards compatibility). The last line of code should return the converted value. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of code for the conversion have been given. Multiple write conversions on command parameters When a command is built, each item gets written (and write conversions are run) to set the default value. Then items are written (again write conversions are run) with user provided values. Thus write conversions can be run twice. Also there are no guarantees which parameters have already been written. The packet itself has a given_values() method which can be used to retrieve a hash of the user provided values to the command. That can be used to check parameter values passed in. warning Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance. Ruby Example: APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0 GENERIC_WRITE_CONVERSION_START return (value * 1.5).to_i # Convert the value by a scale factor GENERIC_WRITE_CONVERSION_END Python Example: APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0 GENERIC_WRITE_CONVERSION_START return int(value * 1.5) # Convert the value by a scale factor GENERIC_WRITE_CONVERSION_END GENERIC_WRITE_CONVERSION_END Complete a generic write conversion OVERFLOW Set the behavior when writing a value overflows the type By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value. Parameter\tDescription\tRequiredBehavior\tHow OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types. Valid Values: ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE\tTrue Example Usage: OVERFLOW TRUNCATE ","version":"Next","tagName":"h3"},{"title":"APPEND_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#append_parameter","content":" Defines a command parameter in the current command packet Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue Default Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_PARAMETER SYNC 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern" APPEND_PARAMETER VALUE 32 FLOAT 0 10.5 2.5 APPEND_PARAMETER LABEL 0 STRING "OPENC3" "The label to apply" ","version":"Next","tagName":"h3"},{"title":"ID_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#id_parameter","content":" Defines an identification command parameter in the current command packet ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified. Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Bit Offset\tBit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue ID Value\tIdentification value for this parameter. The binary data must match this value for the buffer to be identified as this packet.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: ID_PARAMETER OPCODE 32 32 UINT 2 2 2 "Opcode identifier" ","version":"Next","tagName":"h3"},{"title":"APPEND_ID_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#append_id_parameter","content":" Defines an identification command parameter in the current command packet ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified. Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Bit Size\tBit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'.\tTrue Data Type\tData Type of this parameter Valid Values: INT, UINT, FLOAT, DERIVED, STRING, BLOCK\tTrue When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are: Parameter\tDescription\tRequiredMinimum Value\tMinimum allowed value for this parameter\tTrue Maximum Value\tMaximum allowed value for this parameter\tTrue ID Value\tIdentification value for this parameter. The binary data must match this value for the buffer to be identified as this packet.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on Little Endian Bitfields. Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse When Data Type is STRING, BLOCK the remaining parameters are: Parameter\tDescription\tRequiredDefault Value\tDefault value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value.\tTrue Description\tDescription for this parameter which must be enclosed with quotes\tFalse Endianness\tIndicates if the data in this command is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_ID_PARAMETER OPCODE 32 UINT 2 2 2 "Opcode identifier" ","version":"Next","tagName":"h3"},{"title":"ARRAY_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#array_parameter","content":" Defines a command parameter in the current command packet that is an array Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Bit Offset\tBit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters.\tTrue Item Bit Size\tBit size of each array item\tTrue Item Data Type\tData Type of each array item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Array Bit Size\tTotal Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value.\tTrue Description\tDescription which must be enclosed with quotes\tFalse Endianness\tIndicates if the data is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: ARRAY_PARAMETER ARRAY 64 64 FLOAT 640 "Array of 10 64bit floats" ","version":"Next","tagName":"h3"},{"title":"APPEND_ARRAY_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#append_array_parameter","content":" Defines a command parameter in the current command packet that is an array Parameter\tDescription\tRequiredName\tName of the parameter. Must be unique within the command.\tTrue Item Bit Size\tBit size of each array item\tTrue Item Data Type\tData Type of each array item Valid Values: INT, UINT, FLOAT, STRING, BLOCK, DERIVED\tTrue Array Bit Size\tTotal Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value.\tTrue Description\tDescription which must be enclosed with quotes\tFalse Endianness\tIndicates if the data is to be sent in Big Endian or Little Endian format Valid Values: BIG_ENDIAN, LITTLE_ENDIAN\tFalse Example Usage: APPEND_ARRAY_PARAMETER ARRAY 64 FLOAT 640 "Array of 10 64bit floats" ","version":"Next","tagName":"h3"},{"title":"SELECT_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#select_parameter","content":" Selects an existing command parameter for editing Must be used in conjunction with SELECT_COMMAND to first select the packet. Typically used to override generated values or make specific changes to commands that only affect a particular instance of a target used multiple times. Parameter\tDescription\tRequiredParameter\tName of the parameter to select for modification\tTrue Example Usage: SELECT_COMMAND INST COLLECT SELECT_PARAMETER DURATION # Add units UNITS Seconds S ","version":"Next","tagName":"h3"},{"title":"DELETE_PARAMETER","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#delete_parameter","content":" (Since 4.4.1) Deletes an existing command parameter from the packet definition Deleting a parameter from the command definition does not remove the defined space for that parameter. Thus unless you redefine a new parameter, there will be a "hole" in the packet where the data is not accessible. You can use SELECT_COMMAND and then PARAMETER to define a new parameter. Parameter\tDescription\tRequiredParameter\tName of the parameter to delete\tTrue Example Usage: SELECT_COMMAND INST COLLECT DELETE_PARAMETER DURATION ","version":"Next","tagName":"h3"},{"title":"HIDDEN","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#hidden","content":" Hides this command from all OpenC3 tools such as Command Sender and Handbook Creator Hidden commands do not appear in the Script Runner popup helper when writing scripts. The command still exists in the system and can be sent by scripts. ","version":"Next","tagName":"h3"},{"title":"DISABLED","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#disabled","content":" Disables this command from being sent Hides the command and also disables it from being sent by scripts. Attempts to send DISABLED commands result in an error message. ","version":"Next","tagName":"h3"},{"title":"DISABLE_MESSAGES","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#disable_messages","content":" Disable the Server from printing cmd(...) messages. Commands are still logged. ","version":"Next","tagName":"h3"},{"title":"META","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#meta-1","content":" Stores metadata for the current command Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files. Parameter\tDescription\tRequiredMeta Name\tName of the metadata to store\tTrue Meta Values\tOne or more values to be stored for this Meta Name\tFalse Example Usage: META FSW_TYPE "struct command" ","version":"Next","tagName":"h3"},{"title":"HAZARDOUS","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#hazardous","content":" Designates the current command as hazardous Sending a hazardous command causes a dialog asking for confirmation before sending the command Parameter\tDescription\tRequiredDescription\tDescription for why the command is hazardous which must be enclosed with quotes\tFalse ","version":"Next","tagName":"h3"},{"title":"ACCESSOR","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#accessor","content":" (Since 5.0.10) Defines the class used to read and write raw values from the packet Defines the class that is used too read raw values from the packet. Defaults to BinaryAccessor. Provided accessors also include JsonAccessor, CborAccessor, HtmlAccessor, and XmlAccessor. Parameter\tDescription\tRequiredAccessor Class Name\tThe name of the accessor class\tTrue Argument\tAdditional argument passed to the accessor class constructor\tFalse ","version":"Next","tagName":"h3"},{"title":"TEMPLATE","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#template","content":" (Since 5.0.10) Defines a template string used to initialize the command before default values are filled in Generally the template string is formatted in JSON or HTML and then values are filled in with command parameters. Must be UTF-8 encoded. Parameter\tDescription\tRequiredTemplate\tThe template string which should be enclosed in quotes\tTrue ","version":"Next","tagName":"h3"},{"title":"TEMPLATE_FILE","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#template_file","content":" (Since 5.0.10) Defines a template file used to initialize the command before default values are filled in Generally the template file is formatted in JSON or HTML and then values are filled in with command parameters. Can be binary or UTF-8. Parameter\tDescription\tRequiredTemplate File Path\tThe relative path to the template file. Filename should generally start with an underscore.\tTrue ","version":"Next","tagName":"h3"},{"title":"RESPONSE","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#response","content":" (Since 5.14.0) Indicates the expected telemetry packet response to this command Parameter\tDescription\tRequiredTarget Name\tTarget Name of telemetry response packet\tTrue Packet Name\tPacket Name of telemetry response packet\tTrue ","version":"Next","tagName":"h3"},{"title":"ERROR_RESPONSE","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#error_response","content":" (Since 5.14.0) Indicates the expected telemetry packet error response to this command Parameter\tDescription\tRequiredTarget Name\tTarget Name of telemetry error response packet\tTrue Packet Name\tPacket Name of telemetry error response packet\tTrue ","version":"Next","tagName":"h3"},{"title":"RELATED_ITEM","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#related_item","content":" (Since 5.14.0) Defines a related telemetry item to this command Parameter\tDescription\tRequiredTarget Name\tTarget Name of related telemetry item\tTrue Packet Name\tPacket Name of related telemetry item\tTrue Item Name\tItem Name of related telemetry item\tTrue ","version":"Next","tagName":"h3"},{"title":"SCREEN","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#screen","content":" (Since 5.14.0) Defines a related telemetry screen to this command Parameter\tDescription\tRequiredTarget Name\tTarget Name of related telemetry screen\tTrue Screen Name\tScreen Name of related telemetry screen\tTrue ","version":"Next","tagName":"h3"},{"title":"VIRTUAL","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#virtual","content":" (Since 5.18.0) Marks this packet as virtual and not participating in identification Used for packet definitions that can be used as structures for items with a given packet. ","version":"Next","tagName":"h3"},{"title":"VALIDATOR","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#validator","content":" (Since 5.19.0) Defines a validator class for a command Validator class is used to validate the command success or failure with both a pre_check and post_check method. Parameter\tDescription\tRequiredClass Filename\tThe filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'command_validator.rb' should contain 'class CommandValidator'.\tTrue Argument\tAdditional argument passed to the validator class constructor\tFalse Ruby Example: VALIDATOR custom_validator.rb Defined in custom_validator.rb: require 'openc3/packets/command_validator' class CustomValidator < OpenC3::CommandValidator def pre_check(packet) if tlm("TGT PKT ITEM") == 0 return [false, "TGT PKT ITEM is 0"] end @cmd_acpt_cnt = tlm("TGT PKT CMD_ACPT_CNT") return [true, nil] end def post_check(packet) wait_check("TGT PKT CMD_ACPT_CNT > #{@cmd_acpt_cnt}", 10) return [true, nil] end end Python Example: VALIDATOR custom_validator.rb Defined in custom_validator.py: class CustomValidator(CommandValidator): def pre_check(self, command): if tlm("TGT PKT ITEM") == 0: return [False, "TGT PKT ITEM is 0"] self.cmd_acpt_cnt = tlm("INST HEALTH_STATUS CMD_ACPT_CNT") return [True, None] def post_check(self, command): wait_check(f"INST HEALTH_STATUS CMD_ACPT_CNT > {self.cmd_acpt_cnt}", 10) return [True, None] ","version":"Next","tagName":"h3"},{"title":"SELECT_COMMAND","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#select_command","content":" Selects an existing command packet for editing Typically used in a separate configuration file from where the original command is defined to override or add to the existing command definition. Must be used in conjunction with SELECT_PARAMETER to change an individual parameter. Parameter\tDescription\tRequiredTarget Name\tName of the target this command is associated with\tTrue Command Name\tName of the command to select\tTrue Example Usage: SELECT_COMMAND INST COLLECT SELECT_PARAMETER DURATION # Add units UNITS Seconds S ","version":"Next","tagName":"h2"},{"title":"Example File","type":1,"pageTitle":"Commands","url":"/docs/configuration/command#example-file","content":" Example File: TARGET/cmd_tlm/cmd.txt COMMAND TARGET COLLECT_DATA BIG_ENDIAN "Commands my target to collect data" PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER" PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE" PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG" ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 100 "CCSDS PRIMARY HEADER APPLICATION ID" PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS" PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT" PARAMETER CCSDSLENGTH 32 16 UINT 4 4 4 "CCSDS PRIMARY HEADER PACKET LENGTH" PARAMETER ANGLE 48 32 FLOAT -180.0 180.0 0.0 "ANGLE OF INSTRUMENT IN DEGREES" POLY_WRITE_CONVERSION 0 0.01745 0 0 PARAMETER MODE 80 8 UINT 0 1 0 "DATA COLLECTION MODE" STATE NORMAL 0 STATE DIAG 1 COMMAND TARGET NOOP BIG_ENDIAN "Do Nothing" PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER" PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE" PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG" ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 101 "CCSDS PRIMARY HEADER APPLICATION ID" PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS" PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT" PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH" PARAMETER DUMMY 48 8 UINT 0 0 0 "DUMMY PARAMETER BECAUSE CCSDS REQUIRES 1 BYTE OF DATA" COMMAND TARGET SETTINGS BIG_ENDIAN "Set the Settings" PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER" PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE" PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG" ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 102 "CCSDS PRIMARY HEADER APPLICATION ID" PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS" PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT" PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH" <% 5.times do |x| %> APPEND_PARAMETER SETTING<%= x %> 16 UINT 0 5 0 "Setting <%= x %>" <% end %> ","version":"Next","tagName":"h2"},{"title":"Contributing","type":0,"sectionRef":"#","url":"/docs/meta/contributing","content":"","keywords":"","version":"Next"},{"title":"Test Dependencies","type":1,"pageTitle":"Contributing","url":"/docs/meta/contributing#test-dependencies","content":" To run the test suite and build the gem you'll need to install COSMOS's dependencies. COSMOS uses Bundler, so a quick run of the bundle command and you're all set! \\$ bundle Before you start, run the tests and make sure that they pass (to confirm your environment is configured properly): \\$ bundle exec rake build spec ","version":"Next","tagName":"h2"},{"title":"Workflow","type":1,"pageTitle":"Contributing","url":"/docs/meta/contributing#workflow","content":" Here's the most direct way to get your work merged into the project: Fork the project.Clone down your fork: git clone git://github.com/<username>/openc3.git Create a topic branch to contain your change: git checkout -b my_awesome_feature Hack away, add tests. Not necessarily in that order.Make sure everything still passes by running bundle exec rake.If necessary, rebase your commits into logical chunks, without errors.Push the branch up: git push origin my_awesome_feature Create a pull request against openc3/cosmos:main and describe what your change does and the why you think it should be merged. Find a problem in the code or documentation? Please create an issue on GitHub describing what we can do to make it better. ","version":"Next","tagName":"h2"},{"title":"Understanding Licenses","type":0,"sectionRef":"#","url":"/docs/meta/licenses","content":"","keywords":"","version":"Next"},{"title":"AGPLv3","type":1,"pageTitle":"Understanding Licenses","url":"/docs/meta/licenses#agplv3","content":" This is our default open source license and the license that most free users use. The AGPLv3 is a modification of the GPLv3 which is what is known as a copy-left license or a viral license. You can read the whole thing here: OpenC3 AGPLv3 Obviously, the actual license text applies, but here is a short summary: The AGPL allows users to use the code however they want: For business, personal, etc., as long as they follow the other terms: Users are anyone who could access the web-app. On the public internet, that is the whole world. On a private network, it is anyone with access to that network. The software is provided as-is, no warranty Users must be given access to all the source code and are also allowed to use it however they want under the same terms of the AGPLv3. This includes any modifications made, anything added, and all plugins. For web applications (like COSMOS), a link must be provided to all of the source code. There are some key implications of the above: You cannot keep anything proprietary from your users. They have the rights to take the code (and configuration) and do anything they want with it. You CANNOT impede these rights or you are violating the AGPLv3 and YOU lose the rights to use our software. You must provide a digital link to all source code for your users, including plugins. All plugins must be licensed in an AGPLv3 compatible fashion. We recommend the MIT license because that allows your plugins to be compatible with the AGPLv3 and our commercial license. You can also use a dual license similar to what we do indicating the AGPLv3 or a purchased OpenC3 Commercial license. The AGPLv3 license is often chosen because it works well for open core products like COSMOS. Competitors cannot take the open source product and license it under different terms. They would be forever locked into the AGPLv3 which is difficult to monetize, because your customers can take any code you provide and publish it on the internet for free use by everyone. As the copyright holder, OpenC3 is able to license the product and derivatives commercially. No-one else can do this. (OpenC3 is also able to license legacy Ball Aerospace COSMOS code under IP agreement) ","version":"Next","tagName":"h2"},{"title":"Evaluation and Education Use Only","type":1,"pageTitle":"Understanding Licenses","url":"/docs/meta/licenses#evaluation-and-education-use-only","content":" This license takes effect as soon as you use any plugin we publish under Evaluation and Education terms. Currently the only plugin we use for this is our CCSDS CFDP plugin: CFDP Plugin You can read the whole license here: # OpenC3 Evaluation and Educational License # # Copyright 2023 OpenC3, Inc. # # This work is licensed for evaluation and educational purposes only. # It may NOT be used for formal development, integration and test, operations # or any other commercial purpose without the purchase of a commercial license # from OpenC3, Inc. # # The above copyright notice and this permission notice shall be included in all copies # or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. This license is pretty straight forward, but the key is you can't use this code for any real work leading to a product (Formal Development, Integration and Test, or Operations) unless you switch to purchasing a commercial license. ","version":"Next","tagName":"h2"},{"title":"Commercial License","type":1,"pageTitle":"Understanding Licenses","url":"/docs/meta/licenses#commercial-license","content":" This license is a signed contract with OpenC3. It allows use of our code for a program under contractual terms where you do not have to follow the AGPLv3. Generally we license to a specific project with terms that allow for unlimited users, and installs as needed by that project. Any code and plugins that you develop under the commercial license can be kept proprietary. These licenses are sold as yearly subscriptions, or as a non-expiring perpetual license. We also offer site licenses, and licenses to support unlimited missions on a government framework architecture. Of course with our commercial license, you also get all the extra functionality of our Enterprise product. ","version":"Next","tagName":"h2"},{"title":"Why you should buy a Commercial License","type":1,"pageTitle":"Understanding Licenses","url":"/docs/meta/licenses#why-you-should-buy-a-commercial-license","content":" You want to save years and tens of millions of dollars developing the same functionality yourself. You want all of the Enterprise functionality of COSMOS Enterprise Edition User AccountsRole Based Access ControlLDAP SupportKubernetes SupportCloud Deployment ConfigurationsThe right to use CFDP and other Enterprise Only pluginsGrafana SupportSupport from the COSMOS DevelopersLots more - See our Enterprise page You don't want to follow the AGPLv3 You want to keep the code and plugins you develop proprietaryYou don't want to publish an accessible link to your source code You want to support the continued development and innovation of the COSMOS product We appreciate all of our commercial customers. You make OpenC3 possible. Thank you. ","version":"Next","tagName":"h2"},{"title":"Philosophy","type":0,"sectionRef":"#","url":"/docs/meta/philosophy","content":"Philosophy COSMOS is a C3 (Command, Control and Communication) system with the following primary goals: Interface with Anything COSMOS should be able to communicate with anything that provides a computer-to-computer interface, regardless of what the interface is. This means that COSMOS adapts to what other systems are doing and evolves over time. It does not publish an API that hardware must adhere to if it wants to communicate with COSMOS. Log Everything All data that flows into and out of COSMOS is logged. This provides history as well as attribution for what happened when and why. Keeping accurate logs is an essential and critical aspect of COSMOS. Open Architecture and Source Nothing about how COSMOS is implemented is meant to be secret or hidden, even in Enterprise Edition. In all editions, the source code for everything in COSMOS is provided and available for users to inspect or modify as needed. Never worry about an unsolvable problem or having to accept some detail that you don't like. This also opens the world to integrate anything they need into COSMOS without restriction or limitation. Be Modular There are infinite number of things for COSMOS to connect to, but it is impossible to ship COSMOS with all the code it would need to talk to everything. For this reason, COSMOS is designed to be modular in all the places that matter. Use Configuration when Possible, and Code When Logic Is Needed Configuration is great for making COSMOS as usable as possible by non-software engineers. It also shows where common patterns exist. However, configuration is horrible when logic or custom math are needed. Empower Developers COSMOS is meant to be easy enough to be used by everyone, not just C2 software experts.","keywords":"","version":"Next"},{"title":"Requirements and Design","type":0,"sectionRef":"#","url":"/docs/getting-started/requirements","content":"","keywords":"","version":"Next"},{"title":"Terminology","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#terminology","content":" The COSMOS system uses several terms that are important to understand. The following table defines these terms. Term\tDefinitionTarget\tA COSMOS target is an embedded system that the COSMOS Command and Telemetry Server connects to using an interface in order to send commands to and/or receive telemetry from. Command\tA packet of information telling a target to perform an action of some sort. Telemetry Packet\tA packet of information providing status from a target. Interface\tA Ruby class that knows how to send commands to and/or receive telemetry from a target. COSMOS comes with interfaces that support TCP/IP, UDP, and serial connections. Custom interfaces are easy to add to the system. Ruby\tThe powerful dynamic programming language used to write the COSMOS applications and libraries as well as COSMOS scripts and test procedures. Configuration Files\tCOSMOS uses simple plain text configuration files to define commands and telemetry packets, and to configure each COSMOS application. These files are easily human readable/editable and machine readable/editable. Packet Log Files\tBinary files containing either logged commands or telemetry packets. Message Log Files\tText files containing messages generated by the system. Tool\tAnother name for a COSMOS application. ","version":"Next","tagName":"h2"},{"title":"Overall Architecture and Context Diagram","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#overall-architecture-and-context-diagram","content":" The following diagram shows the COSMOS 5 architecture. Key aspects of this architecture: COSMOS 5 is a cloud native, containerized, microservice oriented command and control system. All the COSMOS microservices are docker containers which is why Docker is shown containing the entire COSMOS system. The green boxes on the left represent external embedded systems (Targets) which COSMOS connects to. The Redis data store contains the configuration for all the microservices, the current value table, as well as data streams containing decommutated data. The Minio data store contains plugins, targets, configuration data, text logs as well as binary logs of all the raw, decommutated, and reduced data. Users interact with COSMOS from a web browser which routes through the internal Traefik load balancer. COSMOS can connect to many different kinds of targets. The examples include things like Flight software (FSW), Ground Support Equipment (GSE), Labview, and COTS targets such as an Agilent power supply. Any embedded system that provides a communication interface can be connected to COSMOS.COSMOS ships with interfaces for connecting over TCP/IP, UDP, MQTT, and serial connections. This covers most systems, but custom interfaces can also be written to connect to anything.All realtime communication with targets flows through the COSMOS system. This ensures all commands and telemetry are logged.Every tool is configured with plain text configuration files.Program specific tools can be written using the COSMOS libraries that can interact with the realtime command and telemetry streams and can process logged data. ","version":"Next","tagName":"h2"},{"title":"Overall Requirements","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#overall-requirements","content":" Reqt. ID\tDescription\tTest DescriptionCOSMOS-1\tAll COSMOS core functionality shall be containerized.\tVerify COSMOS is running in Docker COSMOS-2\tThe COSMOS user interface shall be accessible from Chromium based web browsers\tOpen COSMOS in Chrome/Edge COSMOS-3\tThe COSMOS user interface shall be accessible from the Firefox web browser\tOpen COSMOS in Firefox COSMOS-4\tCOSMOS shall log all commands sent COSMOS-5\tCOSMOS shall log all telemetry received COSMOS-6\tCOSMOS shall decommutate all telemetry packets received COSMOS-7\tCOSMOS shall support autonomously attempting to connect to targets.\tVerify targets are connected upon starting the CTS. COSMOS-8\tCOSMOS shall time stamp telemetry packets upon receipt.\tVerify logged packets are timestamped. COSMOS-9\tCOSMOS shall time stamp telemetry packets to a resolution of 1 millisecond or better. Note: This requirement only refers to resolution. COSMOS does not run on real-time operating systems and accuracy cannot be guaranteed.\tView time stamps in log. COSMOS-10\tCOSMOS shall time stamp received telemetry with a UTC timestamp.\tVerify logged time stamps are as expected. COSMOS-11\tCOSMOS shall maintain a timestamped log of commands received, limits violations, and errors encountered.\tView COSMOS message log. ","version":"Next","tagName":"h2"},{"title":"Api Requirements","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#api-requirements","content":" Reqt. ID\tDescription\tTest DescriptionAPI-1\tThe COSMOS API shall allow scripted connection and disconnection of interfaces.\tDisconnect and connect an interface from a script. API-2\tThe COSMOS API shall allow scripted connection and disconnection of routers.\tDisconnect and connect a router from a script. API-3\tThe COSMOS API shall allow scripted setting of the current limits set.\tSelect a different limits set from a script. API-4\tThe COSMOS API shall allow commanding of targets\tSend a command API-5\tThe COSMOS API shall allow reading the current value of any telemetry item\tRead a telemetry point API-6\tThe COSMOS API shall allow streaming realtime and logged telemetry packets\tStream telemetry packets API-7\tThe COSMOS API shall allow streaming realtime and logged command packets\tStream command packets API-8\tThe COSMOS API shall allow starting COSMOS scripts\tStart a script using the API ","version":"Next","tagName":"h2"},{"title":"Command and Telemetry Server","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#command-and-telemetry-server","content":" The Command and Telemetry server provides status on the the overall COSMOS installation for a specific scope. Reqt. ID\tDescription\tTest DescriptionCTS-1\tThe Command and Telemetry Server shall display a list of all interfaces.\tView the Interfaces tab. CTS-2\tThe Command and Telemetry Server shall allow manual connection and disconnection of interfaces.\tPress a GUI button to disconnect and connect an interface. CTS-3\tThe Command and Telemetry Server shall display a list of all targets.\tView the Targets tab. CTS-4\tThe Command and Telemetry Server shall display a list of known commands.\tView the Cmd Packets tab. CTS-5\tThe Command and Telemetry Server shall display raw command data for the most recent command received.\tView the Cmd Packets tab and click the View Raw button for a command. CTS-6\tThe Command and Telemetry Server shall display a list of known telemetry packets.\tView the Tlm Packets tab. CTS-7\tThe Command and Telemetry Server shall display raw telemetry packet data for the most recent telemetry packet received.\tView the Tlm Packets tab and click the View Raw button for a telemetry packet. CTS-8\tThe Command and Telemetry Server shall display a list of all routers.\tView the Routers tab. CTS-9\tThe Command and Telemetry Server shall allow manual connection and disconnection of routers.\tPress a GUI button to disconnect and connect a router. CTS-10\tThe Command and Telemetry Server shall allow manually setting the current limits set.\tSelect a different limits set from the combobox. CTS-11\tThe Command and Telemetry Server shall support opening telemetry packets in Packet Viewer.\tOn the Tlm Packets tab click View in Packet Viewer for a telemetry packet. CTS-12\tThe Command and Telemetry Server shall display time stamps in local time.\tView time stamps in log. ","version":"Next","tagName":"h2"},{"title":"Limits Monitor","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#limits-monitor","content":" Limits Monitor displays all telemetry points that are currently out of limits and also shows any telemetry points that have gone out of limits since Limits Monitor was started. Reqt. ID\tDescription\tTest DescriptionLM-1\tLimits Monitor shall display all telemetry points currently out of limits.\tView displayed telemetry points. LM-2\tLimits Monitor shall support ignoring telemetry points.\tClick ignore on a telemetry point. LM-3\tLimits Monitor shall keep a displayed log of limits violations.\tView the log tab. LM-4\tLimits Monitor shall continue displaying a telemetry point that temporarily went out of limits.\tWatch until a telemetry points returns to green. LM-5\tLimits Monitor shall support saving its configuration.\tSave the configuration. LM-6\tLimits Monitor shall support loading its configuration.\tLoad the configuration. ","version":"Next","tagName":"h2"},{"title":"Command Sender","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#command-sender","content":" Command Sender provides an easy method to send single commands to targets. The graphical user interface provides simple dropdowns to quickly select the desired command to send organized by target name and command name. After the user has selected the command, they then fill in the desired command parameters and click send to send the command to the target. Reqt. ID\tDescription\tTest DescriptionCMD-1\tCommand Sender shall allow selection of a command by target name and packet name.\tSelect a specific command by target name and packet name in the drop down menus. CMD-2\tCommand Sender shall allow sending the selected command.\tSend the selected command by pressing the Send button. CMD-3\tCommand Sender shall display non-ignored parameters for the selected command.\tSelect a specific command and verify the expected parameters are shown. CMD-4\tCommand Sender shall provide a mechanism to select state values for command parameters with states.\tSelect a specific state value for a specific command with states. CMD-5\tCommand Sender shall allow sending a manually entered value for a command parameter with states.\tManually enter a value for a specific command with states. CMD-6\tCommand Sender shall refuse to send commands if required parameters are not provided.\tAttempt to send a command with a required parameter not filled out. CMD-7\tCommand Sender shall support sending commands while ignoring range checking.\tEnter Ignore Range Checking mode and then send a command with an out of range parameter. CMD-8\tCommand Sender shall optionally display state values in hex.\tEnter "Display State Values in Hex" mode and verify state values are displayed as hex. CMD-9\tCommand Sender shall optionally display ignored command parameters.\tEnter "Show Ignored Parameters" mode and verify ignored parameters are displayed. CMD-10\tCommand Sender shall respect hazardous commands and notify the user before proceeding.\tSend a hazardous command and verify a dialog box appears before the command is sent. Verify both accepting the dialog and declining to send. CMD-11\tCommand Sender shall keep a command history of each command sent.\tSend a command and verify that it shows up in the command history box. CMD-12\tCommand Sender shall allow resending of any command in the command history.\tResend one of the commands in the command history box. ","version":"Next","tagName":"h2"},{"title":"Script Runner","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#script-runner","content":" Script Runner provides a visual interface for editing and executing scripts/procedures. A full featured text editor provides syntax highlighting and code completion while developing scripts. During script execution, the currently executing line is highlighted and any logged messages are highlighted to the user. If any failure occurs, the script is paused and the user alerted. The user can then decide whether to stop the script, or ignore the failure and continue. The user can also retry the failed lines, or other nearby lines before proceeding. Script Runner now also provides a structured methodology for designing system level scripting that mirrors the very successful pattern used in software unit tests (previously implemented in the Test Runner tool). System level tests/procedures are built up of cases that are organized into groups. For example, you might have one group that verified all of the requirements associated with a particular mechanism. Ideally you would break this down into individual cases for different scenarios. One perhaps for opening a shutter, another for closing it, etc. Cases are ideally small and independent tasks. A number of these groups are then combined into an overall suite which would be run to execute a major test such as EMI, or software FQT. Reqt. ID\tDescription\tTest DescriptionSR-1\tScript Runner shall provide a text editor for developing test scripts.\tOpen Script Runner and create a simple test script. Perform all standard file operations including New, Open, Reload, Close, Save, and Save As. Perform all standard editing operations such as Cut, Copy, Paste, Undo, Redo, Select All, and Comment/Uncomment lines. SR-2\tScript Runner shall provide search and replace functionality.\tPerform all standard search and replace functionality, including search, replace, find next, and find previous. SR-3\tScript Runner shall provide code completion for cmd(), tlm(), and wait_check() COSMOS API methods. Note: Other methods may also be supported.\tCreate a script and exercise code completion on the mentioned keywords. SR-4\tScript Runner shall execute Ruby-based COSMOS scripts.\tPress start and execute a script. SR-5\tScript Runner shall highlight the currently executing line of the script.\tVerify that lines are highlighted as a test script executes. SR-6\tScript Runner shall allow pausing an executing script.\tPress pause button and verify script is paused. Press start to resume. SR-7\tScript Runner shall allow stopping an executing script.\tPress stop and verify script stops. SR-8\tScript Runner shall pause an executing script upon the occurrence of an error.\tCreate a script with a statement that is guaranteed to fail and verify that the script is paused. SR-9\tScript Runner shall log commands sent.\tExecute a script that sends a command and verify it is logged. SR-10\tScript Runner shall log text written to STDOUT. Note: Typically through the puts method.\tExecute a script that uses puts to write a message and verify it is logged. SR-11\tScript Runner shall log wait times.\tExecute a script that includes a wait method and verify wait time is logged. SR-12\tScript Runner shall log errors that occur while the script is executing.\tCreate a script with a check statement that is guaranteed to fail and verify it is logged. SR-13\tScript Runner shall log check statement success and failure.\tCreate a script with a check statement that is guaranteed to fail and one that is guaranteed to succeed. Verify both the success and failure are logged. SR-14\tScript Runner shall support executing selected lines.\tSelect a set of lines and execute them using Script->Execute Selected Lines. SR-15\tScript Runner shall support executing selected lines while paused.\tSelect a set of lines and execute them from the right-click context menu. SR-16\tScript Runner shall support starting a script from any line.\tPlace the mouse cursor at the desired first line and then select Script->Execute From Cursor. SR-17\tScript Runner shall support a mnemonic checking function.\tSelect Script->Mnemonic Check. SR-18\tScript Runner shall support a syntax checking function.\tSelect Script->Ruby Syntax Check. SR-19\tScript Runner shall support viewing the script instrumentation.\tSelect Script->View Instrumented Script. SR-20\tScript Runner shall support an disconnected mode to allow for executing scripts without a connection to the Command and Telemetry Server.\tSelect Script->Toggle Disconnect. Execute a script with commands and check statements and verify that it runs to completion. SR-21\tScript Runner shall support a Debug terminal to aid in debugging scripts.\tSelect Script->Toggle Debug. SR-22\tScript Runner shall support a step mode where the script will stop and wait for use interaction after each line.\tPress Step to progress through the script. SR-23\tScript Runner shall support breakpoint functionality.\tCreate a breakpoint then execute the script and verify it stops at the specified line. SR-25\tScript Runner Suite Mode shall support executing individual test suites.\tExecute an individual test suite. SR-26\tScript Runner Suite Mode shall support executing individual test groups.\tExecute an individual test group. SR-27\tScript Runner Suite Mode shall support executing individual test cases.\tExecute an individual test case. SR-28\tScript Runner Suite Mode shall support executing test group setup and teardown methods individually.\tExecute a test group setup. Execute a test group teardown. SR-29\tScript Runner Suite Mode shall support executing test suite setup and teardown methods individually.\tExecute a test suite setup. Execute a test suite teardown. SR-30\tScript Runner Suite Mode shall create a report after executing any suite test.\tVerify a report is generated after executing a suite. SR-31\tScript Runner Suite Mode shall support pausing when an error occurs.\tExecute a test script with the pause on error box checked and without. SR-32\tScript Runner Suite Mode shall support allowing the user to proceed on an error.\tExecute a test script with the Allow go/retry on error box checked and without. SR-33\tScript Runner Suite Mode shall support aborting execution on an error.\tExecute a test script with the abort on error box checked and without. SR-34\tScript Runner Suite Mode shall support looping a test.\tExecute a test script with the loop testing box checked and without. SR-35\tScript Runner Suite Mode shall support breaking the looping of a test on error.\tExecute a test script with the break loop on error box checked and without. SR-36\tScript Runner Suite Mode shall support a user readable flag indicating that loop testing is occurring.\tExecute a test script that checks the $loop_testing variable while looping and again while not looping. SR-37\tScript Runner Suite Mode shall support a user readable flag indicating manual operations are desired.\tExecute a test script with the manual box checked and without. ","version":"Next","tagName":"h2"},{"title":"Packet Viewer","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#packet-viewer","content":" Packet Viewer provides a simple tool to view the realtime contents of any telemetry packet defined in the system in a tabular, key-value format. Reqt. ID\tDescription\tTest DescriptionPV-1\tPacket Viewer shall allow selection of a telemetry packet by target name and packet name.\tSelect a specific telemetry packet by target name and packet name in the drop down menus. PV-2\tPacket Viewer shall display the contents of the selected telemetry packet.\tEnsure all items of the selected telemetry packet are displayed and updating. PV-3\tPacket Viewer shall provide a mechanism to get detailed information on a telemetry item.\tRight click on a telemetry item and select "Details" from the context menu. PV-4\tPacket Viewer shall provide a mechanism to view a graph of any telemetry item.\tRight click on a telemetry item and select "Graph" from the context menu. PV-5\tPacket Viewer shall color telemetry values based upon limits state.\tView a packet with items containing limits and verify they are colored. PV-6\tPacket Viewer shall support a configurable polling rate.\tSelect File->Options and change the polling rate. PV-7\tPacket Viewer shall support a color-blind mode to allow distinguishing limits states for those who are color blind.\tSelect View->Color Blind Mode and verify that items with limits are also displayed with a textual indication of limits state color. PV-8\tPacket Viewer shall support displaying telemetry in each of the four COSMOS value types (raw, converted, formatted, and formatted with units)\tIn the View menu, select each of the four value types and verify values are displayed accordingly. ","version":"Next","tagName":"h2"},{"title":"Telemetry Viewer","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#telemetry-viewer","content":" Telemetry Viewer provides a way to organize telemetry points into custom "screens" that allow for the creation of unique and organized views of telemetry data. Screens are made up of widgets or small GUI components that display telemetry in unique ways. Reqt. ID\tDescription\tTest DescriptionTV-1\tTelemetry Viewer shall display user-defined telemetry screens.\tOpen a telemetry TV-2\tTelemetry Viewer shall display realtime data.\tVerify telemetry screens show realtime data. TV-3\tTelemetry Viewer shall support saving open telemetry screens and their positions.\tOpen three telemetry screens and then select File->Save Configuration. ","version":"Next","tagName":"h2"},{"title":"Telemetry Grapher","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#telemetry-grapher","content":" Telemetry Grapher performs graphing of telemetry points in both realtime and log file playback. Reqt. ID\tDescription\tTest DescriptionTG-1\tTelemetry Grapher shall provide line graphs of telemetry points.\tAdd several housekeeping data objects to a plot. TG-2\tTelemetry Grapher shall support realtime graphing of telemetry.\tPress Start to start realtime graphing. TG-3\tTelemetry Grapher shall support graphing data from logged telemetry.\tSelect the menu option to graph data from a logged data TG-4\tTelemetry Grapher shall support multiple plots per browser tab.\tAdd multiple plots. TG-5\tTelemetry Grapher shall support multiple telemetry points per plot.\tAdd multiple data objects to one plot. TG-6\tTelemetry Grapher shall support saving a variable number of data points.\tEdit Points Saved. TG-7\tTelemetry Grapher shall support graphing a variable duration of time.\tEdit Seconds Plotted. TG-8\tTelemetry Grapher shall support graphing a variable number of data points.\tEdit Points Plotted. TG-9\tTelemetry Grapher shall support saving its configuration.\tSave the current configuration. TG-10\tTelemetry Grapher shall support loading its configuration.\tLoad the previously saved configuration. ","version":"Next","tagName":"h2"},{"title":"Data Extractor","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#data-extractor","content":" Data Extractor processes logged data and extracts data into a CSV format for analysis in Excel or other tools. Reqt. ID\tDescription\tTest DescriptionDE-1\tData Extractor shall support adding individual telemetry points.\tAdd an individual telemetry point. DE-2\tData Extractor shall support adding entire telemetry packets.\tAdd an entire packet. DE-3\tData Extractor shall support adding entire telemetry targets.\tAdd all packets for a target. DE-4\tData Extractor shall support selecting the value type to extract for each telemetry point (RAW, CONVERTED, FORMATTED, WITH_UNITS)\tClick an item and change the value type. DE-5\tData Extractor shall support saving configurations.\tSelect File->Save Config DE-6\tData Extractor shall support loading configurations.\tSelect File->Load Config DE-7\tData Extractor shall support deleting items\tSelect an Item and press delete ","version":"Next","tagName":"h2"},{"title":"Data Viewer","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#data-viewer","content":" Data Viewer provides for textual display of telemetry packets where other display methods are not a good fit. It is especially useful for memory dumps and for log message type data display. Reqt. ID\tDescription\tTest DescriptionDV-1\tData Viewer shall support realtime processing of telemetry packets.\tPress Start to start realtime processing. DV-2\tData Viewer shall support logged playback of telemetry packets.\tSelect a time range to playback. DV-3\tData Viewer shall support textual display of telemetry packets.\tView the display of data. DV-4\tData Viewer shall support multiple tabs for data display.\tSwitch between several tabs of data. DV-5\tData Viewer shall support deleting tabs.\tDelete a tab. ","version":"Next","tagName":"h2"},{"title":"Calendar","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#calendar","content":" The Calendar tool provides a user interface and API for initiating scheduled actions in COSMOS Reqt. ID\tDescription\tTest DescriptionTL-1\tCalendar shall allow creating new timelines\tClick the button and create a new timeline TL-2\tCalendar shall allow scheduling commands for future execection\tAdd a command to a timeline TL-3\tCalendar shall allow scheduling scripts for future execution\tAdd a script to a timeline TL-4\tCalendar shall allow for reserving a resource\tAdd a reservation to a timeline TL-5\tCalendar shall track success or failure of commands\tLook at status from a completed command TL-6\tCalendar shall track success or failure of scripts\tLook at status from a completed script TL-7\tCalendar shall allow deleting activities from timelines\tDelete a preexisting item from a timeline TL-8\tCalendar shall allow deleting timelines\tDelete a timeline ","version":"Next","tagName":"h2"},{"title":"Admin","type":1,"pageTitle":"Requirements and Design","url":"/docs/getting-started/requirements#admin","content":" The Admin tool provides administrative functionality including managing plugins for the COSMOS system Reqt. ID\tDescription\tTest DescriptionAD-1\tThe Admin Tool shall allow installing plugins\tUpload and Install a Plugin AD-2\tThe Admin Tool shall support upgrading plugins\tUpgrade an installed plugin AD-3\tThe Admin Tool shall support uninstalling plugins\tUninstall a plugin AD-4\tThe Admin Tool shall display information on installed plugins\tView info on Interfaces, Microservices, etc AD-5\tThe Admin Tool shall support editing microservices\tEdit the settings for a microservice AD-6\tThe Admin Tool shall support discovery of plugins\tDiscover and download a plugin AD-7\tThe Admin Tool shall support adding links to external tools\tAdd a link to Google AD-8\tThe Admin Tool shall support reordering tools\tReorder tools on the tools tab AD-9\tThe Admin Tool shall support configuring a classification bar\tAdd a classification bar on the settings tab ","version":"Next","tagName":"h2"},{"title":"XTCE Support","type":0,"sectionRef":"#","url":"/docs/meta/xtce","content":"","keywords":"","version":"Next"},{"title":"Running COSMOS using an .xtce definition file","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#running-cosmos-using-an-xtce-definition-file","content":" A single .xtce file containing the command and telemetry definitions for a target can be used in place of the normal COSMOS command and telemetry definition files. Simply place the target's .xtce file in the target's cmd_tlm folder and COSMOS will use it for the command and telemetry definitions. ","version":"Next","tagName":"h2"},{"title":"Converting a .xtce file into a COSMOS configuration","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#converting-a-xtce-file-into-a-cosmos-configuration","content":" Use the following command to convert a .xtce file into COSMOS configuration files. The converted configuration files will be placed into a target folder in the given output directory. openc3.bat cli xtce_converter --import <xtce_filename> --output <output_dir> ","version":"Next","tagName":"h2"},{"title":"Converting a COSMOS Configuration to XTCE","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#converting-a-cosmos-configuration-to-xtce","content":" Use the following command to convert your openc3 plugin into .xtce files, one per target. The converted .xtce files will be placed into a target folder in the given output directory. openc3.bat cli xtce_converter --plugin <plugin.gem> --output <output_dir> ","version":"Next","tagName":"h2"},{"title":"High-level Overview of Current Support","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#high-level-overview-of-current-support","content":" Integer, Float, Enumerated, String, and Binary Parameter/Argument Types are SupportedAll DataEncodings are supportedTelemetry and Commands are SupportedPacket Identification is supportedStates are supportedUnits are supportedPolynomialCalibrators are supportedOnly one SpaceSystem per .xtce filePackets should not have gaps between items ","version":"Next","tagName":"h2"},{"title":"Supported Elements and Attributes","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#supported-elements-and-attributes","content":" The following elements and associated attributes are currently supported. SpaceSystemTelemetryMetaDataCommandMetaDataParameterTypeSetEnumerationListParameterSetContainerSetEntryListDefaultCalibratorDefaultAlarmRestrictionCriteriaComparisonListMetaCommandSetDefaultCalibratorArgumentTypeSetArgumentListArgumentAssignmentListEnumeratedParameterTypeEnumeratedArgumentTypeIntegerParameterTypeIntegerArgumentTypeFloatParameterTypeFloatArgumentTypeStringParameterTypeStringArgumentTypeBinaryParameterTypeBinaryArgumentTypeIntegerDataEncodingFloatDataEncodingStringDataEncodingBinaryDataEncoding'SizeInBitsFixedValueUnitSetUnitPolynomialCalibratorTermStaticAlarmRangesWarningRangeCriticalRangeValidRangeEnumerationParameterArgumentParameterPropertiesSequenceContainerBaseContainerLongDescriptionParameterRefEntryArgumentRefEntryBaseMetaCommandComparisonMetaCommandBaseMetaCommandCommandContainerArgumentAssignment ","version":"Next","tagName":"h2"},{"title":"Ignored Elements","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#ignored-elements","content":" The following elements are simply ignored by COSMOS: HeaderAliasSetAlias ","version":"Next","tagName":"h2"},{"title":"Unsupported Elements","type":1,"pageTitle":"XTCE Support","url":"/docs/meta/xtce#unsupported-elements","content":" Any elements not listed above are currently unsupported. Near term support for the following elements and features are planned and priority will be determined by user requests. SplineCalibratorAlternate methods of specifying offsets into containersOutput to the XUSP standardAdditional Data TypesContainer References If there is a particular element or feature you need supported please submit a ticket on Github. ","version":"Next","tagName":"h2"},{"title":"OpenC3, Inc. Privacy Policy","type":0,"sectionRef":"#","url":"/docs/privacy","content":"","keywords":"","version":"Next"},{"title":"Our Commitment","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#our-commitment","content":" • Your information will not be shared, rented or sold to any third party. • We use state-of-the-art security measures to protect your information from unauthorized users. • We give you the possibility to control the information that you shared with us (opt-out) OpenC3, Inc. is committed to processing data in accordance with its responsibilities under the GDPR. Article 5 of the GDPR requires that personal data shall be: a. processed lawfully, fairly and in a transparent manner in relation to individuals; b. collected for specified, explicit and legitimate purposes and not further processed in a manner that is incompatible with those purposes; further processing for archiving purposes in the public interest, scientific or historical research purposes or statistical purposes shall not be considered to be incompatible with the initial purposes; c. adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed; d. accurate and, where necessary, kept up to date; every reasonable step must be taken to ensure that personal data that are inaccurate, having regard to the purposes for which they are processed, are erased or rectified without delay; e. kept in a form which permits identification of data subjects for no longer than is necessary for the purposes for which the personal data are processed; personal data may be stored for longer periods insofar as the personal data will be processed solely for archiving purposes in the public interest, scientific or historical research purposes or statistical purposes subject to implementation of the appropriate technical and organisational measures required by the GDPR in order to safeguard the rights and freedoms of individuals; and f. processed in a manner that ensures appropriate security of the personal data, including protection against unauthorised or unlawful processing and against accidental loss, destruction or damage, using appropriate technical or organisational measures.” ","version":"Next","tagName":"h2"},{"title":"1. Notice","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#1-notice","content":" We will clearly inform you when information that personally identifies you ("personal information") is asked for and you will have the choice to provide it or not. Generally, this information is requested when you subscribe to product updates, newsletters or other online services. ","version":"Next","tagName":"h2"},{"title":"2. Usage","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#2-usage","content":" We use your personal information for the following purposes: • To provide you information that will allow you to use our services • To automatically customize your documents with your information • To alert you of software upgrades, updates, discounts or other services from OpenC3, Inc. We collect your email when you subscribe to our services or newsletter in order to send you informational communications about OpenC3 Inc's products, such as their purpose and the best use you can make of them. We also collect your email to send you our promotional offers. We may also collect your name, language, currency, operating system, document searched and country information for a better experience with our products/services. When you place your order with us, we collect your email in order to communicate with you. We also collect your phone number in order to contact you in case these emails bounce back because of a typo in your email address and if we cannot figure out what the correct email address is. We also contact the phone number that is provided if we suspect that the cardholder’s credit card information has been compromised, i.e used in a fraudulent way. We also use our clients’ email in order to notify of the release of updated versions of the software, new services or promotional offers. ","version":"Next","tagName":"h2"},{"title":"3. Consent","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#3-consent","content":" When you provide your personal information, you consent that it can be used for the above purposes and that OpenC3, Inc. is an authorized holder of such information. If you choose not to register or provide personal information, you can still use our website but you will not be able to receive additional services or access certain areas that require registration. When you activate your account, you are providing your consent to occasionally receive information from us. In each communication from us you will have the opportunity to unsubscribe from further communications; alternatively, you may contact us to express your choices at the address provided at the bottom of this page. ","version":"Next","tagName":"h2"},{"title":"4. Access to your information","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#4-access-to-your-information","content":" You are entitled to review the personal information you have provided us and ensure that it is accurate and current at all times. To review or update this information simply request that we send you this information. ","version":"Next","tagName":"h2"},{"title":"5. Security of information","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#5-security-of-information","content":" OpenC3, Inc. is strongly committed to protecting your information and ensuring that your choices are honored. We have taken strong security measures to protect your data from loss, misuse, unauthorized access, disclosure, alteration, or destruction. All sensitive data is stored behind multiple firewalls on secure servers with restricted employee access. We guarantee that all e-commerce transactions follow the latest security measures and use the best available technologies. Secure Sockets Layer (SSL) technology is employed when you place online orders or transmit sensitive information. SSL is one of the safest methods of passing information over the Internet. ","version":"Next","tagName":"h2"},{"title":"6. Retention of information","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#6-retention-of-information","content":" We retain information as long as it is necessary to provide the services requested by you and others, subject to any legal obligations to further retain such information. Information associated with your account will generally be kept until it is no longer necessary to provide the services or until you ask us to delete it or your account is deleted whichever comes first. Additionally, we may retain information from deleted accounts to comply with the law, prevent fraud, resolve disputes, troubleshoot problems, assist with investigations, enforce the Terms of Use, and take other actions permitted by law. The information we retain will be handled in accordance with this Privacy Policy. Finally, your data could also be stored for sales statistical purposes. ","version":"Next","tagName":"h2"},{"title":"7. EU and EEA Users’ Rights","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#7-eu-and-eea-users-rights","content":" If you are habitually located in the European Union or European Economic Area, you have the right to access, rectify, download or erase your information, as well as the right to restrict and object to certain processing of your information. While some of these rights apply generally, certain rights apply only in certain limited circumstances. We describe these rights below: You have the right to access your personal data and, if necessary, have it amended or deleted or restricted. In certain instances, you may have the right to the portability of your data. You can also ask us to not send marketing communications and not to use your personal data when we carry out profiling for direct marketing purposes. You can opt out of receiving email newsletters and other marketing communications by following the opt-out instructions provided to you in those emails. Transactional account messages will be unaffected if you opt-out from marketing communications. ","version":"Next","tagName":"h2"},{"title":"8. What we do with the Information you share","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#8-what-we-do-with-the-information-you-share","content":" Your information is never shared outside the company without your permission. Inside the company, data is stored behind multiple firewalls on secure servers with restricted user access. When you register to our website, you are asked to provide your contact information, including a valid email address. We use this information to send you updates about order confirmations and information about our services. When you order from us, we ask for your credit card number and billing address. We use this information only to bill you for the product(s) you ordered at that time. We may on occasion require the help of other companies to provide limited services on our behalf, such as packaging, shipping and delivery, customer support and processing event registrations. We will only provide such companies with the information required for them to perform these services; these service providers are bound by strict privacy policies and are prohibited from using your information for any other purpose. In very rare instances OpenC3, Inc. may disclose your personal information, without notice, only if required to do so by law or in the good faith belief that such action is necessary to: (a) conform to the edicts of the law or comply with legal process served on OpenC3, Inc. or the site; (b) protect and defend the rights or property of OpenC3, Inc. and its family of websites and properties; and (c) act in urgent circumstances to protect the personal safety of users of OpenC3, Inc., its websites, or the public. ","version":"Next","tagName":"h2"},{"title":"9. How to opt-out","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#9-how-to-opt-out","content":" We provide users with the opportunity to opt-out from receiving updates on our products, newsletters and other communications from us. You can opt-out by clicking on the link provided in our electronic mailings or by contacting us at the address at the bottom of this page. ","version":"Next","tagName":"h2"},{"title":"10. Does OpenC3 Inc's privacy policy apply to linked websites?","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#10-does-openc3-incs-privacy-policy-apply-to-linked-websites","content":" Our Privacy Policy applies solely to information collected on our website or through interactions with our company. The Site contains links to web sites of third parties. OpenC3, Inc. is not responsible for the actions of these third parties, including their privacy practices and any content posted on their web sites. We encourage you to review their privacy policies to learn more about what, why and how they collect and use personal information. OpenC3, Inc. adheres to industry recognized standards to secure any personal information in our possession, and to secure it from unauthorized access and tampering. However, as is true with all online actions, it is possible that third parties may unlawfully intercept transmissions of personal information, or other users of the Site may misuse or abuse your personal information that they may collect from the Site. ","version":"Next","tagName":"h2"},{"title":"11. Changes to this policy","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#11-changes-to-this-policy","content":" If we make changes to our Privacy Policy, we will post these changes here so that you are always aware of what information we collect, how we use it and under what circumstances, if any, we disclose it. If at any point we decide to use your information in a manner different from that stated at the time it was collected, we will notify you by email. ","version":"Next","tagName":"h2"},{"title":"12. Enforcement of policy","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#12-enforcement-of-policy","content":" If for some reason you believe OpenC3, Inc. has not adhered to these principles, please notify us and we will do our best to promptly make corrections. ","version":"Next","tagName":"h2"},{"title":"13. Questions or comments","type":1,"pageTitle":"OpenC3, Inc. Privacy Policy","url":"/docs/privacy#13-questions-or-comments","content":" If you have questions or comments about this privacy policy, please email us at: support@openc3.com For additional information about how to contact OpenC3, Inc. please visit our help page. Dated: August 11th, 2022 ","version":"Next","tagName":"h2"},{"title":"Autonomic (Enterprise)","type":0,"sectionRef":"#","url":"/docs/tools/autonomic","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Autonomic (Enterprise)","url":"/docs/tools/autonomic#introduction","content":" Autonomic allows for the automated execution of commands and scripts based on user-defined rules. ","version":"Next","tagName":"h2"},{"title":"Overview","type":1,"pageTitle":"Autonomic (Enterprise)","url":"/docs/tools/autonomic#overview","content":" Autonomic operates with some basic building blocks: Trigger Groups, Triggers, and Reactions. Triggers are simply logical blocks which evaluate true or false. Reactions can be linked to one or many Triggers and specify an action to perform. Together they allow for an action to be taken based on anything going on in your system. ","version":"Next","tagName":"h3"},{"title":"TriggerGroups","type":1,"pageTitle":"Autonomic (Enterprise)","url":"/docs/tools/autonomic#triggergroups","content":" Triggers are organized into groups, these groups are both for organization and to ensure that we can scale. It also allows triggers to be evaluated independently and simultaneously and can be useful for overlapping or high priority triggers. However, each trigger group spawns system resources so they should only be created as needed. ","version":"Next","tagName":"h3"},{"title":"Triggers","type":1,"pageTitle":"Autonomic (Enterprise)","url":"/docs/tools/autonomic#triggers","content":" Triggers are logical components that are evaluated to true or false. Creating a trigger is like specifying an equation to evaluate. The trigger creation dialog specifies the Trigger Group which owns the trigger and the "left operand". This can be a telemetry item or an existing trigger. Once you've chosen the "left operand" you need to choose the operator. Finally you choose the "right operand" which in this case is a simple value. After the trigger is created it is displayed in Autonomic and waits to be activated by the given logic. Active triggers are highlighted in the list. Triggers can also be manually disabled and enabled by clicking the plug icon. Note in the above screenshot the Events which track everything about the trigger. ","version":"Next","tagName":"h3"},{"title":"Reactions","type":1,"pageTitle":"Autonomic (Enterprise)","url":"/docs/tools/autonomic#reactions","content":" Reactions wait for triggers to be evaluated to true and perform actions such as sending a command or running a script. Reactions can not exist without a corresponding trigger. The reaction creation dialog specifies whether to treat the trigger as an Edge or Level. It then allows you to select which trigger(s) the reaction will react to. Selecting multiple triggers allows any of the triggers to trigger the reaction (Note: Creating a reaction which responds to Trigger A AND Trigger B is done by creating additional triggers). After the triggers are specified, the dialog prompts for the actions to take. You can either send a command, run a script, or simply push a notification. Commands and scripts can also optionally push a notification. In this example a script is specified with a notification at the WARN level. Spawning Scripts Be aware of how and when you spawn scripts and whether they are running to completion. Spawning a faulty script can lead to many unfinished scripts consuming resources. Finally the snooze setting is specified. Snooze is the number of seconds after the reaction runs before the reaction will be allowed to run again. This is especially important in Level triggers where if the trigger remains active the reaction can run continuously. Once the reaction is created it is listed in the interface. When the reaction runs the "State" changes to the snooze icon and the "Snooze Until" is updated to indicate the reaction is waiting before being allowed to run again. ","version":"Next","tagName":"h3"},{"title":"Bucket Explorer","type":0,"sectionRef":"#","url":"/docs/tools/bucket-explorer","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Bucket Explorer","url":"/docs/tools/bucket-explorer#introduction","content":" Bucket Explorer is a file browser to the COSMOS backend bucket storage system. It allows you to view files in an intuitive file browser hierarchy and download them. Bucket Explorer works both with local installations of COSMOS as well as cloud deployments which utilize cloud storage such as AWS S3 and GCP Cloud Storage. ","version":"Next","tagName":"h2"},{"title":"Browsing Files","type":1,"pageTitle":"Bucket Explorer","url":"/docs/tools/bucket-explorer#browsing-files","content":" At the top are the three standard COSMOS buckets: config, logs, and tools. Each bucket contains top level folders named after the scope. In the Open Source edition the only scope is DEFAULT. The config bucket holds the COSMOS configuration which is populated as plugins are installed. The logs bucket holds the COSMOS logs which are generated by the various COSMOS microservices (See Logging for more info). These logs are gzipped to save storage space. The tools bucket holds the source code for the built-in COSMOS tools as well as user created tools installed as plugins. Note that the search box only searches the current screen worth of files, e.g. it does not search the entire bucket. Tools as Static Website Using bucket storage allows COSMOS to directly serve the tools as a static website and thus it must be a public bucket in cloud technology like S3 ","version":"Next","tagName":"h2"},{"title":"Upload","type":1,"pageTitle":"Bucket Explorer","url":"/docs/tools/bucket-explorer#upload","content":" Click the Upload icon to bring up a file browser to select a file to upload into the current bucket and path. Note that in COSMOS Enterprise you can only upload files to the config/DEFAULT/targets_modified folder unless you're an Admin. ","version":"Next","tagName":"h3"},{"title":"Download","type":1,"pageTitle":"Bucket Explorer","url":"/docs/tools/bucket-explorer#download","content":" Click the Download icon to download any of the individual files from any bucket and path. ","version":"Next","tagName":"h3"},{"title":"Delete","type":1,"pageTitle":"Bucket Explorer","url":"/docs/tools/bucket-explorer#delete","content":" Click the Trash icon to delete an individual file. Note that in COSMOS Enterprise you can only delete files in the config/DEFAULT/targets_modified folder unless you're an Admin. ","version":"Next","tagName":"h3"},{"title":"Command Sender","type":0,"sectionRef":"#","url":"/docs/tools/cmd-sender","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Command Sender","url":"/docs/tools/cmd-sender#introduction","content":" Command Sender provides the ability to send any command defined by COSMOS. Commands are selected using the Target and Packet drop down fields which populate the command parameter (if any). A command history is stored which is also editable. Commands in the command history can be re-executed by pressing Enter. ","version":"Next","tagName":"h2"},{"title":"Command Sender Menus","type":1,"pageTitle":"Command Sender","url":"/docs/tools/cmd-sender#command-sender-menus","content":" ","version":"Next","tagName":"h2"},{"title":"Mode Menu Items","type":1,"pageTitle":"Command Sender","url":"/docs/tools/cmd-sender#mode-menu-items","content":" Ignores parameter range checkingDisplays parameter state values in hexShows ignored parametersDisables all parameter conversions ","version":"Next","tagName":"h3"},{"title":"Sending Commands","type":1,"pageTitle":"Command Sender","url":"/docs/tools/cmd-sender#sending-commands","content":" Select a command by first selecting the target from the Select Target drop down. Changing the target automatically updates the Select Packet options to only display commands from that target. If the command has parameters a table is generated with all the parameters. Clicking on a parameter with States (like TYPE in the above example) brings up a drop down to select a state. Selecting a state populates the value field next to it. Sending a command updates the Status text and the Command History. You can directly edit the Command History to change a parameter value. Pressing Enter on the line will then execute the command. If the command has changed a new line will be entered in the Command History. Pressing Enter several times on the same line updates the Status text with the number of commands sent (3 in the next example). ","version":"Next","tagName":"h2"},{"title":"Hazardous Commands","type":1,"pageTitle":"Command Sender","url":"/docs/tools/cmd-sender#hazardous-commands","content":" Sending hazardous commands will prompt the user whether to send the command. Commands can also have hazardous states (INST COLLECT with TYPE SPECIAL) which also prompt the user. In this example, we've also checked all the menu options to show ignored parameters, display state values in hex (see SPECIAL, 0x1), disabled range checking (DURATION 1000), and disabled parameter conversions. Selecting Yes will send the command and update the history with all the parameters shown. Note that when writing Scripts all parameters are optional unless explicitly marked required. ","version":"Next","tagName":"h3"},{"title":"Command and Telemetry Server","type":0,"sectionRef":"#","url":"/docs/tools/cmd-tlm-server","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#introduction","content":" The Command and Telemetry Server application provides status about the interfaces and targets instantiated in your COSMOS installation. Interfaces can be connected or disconnected and raw byte counts are returned. The application also provides quick shortcuts to view both raw and formatted command and telemetry packets as they go through the COSMOS system. At the bottom of the Command and Telemetry Server is the Log Messages showing server messages. ","version":"Next","tagName":"h2"},{"title":"Command and Telemetry Server Menus","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#command-and-telemetry-server-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#file-menu-items","content":" The Command and Telemetry Server has one menu under File -> Options: This dialog changes the refresh rate of the Command and Telemetry Server to reduce load on both your browser window and the backend server. Note that this changes the refresh rate of the various tabs in the application. The Log Messages will continue to update as messages are generated. ","version":"Next","tagName":"h3"},{"title":"Interfaces Tab","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#interfaces-tab","content":" The Interfaces tab displays all the interfaces defined by your COSMOS installation. You can Connect or Disconnect interfaces and view raw byte and packet counts. ","version":"Next","tagName":"h2"},{"title":"Targets Tab","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#targets-tab","content":" The Targets tab displays all the targets and their mapped interfaces along with the Command Authority status (Enterprise Only). Command Authority is enabled in the Admin Console and is enabled scope wide. Once Command Authority is enabled, individual users can give and take Command Authority which enables exclusive command and script access to that target. Without Command Authority, users can not send a command or start a script under that target. Note, commands or scripts scheduled with Calendar or Autonomic are not affected by Command Authority. ","version":"Next","tagName":"h2"},{"title":"Command Packets Tab","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#command-packets-tab","content":" The Command Packets tab displays all the available commands. The table can be sorted by clicking on the column headers. The table is paginated to support thousands of commands. The search bar searches all pages for a command. Clicking on View Raw opens a dialog displaying the raw bytes for that command. Clicking View in Command Sender opens up a new Command Sender window with the specified command. ","version":"Next","tagName":"h2"},{"title":"Telemetry Packets Tab","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#telemetry-packets-tab","content":" The Telemetry Packets tab displays all the available telemetry. The table can be sorted by clicking on the column headers. The table is paginated to support thousands of telemetry packets. The search bar searches all pages for a telemetry packet. Clicking on View Raw opens a dialog displaying the raw bytes for that telemetry packet. Clicking View in Packet Viewer opens up a new Packet Viewer window with the specified telemetry packet. ","version":"Next","tagName":"h2"},{"title":"Status Tab","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#status-tab","content":" The Status tab displays COSMOS system metrics. ","version":"Next","tagName":"h2"},{"title":"Log Messages","type":1,"pageTitle":"Command and Telemetry Server","url":"/docs/tools/cmd-tlm-server#log-messages","content":" The Log Messages table sits below all the tabs in the Command and Telemetry Server application. It displays server messages such as limits events (new RED, YELLOW, GREEN values), logging events (new files) and interface events (connecting and disconnecting). It can be filtered by severity or by entering values in the Search box. It can also be paused and resumed to inspect an individual message. ","version":"Next","tagName":"h2"},{"title":"Data Extractor","type":0,"sectionRef":"#","url":"/docs/tools/data-extractor","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#introduction","content":" Data Extractor extracts command and telemetry items into comma or tab separated files. Individual items or entire packets can be processed over any time period. Data Extractor also has a number of options to control the output for post processing in Excel or Matlab, for example. ","version":"Next","tagName":"h2"},{"title":"Data Extractor Menus","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#data-extractor-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#file-menu-items","content":" Opens a saved configurationSave the current configuration (item list)Reset the configuration (default settings)Delimit output with commasDelimit output with tabs Open Configuration The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name. Save Configuration The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name. ","version":"Next","tagName":"h3"},{"title":"Mode Menu Items","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#mode-menu-items","content":" Fill empty cells with the previous valueAdd a Matlab comment ('%') to the headerOnly output changed valuesOnly list item name as column headerList full Target Packet Item as header ","version":"Next","tagName":"h3"},{"title":"Selecting Items for Output","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#selecting-items-for-output","content":" ","version":"Next","tagName":"h2"},{"title":"Start/End Date/Time","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#startend-datetime","content":" Data Extractor provides text fields where you specify the time range to extract items. Clicking the Start Date and End Date text fields opens a Date Chooser dialog. Note you can also manually type in the date. Clicking the Start Time and End Time icon opens up a Time Chooser dialog. Note you can also manually type in the time. ","version":"Next","tagName":"h3"},{"title":"Adding Target(s) Packet(s) Item(s)","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#adding-targets-packets-items","content":" Data Extractor provides Target, Packet, Item drop downs to select the items you want to export. When you select a Target the Packet drop down defaults to [All] which sets the button to "Add Target". This would add EVERY item defined in EVERY packet in the target. Note: This can be a LOT of telemetry points but any added point can be removed. When you select a Packet the Item drop down defaults to [All] which sets the button to "Add Packet". This would add EVERY item defined in the specified packet. Note: This can be a LOT of telemetry points but any added point can be removed. When you select an individual Item the button changes to "Add Item" and the Description field updates with the item's description. ","version":"Next","tagName":"h3"},{"title":"Removing Items","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#removing-items","content":" Once you've added items the Items table will have a list of items. Items can be removed by clicking the Trash icon next to the item. ALL items can be removed by clicking the Trash icon in the header. ","version":"Next","tagName":"h3"},{"title":"Editing Items","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#editing-items","content":" Items can be edited by clicking the Pencil icon next to the item. ALL items can be edited by clicking the pencil icon in the header. Clicking the Edit All brings up the Edit All Items dialog. This allows you to change the data type of all items in the list. Clicking the pencil next to an individual item brings up a similar dialog to edit the individual item. ","version":"Next","tagName":"h3"},{"title":"Processing Items","type":1,"pageTitle":"Data Extractor","url":"/docs/tools/data-extractor#processing-items","content":" Clicking the Process button starts the processing of the items list. A progress wheel is shown on the left side of the table and the Process button changes to Cancel to allow canceling the process. When the processing is complete, the browser shows a file download link. Note this varies by browser. This example is from Chrome. ","version":"Next","tagName":"h2"},{"title":"Data Viewer","type":0,"sectionRef":"#","url":"/docs/tools/data-viewer","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Data Viewer","url":"/docs/tools/data-viewer#introduction","content":" Data Viewer allows you to view packet data in both the past and in real time. ","version":"Next","tagName":"h2"},{"title":"Data Viewer Menus","type":1,"pageTitle":"Data Viewer","url":"/docs/tools/data-viewer#data-viewer-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Data Viewer","url":"/docs/tools/data-viewer#file-menu-items","content":" Opens a saved configurationSave the current configurationReset the configuration (default settings) Open Configuration The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name. Save Configuration The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name. ","version":"Next","tagName":"h3"},{"title":"Adding Components","type":1,"pageTitle":"Data Viewer","url":"/docs/tools/data-viewer#adding-components","content":" DataViewer displays data in a component. To add a new component to the interface click the plus icon. This brings up the Add Component dialog. First you select the component you want to use to visual the data. Next you add packets which will populate the component. Finally click Create to see the DataViewer component visualization. To adjust the settings of the COSMOS Raw/Decom component click the gear icon to bring up the Display Settings dialog. You can turn on and off various visualizations, increase the number of packets displayed and the history. ","version":"Next","tagName":"h3"},{"title":"Handbooks","type":0,"sectionRef":"#","url":"/docs/tools/handbooks","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Handbooks","url":"/docs/tools/handbooks#introduction","content":" Handbooks formats the COSMOS command and telemetry definitions into a nicely formatted webpage that can be exported to a PDF. You can select the targets you want to display and the number of columns to display on the page. You can then use the browser to Print the page. Most browsers have the capability to Save as PDF rather than print to save the resulting page as PDF. ","version":"Next","tagName":"h2"},{"title":"Limits Monitor","type":0,"sectionRef":"#","url":"/docs/tools/limits-monitor","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Limits Monitor","url":"/docs/tools/limits-monitor#introduction","content":" The Limits Monitor application provides situational awareness for all telemetry items with limits. All limits items which violate their yellow or red limits are shown and continue to be shown until explicitly dismissed. Individual items and entire packets can be manually ignored to filter out known issues. In addition, all limits events are logged in a table which can be searched. ","version":"Next","tagName":"h2"},{"title":"Limits Monitor Menus","type":1,"pageTitle":"Limits Monitor","url":"/docs/tools/limits-monitor#limits-monitor-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Limits Monitor","url":"/docs/tools/limits-monitor#file-menu-items","content":" Show the list of ignored itemsChange the overall COSMOS limits setOpens a saved configurationSave the current configuration (ignored items)Reset the configuration (defaults settings) Show Ignored This dialog displays all the items which the user has manually ignored by clicking the ignore icons next to out of limits items. Note that entire Packets which have been ignored are listed as TARGET PACKET without an item (as shown by INST MECH). Ignored items are removed by clicking the Trash icon. This means that the next time this item goes out of limits it will be displayed. Change Limits Set Limits sets are defined with the LIMITS keyword on telemetry items. Each item must have at least a DEFAULT limits set but can also have other named limit sets. COSMOS only has a single limits set active at one time. This dialog allows the user to change the active limits set and apply new limit values across all of COSMOS. Open Configuration The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name. Save Configuration The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name. ","version":"Next","tagName":"h3"},{"title":"Limits Items","type":1,"pageTitle":"Limits Monitor","url":"/docs/tools/limits-monitor#limits-items","content":" The main interface of Limits Monitor is the top where items are displayed when they violate a yellow or red limit. Items with limits values are displayed using a red yellow green limits bar displaying where the current value lies within the defined limits (as shown by the various TEMP items). Items with yellow or red states are simply displayed with their state color (as shown by GROUND1STATUS). The COSMOS Demo contains both INST HEALTH_STATUS TEMP2 and INST2 HEALTH_STATUS TEMP2 which are identically named items within different target packets. Limits Monitor only displays the item name to save space, however if you mouse over the value box the full target and packet name is displayed. Clicking the first nested 'X' icon ignores the entire packet where the item resides. Any additional items in that packet which go out of limits are also ignored by Limits Monitor. Clicking the second (middle) 'X' ignores ONLY that specific item. If any packets or items are ignored the Overall Limits State is updated to indicate "(Some items ignored)" to indicate the Limits State is potentially being affected by ignored items. Clicking the last icon (eye with strike-through) temporarily hides the specified item. This is different from ignoring an item because if this item goes out of limits it will be again be displayed. Hiding an item is useful if the item has gone back to green and you want to continue to track it but want to clean up the current list of items. For example, we might hide the GROUND1STATUS items in the above example as they have transitioned back to green. ","version":"Next","tagName":"h2"},{"title":"Limits Log","type":1,"pageTitle":"Limits Monitor","url":"/docs/tools/limits-monitor#limits-log","content":" The Log section lists all limits events. Events can be filtered by using the Search box as shown. ","version":"Next","tagName":"h2"},{"title":"Packet Viewer","type":0,"sectionRef":"#","url":"/docs/tools/packet-viewer","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#introduction","content":" Packet Viewer is a live telemetry viewer which requires no configuration to display the current values for all defined target, packet, items. Items with limits are displayed colored (blue, green, yellow, or red) according to their current state. Items can be right clicked to get detailed information. ","version":"Next","tagName":"h2"},{"title":"Packet Viewer Menus","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#packet-viewer-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#file-menu-items","content":" Change the refresh and stale intervalOpens a saved configurationSave the current configuration (view settings)Reset the configuration (default settings) ","version":"Next","tagName":"h3"},{"title":"View Menu Items","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#view-menu-items","content":" Shows ignored itemsDisplay derived items lastDisplay formatted items with unitsDisplay formatted itemsDisplay converted itemsDisplay raw items ","version":"Next","tagName":"h3"},{"title":"Selecting Packets","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#selecting-packets","content":" Initially opening Packet Viewer will open the first alphabetical Target and Packet. Click the drop down menus to update the Items table to a new packet. To filter the list of items you can type in the search box. ","version":"Next","tagName":"h2"},{"title":"Details","type":1,"pageTitle":"Packet Viewer","url":"/docs/tools/packet-viewer#details","content":" Right-clicking an item and selecting Details will open the details dialog. This dialog lists everything defined on the telemetry item. ","version":"Next","tagName":"h3"},{"title":"Telemetry Grapher","type":0,"sectionRef":"#","url":"/docs/tools/tlm-grapher","content":"","keywords":"","version":"Next"},{"title":"Introductions","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#introductions","content":" Telemetry Grapher is a graphing application that allows for one or more telemetry points per graph. It supports multiple graphs per screen which can be resized and reordered. Multiple configurations can be saved and restored for different situations. ","version":"Next","tagName":"h2"},{"title":"Telemetry Grapher Menus","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#telemetry-grapher-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#file-menu-items","content":" Open a saved configuration (graphs and items)Save the current configurationReset the configuration (default settings) Open Configuration The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name. Save Configuration The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name. ","version":"Next","tagName":"h3"},{"title":"Graph Menu Items","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#graph-menu-items","content":" Add a new graphStart / Resume graphingPause graphStop graphEdit grapher settings Editing the grapher settings brings up a dialog to change settings affecting every graph in the Telemetry Grapher tool. Changing the Seconds Graphed changes the visible windows displaying graph points. The smaller of Seconds Graphed and Points Graphed will be used when calculating the number of points to display. Changing the Points Saved will affect performance of the browser window if set too high. The default of 1,000,000 points can store over 11.5 days of 1Hz data points. Editing an individual graph by clicking the pencil icon in title bar of the graph brings up the edit graph dialog. Editing the Start Date and Start Time will re-query the data to begin at the specified time. This operation can take several seconds depending on how far back data is requested. Similarly, specifying the End Date and End Time will limit the data request to the specified time. Leaving the End Date / End Time fields blank will cause Telemetry Grapher to continue to graph items in real-time as they arrive. Changing the Min Y and Max Y values simply sets the graph scale. Deleting the Min Y and Max Y values allows the graph to scale automatically as values arrive. Compare the following graph with the minimum set to 0 and the maximum set to 100 with the first graph image (auto-scale). ","version":"Next","tagName":"h3"},{"title":"Selecting Items","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#selecting-items","content":" Selecting a target from the Select Target drop down automatically updates the available packets in the Select Packet drop down which updates the available items in the Select Item drop down. Clicking Add Item adds the item to the graph which immediately begins graphing. As time passes, the main graph fills up and starts scrolling while the overview graph at the bottom shows the entire history. Selecting a new item and adding it to the graph automatically fills the graph with history until the beginning of the first item. This allows you to add items to the graph incrementally and maintain full history. ","version":"Next","tagName":"h2"},{"title":"Graph Window Management","type":1,"pageTitle":"Telemetry Grapher","url":"/docs/tools/tlm-grapher#graph-window-management","content":" All graphs can be moved around the browser window by clicking their title bar and moving them. Other graphs will move around intelligently to fill the space. This allows you order the graphs no matter which order they were created in. Each graph has a set of window buttons in the upper right corner. The first shrinks or grows the graph both horizontally and vertically to allow for 4 graphs in the same browser tab. Note that half height graphs no longer show the overview graph. The second button shrinks or grows the graph horizontally so it will either be half or full width of the browser window. This allows for two full width graphs on top of each other. The second button shrinks or grows the graph vertically so it will either be half or full height of the browser window. This allows for two full height graphs side by side. The line button minimizes the graph to effectively hide it. This allows you to focus on a single graph without losing existing graphs. The final X button closes the graph. ","version":"Next","tagName":"h2"},{"title":"Calendar (Enterprise)","type":0,"sectionRef":"#","url":"/docs/tools/calendar","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#introduction","content":" Calendar visualizes metadata, notes, and timeline information in one easy to understand place. Timelines allow for the simple execution of commands and scripts based on future dates and times. ","version":"Next","tagName":"h2"},{"title":"Adding Timelines","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#adding-timelines","content":" Adding a Timeline to COSMOS is as simple as clicking Create -> Timeline and giving it a unique name. Timelines can be created for organizational purposes or for overlapping activities as no activities can overlap on a given timeline. However, each additional timeline consists of several threads so only create timelines as necessary. ","version":"Next","tagName":"h3"},{"title":"Types of Events","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#types-of-events","content":" ","version":"Next","tagName":"h2"},{"title":"Metadata","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#metadata","content":" Metadata allows you to record arbitrary data into the COSMOS system. For example, you could ask the user for inputs which fall outside the available target telemetry including operators, environmental factors, procedural steps, etc. This allows for searching metadata based on these fields and correlating the related telemetry data. You can create a new metadata item from either the Create menu or by right-clicking on the calendar in the given time slot you want the metadata item to appear. Note that metadata entries only have a start time, they do not have an end time. You then add key / value pairs for all the metadata items you want to create. ","version":"Next","tagName":"h3"},{"title":"Note","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#note","content":" Notes require both a start and end time. You then record the note to create the note event on the calendar. ","version":"Next","tagName":"h3"},{"title":"Activity","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#activity","content":" Scheduled on a timeline, activities take both a start and end time. Activities can run single commands, run a script, or simply "Reserve" space on the calendar for reference or other bookkeeping. When calendar activities are scheduled they appear with a green circle containing a plus (+). Once they complete successfully the icon changes to a green circle containing a checkbox (✓). Reserve activities simply have a blank green circle. Calendar events can also be viewed in a list format via File->Show Table Display which supports pagination for listing both past and future events. ","version":"Next","tagName":"h3"},{"title":"Timeline Implementation Details","type":1,"pageTitle":"Calendar (Enterprise)","url":"/docs/tools/calendar#timeline-implementation-details","content":" When a user creates a timeline, a new timeline microservice starts. The timeline microservice is the main thread of execution for the timeline. This starts a scheduler manager thread. The scheduler manager thread contains a thread pool that hosts more than one thread to run the activity. The scheduler manager will evaluate the schedule and based on the start time of the activity it will add the activity to the queue. The main thread will block on the web socket to listen to request changes to the timeline, these could be adding, removing, or updating activities. The main thread will make the changes to the in memory schedule if these changes are within the hour of the current time. When the web socket gets an update it has an action lookup table. These actions are "created", "updated", "deleted", etc... Some actions require updating the schedule from the database to ensure the schedule and the database are always in sync. The schedule thread checks every second to make sure if a task can be run. If the start time is equal or less then the last 15 seconds it will then check the previously queued jobs list in the schedule. If the activity has not been queued and is not fulfilled the activity will be queued, this adds an event to the activity but is not saved to the database. The workers block on the queue until an activity is placed on the queue. Once a job is pulled from the queue they check the type and run the activity. The thread will mark the activity fulfillment true and update the database record with the complete. If the worker gets an error while trying to run the task the activity will NOT be fulfilled and record the error in the database. ","version":"Next","tagName":"h2"},{"title":"Table Manager","type":0,"sectionRef":"#","url":"/docs/tools/table-manager","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#introduction","content":" Table Manager is a binary file editor. It takes binary file definitions similar to the COSMOS command packet definitions and builds a GUI to edit the fields in the binary file. ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#file-menu-items","content":" Create a new binary based on definitionOpen an existing binarySave the current binaryRename the current binaryDelete the current binary ","version":"Next","tagName":"h3"},{"title":"File Download","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#file-download","content":" The three buttons next to File Download download the binary file, the definition file, and the report file. The binary is the raw bits defined by the table. The definition is the structure definition of those raw bits. The report file is a Table Manager generated CSV that shows all the table values in the binary. ","version":"Next","tagName":"h2"},{"title":"Upload / Download","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#upload--download","content":" Table Manager has the ability to directly call a COSMOS script to upload a binary file to a target or download a file into Table Manager. If a file called upload.rb is found in the Target's procedures directory then the Upload button becomes active. If a file called download.rb is found in the Target's procedures directory then the Download button becomes active. The B/G button indicates whether to run the upload / download scripts in the background. If you uncheck this box a new Script Runner window will show the line by line execution of the script. ","version":"Next","tagName":"h2"},{"title":"upload.rb","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#uploadrb","content":" The COSMOS demo creates the following upload.rb script. Note that the ENV['TBL_FILENAME'] is set to the name of the table file and the script uses get_target_file to get access to the file. At this point the logic to upload the file to the target is specific to the commanding defined by the target but an example script is given. # TBL_FILENAME is set to the name of the table file puts "file:#{ENV['TBL_FILENAME']}" # Open the file file = get_target_file(ENV['TBL_FILENAME']) buffer = file.read # puts buffer.formatted # Implement custom commanding logic to upload the table # Note that buffer is a Ruby string of bytes # You probably want to do something like: # buf_size = 512 # Size of a buffer in the upload command # i = 0 # while i < buffer.length # # Send a part of the buffer # # NOTE: triple dots means start index, up to but not including, end index # # while double dots means start index, up to AND including, end index # cmd("TGT", "UPLOAD", "DATA" => buffer[i...(i + buf_size)]) # i += buf_size # end file.delete ","version":"Next","tagName":"h3"},{"title":"download.rb","type":1,"pageTitle":"Table Manager","url":"/docs/tools/table-manager#downloadrb","content":" The COSMOS demo creates the following download.rb script. Note that the ENV['TBL_FILENAME'] is set to the name of the table file to OVERWRITE and the script uses put_target_file to get access to the file. At this point the logic to download the file from the target is specific to the commanding defined by the target but an example script is given. # TBL_FILENAME is set to the name of the table file to overwrite puts "file:#{ENV['TBL_FILENAME']}" # Download the file # Implement custom commanding logic to download the table # You probably want to do something like: buffer = '' # i = 1 # num_segments = 5 # calculate based on TBL_FILENAME # table_id = 1 # calculate based on TBL_FILENAME # while i < num_segments # # Request a part of the table buffer # cmd("TGT DUMP with TABLE_ID #{table_id}, SEGMENT #{i}") # buffer += tlm("TGT DUMP_PKT DATA") # i += 1 # end put_target_file(ENV['TBL_FILENAME'], buffer) ","version":"Next","tagName":"h3"},{"title":"Telemetry Viewer","type":0,"sectionRef":"#","url":"/docs/tools/tlm-viewer","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#introduction","content":" Telemetry Viewer is a live telemetry viewer which displays custom built screens. Screens are configured through simple text files which utilize numerous built-in widgets. ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#file-menu-items","content":" Open a saved configurationSave the current configurationReset the configuration (default settings) Open Configuration The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name. Save Configuration The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name. ","version":"Next","tagName":"h3"},{"title":"Selecting Screens","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#selecting-screens","content":" Selecting a target from the Select Target drop down automatically updates the available screens for that target in the Select Screen drop down. Clicking Show Screen causes that screen to display. ","version":"Next","tagName":"h2"},{"title":"New Screen","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#new-screen","content":" Clicking New Screen brings up the new screen dialog. Screens are owned by Targets so Select Target chooses where the screen will be created. Screens can be based on a Packet such that all the items in that particular packet will be generated in a simple vertical screen similar to Packet Viewer. This is a good starting point for customizing a screen. Note that screen names must be unique so the screen name is set to 'adcs2' since an 'ADCS' screen already exists. ","version":"Next","tagName":"h2"},{"title":"Edit Screen","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#edit-screen","content":" Clicking the pencil icon in the title bar of the screen brings up the edit dialog. The screen source is displayed in an editor with syntax highlighting and auto-completion. You can download the screen source using the download button in the upper right or delete the screen using the trash icon in the upper left. Click Save to save the screen edits at which point Telemetry Viewer will re-render the screen. ","version":"Next","tagName":"h2"},{"title":"Screen Window Management","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#screen-window-management","content":" All screens can be moved around the browser window by clicking their title bar and moving them. Other screens will move around intelligently to fill the space. This allows you to order the screens no matter which order they were created in. You can also float the screens by clicking the grid icon in the upper left of the title bar. It will change to a balloon icon and allow you to click up and down to change the relative Z index of the window. The image screen is floated in the following screen shot. The dash button in the upper right of the title bar minimizes the screen to effectively hide it. This allows you to focus on a single screen without closing existing screens. In the screen shot below there are two minimized windows at the very bottom. The X button closes the screen. ","version":"Next","tagName":"h2"},{"title":"Building Screens","type":1,"pageTitle":"Telemetry Viewer","url":"/docs/tools/tlm-viewer#building-screens","content":" For documentation on how to build Telemetry Screens and how to configure the screen widgets please see the Telemetry Screens. ","version":"Next","tagName":"h2"},{"title":"Script Runner","type":0,"sectionRef":"#","url":"/docs/tools/script-runner","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#introduction","content":" Script Runner is both an editor of COSMOS scripts as well as executes scripts. Script files are stored within a COSMOS target and Script Runner provides the ability to open, save, download and delete these files. When a suite of scripts is opened, Script Runner provides additional options to run individual scripts, groups of scripts, or entire suites. ","version":"Next","tagName":"h2"},{"title":"Script Runner Menus","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#script-runner-menus","content":" ","version":"Next","tagName":"h2"},{"title":"File Menu Items","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#file-menu-items","content":" Clears the editor and filenameCreates a new test suite in Ruby or PythonOpens a dialog to select a file to openOpens a recently used fileSaves the currently opened file to diskRename the current fileDownloads the current file to the browserDeletes the current file (Permanently!) File Open The File Open Dialog displays a tree view of the installed targets. You can manually open the folders and browse for the file you want. You can also use the search box at the top and start typing part of the filename to filter the results. File Save As When saving a file for the first time, or using File Save As, the File Save As Dialog appears. It works similar to the File Open Dialog displaying the tree view of the installed targets. You must select a folder by clicking the folder name and then filling out the Filename field with a filename before clicking Ok. You will be prompted before over-writing an existing file. ","version":"Next","tagName":"h3"},{"title":"Script Menu Items","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#script-menu-items","content":" Display started and finished scriptsShow environment variablesShow defined metadataShow overridden telemetry valuesPerform a syntax checkPerform a script mnemonic checkView the instrumented scriptShows the script call stackDisplay the debug promptDisconnect from real interfacesDelete all script breakpoints The Execution Status popup lists the currently running scripts. This allows other users to connect to running scripts and follow along with the currently executing script. It also lists previously executed scripts so you can download the script log. ","version":"Next","tagName":"h3"},{"title":"Running Scripts","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#running-scripts","content":" Running a regular script is simply a matter of opening it and clicking the Start button. By default when you open a script the Filename is updated and the editor loads the script. Once you click Start the script is spawned in the Server and the Script State becomes Connecting. At that point the currently executing line is marked with green. If an error is encountered the line turns red and and the Pause button changes to Retry to allow the line to be re-tried. This allows checks that depend on telemetry changing to potentially be retried as telemetry is being updated live in the background. You can also click Go to continue pass the error or Stop to end the script execution. ","version":"Next","tagName":"h2"},{"title":"Right Click Script","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#right-click-script","content":" Right clicking a script brings up several options: 'Execute selection' causes the selected piece of code to be copied to a fresh Script Runner tab and executed independently of the current script. This is useful to run a selected section of code but be careful of references to other variables that are not selected. COSMOS will not be able to reference undefined variables! 'Run from here' causes the script to start execution at the current location of the cursor. This is useful to avoid executing earlier pieces of code but be careful of references to other variables that are not selected. COSMOS will not be able to reference undefined variables! 'Clear all breakpoints' allows you to quickly clear breakpoints set by clicking on the editor line number. ","version":"Next","tagName":"h3"},{"title":"Running Script Suites","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#running-script-suites","content":" If a script is structured as a Suite it automatically causes Script Runner to parse the file to populate the Suite, Group, and Script drop down menus. To generate a new Suite use the File -> New Suite and then choose either Ruby or Python to create a Suite in that language. ","version":"Next","tagName":"h2"},{"title":"Group","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#group","content":" The Group class contains the methods used to run the test or operations. Any methods starting with 'script', 'op', or 'test' which are implemented inside a Group class are automatically included as scripts to run. For example, in the above image, you'll notice the 'script_power_on' is in the Script drop down menu. Here's another simple Ruby example: require 'openc3/script/suite.rb' class ExampleGroup < OpenC3::Group def setup puts "setup" end def script_1 puts "script 1" end def teardown puts "teardown" end end Equivalent Python example: from openc3.script.suite import Suite, Group class ExampleGroup(Group): def setup(self): print("setup") def script_1(self): print("script 1") def teardown(self) print("teardown") The setup and teardown methods are special methods which enable the Setup and Teardown buttons next to the Group drop down menu. Clicking these buttons runs the associated method. ","version":"Next","tagName":"h3"},{"title":"Suite","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#suite","content":" Groups are added to Suites by creating a class inheriting from Suite and then calling the add_group method. For example in Ruby: class MySuite < OpenC3::Suite def initialize add_group('ExampleGroup') end def setup puts "Suite setup" end def teardown puts "Suite teardown" end end In Python: from openc3.script.suite import Suite, Group class MySuite(Suite): def __init__(self): self.add_group('ExampleGroup') def setup(self): print("Suite setup") def teardown(self): print("Suite teardown") Again there are setup and teardown methods which enable the Setup and Teardown buttons next to the Suite drop down menu. Multiple Suites and Groups can be created in the same file and will be parsed and added to the drop down menus. Clicking Start at the Suite level will run ALL Groups and ALL Scripts within each Group. Similarly, clicking Start at the Group level will run all Scripts in the Group. Clicking Start next to the Script will run just the single Script. ","version":"Next","tagName":"h3"},{"title":"Script Suite Options","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#script-suite-options","content":" Opening a Script Suite creates six checkboxes which provide options to the running script. Pause on Error Pauses the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box allows the script to continue past errors without user intervention. Similar to the User clicking Go upon encountering an error. Continue after Error Continue the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box means that the script will end after the first encountered error and execution will continue with any other scripts in the Suite/Group. Abort after Error Abort the entire execution upon encountering an error. If the first Script in a Suite's Group encounters an error the entire Suite will stop execution. Note, if Continue after Error is set, the current script is allowed to continue and complete. Manual In Ruby, sets the global variable called $manual to true. In Python, sets RunningScript.manual to True. Setting this box only allows the script author to determine if the operator wants to execute manual steps or not. It is up the script author to use the variable in their scripts. Loop Loop whatever the user started continuously. If the user clicks Start next to the Group then the entire Group will be looped. This is useful to catch and debug those tricky timing errors that only sometimes happen. Break Loop on Error Break the loop if an Error occurs. Only available if the Loop option is set. ","version":"Next","tagName":"h3"},{"title":"Debugging Scripts","type":1,"pageTitle":"Script Runner","url":"/docs/tools/script-runner#debugging-scripts","content":" When you enable the Debug prompt an additional line appears between the script and the Log Messages. You can type local variables to cause them to be output in the Log Messages. You can also set local variables by typing var = 10. The Step button allows you to step line by line through the script. Clicking Go continues regular execution. ","version":"Next","tagName":"h2"},{"title":"Script Writing Guide","type":0,"sectionRef":"#","url":"/docs/guides/script-writing","content":"","keywords":"","version":"Next"},{"title":"Introduction","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#introduction","content":" This guide aims to provide the best practices for using the scripting capabilities provided by COSMOS. Scripts are used to automate a series of activities for operations or testing. The goal of this document is to ensure scripts are written that are simple, easy to understand, maintainable, and correct. Guidance on some of the key details of using the COSMOS Script Runner is also provided. ","version":"Next","tagName":"h2"},{"title":"Concepts","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#concepts","content":" COSMOS supports both Ruby and Python for writing scripts. Ruby and Python are very similar scripting languages and most of this guide applies directly to both. Where examples are used, both a Ruby and Python example are given. ","version":"Next","tagName":"h2"},{"title":"Ruby vs Python in COSMOS","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#ruby-vs-python-in-cosmos","content":" There are many similarities and a few key differences between Ruby and Python when it comes to writing COSMOS scripts. There is no 80 character limit on line length. Lines can be as long as you like, but be careful to not make them too long as it makes printed reviews of scripts more difficult.Indentation white space: Ruby: Not significant. Ruby uses the end keyword to determine indented code blocks with a standard of 2 spaces.Python: Significant. Python uses indentation to determine code blocks with a standard of 4 spaces. Variables do not have to be declared ahead of time and can be reassigned later, i.e. Ruby and Python are dynamically typed.Variable interpolation: Ruby: Variable values can be placed into strings using the "#{variable}" syntax.Python: Variable values can be placed into f-strings using the f"{variable}" syntax. A variable declared inside of a block or loop will not exist outside of that block unless it was already declared. Both languages provides a script writer a lot of power. But with great power comes great responsibility. Remember when writing your scripts that you or someone else will come along later and need to understand them. Therefore use the following style guidelines: Use consistent spacing for indentation and do NOT use tabsConstants should be all caps with underscores SPEED_OF_LIGHT = 299792458 # meters per s Variable names and method names should be in lowercase with underscores last_name = "Smith"perform_setup_operation() Class names (when used) should be camel case and the files which contain them should match but be lowercase with underscores class DataUploader # in 'data_uploader.rb'class CcsdsUtility: # in 'ccsds_utility.py' Don't add useless comments but instead describe intent The following is an example of good Ruby style: load 'TARGET/lib/upload_utility.rb' # library we do NOT want to show executing load_utility 'TARGET/lib/helper_utility.rb' # library we do want to show executing # Declare constants OUR_TARGETS = ['INST','INST2'] # Clear the collect counter of the passed in target name def clear_collects(target) cmd("#{target} CLEAR") wait_check("#{target} HEALTH_STATUS COLLECTS == 0", 5) end ###################################### # START ###################################### helper = HelperUtility.new helper.setup # Perform collects on all the targets OUR_TARGETS.each do |target| collects = tlm("#{target} HEALTH_STATUS COLLECTS") cmd("#{target} COLLECT with TYPE SPECIAL") wait_check("#{target} HEALTH_STATUS COLLECTS == #{collects + 1}", 5) end clear_collects('INST') clear_collects('INST2') The following is an example of good Python style: from openc3.script import * import TARGET.lib.upload_utility # library we do NOT want to show executing load_utility('TARGET/lib/helper_utility.rb') # library we do want to show executing # Declare constants OUR_TARGETS = ['INST','INST2'] # Clear the collect counter of the passed in target name def clear_collects(target): cmd(f"{target} CLEAR") wait_check(f"{target} HEALTH_STATUS COLLECTS == 0", 5) ###################################### # START ###################################### helper = HelperUtility() helper.setup() # Perform collects on all the targets for target in OUR_TARGETS: collects = tlm(f"{target} HEALTH_STATUS COLLECTS") cmd(f"{target} COLLECT with TYPE SPECIAL") wait_check(f"{target} HEALTH_STATUS COLLECTS == {collects + 1}", 5) clear_collects('INST') clear_collects('INST2') Both examples shows several features of COSMOS scripting in action. Notice the difference between 'load' or 'import' and 'load_utility'. The first is to load additional scripts which will NOT be shown in Script Runner when executing. This is a good place to put code which takes a long time to run such as image analysis or other looping code where you just want the output. 'load_utility' will visually execute the code line by line to show the user what is happening. Next we declare our constants and create an array of strings which we store in OUR_TARGETS. Notice the constant is all uppercase with underscores. Then we declare our local methods of which we have one called clear_collects. Please provide a comment at the beginning of each method describing what it does and the parameters that it takes. The 'helper_utility' is then created. Note the similarity in the class name and the file name we loaded. The collect example shows how you can iterate over the array of strings we previously created and use variables when commanding and checking telemetry. The Ruby pound bracket # notation and python f-string f" notation puts whatever the variable holds into the string. You can even execute additional code inside the brackets like we do when checking for the collect count to increment. Finally we call our 'clear_collects' method on each target by passing the target name. ","version":"Next","tagName":"h3"},{"title":"Scripting Philosophy","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#scripting-philosophy","content":" ","version":"Next","tagName":"h2"},{"title":"A Super Basic Script Example","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#a-super-basic-script-example","content":" Most COSMOS scripts can be broken down into the simple pattern of sending a command to a system/subsystem and then verifying that the command worked as expected. This pattern is most commonly implemented with cmd() followed by wait_check(), like the following: cmd("INST COLLECT with TYPE NORMAL, TEMP 10.0") wait_check("INST HEALTH_STATUS TYPE == 'NORMAL'", 5) or similarly with a counter that is sampled before the command. Ruby: count = tlm("INST HEALTH_STATUS COLLECTS") cmd("INST COLLECT with TYPE NORMAL, TEMP 10.0") wait_check("INST HEALTH_STATUS COLLECTS >= #{count + 1}", 5) Python: count = tlm("INST HEALTH_STATUS COLLECTS") cmd("INST COLLECT with TYPE NORMAL, TEMP 10.0") wait_check(f"INST HEALTH_STATUS COLLECTS >= {count + 1}", 5) 90% of the COSMOS scripts you write should be the simple patterns shown above except that you may need to check more than one item after each command to make sure the command worked as expected. ","version":"Next","tagName":"h3"},{"title":"KISS (Keep It Simple Stupid)","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#kiss-keep-it-simple-stupid","content":" Ruby and Python are very powerful languages with many ways to accomplish the same thing. Given that, always choose the method that is easiest to understand for yourself and others. While it is possible to create complex one liners or obtuse regular expressions, you'll thank yourself later by expanding complex one liners and breaking up and documenting regular expressions. ","version":"Next","tagName":"h3"},{"title":"Keep things DRY (Don't Repeat Yourself)","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#keep-things-dry-dont-repeat-yourself","content":" A widespread problem in scripts written for any command and control system is large blocks of code that are repeated multiple times. In extreme cases, this has led to 100,000+ line scripts that are impossible to maintain and review. There are two common ways repetition presents itself: exact blocks of code to perform a common action such as powering on a subsystem, and blocks of code that only differ in the name of the mnemonic being checked or the values checked against. Both are solved by removing the repetition using methods (or functions). For example, a script that powers on a subsystem and ensures correct telemetry would become: Ruby: def power_on_subsystem # 100 lines of cmd(), wait_check(), etc end Python: def power_on_subsystem(): # 100 lines of cmd(), wait_check(), etc Ideally, the above methods would be stored in another file where it could be used by other scripts. If it is truly only useful in the one script, then it could be at the top of the file. The updated script would then look like: power_on_subsystem() # 150 lines operating the subsystem (e.g.) # cmd(...) # wait_check(...) #... power_off_subystem() # Unrelated activities power_on_subsystem() # etc. Blocks of code where only the only variation is the mnemonics or values checked can be replaced by methods with arguments. Ruby: def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp) cmd("TARGET #{enable_cmd_name} with ENABLE TRUE") wait_check("TARGET #{enable_tlm} == 'TRUE'", 5) wait_check("TARGET #{temp_tlm} >= #{expected_temp}", 50) end Python: def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp): cmd(f"TARGET {enable_cmd_name} with ENABLE TRUE") wait_check(f"TARGET {enable_tlm} == 'TRUE'", 5) wait_check(f"TARGET {temp_tlm} >= {expected_temp}", 50) ","version":"Next","tagName":"h3"},{"title":"Use Comments Appropriately","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#use-comments-appropriately","content":" Use comments when what you are doing is unclear or there is a higher-level purpose to a set of lines. Try to avoid putting numbers or other details in a comment as they can become out of sync with the underlying code. Ruby and Python comments start with a # pound symbol and can be anywhere on a line. # This line sends an abort command - BAD COMMENT, UNNECESSARY cmd("INST ABORT") # Rotate the gimbal to look at the calibration target - GOOD COMMENT cmd("INST ROTATE with ANGLE 180.0") # Rotate 180 degrees - BAD COMMENT ","version":"Next","tagName":"h3"},{"title":"Script Runner","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#script-runner","content":" COSMOS provides two unique ways to run scripts (also known as procedures). Script Runner provides both a script execution environment and a script editor. The script editor includes code completion for both COSMOS methods and command/telemetry item names. It is also a great environment to develop and test scripts. Script Runner provides a framework for users that are familiar with a traditional scripting model with longer style procedures, and for users that want to be able to edit their scripts in place. When opening a suite file (named with 'suite') Script Runner provides a more formal, but also more powerful, environment for running scripts. Suite files breaks scripts down into suites, groups, and scripts (individual methods). Suites are the highest-level concept and would typically cover a large procedure such as a thermal vacuum test, or a large operations scenario such as performing on orbit checkout. Groups capture a related set of scripts such as all the scripts regarding a specific mechanism. A Group might be a collection of scripts all related to a subsystem, or a specific series of tests such as an RF checkout. Scripts capture individual activities that can either pass or fail. Script Runner allows for running an entire suite, one or more groups, or one or more scripts easily. It also automatically produces reports containing timing, pass / fail counts, etc. The correct environment for the job is up to individual users, and many programs will use both script formats to complete their goals. ","version":"Next","tagName":"h3"},{"title":"Looping vs Unrolled Loops","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#looping-vs-unrolled-loops","content":" Loops are powerful constructs that allow you to perform the same operations multiple times without having to rewrite the same code over and over (See the DRY Concept). However, they can make restarting a COSMOS script at the point of a failure difficult or impossible. If there is a low probability of something failing, then loops are an excellent choice. If a script is running a loop over a list of telemetry points, it may be a better choice to “unroll” the loop by making the loop body into a method, and then calling that method directly for each iteration of a loop that would have occurred. Ruby: 10.times do |temperature_number| check_temperature(temperature_number + 1) end Python: for temperature_number in range(1, 11): check_temperature(temperature_number) If the above script was stopped after temperature number 3, there would be no way to restart the loop at temperature number 4. A better solution for small loop counts is to unroll the loop. check_temperature(1) check_temperature(2) check_temperature(3) check_temperature(4) check_temperature(5) check_temperature(6) check_temperature(7) check_temperature(8) check_temperature(9) check_temperature(10) In the unrolled version above, the COSMOS “Start script at selected line” feature can be used to resume the script at any point. ","version":"Next","tagName":"h3"},{"title":"Script Organization","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#script-organization","content":" All scripts must be part of a Plugin. You can create a simple plugin called SCRIPTS or PROCEDURES that only contains lib and procedures directories to store scripts. If COSMOS detects a plugin without defined cmd/tlm it will not spawn microservices for telemetry processing. ","version":"Next","tagName":"h2"},{"title":"Organizing Your Scripts into a Plugin","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#organizing-your-scripts-into-a-plugin","content":" As your scripts become large with many methods, it makes sense to break them up into multiple files within a plugin. Here is a recommended organization for your plugin's scripts/procedures. Folder\tDescriptiontargets/TARGET_NAME/lib\tPlace script files containing reusable target specific methods here targets/TARGET_NAME/procedures\tPlace simple procedures that are centered around one specific target here In your main procedure you will usually bring in the other files with instrumentation using load_utility. # Ruby: load_utility('TARGET/lib/my_other_script.rb') # Python: load_utility('TARGET/procedures/my_other_script.py') ","version":"Next","tagName":"h3"},{"title":"Organize Scripts into Methods","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#organize-scripts-into-methods","content":" Put each activity into a distinct method. Putting your scripts into methods makes organization easy and gives a great high-level overview of what the overall script does (assuming you name the methods well). There are no bonus points for vague, short method names. Make your method names long and clear. Ruby: def test_1_heater_zone_control puts "Verifies requirements 304, 306, and 310" # Test code here end def script_1_heater_zone_control puts "Verifies requirements 304, 306, and 310" # Test code here end Python: def test_1_heater_zone_control(): print("Verifies requirements 304, 306, and 310") # Test code here def script_1_heater_zone_control(): print("Verifies requirements 304, 306, and 310") # Test code here ","version":"Next","tagName":"h3"},{"title":"Using Classes vs Unscoped Methods","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#using-classes-vs-unscoped-methods","content":" Classes in object-oriented programming allow you to organize a set of related methods and some associated state. The most important aspect is that the methods work on some shared state. For example, if you have code that moves a gimbal around, and need to keep track of the number of moves, or steps, performed across methods, then that is a wonderful place to use a class. If you just need a helper method to do something that happens multiple times in a script without copy and pasting, it probably does not need to be in a class. NOTE: The convention in COSMOS is to have a TARGET/lib/target.[rb/py] file which is named after the TARGET name and contains a class called Target. This discussion refers to scripts in the TARGET/procedures directory. Ruby: class Gimbal attr_accessor :gimbal_steps def initialize() @gimbal_steps = 0 end def move(steps_to_move) # Move the gimbal @gimbal_steps += steps_to_move end def home_gimbal # Home the gimbal @gimbal_steps = 0 end end def perform_common_math(x, y) x + y end gimbal = Gimbal.new gimbal.home_gimbal gimbal.move(100) gimbal.move(200) puts "Moved gimbal #{gimbal.gimbal_steps}" result = perform_common_math(gimbal.gimbal_steps, 10) puts "Math:#{result}" Python: class Gimbal: def __init__(self): self.gimbal_steps = 0 def move(self, steps_to_move): # Move the gimbal self.gimbal_steps += steps_to_move def home_gimbal(self): # Home the gimbal self.gimbal_steps = 0 def perform_common_math(x, y): return x + y gimbal = Gimbal() gimbal.home_gimbal() gimbal.move(100) gimbal.move(200) print(f"Moved gimbal {gimbal.gimbal_steps}") result = perform_common_math(gimbal.gimbal_steps, 10) print(f"Math:{result}") ","version":"Next","tagName":"h3"},{"title":"Instrumented vs Uninstrumented Lines (require vs load)","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#instrumented-vs-uninstrumented-lines-require-vs-load","content":" COSMOS scripts are normally “instrumented”. This means that each line has some extra code added behind the scenes that primarily highlights the current executing line and catches exceptions if things fail such as a wait_check. If your script needs to use code in other files, there are a few ways to bring in that code. Some techniques bring in instrumented code and others bring in uninstrumented code. There are reasons to use both. load_utility (and the deprecated require_utility), bring in instrumented code from other files. When COSMOS runs the code in the other file, Script Runner will dive into the other file and show each line highlighted as it executes. This should be the default way to bring in other files, as it allows continuing if something fails, and provides better visibility to operators. However, sometimes you don't want to display code executing from other files. Externally developed libraries generally do not like to be instrumented, and code that contains large loops or that just takes a long time to execute when highlighting lines, will be much faster if included in a method that does not instrument lines. Ruby provides two ways to bring in uninstrumented code. The first is the “load” keyword. Load will bring in the code from another file and will bring in any changes to the file if it is updated on the next call to load. “require” is like load but is optimized to only bring in the code from another file once. Therefore, if you use require and then change the file it requires, you must restart Script Runner to re-require the file and bring in the changes. In general, load is recommended over require for COSMOS scripting. One gotcha with load is that it requires the full filename including extension, while the require keyword does not. In Python, libraries are included using the import syntax. Any code imported using import is not instrumented. Only the code imported using load_utility is instrumented. Finally, COSMOS scripting has a special syntax for disabling instrumentation in the middle of an instrumented script, with the disable_instrumentation method. This allows you to disable instrumentation for large loops and other activities that are too slow when running instrumented. Ruby: temp = 0 disable_instrumentation do # Make sure nothing in here will raise exceptions! 5000000.times do temp += 1 end end puts temp Python: temp = 0 with disable_instrumentation(): # Make sure nothing in here will raise exceptions! for x in range(0,5000000): temp += 1 print(temp) When Running Uninstrumented Code Make sure that the code will not raise any exceptions or have any check failures. If an exception is raised from uninstrumented code, then your entire script will stop. ","version":"Next","tagName":"h3"},{"title":"Debugging and Auditing","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#debugging-and-auditing","content":" ","version":"Next","tagName":"h2"},{"title":"Built-In Debugging Capabilities","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#built-in-debugging-capabilities","content":" Script Runner has built in debugging capabilities that can be useful in determining why your script is behaving in a certain way. Of primary importance is the ability to inspect and set script variables. To use the debugging functionality, first select the “Toggle Debug” option from the Script Menu. This will add a small Debug: prompt to the bottom of the tool. Any code entered in this prompt will be executed when Enter is pressed. To inspect variables in a running script, pause the script and then type the variable name to print out the value of the variable in the debug prompt. variable_name Variables can also be set simply by using equals. variable_name = 5 If necessary, you can also inject commands from the debug prompt using the normal commanding methods. These commands will be logged to the Script Runner message log, which may be advantageous over using a different COSMOS tool like CmdSender (where the command would only be logged in the CmdTlmServer message log). cmd("INST COLLECT with TYPE NORMAL") Note that the debug prompt keeps the command history and you can scroll through the history by using the up and down arrows. ","version":"Next","tagName":"h3"},{"title":"Breakpoints","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#breakpoints","content":" You can click the line number (left side gutter) in Script Runner to add a breakpoint. The script will automatically pause when it hits the breakpoint. Once stopped at the breakpoint, you can evaluate variables using the Debug line. ","version":"Next","tagName":"h3"},{"title":"Using Disconnect Mode","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#using-disconnect-mode","content":" Disconnect mode is a feature of Script Runner that allows testing scripts in an environment without real hardware in the loop. Disconnect mode is started by selecting Script -> Toggle Disconnect. Once selected, the user is prompted to select which targets to disconnect. By default, all targets are disconnected, which allows for testing scripts without any real hardware. Optionally, only a subset of targets can be selected which can be useful for trying out scripts in partially integrated environments. While in disconnect mode, commands to the disconnected targets always succeed. Additionally, all checks of disconnected targets' telemetry are immediately successful. This allows for a quick run-through of procedures for logic errors and other script specific errors without having to worry about the behavior and proper functioning of hardware. ","version":"Next","tagName":"h3"},{"title":"Auditing your Scripts","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#auditing-your-scripts","content":" Script Runner includes several tools to help audit your scripts both before and after execution. Ruby Syntax Check The Ruby Syntax Check tool is found under the Script Menu. This tool uses the ruby executable with the -c flag to run a syntax check on your script. If any syntax errors are found the exact message presented by the Ruby interpreter is shown to the user. These can be cryptic, but the most common faults are not closing a quoted string, forgetting an “end” keyword, or using a block but forgetting the proceeding “do” keyword. ","version":"Next","tagName":"h3"},{"title":"Common Scenarios","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#common-scenarios","content":" ","version":"Next","tagName":"h2"},{"title":"User Input Best Practices","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#user-input-best-practices","content":" COSMOS provides several different methods to gather manual user input in scripts. When using user input methods that allow for arbitrary values (like ask() and ask_string()), it is very important to validate the value given in your script before moving on. When asking for text input, it is extra important to handle different casing possibilities and to ensure that invalid input will either re-prompt the user or take a safe path. Ruby: answer = ask_string("Do you want to continue (y/n)?") if answer != 'y' and answer != 'Y' raise "User entered: #{answer}" end temp = 0.0 while temp < 10.0 or temp > 50.0 temp = ask("Enter the desired temperature between 10.0 and 50.0") end Python: answer = ask_string("Do you want to continue (y/n)?") if answer != 'y' and answer != 'Y': raise RuntimeError(f"User entered: {answer}") temp = 0.0 while temp < 10.0 or temp > 50.0: temp = ask("Enter the desired temperature between 10.0 and 50.0") When possible, always use one of the other user input methods that has a constrained list of choices for your users (message_box, vertical_message_box, combo_box). Note that all these user input methods provide the user the option to “Cancel”. When cancel is clicked, the script is paused but remains at the user input line. When hitting “Go” to the continue, the user will be re-prompted to enter the value. ","version":"Next","tagName":"h3"},{"title":"Conditionally Require Manual User Input Steps","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#conditionally-require-manual-user-input-steps","content":" When possible, a useful design pattern is to write your scripts such that they can run without prompting for any user input. This allows the scripts to be more easily tested and provides a documented default value for any user input choices or values. To implement this pattern, all manual steps such as ask(), prompt(), and infinite wait() statements need to be wrapped with an if statement that checks the value of $manual in Ruby or RunningScript.manual in Python. If the variable is set, then the manual steps should be executed. If not, then a default value should be used. Ruby Example: if $manual temp = ask("Please enter the temperature") else temp = 20.0 end if !$manual puts "Skipping infinite wait in auto mode" else wait end Python Example: if RunningScript.manual: temp = ask("Please enter the temperature") else: temp = 20.0 if not RunningScript.manual: print("Skipping infinite wait in auto mode") else: wait() When running suites, there is a checkbox at the top of the tool called “Manual” that affects this $manual variable directly. ","version":"Next","tagName":"h3"},{"title":"Outputting Extra Information to a Report","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#outputting-extra-information-to-a-report","content":" COSMOS Script Runner operating on a script suite automatically generates a report that shows the PASS/FAILED/SKIPPED state for each script. You can also inject arbitrary text into this report using the example as follows. Alternatively, you can simply use print text into the Script Runner message log. Ruby: class MyGroup < OpenC3::Group def script_1 # The following text will be placed in the report OpenC3::Group.puts "Verifies requirements 304, 306, 310" # This puts line will show up in the sr_messages log file puts "script_1 complete" end end Python: from openc3.script.suite import Group class MyGroup(Group): def script_1(): # The following text will be placed in the report Group.print("Verifies requirements 304, 306, 310") # This puts line will show up in the sr_messages log file print("script_1 complete") ","version":"Next","tagName":"h3"},{"title":"Getting the Most Recent Value of a Telemetry Point from Multiple Packets","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#getting-the-most-recent-value-of-a-telemetry-point-from-multiple-packets","content":" Some systems include high rate data points with the same name in every packet. COSMOS supports getting the most recent value of a telemetry point that is in multiple packets using a special packet name of LATEST. Assume the target INST has two packets, PACKET1 and PACKET2. Both packets have a telemetry point called TEMP. # Get the value of TEMP from the most recently received PACKET1 value = tlm("INST PACKET1 TEMP") # Get the value of TEMP from the most recently received PACKET2 value = tlm("INST PACKET2 TEMP") # Get the value of TEMP from the most recently received PACKET1 or PACKET2 value = tlm("INST LATEST TEMP") ","version":"Next","tagName":"h3"},{"title":"Checking Every Single Sample of a Telemetry Point","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#checking-every-single-sample-of-a-telemetry-point","content":" When writing COSMOS scripts, checking the most recent value of a telemetry point normally gets the job done. The tlm(), tlm_raw(), etc methods all retrieve the most recent value of a telemetry point. Sometimes you need to perform analysis on every single sample of a telemetry point. This can be done using the COSMOS packet subscription system. The packet subscription system lets you choose one or more packets and receive them all from a queue. You can then pick out the specific telemetry points you care about from each packet. Ruby: id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]) wait 1.5 id, packets = get_packets(id) packets.each do |packet| puts "#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}" end # Wait for some time later and reuse the last returned ID id, packets = get_packets(id) Python: id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]) wait(1.5) id, packets = get_packets(id) for packet in packets: print(f"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}") # Wait for some time later and reuse the last returned ID id, packets = get_packets(id) ","version":"Next","tagName":"h3"},{"title":"Using Variables in Mnemonics","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#using-variables-in-mnemonics","content":" Because command and telemetry mnemonics are just strings in COSMOS scripts, you can make use of variables in some contexts to make reusable code. For example, a method can take a target name as an input to support multiple instances of a target. You could also pass in the value for a set of numbered telemetry points. Ruby: def example(target_name, temp_number) cmd("#{target_name} COLLECT with TYPE NORMAL") wait_check("#{target_name} TEMP#{temp_number} > 50.0") end Python: def example(target_name, temp_number): cmd(f"{target_name} COLLECT with TYPE NORMAL") wait_check(f"{target_name} TEMP{temp_number} > 50.0") This can also be useful when looping through a numbered set of telemetry points but be considerate of the downsides of looping as discussed in the Looping vs Unrolled Loops section. ","version":"Next","tagName":"h3"},{"title":"Using Custom wait_check_expression","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#using-custom-wait_check_expression","content":" The COSMOS wait_check_expression (and check_expression) allow you to perform more complicated checks and still stop the script with a CHECK error message if something goes wrong. For example, you can check variables against each other or check a telemetry point against a range. The exact string of text passed to wait_check_expression is repeatedly evaluated until it passes, or a timeout occurs. It is important to not use string interpolation within the actual expression or the values inside of the string interpolation syntax will only be evaluated once when it is converted into a string. Ruby: one = 1 two = 2 wait_check_expression("one == two", 1) # ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds # Checking an integer range wait_check_expression("one > 0 and one < 10 # init value one = #{one}", 1) Python: one = 1 two = 2 wait_check_expression("one == two", 1, 0.25, locals()) # ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds # Checking an integer range wait_check_expression("one > 0 and one < 10", 1, 0.25, locals()) ","version":"Next","tagName":"h3"},{"title":"COSMOS Scripting Differences from Regular Ruby Scripting","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#cosmos-scripting-differences-from-regular-ruby-scripting","content":" Do not use single line if statements COSMOS scripting instruments each line to catch exceptions if things go wrong. With single line if statements the exception handling doesn't know which part of the statement failed and cannot properly continue. If an exception is raised in a single line if statement, then the entire script will stop and not be able to continue. Do not use single line if statements in COSMOS scripts. (However, they are fine to use in interfaces and other Ruby code, just not COSMOS scripts). Don't do this: run_method() if tlm("INST HEALTH_STATUS TEMP1") > 10.0 Do this instead: # It is best not to execute any code that could fail in an if statement, ie # tlm() could fail if the CmdTlmServer was not running or a mnemonic # was misspelled temp1 = tlm("INST HEALTH_STATUS TEMP1") if temp1 > 10.0 run_method() end ","version":"Next","tagName":"h3"},{"title":"When Things Go Wrong","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#when-things-go-wrong","content":" ","version":"Next","tagName":"h2"},{"title":"Common Reasons Checks Fail","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#common-reasons-checks-fail","content":" There are three common reasons that checks fail in COSMOS scripts: The delay given was too short The wait_check() method takes a timeout that indicates how long to wait for the referenced telemetry point to pass the check. The timeout needs to be large enough for the system under test to finish its action and for updated telemetry to be received. Note that the script will continue as soon as the check completes successfully. Thus, the only penalty for a longer timeout is the additional wait time in a failure condition. The range or value checked against was incorrect or too stringent Often the actual telemetry value is ok, but the expected value checked against was too tight. Loosen the ranges on checks when it makes sense. Ensure your script is using the wait_check_tolerance() routine when checking floating point numbers and verify you're using an appropriate tolerance value. The check really failed Of course, sometimes there are real failures. See the next section for how to handle them and recover. ","version":"Next","tagName":"h3"},{"title":"How to Recover from Anomalies","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#how-to-recover-from-anomalies","content":" Once something has failed, and your script has stopped with a pink highlighted line, how can you recover? Fortunately, COSMOS provides several mechanisms that can be used to recover after something in your script fails. Retry After a failure, the Script Runner “Pause” button changes to “Retry”. Clicking on the Retry button will re-execute the line the failed. For failures due to timing issues, this will often resolve the issue and allow the script to continue. Make note of the failure and be sure to update your script prior to the next run. Use the Debug Prompt By selecting Script -> Toggle Debug, you can perform arbitrary actions that may be needed to correct the situation without stopping the running script. You can also inspect variables to help determine why something failed. Execute Selection If only a small section of a script needs to be run, then “Execute Selection" can be used to execute only a small portion of the script. This can also be used when a script is paused or stopped in error. Run from here By clicking into a script, and right clicking to select "Run from here", users can restart a script at an arbitrary point. This works well if no required variable definitions exist earlier in the script. ","version":"Next","tagName":"h3"},{"title":"Advanced Topics","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#advanced-topics","content":" ","version":"Next","tagName":"h2"},{"title":"Advanced Script Configuration with CSV or Excel","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#advanced-script-configuration-with-csv-or-excel","content":" Using a spreadsheet to store the values for use by a script can be a great option if you have a CM-controlled script but need to be able to tweak some values for a test or if you need to use different values for different serial numbers. The Ruby CSV class be used to easily read data from CSV files (recommended for cross platform projects). require 'csv' values = CSV.read('test.csv') puts values[0][0] If you are only using Windows, COSMOS also contains a library for reading Excel files. require 'openc3/win32/excel' ss = ExcelSpreadsheet.new('C:/git/cosmos/test.xlsx') puts ss[0][0][0] ","version":"Next","tagName":"h3"},{"title":"When to use Ruby Modules","type":1,"pageTitle":"Script Writing Guide","url":"/docs/guides/script-writing#when-to-use-ruby-modules","content":" Modules in Ruby have two purposes: namespacing and mixins. Namespacing allows having classes and methods with the same name, but with different meanings. For example, if they are namespaced, COSMOS can have a Packet class and another Ruby library can have a Packet class. This isn't typically useful for COSMOS scripting though. Mixins allow adding common methods to classes without using inheritance. Mixins can be useful to add common functionality to some classes but not others, or to break up classes into multiple files. module MyModule def module_method end end class MyTest < OpenC3::Group include MyModule def test_1 module_method() end end ","version":"Next","tagName":"h3"},{"title":"Screens","type":0,"sectionRef":"#","url":"/docs/configuration/telemetry-screens","content":"","keywords":"","version":"Next"},{"title":"Definitions","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#definitions","content":" Name\tDefinitionWidget\tA widget is a graphical element on a COSMOS telemetry screen. It could display text, graph data, provide a button, or perform any other display/user input task. Screen\tA screen is a single window that contains any number of widgets which are organized and layed-out in a useful fashion. Screen Definition File\tA screen definition file is an ASCII file that tells Telemetry Viewer how to draw a screen. It is made up of a series of keyword/parameter lines that define the telemetry points that are displayed on the screen and how to display them. ","version":"Next","tagName":"h2"},{"title":"Telemetry Screen Definition Files","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#telemetry-screen-definition-files","content":" Telemetry screen definition files define the the contents of telemetry screens. They take the general form of a SCREEN keyword followed by a series of widget keywords that define the telemetry screen. Screen definition files specific to a particular target go in that target's screens directory. For example: TARGET/screens/version.txt. Screen definition files must be lowercase. ","version":"Next","tagName":"h2"},{"title":"New Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#new-widgets","content":" When a telemetry screen definition is parsed and a keyword is encountered that is unrecognized, it is assumed that a file of the form widgetname_widget.rb exists, and contains a class called WidgetnameWidget. Because of this convention, new widgets can be added to the system without any change to the telemetry screen definition format. For more information about creating custom widgets please read the Custom Widgets guide. Screen Keywords ","version":"Next","tagName":"h2"},{"title":"SCREEN","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#screen","content":" Define a telemetry viewer screen The SCREEN keyword is the first keyword in any telemetry screen definition. It defines the name of the screen and parameters that affect the screen overall. Parameter\tDescription\tRequiredWidth\tWidth in pixels or AUTO to let Telemetry Viewer automatically layout the screen\tTrue Height\tHeight in pixels or AUTO to let Telemetry Viewer automatically layout the screen\tTrue Polling Period\tNumber of seconds between screen updates\tTrue Example Usage: SCREEN AUTO AUTO 1.0 FIXED ","version":"Next","tagName":"h2"},{"title":"END","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#end","content":" Indicates the close of a layout widget All layout widgets must be closed to properly identify where they stop. For example, a VERTICALBOX keyword must be matched with an END keyword to indicate where the VERTICALBOX ends. ","version":"Next","tagName":"h2"},{"title":"STALE_TIME","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#stale_time","content":" (Since 5.1.0) Values are marked stale if the packet time is more than Stale Time seconds in the past Parameter\tDescription\tRequiredvalue\tItems from packets with RECEIVED_TIMESECONDS greater than this value in the past will be marked stale. The default is 30s. Recommend a minimum of 2s to avoid false positives due to race conditions.\tTrue Example Usage: STALE_TIME 5 # Number of seconds to wait before marking data stale ","version":"Next","tagName":"h2"},{"title":"GLOBAL_SETTING","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#global_setting","content":" Applies a widget setting to all widgets of a certain type Parameter\tDescription\tRequiredWidget Class Name\tThe name of the class of widgets that this setting will be applied to. For example, LABEL or BUTTON.\tTrue Setting Name\tSee SETTING for details.\tTrue Setting Value(s)\tSee SETTING for details.\tFalse Example Usage: GLOBAL_SETTING LABELVALUELIMITSBAR TEXTCOLOR BLACK ","version":"Next","tagName":"h2"},{"title":"GLOBAL_SUBSETTING","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#global_subsetting","content":" Applies a widget subsetting to all widgets of a certain type Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget. Parameter\tDescription\tRequiredWidget Class Name\tThe name of the class of widgets that this setting will be applied to. For example, LABELVALUE.\tTrue Subwidget Index\tIndex to the desired subwidget\tTrue Setting Name\tSee SETTING for details.\tTrue Setting Value(s)\tSee SETTING for details.\tFalse Example Usage: # Set all text color to white for labelvaluelimitsbars GLOBAL_SUBSETTING LABELVALUELIMITSBAR 0 TEXTCOLOR white ","version":"Next","tagName":"h2"},{"title":"SETTING","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#setting","content":" Applies a widget setting to the previously defined widget Settings allow for additional tweaks and options to be applied to widgets that are not available in their parameters. These settings are all configured through the SETTING, SUBSETTING, GLOBAL_SETTING and GLOBAL_SUBSETTING keywords. SETTING and SUBSETTING applies only to the widget defined immediately before it. GLOBAL_SETTING and GLOBAL_SUBSETTING applies to all widgets. Common wiget settings are defined here. Some widgets define their own unique settings which are documented under that specific widget. ","version":"Next","tagName":"h2"},{"title":"WIDTH","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#width","content":" Sets the widget width WIDTH supports css units with the default (no units) of px (pixels) Parameter\tDescription\tRequiredWidth\tWidth in pixels or explicitly declared with units\tTrue Example Usage: LABEL "THIS IS A TEST" SETTING WIDTH 50 LABEL "THIS IS A TEST" SETTING WIDTH 20em ","version":"Next","tagName":"h3"},{"title":"HEIGHT","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#height","content":" Sets the widget height HEIGHT supports css units with the default (no units) of px (pixels) Parameter\tDescription\tRequiredHeight\tHeight in pixels or explicitly declared with units\tTrue Example Usage: LABEL "THIS IS A TEST" SETTING BACKCOLOR BLUE SETTING HEIGHT 50 LABEL "THIS IS A TEST" SETTING BACKCOLOR GREY SETTING HEIGHT 2em ","version":"Next","tagName":"h3"},{"title":"MARGIN","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#margin","content":" Sets the widget margin MARGIN supports css units with the default (no units) of px (pixels) Parameter\tDescription\tRequiredSize\tSize in pixels or explicitly declared with units\tTrue Example Usage: LABEL "THIS IS A TEST" SETTING BACKCOLOR BLUE LABEL "THIS IS A TEST" SETTING BACKCOLOR GREY SETTING MARGIN 10 LABEL "THIS IS A TEST" SETTING BACKCOLOR GREEN ","version":"Next","tagName":"h3"},{"title":"PADDING","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#padding","content":" Sets the widget padding PADDING supports css units with the default (no units) of px (pixels) Parameter\tDescription\tRequiredSize\tSize in pixels or explicitly declared with units\tTrue Example Usage: LABEL "THIS IS A TEST" SETTING BACKCOLOR BLUE LABEL "THIS IS A TEST" SETTING BACKCOLOR GREY SETTING PADDING 10 LABEL "THIS IS A TEST" SETTING BACKCOLOR GREEN ","version":"Next","tagName":"h3"},{"title":"BACKCOLOR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#backcolor","content":" The BACKCOLOR setting sets the background color for a widget Parameter\tDescription\tRequiredColor name or Red value\tCommon name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value\tTrue Green value\tGreen value of the RGB value\tFalse Blue value\tBlue value of the RGB value\tFalse Example Usage: LABEL "THIS IS A TEST" SETTING BACKCOLOR red LABEL "THIS IS A TEST" SETTING BACKCOLOR 155 50 155 ","version":"Next","tagName":"h3"},{"title":"TEXTCOLOR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#textcolor","content":" The TEXTCOLOR setting sets the text color for a widget Parameter\tDescription\tRequiredColor name or Red value\tCommon name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value\tTrue Green value\tGreen value of the RGB value\tFalse Blue value\tBlue value of the RGB value\tFalse Example Usage: LABEL "THIS IS A TEST" SETTING TEXTCOLOR red LABEL "THIS IS A TEST" SETTING TEXTCOLOR 155 50 155 ","version":"Next","tagName":"h3"},{"title":"BORDERCOLOR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#bordercolor","content":" The BORDERCOLOR setting sets the border color for a layout widget Parameter\tDescription\tRequiredColor name or Red value\tCommon name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value\tTrue Green value\tGreen value of the RGB value\tFalse Blue value\tBlue value of the RGB value\tFalse Example Usage: HORIZONTAL LABEL "Label 1" END SETTING BORDERCOLOR red VERTICAL LABEL "Label 2" END SETTING BORDERCOLOR 155 50 155 ","version":"Next","tagName":"h3"},{"title":"RAW","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#raw","content":" Apply a raw CSS stylesheet key and value Parameter\tDescription\tRequiredKey\tCSS key like font-size, max-width, etc\tTrue Value\tCSS Value\tTrue Example Usage: LABEL "Label 1" SETTING RAW font-size 30px ","version":"Next","tagName":"h3"},{"title":"SUBSETTING","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#subsetting","content":" Applies a widget subsetting to the previously defined widget Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget. Parameter\tDescription\tRequiredSubwidget Index\tIndex to the desired subwidget or 'ALL' to apply the setting to all the subwidgets of this composite widget.\tTrue Setting Name\tSee SETTING for details.\tTrue Setting Value(s)\tSee SETTING for details.\tFalse Example Usage: VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 SUBSETTING 0 TEXTCOLOR blue # Change the label's text to blue LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP1 SUBSETTING 0 TEXTCOLOR green # Change the label's text to green END ","version":"Next","tagName":"h2"},{"title":"NAMED_WIDGET","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#named_widget","content":" Name a widget to allow access to it via the getNamedWidget method To programmatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets. warning getNamedWidget returns the widget itself and thus must be operated on using methods native to that widget Parameter\tDescription\tRequiredWidget Name\tThe unique name applied to the following widget instance. Names must be unique per screen.\tTrue Widget Type\tOne of the widget types listed in Widget Descriptions\tTrue Widget Parameters\tThe unique parameters for the given widget type\tTrue Example Usage: NAMED_WIDGET DURATION TEXTFIELD BUTTON "Push" "screen.getNamedWidget('DURATION').text()" ","version":"Next","tagName":"h2"},{"title":"Layout Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#layout-widgets","content":" Layout widgets are used to position other widgets on the screen. For example, the HORIZONTAL layout widget places the widgets it encapsulates horizontally on the screen. ","version":"Next","tagName":"h2"},{"title":"VERTICAL","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#vertical","content":" Places the widgets it encapsulates vertically The screen defaults to a vertical layout, so if no layout widgets are specified, all widgets will be automatically placed within a VERTICAL layout widget. The VERTICAL widget sizes itself to fit its contents. Parameter\tDescription\tRequiredMargin\tMargin between widgets (default = 0px)\tFalse Example Usage: VERTICAL 5px LABEL "TEST" LABEL "SCREEN" END ","version":"Next","tagName":"h3"},{"title":"VERTICALBOX","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#verticalbox","content":" Places the widgets it encapsulates vertically inside a thin border The VERTICALBOX widget sizes itself to fit its contents vertically and to fit the screen horizontally Parameter\tDescription\tRequiredTitle\tText to place within the border to label the box\tFalse Margin\tMargin between widgets (default = 0px)\tFalse Example Usage: VERTICALBOX Info LABEL "TEST" LABEL "SCREEN" END ","version":"Next","tagName":"h3"},{"title":"HORIZONTAL","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#horizontal","content":" Places the widgets it encapsulates horizontally The HORIZONTAL widget sizes itself to fit its contents Parameter\tDescription\tRequiredMargin\tMargin between widgets (default = 0px)\tFalse Example Usage: HORIZONTAL 100 LABEL "TEST" LABEL "SCREEN" END ","version":"Next","tagName":"h3"},{"title":"HORIZONTALBOX","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#horizontalbox","content":" Places the widgets it encapsulates horizontally inside a thin border The HORIZONTALBOX widget sizes itself to fit its contents Parameter\tDescription\tRequiredTitle\tText to place within the border to label the box\tFalse Margin\tMargin between widgets (default = 0px)\tFalse Example Usage: HORIZONTALBOX Info 10 LABEL "TEST" LABEL "SCREEN" END ","version":"Next","tagName":"h3"},{"title":"MATRIXBYCOLUMNS","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#matrixbycolumns","content":" Places the widgets into a table-like matrix The MATRIXBYCOLUMNS widget sizes itself to fit its contents Parameter\tDescription\tRequiredColumns\tThe number of columns to create\tTrue Margin\tMargin between widgets (default = 0px)\tFalse Example Usage: MATRIXBYCOLUMNS 3 10 LABEL "COL 1" LABEL "COL 2" LABEL "COL 3" LABEL "100" LABEL "200" LABEL "300" END ","version":"Next","tagName":"h3"},{"title":"SCROLLWINDOW","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#scrollwindow","content":" Places the widgets inside of it into a scrollable area The SCROLLWINDOW widget sizes itself to fit the screen in which it is contained Parameter\tDescription\tRequiredHeight\tMaximum height of the scroll window in pixels (default = 200)\tFalse Margin\tMargin between widgets (default = 0px)\tFalse Example Usage: SCROLLWINDOW 100 10 VERTICAL LABEL "100" LABEL "200" LABEL "300" LABEL "400" LABEL "500" LABEL "600" LABEL "700" LABEL "800" LABEL "900" END END ","version":"Next","tagName":"h3"},{"title":"TABBOOK","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#tabbook","content":" Creates a tabbed area in which to place TABITEM widgets ","version":"Next","tagName":"h3"},{"title":"TABITEM","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#tabitem","content":" Creates a VERTICAL layout tab into which to place widgets Parameter\tDescription\tRequiredTab text\tText to display in the tab\tTrue Example Usage: TABBOOK TABITEM "Tab 1" LABEL "100" LABEL "200" END TABITEM "Tab 2" LABEL "300" LABEL "400" END END ","version":"Next","tagName":"h3"},{"title":"IFRAME","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#iframe","content":" Open external tools in an Iframe within OpenC3 Parameter\tDescription\tRequiredURL\tThe path to the page to display in the iframe\tTrue Width\tWidth of the widget\tFalse Height\tHeight of the widget\tFalse Example Usage: IFRAME https://openc3.com 900 450 ","version":"Next","tagName":"h3"},{"title":"Decoration Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#decoration-widgets","content":" Decoration widgets are used to enhance the appearance of the screen. They do not respond to input, nor does the output vary with telemetry. ","version":"Next","tagName":"h2"},{"title":"LABEL","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#label","content":" Displays text on the screen Generally, label widgets contain a telemetry mnemonic and are placed next to the telemetry VALUE widget. Parameter\tDescription\tRequiredText\tText to display on the label\tTrue Example Usage: LABEL "Note: This is only a warning" ","version":"Next","tagName":"h3"},{"title":"HORIZONTALLINE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#horizontalline","content":" (Since 5.5.1) Displays a horizontal line on the screen that can be used as a separator Example Usage: LABEL Over HORIZONTALLINE LABEL Under ","version":"Next","tagName":"h3"},{"title":"SECTIONHEADER","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#sectionheader","content":" DEPRECATED - Displays a label that is underlined with a horizontal line Use a VERTICALBOX or HORIZONTALBOX with title parameter instead of SECTIONHEADER Parameter\tDescription\tRequiredText\tText to display\tTrue ","version":"Next","tagName":"h3"},{"title":"TITLE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#title","content":" Displays a large centered title on the screen Parameter\tDescription\tRequiredText\tText to display\tTrue Example Usage: TITLE "Title" HORIZONTALLINE LABEL "Label" ","version":"Next","tagName":"h3"},{"title":"SPACER","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#spacer","content":" Places a fixed size spacer in between widgets Parameter\tDescription\tRequiredWidth\tWidth of the spacer in pixels\tTrue Height\tHeight of the spacer in pixels\tTrue Example Usage: VERTICAL 3 LABEL "Spacer below" SPACER 0 100 LABEL "Spacer above" END ","version":"Next","tagName":"h3"},{"title":"Telemetry Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#telemetry-widgets","content":" Telemetry widgets are used to display telemetry values. The first parameters to each of these widgets is a telemetry mnemonic. Depending on the type and purpose of the telemetry item, the screen designer may select from a wide selection of widgets to display the value in the most useful format. ","version":"Next","tagName":"h2"},{"title":"ARRAY","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#array","content":" Displays ARRAY data organized into rows and space separated Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Width\tWidth of the widget (default = 200)\tFalse Height\tHeight of the widget (default = 100)\tFalse Format string\tFormat string applied to each array item (default = nil)\tFalse Items per row\tNumber of array items per row (default = 4)\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: ARRAY INST HEALTH_STATUS ARY 250 80 "0x%x" 6 FORMATTED ARRAY INST HEALTH_STATUS ARY2 200 100 nil 4 WITH_UNITS ","version":"Next","tagName":"h3"},{"title":"BLOCK","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#block","content":" Displays BLOCK data organized into rows and space separated Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Width\tWidth of the widget (default = 200)\tFalse Height\tHeight of the widget (default = 100)\tFalse Format string\tFormat string applied to each array item (default = nil)\tFalse Bytes per word\tNumber of bytes per word (default = 4)\tFalse Words per row\tNumber of words per row (default = 4\tFalse Address format\tFormat for the address printed at the beginning of each line (default = nil which means do not print an address)\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: BLOCK INST IMAGE IMAGE 400 130 "%02X" 4 4 "0x%08X:" ","version":"Next","tagName":"h3"},{"title":"FORMATVALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#formatvalue","content":" Displays a box with a formatted value Data is formatted by the specified string rather than by a format string given in the telemetry definition files. The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits). Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Format string\tPrintf style format string to apply to the telemetry item\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: FORMATVALUE INST LATEST TIMESEC %012u CONVERTED 20 ","version":"Next","tagName":"h3"},{"title":"LABELLED","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelled","content":" Displays a LABEL followed by a LED Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Width\tWidth of the LED circle (default = 15)\tFalse Height\tHeight of the LED circle (default = 15)\tFalse Justification\tHow to justify the label and LED together. The default of 'SPLIT' aligns the label to the left and the LED to the right with any additional space going between them. 'CENTER' pushes the label and LED together with any additional space to the left and right. 'LEFT' or 'RIGHT' pushes them to the respective side with the space going on the opposite. Valid Values: SPLIT, CENTER, LEFT, RIGHT\tFalse Example Usage: LABELLED INST PARAMS VALUE1 SETTING LED_COLOR GOOD GREEN SETTING LED_COLOR BAD RED The following settings apply to LABELLED. They are applied using the SETTING keyword. LED_COLOR Map a state or value to a color Parameter\tDescription\tRequiredValue\tState or value. ANY used to match any value or state not declared.\tTrue LED color\tColor of the LED\tTrue ","version":"Next","tagName":"h3"},{"title":"LABELPROGRESSBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelprogressbar","content":" Displays a LABEL with the item name followed by a PROGRESSBAR Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Scale factor\tValue to multiply the telemetry item by before displaying in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0.\tFalse Width\tWidth of the progress bar (default = 80 pixels\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: LABELPROGRESSBAR INST ADCS POSPROGRESS 2 200 RAW LABELPROGRESSBAR INST ADCS POSPROGRESS ","version":"Next","tagName":"h3"},{"title":"LABELVALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelvalue","content":" Displays a LABEL with the item name followed by a VALUE Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: LABELVALUE INST LATEST TIMESEC CONVERTED 18 LABELVALUE INST LATEST COLLECT_TYPE ","version":"Next","tagName":"h3"},{"title":"LABELVALUEDESC","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelvaluedesc","content":" Displays a LABEL with the items description followed by a VALUE Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Description\tThe description to display in the label (default is to display the description text associated with the telemetry item)\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: LABELVALUEDESC INST HEALTH_STATUS TEMP1 "Temperature number 1" RAW 18 LABELVALUEDESC INST HEALTH_STATUS COLLECT_TYPE ","version":"Next","tagName":"h3"},{"title":"LABELVALUELIMITSBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelvaluelimitsbar","content":" Displays a LABEL with the item name followed by VALUE and LIMITSBAR widgets Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse ","version":"Next","tagName":"h3"},{"title":"LABELVALUELIMITSCOLUMN","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelvaluelimitscolumn","content":" Displays a LABEL with the item name followed by VALUE and LIMITSCOLUMN widgets Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: LABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18 LABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"LABELVALUERANGEBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelvaluerangebar","content":" Displays a LABEL with the item name followed by VALUE and RANGEBAR widgets Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Low Value\tMinimum value to display on the range bar. If the telemetry item goes below this value the bar is “pegged” on the low end.\tTrue High Value\tMaximum value to display on the range bar. If the telemetry item goes above this value the bar is “pegged” on the high end.\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Width\tWidth of the range bar (default = 160)\tFalse Height\tHeight of the range bar (default = 25)\tFalse Example Usage: LABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40 LABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120 ","version":"Next","tagName":"h3"},{"title":"LED","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#led","content":" Displays a LED which changes color based on telemetry values By default TRUE is green and FALSE is red and all other values are black. Additional values can be added by using the LED_COLOR setting. For example LED INST PARAMS VALUE3 RAW can be followed by SETTING LED_COLOR 0 GREEN, SETTING LED_COLOR 1 RED, and SETTING LED_COLOR ANY ORANGE. Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Width\tWidth of the LED circle (default = 15)\tFalse Height\tHeight of the LED circle (default = 15)\tFalse Example Usage: LED INST PARAMS VALUE5 RAW 25 20 # Ellipse SETTING LED_COLOR 0 GREEN SETTING LED_COLOR 1 RED SETTING LED_COLOR ANY YELLOW The following settings apply to LED. They are applied using the SETTING keyword. LED_COLOR Map a state or value to a color Parameter\tDescription\tRequiredValue\tState or value. ANY used to match any value or state not declared.\tTrue LED color\tColor of the LED\tTrue ","version":"Next","tagName":"h3"},{"title":"LIMITSBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#limitsbar","content":" Displays an item's current value within its colored limits horizontally Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Width\tWidth of the range bar (default = 160)\tFalse Height\tHeight of the range bar (default = 25)\tFalse Example Usage: LIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 200 50 LIMITSBAR INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"LIMITSCOLUMN","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#limitscolumn","content":" Displays an item's current value within its colored limits vertically Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Width\tWidth of the range bar (default = 160)\tFalse Height\tHeight of the range bar (default = 25)\tFalse Example Usage: LIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 50 200 LIMITSCOLUMN INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"LIMITSCOLOR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#limitscolor","content":" Displays a circle depicting the limits color of an item Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Radius\tRadius of the circle (default is 10)\tFalse Full Item Name\tShow the full item name (default is false)\tFalse Example Usage: LIMITSCOLOR INST HEALTH_STATUS TEMP1 CONVERTED 30 TRUE LIMITSCOLOR INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"VALUELIMITSBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#valuelimitsbar","content":" Displays an item VALUE followed by LIMITSBAR Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: VALUELIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 18 VALUELIMITSBAR INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"VALUELIMITSCOLUMN","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#valuelimitscolumn","content":" Displays an item VALUE followed by LIMITSCOLUMN Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 8)\tFalse Example Usage: VALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18 VALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"VALUERANGEBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#valuerangebar","content":" Displays an item VALUE followed by RANGEBAR Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Low Value\tMinimum value to display on the range bar. If the telemetry item goes below this value the bar is “pegged” on the low end.\tTrue High Value\tMaximum value to display on the range bar. If the telemetry item goes above this value the bar is “pegged” on the high end.\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Width\tWidth of the range bar (default = 160)\tFalse Height\tHeight of the range bar (default = 25)\tFalse Example Usage: VALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40 VALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120 ","version":"Next","tagName":"h3"},{"title":"LINEGRAPH","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#linegraph","content":" Displays a line graph of a telemetry item Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse Example Usage: LINEGRAPH INST HEALTH_STATUS TEMP1 SETTING ITEM INST ADCS Q1 # Add additional item to graph LINEGRAPH INST HEALTH_STATUS TEMP2 RAW LINEGRAPH INST HEALTH_STATUS TEMP3 CONVERTED REDUCED_MINUTE MIN SETTING SIZE 600 500 # width height SETTING HISTORY 1h # load 1 hour of data into graph LINEGRAPH INST HEALTH_STATUS TEMP4 SETTING HISTORY 30m # load 30 minutes of data into graph The following settings apply to LINEGRAPH. They are applied using the SETTING keyword. ITEM Add a telemetry item to the graph Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse STARTTIME (Since 5.5.1) Start the graph history at the designated Time Parameter\tDescription\tRequiredStart Time\tStart time as formatted 'YYYY/MM/DD HH:MM:SS'\tTrue HISTORY (Since 5.5.1) Display an initial history of data Parameter\tDescription\tRequiredValue\tValue(d,h,m,s). For example 1d, 2h, 30m, 15s\tTrue SECONDSGRAPHED Display the specified number of seconds in the graph Parameter\tDescription\tRequiredTime\tNumber of seconds to display\tTrue POINTSSAVED Save the number of seconds in graph memory Parameter\tDescription\tRequiredTime\tNumber of seconds to save\tTrue POINTSGRAPHED Number of points to display on the graph Parameter\tDescription\tRequiredTime\tNumber of points to graph\tTrue SIZE Size of the graph Parameter\tDescription\tRequiredWidth\tWidth in pixels\tTrue Height\tHeight in pixels\tTrue ","version":"Next","tagName":"h3"},{"title":"SPARKLINE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#sparkline","content":" Displays a sparkline graph (no cursor, scale or legend) of a telemetry item Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse Example Usage: SPARKLINE INST HEALTH_STATUS TEMP1 SETTING SIZE 400 50 SETTING HISTORY 30s # Add 30 seconds of data into graph The following settings apply to SPARKLINE. They are applied using the SETTING keyword. ITEM Add a telemetry item to the graph Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse STARTTIME (Since 5.5.1) Start the graph history at the designated Time Parameter\tDescription\tRequiredStart Time\tStart time as formatted 'YYYY/MM/DD HH:MM:SS'\tTrue HISTORY (Since 5.5.1) Display an initial history of data Parameter\tDescription\tRequiredValue\tValue(d,h,m,s). For example 1d, 2h, 30m, 15s\tTrue SECONDSGRAPHED Display the specified number of seconds in the graph Parameter\tDescription\tRequiredTime\tNumber of seconds to display\tTrue POINTSSAVED Save the number of seconds in graph memory Parameter\tDescription\tRequiredTime\tNumber of seconds to save\tTrue POINTSGRAPHED Number of points to display on the graph Parameter\tDescription\tRequiredTime\tNumber of points to graph\tTrue SIZE Size of the graph Parameter\tDescription\tRequiredWidth\tWidth in pixels\tTrue Height\tHeight in pixels\tTrue ","version":"Next","tagName":"h3"},{"title":"LABELSPARKLINE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#labelsparkline","content":" Displays a LABEL with the item name followed by a SPARKLINE Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse Example Usage: LABELSPARKLINE INST HEALTH_STATUS TEMP1 SETTING HISTORY 5m # Add 5 minutes of data into graph The following settings apply to LABELSPARKLINE. They are applied using the SETTING keyword. ITEM Add a telemetry item to the graph Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Reduced\tWhether to display reduced data. Default is DECOM. Valid Values: DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY\tFalse Reduced Type\tThe type of reduce data to display. Only applies if Reduced is not DECOM. Valid Values: MIN, MAX, AVG, STDDEV\tFalse STARTTIME (Since 5.5.1) Start the graph history at the designated Time Parameter\tDescription\tRequiredStart Time\tStart time as formatted 'YYYY/MM/DD HH:MM:SS'\tTrue HISTORY (Since 5.5.1) Display an initial history of data Parameter\tDescription\tRequiredValue\tValue(d,h,m,s). For example 1d, 2h, 30m, 15s\tTrue SECONDSGRAPHED Display the specified number of seconds in the graph Parameter\tDescription\tRequiredTime\tNumber of seconds to display\tTrue POINTSSAVED Save the number of seconds in graph memory Parameter\tDescription\tRequiredTime\tNumber of seconds to save\tTrue POINTSGRAPHED Number of points to display on the graph Parameter\tDescription\tRequiredTime\tNumber of points to graph\tTrue SIZE Size of the graph Parameter\tDescription\tRequiredWidth\tWidth in pixels\tTrue Height\tHeight in pixels\tTrue ","version":"Next","tagName":"h3"},{"title":"IMAGEVIEWER","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#imageviewer","content":" Display a base64 image from a TLM packet Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name to pull the CONVERTED value from. If additional processing (base64 encoding) is needed consider using a DERIVED item.\tTrue Format\tThe image format of the base64 data (e.g. jpg, png, etc)\tTrue Example Usage: IMAGEVIEWER INST IMAGE IMAGE jpg ","version":"Next","tagName":"h3"},{"title":"PROGRESSBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#progressbar","content":" Displays a progress bar that is useful for displaying percentages Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Scale factor\tValue to multiple the telemetry item by before displaying the in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0.\tFalse Width\tWidth of the progress bar (default = 100 pixels)\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: PROGRESSBAR INST ADCS POSPROGRESS 0.5 200 PROGRESSBAR INST ADCS POSPROGRESS ","version":"Next","tagName":"h3"},{"title":"RANGEBAR","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#rangebar","content":" Displays a custom range bar displaying the item value Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Low Value\tMinimum value to display on the range bar. If the telemetry item goes below this value the bar is “pegged” on the low end.\tTrue High Value\tMaximum value to display on the range bar. If the telemetry item goes above this value the bar is “pegged” on the high end.\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Width\tWidth of the range bar (default = 100)\tFalse Height\tHeight of the range bar (default = 25)\tFalse Example Usage: RANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 200 50 RANGEBAR INST HEALTH_STATUS TEMP1 -100 100 ","version":"Next","tagName":"h3"},{"title":"ROLLUP","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#rollup","content":" (Since 5.17.1) Displays a notification icon which changes color based on a rollup telemetry Parameter\tDescription\tRequiredIcon name\tThe astro UX icon to display. Valid choices are 'astro' icons taken from https://github.com/RocketCommunicationsInc/astro-components/blob/master/static/json/rux-icons.json.\tTrue Icon label\tText to apply to the icon label\tFalse Icon sublabel\tText to apply to the icon sublabel\tFalse Example Usage: ROLLUP satellite-transmit "SAT 1" "Details" # Screen to open on click SETTING SCREEN INST HS # Telemetry items to rollup status SETTING TLM INST HEALTH_STATUS TEMP1 SETTING TLM INST HEALTH_STATUS TEMP2 ROLLUP antenna "GND 2" "Location" # Screen to open on click SETTING SCREEN INST HS # Telemetry items to rollup status SETTING TLM INST HEALTH_STATUS TEMP3 SETTING TLM INST HEALTH_STATUS TEMP4 ","version":"Next","tagName":"h3"},{"title":"SIGNAL","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#signal","content":" (Since 5.17.2) Displays a cellular signal icon which changes based on telemetry value Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED\tFalse Example Usage: SIGNAL INST HEALTH_STATUS TEMP1 # Screen to open on click SETTING SCREEN INST HS # Values to compare when setting the 1-bar, 2-bar and 3-bar icons # Default is 30, 60, 90 (e.g. 0 to 100 range) # Value < -50 display no bars # Value >= -50 and < 0 displays 1 bar # Value >= 0 and < 50 displays 2 bars # Value >= 50 displays 5 bars SETTING RANGE -50 0 50 ","version":"Next","tagName":"h3"},{"title":"TEXTBOX","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#textbox","content":" Provides a large box for multiline text Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Width\tWidth of the textbox in px (default = 200)\tFalse Height\tHeight of the textbox in px (default = 200)\tFalse Example Usage: TEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED 150 70 TEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED ","version":"Next","tagName":"h3"},{"title":"VALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#value","content":" Displays a box with a telemetry item value The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits). Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Number of characters\tThe number of characters wide to make the value box (default = 12)\tFalse Example Usage: VALUE INST HEALTH_STATUS TEMP1 CONVERTED 18 VALUE INST HEALTH_STATUS TEMP1 ","version":"Next","tagName":"h3"},{"title":"Interactive Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#interactive-widgets","content":" Interactive widgets are used to gather input from the user. Unlike all other widgets, which only output some graphical representation, interactive widgets permit input either from the keyboard or mouse. ","version":"Next","tagName":"h2"},{"title":"BUTTON","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#button","content":" Displays a rectangular clickable button Upon clicking, the button executes the Javascript code assigned. Buttons can be used to send commands and perform other tasks. If you want your button to use values from other widgets, define them as named widgets and read their values using the screen.getNamedWidget("WIDGET_NAME").text() method. See the example in CHECKBUTTON. Button code can get rather complex so remember to use string concatenation to make things more readable. If you use + newlines are inserted automatically during string concatenation. If you use \\ you'll need to separate lines with a single semicolon ;. COSMOS uses double semicolon ;; to indicate lines should be evaluated separately. Note that all OpenC3 commands (using api.cmd) must be separated by ;;. You can send commands with buttons using api.cmd(). The cmd() syntax looks exactly like the standard COSMOS scripting syntax. You can also request and use telemetry in screens using Javascript Promises. api.tlm('INST PARAMS VALUE3', 'RAW').then(dur => api.cmd('INST COLLECT with TYPE NORMAL, DURATION '+dur))" The api.tlm() function returns a Promise which is resolved with then() at which point we send the command with the telemetry value we received. Scripts can be launched from a BUTTON using the runScript() method. runScript() takes three parameters, the name of the script, whether to open the script in the foreground of Script Runner (default = true), and a hash of environment variables. For example: runScript('INST/procedures/script.rb', false, {'VAR': 'VALUE'}) Parameter\tDescription\tRequiredButton Text\tText displayed on the button\tTrue Button Code\tJavascript code to execute when the button is pressed\tTrue Example Usage: BUTTON 'Start Collect' 'api.cmd("INST COLLECT with TYPE NORMAL, DURATION 5")' BUTTON 'Run Checks' 'runScript("INST/procedures/checks.rb")' # More complex example with background checkbox and env vars NAMED_WIDGET SCRIPTNAME COMBOBOX collect.rb checks.rb NAMED_WIDGET BG CHECKBUTTON 'Background' BUTTON 'Run Script' "var script=screen.getNamedWidget('SCRIPTNAME').text();" \\ # Set an environment variable to be used by the script as ENV['TYPE'] "var env = {}; env['TYPE'] = 'TEST';" \\ "runScript('INST/procedures/'+script, !screen.getNamedWidget('BG').checked(), env)" ","version":"Next","tagName":"h3"},{"title":"CHECKBUTTON","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#checkbutton","content":" Displays a check box Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET. Parameter\tDescription\tRequiredCheckbox Text\tText displayed next to the checkbox\tTrue Example Usage: NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks' BUTTON 'Send' 'screen.getNamedWidget("CHECK").checked() ? ' \\ 'api.cmd_no_hazardous_check("INST CLEAR") : api.cmd("INST CLEAR")' ","version":"Next","tagName":"h3"},{"title":"COMBOBOX","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#combobox","content":" Displays a drop down list of text items Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET. Parameter\tDescription\tRequiredOption Text 1\tText to display in the selection drop down\tTrue Option Text n\tText to display in the selection drop down\tFalse Example Usage: BUTTON 'Start Collect' 'var type = screen.getNamedWidget("COLLECT_TYPE").text();' + 'api.cmd("INST COLLECT with TYPE "+type+", DURATION 10.0")' NAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL ","version":"Next","tagName":"h3"},{"title":"RADIOGROUP","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#radiogroup","content":" Creates a group of RADIOBUTTONs RADIOBUTTONs must be part of a group to enable selection logic Parameter\tDescription\tRequiredInitial selected button\tSelects a radio button at initialization (0-based)\tFalse ","version":"Next","tagName":"h3"},{"title":"RADIOBUTTON","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#radiobutton","content":" Displays a radio button and text Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET. It must be contained by a RADIOGROUP to enable typical selection of a single RADIOBUTTON. Parameter\tDescription\tRequiredText\tText to display next to the radio button\tTrue Example Usage: NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index RADIOBUTTON 'Abort' RADIOBUTTON 'Clear' END BUTTON 'Send' "screen.getNamedWidget('GROUP').selected() === 0 ? " + "api.cmd('INST ABORT') : api.cmd('INST CLEAR')" ","version":"Next","tagName":"h3"},{"title":"TEXTFIELD","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#textfield","content":" Displays a rectangular box where the user can enter text Parameter\tDescription\tRequiredCharacters\tWidth of the text field in characters (default = 12)\tFalse Text\tDefault text to put in the text field (default is blank)\tFalse Example Usage: NAMED_WIDGET DURATION TEXTFIELD 12 "10.0" BUTTON 'Start Collect' 'var dur = screen.getNamedWidget("DURATION").text();' + 'api.cmd("INST COLLECT with TYPE NORMAL, DURATION "+dur+"")' ","version":"Next","tagName":"h3"},{"title":"Canvas Widgets","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvas-widgets","content":" Canvas Widgets are used to draw custom displays into telemetry screens. The canvas coordinate frame places (0,0) in the upper-left corner of the canvas. ","version":"Next","tagName":"h2"},{"title":"CANVAS","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvas","content":" Layout widget for the other canvas widgets All canvas widgets must be enclosed within a CANVAS widget. warning The canvas coordinate frame places (0,0) in the upper-left corner of the canvas. Parameter\tDescription\tRequiredWidth\tWidth of the canvas\tTrue Height\tHeight of the canvas\tTrue ","version":"Next","tagName":"h3"},{"title":"CANVASLABEL","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvaslabel","content":" Draws text onto the canvas Parameter\tDescription\tRequiredX Position\tX position of the upper-left corner of the text on the canvas\tTrue Y Position\tY position of the upper-left corner of the text on the canvas\tTrue Text\tText to draw onto the canvas\tTrue Font Size\tFont size of the text (Default = 12)\tFalse Color\tColor of the text\tFalse Example Usage: CANVAS 100 100 CANVASLABEL 5 34 "Label1" 24 red CANVASLABEL 5 70 "Label2" 18 blue END ","version":"Next","tagName":"h3"},{"title":"CANVASLABELVALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvaslabelvalue","content":" Draws the text value of a telemetry item onto the canvas in an optional frame Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue X Position\tX position of the upper-left corner of the text on the canvas\tTrue Y Position\tY position of the upper-left corner of the text on the canvas\tTrue Font Size\tFont size of the text (Default = 12)\tFalse Color\tColor of the text\tFalse Value type\tThe type of the value to display. Default is CONVERTED. Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: CANVAS 200 100 CANVASLABELVALUE INST HEALTH_STATUS TEMP1 5 34 12 red CANVASLABELVALUE INST HEALTH_STATUS TEMP2 5 70 10 blue WITH_UNITS END ","version":"Next","tagName":"h3"},{"title":"CANVASIMAGE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvasimage","content":" Displays an image on the canvas Parameter\tDescription\tRequiredImage filename\tName of a image file. The file must be in the plugin's targets/TARGET/public directory.\tTrue X Position\tX position of the upper-left corner of the image on the canvas\tTrue Y Position\tY position of the upper-left corner of the image on the canvas\tTrue Example Usage: CANVAS 250 430 CANVASIMAGE "satellite.png" 10 10 200 200 SETTING SCREEN INST HS CANVASIMAGE "https://images.pexels.com/photos/256152/pexels-photo-256152.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=640&w=426" 0 250 250 150 END The following settings apply to CANVASIMAGE. They are applied using the SETTING keyword. SCREEN Open another screen when clicked Parameter\tDescription\tRequiredTarget name\tName of the target\tTrue Screen name\tName of the screen\tTrue ","version":"Next","tagName":"h3"},{"title":"CANVASIMAGEVALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvasimagevalue","content":" Displays an image on the canvas that changes with a telemetry value Use various SETTING values to indicate which images should be displayed based on telemetry. For example, SETTING IMAGE CONNECTED "ground_on.png" 400 100. See the DEMO for a complete example. Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Value type\tThe type of the value to display Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tTrue Default image filename\tThe default image to display. The file must be in the targets/TARGET/public directory.\tTrue X Position\tX position of the upper-left corner of the image on the canvas\tTrue Y Position\tY position of the upper-left corner of the image on the canvas\tTrue Image width\tWidth of the image (default is 100%)\tFalse Image height\tHeight of the image (default is 100%)\tFalse Example Usage: CANVAS 230 230 CANVASIMAGEVALUE INST HEALTH_STATUS GROUND1STATUS CONVERTED "ground_error.png" 10 10 180 180 SETTING IMAGE CONNECTED "ground_on.png" 10 10 SETTING IMAGE UNAVAILABLE "ground_off.png" 10 10 SETTING SCREEN INST HS END The following settings apply to CANVASIMAGEVALUE. They are applied using the SETTING keyword. IMAGE Map an image to a state or value Parameter\tDescription\tRequiredValue\tState or value\tTrue Image filename\tImage to display. The file must be in the targets/TARGET/public directory.\tTrue X Position\tX position of the upper-left corner of the image on the canvas\tTrue Y Position\tY position of the upper-left corner of the image on the canvas\tTrue SCREEN Open another screen when clicked Parameter\tDescription\tRequiredTarget name\tName of the target\tTrue Screen name\tName of the screen\tTrue ","version":"Next","tagName":"h3"},{"title":"CANVASLINE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvasline","content":" Draws a line onto the canvas Parameter\tDescription\tRequiredStart X Position\tX position of the start of the line on the canvas\tTrue Start Y Position\tY position of the start of the line on the canvas\tTrue End X Position\tX position of the end of the line on the canvas\tTrue End Y Position\tY position of the end of the line on the canvas\tTrue Color\tColor of the line\tFalse Width\tWidth of the line in pixels (default = 1)\tFalse Example Usage: CANVAS 100 50 CANVASLINE 5 5 95 5 CANVASLINE 5 5 5 45 green 2 CANVASLINE 95 5 95 45 blue 3 END ","version":"Next","tagName":"h3"},{"title":"CANVASLINEVALUE","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvaslinevalue","content":" Draws a color changing line onto the canvas The line is represented by one of two colors based on the value of the associated telemetry item Parameter\tDescription\tRequiredTarget name\tThe target name\tTrue Packet name\tThe packet name\tTrue Item name\tThe item name\tTrue Start X Position\tX position of the start of the line on the canvas\tTrue Start Y Position\tY position of the start of the line on the canvas\tTrue End X Position\tX position of the end of the line on the canvas\tTrue End Y Position\tY position of the end of the line on the canvas\tTrue Width\tWidth of the line in pixels (default = 3)\tFalse Value type\tThe type of the value to display. Default is CONVERTED Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS\tFalse Example Usage: CANVAS 120 50 CANVASLABELVALUE INST HEALTH_STATUS GROUND1STATUS 0 12 12 black CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 25 115 25 5 RAW SETTING VALUE_EQ 1 GREEN SETTING VALUE_EQ 0 RED CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 45 115 45 SETTING VALUE_EQ CONNECTED GREEN SETTING VALUE_EQ UNAVAILABLE RED END The following settings apply to CANVASLINEVALUE. They are applied using the SETTING keyword. VALUE_EQ (Since 5.5.1) Map a value to a color Parameter\tDescription\tRequiredValue\tState or value\tTrue Color\tColor of the line\tTrue ","version":"Next","tagName":"h3"},{"title":"CANVASDOT","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#canvasdot","content":" Draws a dot onto the canvas Parameter\tDescription\tRequiredX Position\tX position of the dot\tTrue Y Position\tY position of the dot\tTrue Color\tColor of the dot\tTrue Radius\tRadius of the dot in pixels\tTrue Example Usage: CANVAS 50 50 CANVASDOT 10 15 BLUE 5 END ","version":"Next","tagName":"h3"},{"title":"Example File","type":1,"pageTitle":"Screens","url":"/docs/configuration/telemetry-screens#example-file","content":" Example File: TARGET/myscreen.txt SCREEN AUTO AUTO 0.5 VERTICAL TITLE "<%= target_name %> Commanding Examples" LABELVALUE INST HEALTH_STATUS COLLECTS LABELVALUE INST HEALTH_STATUS COLLECT_TYPE LABELVALUE INST HEALTH_STATUS DURATION VERTICALBOX "Send Collect Command:" HORIZONTAL LABEL "Type: " NAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL END HORIZONTAL LABEL " Duration: " NAMED_WIDGET DURATION TEXTFIELD 12 "10.0" END BUTTON 'Start Collect' "api.cmd('INST COLLECT with TYPE '+screen.getNamedWidget('COLLECT_TYPE').text()+', DURATION '+screen.getNamedWidget('DURATION').text())" END SETTING BACKCOLOR 163 185 163 VERTICALBOX "Parameter-less Commands:" NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index RADIOBUTTON 'Abort' RADIOBUTTON 'Clear' END NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks' # No option is by default UNCHECKED BUTTON 'Send' "screen.getNamedWidget('GROUP').selected() === 0 ? api.cmd('INST ABORT') : (screen.getNamedWidget('CHECK').checked() ? api.cmd_no_hazardous_check('INST CLEAR') : api.cmd('INST CLEAR'))" END SETTING BACKCOLOR 163 185 163 END ","version":"Next","tagName":"h2"},{"title":"Scripting API Guide","type":0,"sectionRef":"#","url":"/docs/guides/scripting-api","content":"","keywords":"","version":"Next"},{"title":"Concepts","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#concepts","content":" ","version":"Next","tagName":"h2"},{"title":"Programming Languages","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#programming-languages","content":" COSMOS scripting is implemented using either Ruby or Python. Ruby and Python are very similar scripting languages and in many cases the COSMOS APIs are identical between the two. This guide is written to support both with additional language specific information found in the Script Writing Guide. ","version":"Next","tagName":"h3"},{"title":"Using Script Runner","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#using-script-runner","content":" Script Runner is a graphical application that provides the ideal environment for running and implementing your test procedures. The Script Runner tool is broken into 4 main sections. At the top of the tool is a menu bar that allows you to do such things as open and save files, perform a syntax check, and execute your script. Next is a tool bar that displays the currently executing script and three buttons, "Start/Go", "Pause/Retry", and "Stop". The Start/Go button is used to start the script and continue past errors or waits. The Pause/Retry button will pause the executing script. If an error is encountered the Pause button changes to Retry to re-execute the errored line. Finally, the Stop button will stop the executing script at any time. Third is the display of the actual script. While the script is not running, you may edit and compose scripts in this area. A handy code completion feature is provided that will list out the available commands or telemetry points as you are writing your script. Simply begin writing a cmd( or tlm( line to bring up code completion. This feature greatly reduces typos in command and telemetry mnemonics. Finally, the bottom of the display is the log messages. All commands that are sent, errors that occur, and user print statements appear in this area. ","version":"Next","tagName":"h3"},{"title":"Telemetry Types","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#telemetry-types","content":" There are four different ways that telemetry values can be retrieved in COSMOS. The following chart explains their differences. Telemetry Type\tDescriptionRaw\tRaw telemetry is exactly as it is in the telemetry packet before any conversions. All telemetry items will have a raw value except for Derived telemetry points which have no real location in a packet. Requesting raw telemetry on a derived item will return nil. Converted\tConverted telemetry is raw telemetry that has gone through a conversion factor such as a state conversion or a polynomial conversion. If a telemetry item does not have a conversion defined, then converted telemetry will be the same as raw telemetry. This is the most common type of telemety used in scripts. Formatted\tFormatted telemetry is converted telemetry that has gone through a printf style conversion into a string. Formatted telemetry will always have a string representation. If no format string is defined for a telemetry point, then formatted telemetry will be the same as converted telemetry except represented as string. Formatted with Units\tFormatted with Units telemetry is the same as Formatted telemetry except that a space and the units of the telemetry item are appended to the end of the string. If no units are defined for a telemetry item then this type is the same as Formatted telemetry. ","version":"Next","tagName":"h3"},{"title":"Script Runner API","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#script-runner-api","content":" The following methods are designed to be used in Script Runner procedures. Many can also be used in custom built COSMOS tools. Please see the COSMOS Tool API section for methods that are more efficient to use in custom tools. ","version":"Next","tagName":"h2"},{"title":"Migration from COSMOS v4","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#migration-from-cosmos-v4","content":" The following API methods are either deprecated (will not be ported to COSMOS 5) or currently unimplemented (eventually will be ported to COSMOS 5): Method\tTool\tStatusclear\tTelemetry Viewer\tDeprecated, use clear_screen clear_all\tTelemetry Viewer\tDeprecated, use clear_all_screens close_local_screens\tTelemetry Viewer\tDeprecated, use clear_screen clear_disconnected_targets\tScript Runner\tDeprecated cmd_tlm_clear_counters\tCommand and Telemetry Server\tDeprecated cmd_tlm_reload\tCommand and Telemetry Server\tDeprecated display\tTelemetry Viewer\tDeprecated, use display_screen get_all_packet_logger_info\tCommand and Telemetry Server\tDeprecated get_all_target_info\tCommand and Telemetry Server\tDeprecated, use get_target_interfaces get_background_tasks\tCommand and Telemetry Server\tDeprecated get_all_cmd_info\tCommand and Telemetry Server\tDeprecated, use get_all_cmds get_all_tlm_info\tCommand and Telemetry Server\tDeprecated, use get_all_tlm get_cmd_list\tCommand and Telemetry Server\tDeprecated, use get_all_cmds get_cmd_log_filename\tCommand and Telemetry Server\tDeprecated get_cmd_param_list\tCommand and Telemetry Server\tDeprecated, use get_cmd get_cmd_tlm_disconnect\tScript Runner\tDeprecated, use $disconnect get_disconnected_targets\tScript Runner\tUnimplemented get_interface_info\tCommand and Telemetry Server\tDeprecated, use get_interface get_interface_targets\tCommand and Telemetry Server\tDeprecated get_output_logs_filenames\tCommand and Telemetry Server\tDeprecated get_packet\tCommand and Telemetry Server\tDeprecated, use get_packets get_packet_data\tCommand and Telemetry Server\tDeprecated, use get_packets get_packet_logger_info\tCommand and Telemetry Server\tDeprecated get_packet_loggers\tCommand and Telemetry Server\tDeprecated get_replay_mode\tReplay\tDeprecated get_router_info\tCommand and Telemetry Server\tDeprecated, use get_router get_scriptrunner_message_log_filename\tCommand and Telemetry Server\tDeprecated get_server_message\tCommand and Telemetry Server\tDeprecated get_server_message_log_filename\tCommand and Telemetry Server\tDeprecated get_server_status\tCommand and Telemetry Server\tDeprecated get_stale\tCommand and Telemetry Server\tDeprecated get_target_ignored_items\tCommand and Telemetry Server\tDeprecated, use get_target get_target_ignored_parameters\tCommand and Telemetry Server\tDeprecated, use get_target get_target_info\tCommand and Telemetry Server\tDeprecated, use get_target get_target_list\tCommand and Telemetry Server\tDeprecated, use get_target_names get_tlm_details\tCommand and Telemetry Server\tDeprecated get_tlm_item_list\tCommand and Telemetry Server\tDeprecated get_tlm_list\tCommand and Telemetry Server\tDeprecated get_tlm_log_filename\tCommand and Telemetry Server\tDeprecated interface_state\tCommand and Telemetry Server\tDeprecated, use get_interface override_tlm_raw\tCommand and Telemetry Server\tDeprecated, use override_tlm open_directory_dialog\tScript Runner\tDeprecated replay_move_end\tReplay\tDeprecated replay_move_index\tReplay\tDeprecated replay_move_start\tReplay\tDeprecated replay_play\tReplay\tDeprecated replay_reverse_play\tReplay\tDeprecated replay_select_file\tReplay\tDeprecated replay_set_playback_delay\tReplay\tDeprecated replay_status\tReplay\tDeprecated replay_step_back\tReplay\tDeprecated replay_step_forward\tReplay\tDeprecated replay_stop\tReplay\tDeprecated require_utility\tScript Runner\tDeprecated but exists for backwards compatibility, use load_utility router_state\tCommand and Telemetry Server\tDeprecated, use get_router save_file_dialog\tScript Runner\tDeprecated save_setting\tCommand and Telemetry Server\tDeprecated but exists for backwards compatibility, use set_setting set_cmd_tlm_disconnect\tScript Runner\tDeprecated, use disconnect_script set_disconnected_targets\tScript Runner\tUnimplemented set_replay_mode\tReplay\tDeprecated set_stdout_max_lines\tScript Runner\tDeprecated set_tlm_raw\tScript Runner\tDeprecated, use set_tlm show_backtrace\tScript Runner\tDeprecated, backtrace always shown shutdown_cmd_tlm\tCommand and Telemetry Server\tDeprecated start_cmd_log\tCommand and Telemetry Server\tDeprecated start_logging\tCommand and Telemetry Server\tDeprecated start_new_scriptrunner_message_log\tCommand and Telemetry Server\tDeprecated start_new_server_message_log\tCommand and Telemetry Server\tDeprecated start_tlm_log\tCommand and Telemetry Server\tDeprecated stop_background_task\tCommand and Telemetry Server\tDeprecated stop_cmd_log\tCommand and Telemetry Server\tDeprecated stop_logging\tCommand and Telemetry Server\tDeprecated stop_tlm_log\tCommand and Telemetry Server\tDeprecated subscribe_limits_events\tCommand and Telemetry Server\tDeprecated subscribe_packet_data\tCommand and Telemetry Server\tDeprecated, use subscribe_packets subscribe_server_messages\tCommand and Telemetry Server\tUnimplemented tlm_variable\tScript Runner\tDeprecated, use tlm() and pass type unsubscribe_limits_events\tCommand and Telemetry Server\tDeprecated unsubscribe_packet_data\tCommand and Telemetry Server\tDeprecated unsubscribe_server_messages\tCommand and Telemetry Server\tDeprecated wait_raw\tScript Runner\tDeprecated, use wait(..., type: :RAW) wait_check_raw\tScript Runner\tDeprecated, use wait_check(..., type: :RAW) wait_tolerance_raw\tScript Runner\tDeprecated, use wait_tolerance(..., type: :RAW) wait_check_tolerance_raw\tScript Runner\tDeprecated, use wait_check_tolerance(..., type: :RAW) ","version":"Next","tagName":"h3"},{"title":"Retrieving User Input","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#retrieving-user-input","content":" These methods allow the user to enter values that are needed by the script. ","version":"Next","tagName":"h2"},{"title":"ask","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#ask","content":" Prompts the user for input with a question. User input is automatically converted from a string to the appropriate data type. For example if the user enters "1", the number 1 as an integer will be returned. Ruby / Python Syntax: ask("<question>", <blank_or_default>, <password>) Parameter\tDescriptionquestion\tQuestion to prompt the user with. blank_or_default\tWhether or not to allow empty responses (optional - defaults to false). If a non-boolean value is passed it is used as a default value. password\tWhether to treat the entry as a password which is displayed with dots and not logged. Default is false. Ruby Example: value = ask("Enter an integer") value = ask("Enter a value or nothing", true) value = ask("Enter a value", 10) password = ask("Enter your password", false, true) Python Example: value = ask("Enter an integer") value = ask("Enter a value or nothing", True) value = ask("Enter a value", 10) password = ask("Enter your password", False, True) ","version":"Next","tagName":"h3"},{"title":"ask_string","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#ask_string","content":" Prompts the user for input with a question. User input is always returned as a string. For example if the user enters "1", the string "1" will be returned. Ruby / Python Syntax: ask_string("<question>", <blank_or_default>, <password>) Parameter\tDescriptionquestion\tQuestion to prompt the user with. blank_or_default\tWhether or not to allow empty responses (optional - defaults to false). If a non-boolean value is passed it is used as a default value. password\tWhether to treat the entry as a password which is displayed with dots and not logged. Default is false. Ruby Example: string = ask_string("Enter a String") string = ask_string("Enter a value or nothing", true) string = ask_string("Enter a value", "test") password = ask_string("Enter your password", false, true) Python Example: string = ask_string("Enter a String") string = ask_string("Enter a value or nothing", True) string = ask_string("Enter a value", "test") password = ask_string("Enter your password", False, True) ","version":"Next","tagName":"h3"},{"title":"message_box","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#message_box","content":" ","version":"Next","tagName":"h3"},{"title":"vertical_message_box","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#vertical_message_box","content":" ","version":"Next","tagName":"h3"},{"title":"combo_box","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#combo_box","content":" The message_box, vertical_message_box, and combo_box methods create a message box with arbitrary buttons or selections that the user can click. The text of the button clicked is returned. Ruby / Python Syntax: message_box("<message>", "<button text 1>", ...) vertical_message_box("<message>", "<button text 1>", ...) combo_box("<message>", "<selection text 1>", ...) Parameter\tDescriptionmessage\tMessage to prompt the user with. button/selection text\tText for a button or selection Ruby Example: value = message_box("Select the sensor number", 'One', 'Two') value = vertical_message_box("Select the sensor number", 'One', 'Two') value = combo_box("Select the sensor number", 'One', 'Two') case value when 'One' puts 'Sensor One' when 'Two' puts 'Sensor Two' end Python Example: value = message_box("Select the sensor number", 'One', 'Two') value = vertical_message_box("Select the sensor number", 'One', 'Two') value = combo_box("Select the sensor number", 'One', 'Two') match value: case 'One': print('Sensor One') case 'Two': print('Sensor Two') ","version":"Next","tagName":"h3"},{"title":"get_target_file","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_target_file","content":" Return a file handle to a file in the target directory Ruby Syntax: get_target_file("<File Path>", original: false) Python Syntax: get_target_file("<File Path>", original=False) Parameter\tDescriptionpath\tThe path to the file in the target directory. Should assume to start with a TARGET name, e.g. INST/procedures/proc.rb original\tWhether to get the original file from the plug-in, or any modifications to the file. Default is false which means to grab the modified file. If the modified file does not exist the API will automatically try to pull the original. Ruby Example: file = get_target_file("INST/data/attitude.bin") puts file.read().formatted # format a binary file file.unlink # delete file file = get_target_file("INST/procedures/checks.rb", original: true) puts file.read() file.unlink # delete file Python Example: from openc3.utilities.string import formatted file = get_target_file("INST/data/attitude.bin") print(formatted(file.read())) # format a binary file file.close() # delete file file = get_target_file("INST/procedures/checks.rb", original=True) print(file.read()) file.close() # delete file ","version":"Next","tagName":"h3"},{"title":"put_target_file","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#put_target_file","content":" Writes a file to the target directory Ruby or Python Syntax: put_target_file("<File Path>", "IO or String") Parameter\tDescriptionpath\tThe path to the file in the target directory. Should assume to start with a TARGET name, e.g. INST/procedures/proc.rb. The file can previously exist or not. Note: The original file from the plug-in will not be modified, however existing modified files will be overwritten. data\tThe data can be an IO object or String Ruby Example: put_target_file("INST/test1.txt", "this is a string test") file = Tempfile.new('test') file.write("this is a Io test") file.rewind put_target_file("INST/test2.txt", file) put_target_file("INST/test3.bin", "\\x00\\x01\\x02\\x03\\xFF\\xEE\\xDD\\xCC") # binary Python Example: put_target_file("INST/test1.txt", "this is a string test") file = tempfile.NamedTemporaryFile(mode="w+t") file.write("this is a Io test") file.seek(0) put_target_file("INST/test2.txt", file) put_target_file("INST/test3.bin", b"\\x00\\x01\\x02\\x03\\xFF\\xEE\\xDD\\xCC") # binary ","version":"Next","tagName":"h3"},{"title":"delete_target_file","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#delete_target_file","content":" Delete a file in the target directory Ruby / Python Syntax: delete_target_file("<File Path>") Parameter\tDescriptionpath\tThe path to the file in the target directory. Should assume to start with a TARGET name, e.g. INST/procedures/proc.rb. Note: Only files created with put_target_file can be deleted. Original files from the plugin installation will remain. Ruby / Python Example: put_target_file("INST/delete_me.txt", "to be deleted") delete_target_file("INST/delete_me.txt") ","version":"Next","tagName":"h3"},{"title":"open_file_dialog","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#open_file_dialog","content":" ","version":"Next","tagName":"h3"},{"title":"open_files_dialog","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#open_files_dialog","content":" The open_file_dialog and open_files_dialog methods create a file dialog box so the user can select a single or multiple files. The selected file(s) is returned. Note: COSMOS 5 has deprecated the save_file_dialog and open_directory_dialog methods. save_file_dialog can be replaced by put_target_file if you want to write a file back to the target. open_directory_dialog doesn't make sense in new architecture so you must request individual files. Ruby Syntax: open_file_dialog("<title>", "<message>", filter: "<filter>") open_files_dialog("<title>", "<message>", filter: "<filter>") Python Syntax: open_file_dialog("<title>", "<message>", filter="<filter>") open_files_dialog("<title>", "<message>", filter="<filter>") Parameter\tDescriptionTitle\tThe title to put on the dialog. Required. Message\tThe message to display in the dialog box. Optional parameter. filter\tNamed parameter to filter allowed file types. Optional parameter, specified as comma delimited file types, e.g. ".txt,.doc". See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept for more information. Ruby Example: file = open_file_dialog("Open a single file", "Choose something interesting", filter: ".txt") puts file # Ruby File object puts file.read file.delete files = open_files_dialog("Open multiple files") # message is optional puts files # Array of File objects (even if you select only one) files.each do |file| puts file puts file.read file.delete end Python Example: file = open_file_dialog("Open a single file", "Choose something interesting", filter=".txt") print(file) print(file.read()) file.close() files = open_files_dialog("Open multiple files") # message is optional print(files) # Array of File objects (even if you select only one) for file in files: print(file) print(file.read()) file.close() ","version":"Next","tagName":"h3"},{"title":"Providing information to the user","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#providing-information-to-the-user","content":" These methods notify the user that something has occurred. ","version":"Next","tagName":"h2"},{"title":"prompt","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#prompt","content":" Displays a message to the user and waits for them to press an ok button. Ruby / Python Syntax: prompt("<message>") Parameter\tDescriptionmessage\tMessage to prompt the user with. Ruby / Python Example: prompt("Press OK to continue") ","version":"Next","tagName":"h3"},{"title":"Commands","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#commands","content":" These methods provide capability to send commands to a target and receive information about commands in the system. ","version":"Next","tagName":"h2"},{"title":"cmd","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd","content":" Sends a specified command. Ruby Syntax: cmd("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd("<Target Name>", "<Command Name>", "Param #1 Name" => <Param #1 Value>, "Param #2 Name" => <Param #2 Value>, ...) Python Syntax: cmd("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd("<Target Name>", "<Command Name>", {"Param #1 Name": <Param #1 Value>, "Param #2 Name": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd("INST COLLECT with DURATION 10, TYPE NORMAL") # In Ruby the brackets around parameters are optional cmd("INST", "COLLECT", "DURATION" => 10, "TYPE" => "NORMAL") cmd("INST", "COLLECT", { "DURATION" => 10, "TYPE" => "NORMAL" }) cmd("INST ABORT", timeout: 10, log_message: false) Python Example: cmd("INST COLLECT with DURATION 10, TYPE NORMAL") cmd("INST", "COLLECT", { "DURATION": 10, "TYPE": "NORMAL" }) cmd("INST ABORT", timeout=10, log_message=False) ","version":"Next","tagName":"h3"},{"title":"cmd_no_range_check","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_no_range_check","content":" Sends a specified command without performing range checking on its parameters. This should only be used when it is necessary to intentionally send a bad command parameter to test a target. Ruby Syntax: cmd_no_range_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_range_check("<Target Name>", "<Command Name>", "Param #1 Name" => <Param #1 Value>, "Param #2 Name" => <Param #2 Value>, ...) Python Syntax: cmd_no_range_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_range_check("<Target Name>", "<Command Name>", {"Param #1 Name": <Param #1 Value>, "Param #2 Name": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd_no_range_check("INST COLLECT with DURATION 11, TYPE NORMAL") cmd_no_range_check("INST", "COLLECT", "DURATION" => 11, "TYPE" => "NORMAL") Python Example: cmd_no_range_check("INST COLLECT with DURATION 11, TYPE NORMAL") cmd_no_range_check("INST", "COLLECT", {"DURATION": 11, "TYPE": "NORMAL"}) ","version":"Next","tagName":"h3"},{"title":"cmd_no_hazardous_check","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_no_hazardous_check","content":" Sends a specified command without performing the notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands. Ruby Syntax: cmd_no_hazardous_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_hazardous_check("<Target Name>", "<Command Name>", "Param #1 Name" => <Param #1 Value>, "Param #2 Name" => <Param #2 Value>, ...) Python Syntax: cmd_no_hazardous_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_hazardous_check("<Target Name>", "<Command Name>", {"Param #1 Name": <Param #1 Value>, "Param #2 Name": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby / Python Example: cmd_no_hazardous_check("INST CLEAR") cmd_no_hazardous_check("INST", "CLEAR") ","version":"Next","tagName":"h3"},{"title":"cmd_no_checks","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_no_checks","content":" Sends a specified command without performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentionally have invalid parameters. Ruby Syntax: cmd_no_checks("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_checks("<Target Name>", "<Command Name>", "Param #1 Name" => <Param #1 Value>, "Param #2 Name" => <Param #2 Value>, ...) Python Syntax: cmd_no_checks("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_no_checks("<Target Name>", "<Command Name>", {"Param #1 Name": <Param #1 Value>, "Param #2 Name": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd_no_checks("INST COLLECT with DURATION 11, TYPE SPECIAL") cmd_no_checks("INST", "COLLECT", "DURATION" => 11, "TYPE" => "SPECIAL") Python Example: cmd_no_checks("INST COLLECT with DURATION 11, TYPE SPECIAL") cmd_no_checks("INST", "COLLECT", {"DURATION": 11, "TYPE": "SPECIAL"}) ","version":"Next","tagName":"h3"},{"title":"cmd_raw","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_raw","content":" Sends a specified command without running conversions. Ruby Syntax: cmd_raw("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw("<Target Name>", "<Command Name>", "<Param #1 Name>" => <Param #1 Value>, "<Param #2 Name>" => <Param #2 Value>, ...) Python Syntax: cmd_raw("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw("<Target Name>", "<Command Name>", {"<Param #1 Name>": <Param #1 Value>, "<Param #2 Name>": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd_raw("INST COLLECT with DURATION 10, TYPE 0") cmd_raw("INST", "COLLECT", "DURATION" => 10, "TYPE" => 0) Python Example: cmd_raw("INST COLLECT with DURATION 10, TYPE 0") cmd_raw("INST", "COLLECT", {"DURATION": 10, "TYPE": 0}) ","version":"Next","tagName":"h3"},{"title":"cmd_raw_no_range_check","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_raw_no_range_check","content":" Sends a specified command without running conversions or performing range checking on its parameters. This should only be used when it is necessary to intentionally send a bad command parameter to test a target. Ruby Syntax: cmd_raw_no_range_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_range_check("<Target Name>", "<Command Name>", "<Param #1 Name>" => <Param #1 Value>, "<Param #2 Name>" => <Param #2 Value>, ...) Python Syntax: cmd_raw_no_range_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_range_check("<Target Name>", "<Command Name>", {"<Param #1 Name>": <Param #1 Value>, "<Param #2 Name>": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd_raw_no_range_check("INST COLLECT with DURATION 11, TYPE 0") cmd_raw_no_range_check("INST", "COLLECT", "DURATION" => 11, "TYPE" => 0) Python Example: cmd_raw_no_range_check("INST COLLECT with DURATION 11, TYPE 0") cmd_raw_no_range_check("INST", "COLLECT", {"DURATION": 11, "TYPE": 0}) ","version":"Next","tagName":"h3"},{"title":"cmd_raw_no_hazardous_check","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_raw_no_hazardous_check","content":" Sends a specified command without running conversions or performing the notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands. Ruby Syntax: cmd_raw_no_hazardous_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_hazardous_check("<Target Name>", "<Command Name>", "<Param #1 Name>" => <Param #1 Value>, "<Param #2 Name>" => <Param #2 Value>, ...) Python Syntax: cmd_raw_no_hazardous_check("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_hazardous_check("<Target Name>", "<Command Name>", {"<Param #1 Name>": <Param #1 Value>, "<Param #2 Name>": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby / Python Example: cmd_raw_no_hazardous_check("INST CLEAR") cmd_raw_no_hazardous_check("INST", "CLEAR") ","version":"Next","tagName":"h3"},{"title":"cmd_raw_no_checks","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#cmd_raw_no_checks","content":" Sends a specified command without running conversions or performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentionally have invalid parameters. Ruby Syntax: cmd_raw_no_checks("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_checks("<Target Name>", "<Command Name>", "<Param #1 Name>" => <Param #1 Value>, "<Param #2 Name>" => <Param #2 Value>, ...) Python Syntax: cmd_raw_no_checks("<Target Name> <Command Name> with <Param #1 Name> <Param #1 Value>, <Param #2 Name> <Param #2 Value>, ...") cmd_raw_no_checks("<Target Name>", "<Command Name>", {"<Param #1 Name>": <Param #1 Value>, "<Param #2 Name>": <Param #2 Value>, ...}) Parameter\tDescriptionTarget Name\tName of the target this command is associated with. Command Name\tName of this command. Also referred to as its mnemonic. Param #x Name\tName of a command parameter. If there are no parameters then the 'with' keyword should not be given. Param #x Value\tValue of the command parameter. Values are automatically converted to the appropriate type. timeout\tOptional named parameter to change the default timeout value of 5 seconds log_message\tOptional named parameter to prevent logging of the command Ruby Example: cmd_raw_no_checks("INST COLLECT with DURATION 11, TYPE 1") cmd_raw_no_checks("INST", "COLLECT", "DURATION" => 11, "TYPE" => 1) Python Example: cmd_raw_no_checks("INST COLLECT with DURATION 11, TYPE 1") cmd_raw_no_checks("INST", "COLLECT", {"DURATION": 11, "TYPE": 1}) ","version":"Next","tagName":"h3"},{"title":"build_cmd (since 5.13.0, since 5.8.0 as build_command)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#build_cmd-since-5130-since-580-as-build_command","content":" Builds a command binary string Ruby Syntax: build_cmd(<ARGS>, range_check: true, raw: false) Python Syntax: build_cmd(<ARGS>, range_check=True, raw=False) Parameter\tDescriptionARGS\tCommand parameters (see cmd) range_check\tWhether to perform range checking on the command. Default is true. raw\tWhether to write the command arguments as RAW or CONVERTED value. Default is CONVERTED. Ruby Example: x = build_cmd("INST COLLECT with DURATION 10, TYPE NORMAL") puts x #=> {"id"=>"1696437370872-0", "result"=>"SUCCESS", "time"=>"1696437370872305961", "received_time"=>"1696437370872305961", "target_name"=>"INST", "packet_name"=>"COLLECT", "received_count"=>"3", "buffer"=>"\\x13\\xE7\\xC0\\x00\\x00\\f\\x00\\x01\\x00\\x00A \\x00\\x00\\xAB\\x00\\x00\\x00\\x00"} Python Example: x = build_cmd("INST COLLECT with DURATION 10, TYPE NORMAL") print(x) #=> {'id': '1697298167748-0', 'result': 'SUCCESS', 'time': '1697298167749155717', 'received_time': '1697298167749155717', 'target_name': 'INST', 'packet_name': 'COLLECT', 'received_count': '2', 'buffer': bytearray(b'\\x13\\xe7\\xc0\\x00\\x00\\x0c\\x00\\x01\\x00\\x00A \\x00\\x00\\xab\\x00\\x00\\x00\\x00')} ","version":"Next","tagName":"h3"},{"title":"send_raw","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#send_raw","content":" Sends raw data on an interface. Ruby / Python Syntax: send_raw(<Interface Name>, <Data>) Parameter\tDescriptionInterface Name\tName of the interface to send the raw data on. Data\tRaw ruby string of data to send. Ruby / Python Example: send_raw("INST_INT", data) ","version":"Next","tagName":"h3"},{"title":"get_all_cmds (since 5.13.0, since 5.0.0 as get_all_commands)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_cmds-since-5130-since-500-as-get_all_commands","content":" Returns an array of the commands that are available for a particular target. The returned array is an array of hashes which fully describe the command packet. Ruby / Python Syntax: get_all_cmds("<Target Name>") Parameter\tDescriptionTarget Name\tName of the target. Ruby Example: cmd_list = get_all_cmds("INST") puts cmd_list #=> # [{"target_name"=>"INST", # "packet_name"=>"ABORT", # "endianness"=>"BIG_ENDIAN", # "description"=>"Aborts a collect on the instrument", # "items"=> [{"name"=>"CCSDSVER", "bit_offset"=>0, "bit_size"=>3, ... }] # ... # }] Python Example: cmd_list = get_all_cmds("INST") print(cmd_list) #=> # [{'target_name': 'INST', # 'packet_name': 'ABORT', # 'endianness': 'BIG_ENDIAN', # 'description': 'Aborts a collect on the INST instrument', # 'items': [{'name': 'CCSDSVER', 'bit_offset': 0, 'bit_size': 3, ... }] # ... # }] ","version":"Next","tagName":"h3"},{"title":"get_all_cmd_names (since 5.13.0, since 5.0.6 as get_all_command_names)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_cmd_names-since-5130-since-506-as-get_all_command_names","content":" Returns an array of the command names for a particular target. Ruby / Python Syntax: get_all_cmd_names("<Target Name>") Parameter\tDescriptionTarget Name\tName of the target Ruby Example: cmd_list = get_all_cmd_names("INST") puts cmd_list #=> ['ABORT', 'ARYCMD', 'ASCIICMD', ...] Python Example: cmd_list = get_all_cmd_names("INST") print(cmd_list) #=> ['ABORT', 'ARYCMD', 'ASCIICMD', ...] ","version":"Next","tagName":"h3"},{"title":"get_cmd (since 5.13.0, since 5.0.0 as get_command)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd-since-5130-since-500-as-get_command","content":" Returns a command hash which fully describes the command packet. Ruby / Python Syntax: get_cmd("<Target Name> <Packet Name>") get_cmd("<Target Name>", "<Packet Name>") Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. Ruby / Python Example: abort_cmd = get_cmd("INST ABORT") puts abort_cmd #=> # [{"target_name"=>"INST", # "packet_name"=>"ABORT", # "endianness"=>"BIG_ENDIAN", # "description"=>"Aborts a collect on the instrument", # "items"=> [{"name"=>"CCSDSVER", "bit_offset"=>0, "bit_size"=>3, ... }] # ... # }] Python Example: abort_cmd = get_cmd("INST ABORT") print(abort_cmd) #=> # [{'target_name': 'INST', # 'packet_name': 'ABORT', # 'endianness': 'BIG_ENDIAN', # 'description': 'Aborts a collect on the INST instrument', # 'items': [{'name': 'CCSDSVER', 'bit_offset': 0, 'bit_size': 3, ... }] # ... # }] ","version":"Next","tagName":"h3"},{"title":"get_param (since 5.13.0, since 5.0.0 as get_parameter)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_param-since-5130-since-500-as-get_parameter","content":" Returns a hash of the given command parameter Ruby / Python Syntax: get_param("<Target Name> <Command Name> <Parameter Name>") get_param("<Target Name>", "<Command Name>", "<Parameter Name>") Parameter\tDescriptionTarget Name\tName of the target. Command Name\tName of the command. Parameter Name\tName of the parameter. Ruby Example: param = get_param("INST COLLECT TYPE") puts param #=> # {"name"=>"TYPE", "bit_offset"=>64, "bit_size"=>16, "data_type"=>"UINT", # "description"=>"Collect type which can be normal or special", "default"=>0, # "minimum"=>0, "maximum"=>65535, "endianness"=>"BIG_ENDIAN", "required"=>true, "overflow"=>"ERROR", # "states"=>{"NORMAL"=>{"value"=>0}, "SPECIAL"=>{"value"=>1, "hazardous"=>""}}, "limits"=>{}} Python Example: param = get_param("INST COLLECT TYPE") print(param) #=> # {'name': 'TYPE', 'bit_offset': 64, 'bit_size': 16, 'data_type': 'UINT', # 'description': 'Collect type which can be normal or special', 'default': 0, # 'minimum': 0, 'maximum': 65535, 'endianness': 'BIG_ENDIAN', 'required': True, 'overflow': 'ERROR', # 'states': {'NORMAL': {'value': 0}, 'SPECIAL': {'value': 1, 'hazardous': ''}}, 'limits': {}} ","version":"Next","tagName":"h3"},{"title":"get_cmd_buffer","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd_buffer","content":" Returns a packet hash (similar to get_cmd) along with the raw packet buffer as a Ruby string. Ruby / Python Syntax: buffer = get_cmd_buffer("<Target Name> <Packet Name>")['buffer'] buffer = get_cmd_buffer("<Target Name>", "<Packet Name>")['buffer'] Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. Ruby Example: packet = get_cmd_buffer("INST COLLECT") puts packet #=> # {"time"=>"1697298846752053420", "received_time"=>"1697298846752053420", # "target_name"=>"INST", "packet_name"=>"COLLECT", "received_count"=>"20", "stored"=>"false", # "buffer"=>"\\x13\\xE7\\xC0\\x00\\x00\\f\\x00\\x01\\x00\\x00@\\xE0\\x00\\x00\\xAB\\x00\\x00\\x00\\x00"} Python Example: packet = get_cmd_buffer("INST COLLECT") print(packet) #=> # {'time': '1697298923745982470', 'received_time': '1697298923745982470', # 'target_name': 'INST', 'packet_name': 'COLLECT', 'received_count': '21', 'stored': 'false', # 'buffer': bytearray(b'\\x13\\xe7\\xc0\\x00\\x00\\x0c\\x00\\x01\\x00\\x00@\\xe0\\x00\\x00\\xab\\x00\\x00\\x00\\x00')} ","version":"Next","tagName":"h3"},{"title":"get_cmd_hazardous","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd_hazardous","content":" Returns true/false indicating whether a particular command is flagged as hazardous. Ruby / Python Syntax: get_cmd_hazardous("<Target Name>", "<Command Name>", <Command Params - optional>) Parameter\tDescriptionTarget Name\tName of the target. Command Name\tName of the command. Command Params\tHash of the parameters given to the command (optional). Note that some commands are only hazardous based on parameter states. Ruby Example: hazardous = get_cmd_hazardous("INST", "COLLECT", {'TYPE' => 'SPECIAL'}) puts hazardous #=> true Python Example: hazardous = get_cmd_hazardous("INST", "COLLECT", {'TYPE': 'SPECIAL'}) print(hazardous) #=> True ","version":"Next","tagName":"h3"},{"title":"get_cmd_value","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd_value","content":" Returns reads a value from the most recently sent command packet. The pseudo-parameters 'PACKET_TIMESECONDS', 'PACKET_TIMEFORMATTED', 'RECEIVED_COUNT', 'RECEIVED_TIMEFORMATTED', and 'RECEIVED_TIMESECONDS' are also supported. Ruby / Python Syntax: get_cmd_value("<Target Name>", "<Command Name>", "<Parameter Name>", <Value Type - optional>) Parameter\tDescriptionTarget Name\tName of the target. Command Name\tName of the command. Parameter Name\tName of the command parameter. Value Type\tValue Type to read. RAW, CONVERTED, FORMATTED, or WITH_UNITS. NOTE: Symbol in Ruby and str in Python Ruby Example: value = get_cmd_value("INST", "COLLECT", "TEMP", :RAW) puts value #=> 0.0 Python Example: value = get_cmd_value("INST", "COLLECT", "TEMP", "RAW") print(value) #=> 0.0 ","version":"Next","tagName":"h3"},{"title":"get_cmd_time","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd_time","content":" Returns the time of the most recent command sent. Ruby / Python Syntax: get_cmd_time("<Target Name - optional>", "<Command Name - optional>") Parameter\tDescriptionTarget Name\tName of the target. If not given, then the most recent command time to any target will be returned Command Name\tName of the command. If not given, then the most recent command time to the given target will be returned Ruby / Python Example: target_name, command_name, time = get_cmd_time() # Name of the most recent command sent to any target and time target_name, command_name, time = get_cmd_time("INST") # Name of the most recent command sent to the INST target and time target_name, command_name, time = get_cmd_time("INST", "COLLECT") # Name of the most recent INST COLLECT command and time ","version":"Next","tagName":"h3"},{"title":"get_cmd_cnt","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_cmd_cnt","content":" Returns the number of times a specified command has been sent. Ruby / Python Syntax: get_cmd_cnt("<Target Name> <Command Name>") get_cmd_cnt("<Target Name>", "<Command Name>") Parameter\tDescriptionTarget Name\tName of the target. Command Name\tName of the command. Ruby / Python Example: cmd_cnt = get_cmd_cnt("INST COLLECT") # Number of times the INST COLLECT command has been sent ","version":"Next","tagName":"h3"},{"title":"Handling Telemetry","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#handling-telemetry","content":" These methods allow the user to interact with telemetry items. ","version":"Next","tagName":"h2"},{"title":"check, check_raw, check_formatted, check_with_units","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#check-check_raw-check_formatted-check_with_units","content":" Performs a verification of a telemetry item using its specified telemetry type. If the verification fails then the script will be paused with an error. If no comparison is given to check then the telemetry item is simply printed to the script output. Note: In most cases using wait_check is a better choice than using check. Ruby / Python Syntax: check("<Target Name> <Packet Name> <Item Name> <Comparison - optional>") Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Comparison\tA comparison to perform against the telemetry item. If a comparison is not given then the telemetry item will just be printed into the script log. Ruby Example: check("INST HEALTH_STATUS COLLECTS > 1") check_raw("INST HEALTH_STATUS COLLECTS > 1") check_formatted("INST HEALTH_STATUS COLLECTS > 1") check_with_units("INST HEALTH_STATUS COLLECTS > 1") # Ruby passes type as symbol check("INST HEALTH_STATUS COLLECTS > 1", type: :RAW) Python Example: check("INST HEALTH_STATUS COLLECTS > 1") check_raw("INST HEALTH_STATUS COLLECTS > 1") check_formatted("INST HEALTH_STATUS COLLECTS > 1") check_with_units("INST HEALTH_STATUS COLLECTS > 1") # Python passes type as string check("INST HEALTH_STATUS COLLECTS > 1", type='RAW') ","version":"Next","tagName":"h3"},{"title":"check_tolerance","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#check_tolerance","content":" Checks a converted telemetry item against an expected value with a tolerance. If the verification fails then the script will be paused with an error. Note: In most cases using wait_check_tolerance is a better choice than using check_tolerance. Ruby / Python Syntax: check_tolerance("<Target Name> <Packet Name> <Item Name>", <Expected Value>, <Tolerance>) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Expected Value\tExpected value of the telemetry item. Tolerance\t± Tolerance on the expected value. type\tCONVERTED (default) or RAW (Ruby symbol, Python string) Ruby Example: check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0) check_tolerance("INST HEALTH_STATUS TEMP1", 50000, 20000, type: :RAW) Python Example: check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0) check_tolerance("INST HEALTH_STATUS TEMP1", 50000, 20000, type='RAW') ","version":"Next","tagName":"h3"},{"title":"check_expression","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#check_expression","content":" Evaluates an expression. If the expression evaluates to false the script will be paused with an error. This method can be used to perform more complicated comparisons than using check as shown in the example. Note: In most cases using wait_check_expression is a better choice than using check_expression. Remember that everything inside the check_expression string will be evaluated directly and thus must be valid syntax. A common mistake is to check a variable like so (Ruby variable interpolation): check_expression("#{answer} == 'yes'") # where answer contains 'yes' This evaluates to yes == 'yes' which is not valid syntax because the variable yes is not defined (usually). The correct way to write this expression is as follows: check_expression("'#{answer}' == 'yes'") # where answer contains 'yes' Now this evaluates to 'yes' == 'yes' which is true so the check passes. Ruby / Python Syntax: check_expression("<Expression>") Parameter\tDescriptionExpression\tAn expression to evaluate. Ruby / Python Example: check_expression("tlm('INST HEALTH_STATUS COLLECTS') > 5 and tlm('INST HEALTH_STATUS TEMP1') > 25.0") ","version":"Next","tagName":"h3"},{"title":"check_exception","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#check_exception","content":" Executes a method and expects an exception to be raised. If the method does not raise an exception, a CheckError is raised. Ruby / Python Syntax: check_exception("<Method Name>", "<Method Params - optional>") Parameter\tDescriptionMethod Name\tThe COSMOS scripting method to execute, e.g. 'cmd', etc. Method Params\tParameters for the method Ruby Example: check_exception("cmd", "INST", "COLLECT", "TYPE" => "NORMAL") Python Example: check_exception("cmd", "INST", "COLLECT", {"TYPE": "NORMAL"}) ","version":"Next","tagName":"h3"},{"title":"tlm, tlm_raw, tlm_formatted, tlm_with_units","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#tlm-tlm_raw-tlm_formatted-tlm_with_units","content":" Reads the specified form of a telemetry item. Ruby / Python Syntax: tlm("<Target Name> <Packet Name> <Item Name>") tlm("<Target Name>", "<Packet Name>", "<Item Name>") Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string). Ruby Example: value = tlm("INST HEALTH_STATUS COLLECTS") value = tlm("INST", "HEALTH_STATUS", "COLLECTS") value = tlm_raw("INST HEALTH_STATUS COLLECTS") value = tlm_formatted("INST HEALTH_STATUS COLLECTS") value = tlm_with_units("INST HEALTH_STATUS COLLECTS") # Equivalent to tlm_raw raw_value = tlm("INST HEALTH_STATUS COLLECTS", type: :RAW) Python Example: value = tlm("INST HEALTH_STATUS COLLECTS") value = tlm("INST", "HEALTH_STATUS", "COLLECTS") value = tlm_raw("INST HEALTH_STATUS COLLECTS") value = tlm_formatted("INST HEALTH_STATUS COLLECTS") value = tlm_with_units("INST HEALTH_STATUS COLLECTS") # Equivalent to tlm_raw raw_value = tlm("INST HEALTH_STATUS COLLECTS", type='RAW') ","version":"Next","tagName":"h3"},{"title":"get_tlm_buffer","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_buffer","content":" Returns a packet hash (similar to get_tlm) along with the raw packet buffer. Ruby / Python Syntax: buffer = get_tlm_buffer("<Target Name> <Packet Name>")['buffer'] buffer = get_tlm_buffer("<Target Name>", "<Packet Name>")['buffer'] Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. Ruby / Python Example: packet = get_tlm_buffer("INST HEALTH_STATUS") packet['buffer'] ","version":"Next","tagName":"h3"},{"title":"get_tlm_packet","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_packet","content":" Returns the names, values, and limits states of all telemetry items in a specified packet. The value is returned as an array of arrays with each entry containing [item_name, item_value, limits_state]. Ruby / Python Syntax: get_tlm_packet("<Target Name> <Packet Name>", <type>) get_tlm_packet("<Target Name>", "<Packet Name>", <type>) Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, or WITH_UNITS (Ruby symbol, Python string). Ruby Example: names_values_and_limits_states = get_tlm_packet("INST HEALTH_STATUS", type: :FORMATTED) Python Example: names_values_and_limits_states = get_tlm_packet("INST HEALTH_STATUS", type='FORMATTED') ","version":"Next","tagName":"h3"},{"title":"get_tlm_values (modified in 5.0.0)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_values-modified-in-500","content":" Returns the values and current limits state for a specified set of telemetry items. Items can be in any telemetry packet in the system. They can all be retrieved using the same value type or a specific value type can be specified for each item. Ruby / Python Syntax: values, limits_states, limits_settings, limits_set = get_tlm_values(<Items>) Parameter\tDescriptionItems\tArray of strings of the form ['TGT__PKT__ITEM__TYPE', ... ] Ruby / Python Example: values = get_tlm_values(["INST__HEALTH_STATUS__TEMP1__CONVERTED", "INST__HEALTH_STATUS__TEMP2__RAW"]) print(values) # [[-100.0, :RED_LOW], [0, :RED_LOW]] ","version":"Next","tagName":"h3"},{"title":"get_all_tlm (since 5.13.0, since 5.0.0 as get_all_telemetry)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_tlm-since-5130-since-500-as-get_all_telemetry","content":" Returns an array of all target packet hashes. Ruby / Python Syntax: get_all_tlm("<Target Name>") Parameter\tDescriptionTarget Name\tName of the target. Ruby / Python Example: packets = get_all_tlm("INST") print(packets) #[{"target_name"=>"INST", # "packet_name"=>"ADCS", # "endianness"=>"BIG_ENDIAN", # "description"=>"Position and attitude data", # "stale"=>true, # "items"=> # [{"name"=>"CCSDSVER", # "bit_offset"=>0, # "bit_size"=>3, # ... ","version":"Next","tagName":"h3"},{"title":"get_all_tlm_names (since 5.13.0, since 5.0.6 as get_all_telemetry_names)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_tlm_names-since-5130-since-506-as-get_all_telemetry_names","content":" Returns an array of all target packet names. Ruby / Python Syntax: get_all_tlm_names("<Target Name>") Parameter\tDescriptionTarget Name\tName of the target Ruby / Python Example: get_all_tlm_names("INST") #=> ["ADCS", "HEALTH_STATUS", ...] ","version":"Next","tagName":"h3"},{"title":"get_tlm (since 5.13.0, since 5.0.0 as get_telemetry)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm-since-5130-since-500-as-get_telemetry","content":" Returns a packet hash. Ruby / Python Syntax: get_tlm("<Target Name> <Packet Name>") get_tlm("<Target Name>", "<Packet Name>") Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. Ruby / Python Example: packet = get_tlm("INST HEALTH_STATUS") print(packet) #{"target_name"=>"INST", # "packet_name"=>"HEALTH_STATUS", # "endianness"=>"BIG_ENDIAN", # "description"=>"Health and status from the instrument", # "stale"=>true, # "processors"=> # [{"name"=>"TEMP1STAT", # "class"=>"OpenC3::StatisticsProcessor", # "params"=>["TEMP1", 100, "CONVERTED"]}, # {"name"=>"TEMP1WATER", # "class"=>"OpenC3::WatermarkProcessor", # "params"=>["TEMP1", "CONVERTED"]}], # "items"=> # [{"name"=>"CCSDSVER", # "bit_offset"=>0, # "bit_size"=>3, # ... ","version":"Next","tagName":"h3"},{"title":"get_item (since 5.0.0)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_item-since-500","content":" Returns an item hash. Ruby / Python Syntax: get_item("<Target Name> <Packet Name> <Item Name>") get_item("<Target Name>", "<Packet Name>", "<Item Name>") Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the packet. Item Name\tName of the item. Ruby / Python Example: item = get_item("INST HEALTH_STATUS CCSDSVER") print(item) #{"name"=>"CCSDSVER", # "bit_offset"=>0, # "bit_size"=>3, # "data_type"=>"UINT", # "description"=>"CCSDS packet version number (See CCSDS 133.0-B-1)", # "endianness"=>"BIG_ENDIAN", # "required"=>false, # "overflow"=>"ERROR"} ","version":"Next","tagName":"h3"},{"title":"get_tlm_cnt","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_cnt","content":" Returns the number of times a specified telemetry packet has been received. Ruby / Python Syntax: get_tlm_cnt("<Target Name> <Packet Name>") get_tlm_cnt("<Target Name>", "<Packet Name>") Parameter\tDescriptionTarget Name\tName of the target. Packet Name\tName of the telemetry packet. Ruby / Python Example: tlm_cnt = get_tlm_cnt("INST HEALTH_STATUS") # Number of times the INST HEALTH_STATUS telemetry packet has been received. ","version":"Next","tagName":"h3"},{"title":"set_tlm","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_tlm","content":" Sets a telemetry item value in the Command and Telemetry Server. This value will be overwritten if a new packet is received from an interface. For that reason this method is most useful if interfaces are disconnected or for testing via the Script Runner disconnect mode. Manually setting telemetry values allows for the execution of many logical paths in scripts. Ruby / Python Syntax: set_tlm("<Target> <Packet> <Item> = <Value>", <type>) Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Item\tItem name Value\tValue to set type\tValue type RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string) Ruby Example: set_tlm("INST HEALTH_STATUS COLLECTS = 5") # type is :CONVERTED by default check("INST HEALTH_STATUS COLLECTS == 5") set_tlm("INST HEALTH_STATUS COLLECTS = 10", type: :RAW) check("INST HEALTH_STATUS COLLECTS == 10", type: :RAW) Python Example: set_tlm("INST HEALTH_STATUS COLLECTS = 5") # type is CONVERTED by default check("INST HEALTH_STATUS COLLECTS == 5") set_tlm("INST HEALTH_STATUS COLLECTS = 10", type='RAW') check("INST HEALTH_STATUS COLLECTS == 10", type='RAW') ","version":"Next","tagName":"h3"},{"title":"inject_tlm","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#inject_tlm","content":" Injects a packet into the system as if it was received from an interface. Ruby / Packet Syntax: inject_tlm("<target_name>", "<packet_name>", <item_hash>, <type>) Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Item Hash\tHash of item name/value for each item. If an item is not specified in the hash, the current value table value will be used. Optional parameter, defaults to nil. type\tType of values in the item hash, RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string) Ruby Example: inject_tlm("INST", "PARAMS", {'VALUE1' => 5.0, 'VALUE2' => 7.0}) Python Example: inject_tlm("INST", "PARAMS", {'VALUE1': 5.0, 'VALUE2': 7.0}) ","version":"Next","tagName":"h3"},{"title":"override_tlm","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#override_tlm","content":" Sets the converted value for a telmetry point in the Command and Telemetry Server. This value will be maintained even if a new packet is received on the interface unless the override is canceled with the normalize_tlm method. Ruby / Python Syntax: override_tlm("<Target> <Packet> <Item> = <Value>", <type>) Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Item\tItem name Value\tValue to set type\tType to override, ALL (default), RAW, CONVERTED, FORMATTED, WITH_UNITS (Ruby symbol, Python string) Ruby Example: override_tlm("INST HEALTH_STATUS TEMP1 = 5") # All requests for TEMP1 return 5 override_tlm("INST HEALTH_STATUS TEMP2 = 0", type: :RAW) # Only RAW tlm set to 0 Python Example: override_tlm("INST HEALTH_STATUS TEMP1 = 5") # All requests for TEMP1 return 5 override_tlm("INST HEALTH_STATUS TEMP2 = 0", type='RAW') # Only RAW tlm set to 0 ","version":"Next","tagName":"h3"},{"title":"normalize_tlm","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#normalize_tlm","content":" Clears the override of a telmetry point in the Command and Telemetry Server. Ruby / Python Syntax: normalize_tlm("<Target> <Packet> <Item>", <type>) Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Item\tItem name type\tType to normalize, ALL (default), RAW, CONVERTED, FORMATTED, WITH_UNITS (Ruby symbol, Python string) Ruby Example: normalize_tlm("INST HEALTH_STATUS TEMP1") # clear all overrides normalize_tlm("INST HEALTH_STATUS TEMP1", type: :RAW) # clear only the RAW override Python Example: normalize_tlm("INST HEALTH_STATUS TEMP1") # clear all overrides normalize_tlm("INST HEALTH_STATUS TEMP1", type='RAW') # clear only the RAW override ","version":"Next","tagName":"h3"},{"title":"get_overrides","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_overrides","content":" Returns an array of the the currently overridden values set by override_tlm. NOTE: This returns all the value types that are overridden which by default is all 4 values types when using override_tlm. Ruby / Python Syntax: get_overrides() Ruby Example: override_tlm("INST HEALTH_STATUS TEMP1 = 5") puts get_overrides() #=> # [ {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"RAW", "value"=>5} # {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"CONVERTED", "value"=>5} # {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"FORMATTED", "value"=>"5"} # {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"WITH_UNITS", "value"=>"5"} ] Python Example: override_tlm("INST HEALTH_STATUS TEMP1 = 5") print(get_overrides()) #=> # [ {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'RAW', 'value': 5}, # {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'CONVERTED', 'value': 5}, # {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'FORMATTED', 'value': '5'}, # {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'WITH_UNITS', 'value': '5'} ] ","version":"Next","tagName":"h3"},{"title":"Packet Data Subscriptions","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#packet-data-subscriptions","content":" Methods for subscribing to specific packets of data. This provides an interface to ensure that each telemetry packet is received and handled rather than relying on polling where some data may be missed. ","version":"Next","tagName":"h2"},{"title":"subscribe_packets (since 5.0.3)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#subscribe_packets-since-503","content":" Allows the user to listen for one or more telemetry packets of data to arrive. A unique id is returned which is used to retrieve the data. Ruby / Python Syntax: subscribe_packets(packets) Parameter\tDescriptionpackets\tNested array of target name/packet name pairs that the user wishes to subscribe to. Ruby / Python Example: id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]) ","version":"Next","tagName":"h3"},{"title":"get_packets (since 5.0.3)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_packets-since-503","content":" Streams packet data from a previous subscription. Ruby Syntax: get_packets(id, block: nil, count: 1000) Python Syntax: get_packets(id, block=None, count=1000) Parameter\tDescriptionid\tUnique id returned by subscribe_packets block\tNumber of milliseconds to block while waiting for packets form ANY stream, default nil / None (do not block) count\tMaximum number of packets to return from EACH packet stream Ruby Example: id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]) wait 0.1 id, packets = get_packets(id) packets.each do |packet| puts "#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}" end # Reuse ID from last call, allow for 1s wait, only get 1 packet id, packets = get_packets(id, block: 1000, count: 1) packets.each do |packet| puts "#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}" end Python Example: id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']]) wait(0.1) id, packets = get_packets(id) for packet in packets: print(f"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}") # Reuse ID from last call, allow for 1s wait, only get 1 packet id, packets = get_packets(id, block=1000, count=1) for packet in packets: print(f"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}") ","version":"Next","tagName":"h3"},{"title":"get_tlm_cnt","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_cnt-1","content":" Get the receive count for a telemetry packet Ruby / Python Syntax: get_tlm_cnt("<Target> <Packet>") get_tlm_cnt("<Target>", "<Packet>") Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Ruby / Python Example: get_tlm_cnt("INST HEALTH_STATUS") #=> 10 ","version":"Next","tagName":"h3"},{"title":"get_tlm_cnts","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_tlm_cnts","content":" Get the receive counts for an array of telemetry packets Ruby / Python Syntax: get_tlm_cnts([["<Target>", "<Packet>"], ["<Target>", "<Packet>"]]) Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Ruby / Python Example: get_tlm_cnts([["INST", "ADCS"], ["INST", "HEALTH_STATUS"]]) #=> [100, 10] ","version":"Next","tagName":"h3"},{"title":"get_packet_derived_items","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_packet_derived_items","content":" Get the list of derived telemetry items for a packet Ruby / Python Syntax: get_packet_derived_items("<Target> <Packet>") get_packet_derived_items("<Target>", "<Packet>") Parameter\tDescriptionTarget\tTarget name Packet\tPacket name Ruby / Python Example: get_packet_derived_items("INST HEALTH_STATUS") #=> ['PACKET_TIMESECONDS', 'PACKET_TIMEFORMATTED', ...] ","version":"Next","tagName":"h3"},{"title":"Delays","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#delays","content":" These methods allow the user to pause the script to wait for telemetry to change or for an amount of time to pass. ","version":"Next","tagName":"h2"},{"title":"wait","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait","content":" Pauses the script for a configurable amount of time (minimum 10ms) or until a converted telemetry item meets given criteria. It supports three different syntaxes as shown. If no parameters are given then an infinite wait occurs until the user presses Go. Note that on a timeout, wait does not stop the script, usually wait_check is a better choice. Ruby / Python Syntax: elapsed = wait() #=> Returns the actual time waited elapsed = wait(<Time>) #=> Returns the actual time waited Parameter\tDescriptionTime\tTime in Seconds to delay for. Ruby / Python Syntax: # Returns true or false based on the whether the expression is true or false success = wait("<Target Name> <Packet Name> <Item Name> <Comparison>", <Timeout>, <Polling Rate (optional)>, type, quiet) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Comparison\tA comparison to perform against the telemetry item. Timeout\tTimeout in seconds. Script will proceed if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string). quiet\tNamed parameter indicating whether to log the result. Defaults to true. Ruby Example: elapsed = wait elapsed = wait 5 success = wait("INST HEALTH_STATUS COLLECTS == 3", 10) success = wait("INST HEALTH_STATUS COLLECTS == 3", 10, type: :RAW, quiet: false) Python Example: elapsed = wait() elapsed = wait(5) success = wait("INST HEALTH_STATUS COLLECTS == 3", 10) success = wait("INST HEALTH_STATUS COLLECTS == 3", 10, type='RAW', quiet=False) ","version":"Next","tagName":"h3"},{"title":"wait_tolerance","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_tolerance","content":" Pauses the script for a configurable amount of time or until a converted telemetry item meets equals an expected value within a tolerance. Note that on a timeout, wait_tolerance does not stop the script, usually wait_check_tolerance is a better choice. Ruby Python Syntax: # Returns true or false based on the whether the expression is true or false success = wait_tolerance("<Target Name> <Packet Name> <Item Name>", <Expected Value>, <Tolerance>, <Timeout>, <Polling Rate (optional), type, quiet>) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Expected Value\tExpected value of the telemetry item. Tolerance\t± Tolerance on the expected value. Timeout\tTimeout in seconds. Script will proceed if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string). quiet\tNamed parameter indicating whether to log the result. Defaults to true. Ruby Examples: success = wait_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10) success = wait_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10, type: :RAW, quiet: true) Python Examples: success = wait_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10) success = wait_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10, type='RAW', quiet=True) ","version":"Next","tagName":"h3"},{"title":"wait_expression","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_expression","content":" Pauses the script until an expression is evaluated to be true or a timeout occurs. If a timeout occurs the script will continue. This method can be used to perform more complicated comparisons than using wait as shown in the example. Note that on a timeout, wait_expression does not stop the script, usually wait_check_expression is a better choice. Syntax: # Returns true or false based on the whether the expression is true or false success = wait_expression("<Expression>", <Timeout>, <Polling Rate (optional)>, quiet) Parameter\tDescriptionExpression\tA ruby expression to evaluate. Timeout\tTimeout in seconds. Script will proceed if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. quiet\tNamed parameter indicating whether to log the result. Defaults to true. Ruby / Python Example: success = wait_expression("tlm('INST HEALTH_STATUS COLLECTS') > 5 and tlm('INST HEALTH_STATUS TEMP1') > 25.0", 10) ","version":"Next","tagName":"h3"},{"title":"wait_packet","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_packet","content":" Pauses the script until a certain number of packets have been received. If a timeout occurs the script will continue. Note that on a timeout, wait_packet does not stop the script, usually wait_check_packet is a better choice. Ruby / Python Syntax: # Returns true or false based on the whether the packet was received success = wait_packet("<Target>", "<Packet>", <Num Packets>, <Timeout>, <Polling Rate (optional)>, quiet) Parameter\tDescriptionTarget\tThe target name Packet\tThe packet name Num Packets\tThe number of packets to receive Timeout\tTimeout in seconds. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. quiet\tNamed parameter indicating whether to log the result. Defaults to true. Ruby / Python Example: success = wait_packet('INST', 'HEALTH_STATUS', 5, 10) # Wait for 5 INST HEALTH_STATUS packets over 10s ","version":"Next","tagName":"h3"},{"title":"wait_check","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_check","content":" Combines the wait and check keywords into one. This pauses the script until the converted value of a telemetry item meets given criteria or times out. On a timeout the script stops. Ruby / Python Syntax: # Returns the amount of time elapsed waiting for the expression elapsed = wait_check("<Target Name> <Packet Name> <Item Name> <Comparison>", <Timeout>, <Polling Rate (optional)>, type) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Comparison\tA comparison to perform against the telemetry item. Timeout\tTimeout in seconds. Script will stop if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string). Ruby Example: elapsed = wait_check("INST HEALTH_STATUS COLLECTS > 5", 10) elapsed = wait_check("INST HEALTH_STATUS COLLECTS > 5", 10, type: :RAW) Python Example: elapsed = wait_check("INST HEALTH_STATUS COLLECTS > 5", 10) elapsed = wait_check("INST HEALTH_STATUS COLLECTS > 5", 10, type='RAW') ","version":"Next","tagName":"h3"},{"title":"wait_check_tolerance","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_check_tolerance","content":" Pauses the script for a configurable amount of time or until a converted telemetry item equals an expected value within a tolerance. On a timeout the script stops. Ruby / Python Syntax: # Returns the amount of time elapsed waiting for the expression elapsed = wait_check_tolerance("<Target Name> <Packet Name> <Item Name>", <Expected Value>, <Tolerance>, <Timeout>, <Polling Rate (optional)>, type) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Expected Value\tExpected value of the telemetry item. Tolerance\t± Tolerance on the expected value. Timeout\tTimeout in seconds. Script will stop if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. type\tNamed parameter specifying the type. RAW, CONVERTED (default), FORMATTED, WITH_UNITS (Ruby symbol, Python string). Ruby Example: elapsed = wait_check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10) elapsed = wait_check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10, type: :RAW) Python Example: elapsed = wait_check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10) elapsed = wait_check_tolerance("INST HEALTH_STATUS COLLECTS", 10.0, 5.0, 10, type='RAW') ","version":"Next","tagName":"h3"},{"title":"wait_check_expression","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_check_expression","content":" Pauses the script until an expression is evaluated to be true or a timeout occurs. If a timeout occurs the script will stop. This method can be used to perform more complicated comparisons than using wait as shown in the example. Also see the syntax notes for check_expression. Ruby / Python Syntax: # Returns the amount of time elapsed waiting for the expression elapsed = wait_check_expression("<Expression>", <Timeout>, <Polling Rate (optional)>) Parameter\tDescriptionExpression\tA ruby expression to evaluate. Timeout\tTimeout in seconds. Script will stop if the wait statement times out waiting for the comparison to be true. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. Ruby / Python Example: elapsed = wait_check_expression("tlm('INST HEALTH_STATUS COLLECTS') > 5 and tlm('INST HEALTH_STATUS TEMP1') > 25.0", 10) ","version":"Next","tagName":"h3"},{"title":"wait_check_packet","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#wait_check_packet","content":" Pauses the script until a certain number of packets have been received. If a timeout occurs the script will stop. Ruby / Python Syntax: # Returns the amount of time elapsed waiting for the packets elapsed = wait_check_packet("<Target>", "<Packet>", <Num Packets>, <Timeout>, <Polling Rate (optional)>, quiet) Parameter\tDescriptionTarget\tThe target name Packet\tThe packet name Num Packets\tThe number of packets to receive Timeout\tTimeout in seconds. Script will stop if the wait statement times out waiting specified number of packets. Polling Rate\tHow often the comparison is evaluated in seconds. Defaults to 0.25 if not specified. quiet\tNamed parameter indicating whether to log the result. Defaults to true. Ruby / Python Example: elapsed = wait_check_packet('INST', 'HEALTH_STATUS', 5, 10) # Wait for 5 INST HEALTH_STATUS packets over 10s ","version":"Next","tagName":"h3"},{"title":"Limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#limits","content":" These methods deal with handling telemetry limits. ","version":"Next","tagName":"h2"},{"title":"limits_enabled?, limits_enabled","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#limits_enabled-limits_enabled","content":" The limits_enabled? method returns true/false depending on whether limits are enabled for a telemetry item. Ruby Syntax: limits_enabled?("<Target Name> <Packet Name> <Item Name>") Python Syntax: limits_enabled("<Target Name> <Packet Name> <Item Name>") Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Ruby Example: enabled = limits_enabled?("INST HEALTH_STATUS TEMP1") #=> true or false Python Example: enabled = limits_enabled("INST HEALTH_STATUS TEMP1") #=> True or False ","version":"Next","tagName":"h3"},{"title":"enable_limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#enable_limits","content":" Enables limits monitoring for the specified telemetry item. Ruby / Python Syntax: enable_limits("<Target Name> <Packet Name> <Item Name>") Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Ruby / Python Example: enable_limits("INST HEALTH_STATUS TEMP1") ","version":"Next","tagName":"h3"},{"title":"disable_limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disable_limits","content":" Disables limits monitoring for the specified telemetry item. Ruby / Python Syntax: disable_limits("<Target Name> <Packet Name> <Item Name>") Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Ruby / Python Example: disable_limits("INST HEALTH_STATUS TEMP1") ","version":"Next","tagName":"h3"},{"title":"enable_limits_group","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#enable_limits_group","content":" Enables limits monitoring on a set of telemetry items specified in a limits group. Ruby / Python Syntax: enable_limits_group("<Limits Group Name>") Parameter\tDescriptionLimits Group Name\tName of the limits group. Ruby / Python Example: enable_limits_group("SAFE_MODE") ","version":"Next","tagName":"h3"},{"title":"disable_limits_group","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disable_limits_group","content":" Disables limits monitoring on a set of telemetry items specified in a limits group. Ruby / Python Syntax: disable_limits_group("<Limits Group Name>") Parameter\tDescriptionLimits Group Name\tName of the limits group. Ruby / Python Example: disable_limits_group("SAFE_MODE") ","version":"Next","tagName":"h3"},{"title":"get_limits_groups","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_limits_groups","content":" Returns the list of limits groups in the system. Ruby / Python Syntax / Example: limits_groups = get_limits_groups() ","version":"Next","tagName":"h3"},{"title":"set_limits_set","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_limits_set","content":" Sets the current limits set. The default limits set is DEFAULT. Ruby / Python Syntax: set_limits_set("<Limits Set Name>") Parameter\tDescriptionLimits Set Name\tName of the limits set. Ruby / Python Example: set_limits_set("DEFAULT") ","version":"Next","tagName":"h3"},{"title":"get_limits_set","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_limits_set","content":" Returns the name of the current limits set. The default limits set is DEFAULT. Ruby / Python Syntax / Example: limits_set = get_limits_set() ","version":"Next","tagName":"h3"},{"title":"get_limits_sets","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_limits_sets","content":" Returns the list of limits sets in the system. Ruby / Python Syntax / Example: limits_sets = get_limits_sets() ","version":"Next","tagName":"h3"},{"title":"get_limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_limits","content":" Returns hash / dict of all the limits settings for a telemetry point. Ruby / Python Syntax: get_limits(<Target Name>, <Packet Name>, <Item Name>) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item Packet Name\tName of the telemetry packet of the telemetry item Item Name\tName of the telemetry item Ruby Example: result = get_limits('INST', 'HEALTH_STATUS', 'TEMP1') puts result #=> {"DEFAULT"=>[-80.0, -70.0, 60.0, 80.0, -20.0, 20.0], "TVAC"=>[-80.0, -30.0, 30.0, 80.0]} puts result.keys #=> ['DEFAULT', 'TVAC'] puts result['DEFAULT'] #=> [-80.0, -70.0, 60.0, 80.0, -20.0, 20.0] Python Example: result = get_limits('INST', 'HEALTH_STATUS', 'TEMP1') print(result) #=> {'DEFAULT'=>[-80.0, -70.0, 60.0, 80.0, -20.0, 20.0], 'TVAC'=>[-80.0, -30.0, 30.0, 80.0]} print(result.keys()) #=> dict_keys(['DEFAULT', 'TVAC']) print(result['DEFAULT']) #=> [-80.0, -70.0, 60.0, 80.0, -20.0, 20.0] ","version":"Next","tagName":"h3"},{"title":"set_limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_limits","content":" The set_limits_method sets limits settings for a telemetry point. Note: In most cases it would be better to update your config files or use different limits sets rather than changing limits settings in realtime. Ruby / Python Syntax: set_limits(<Target Name>, <Packet Name>, <Item Name>, <Red Low>, <Yellow Low>, <Yellow High>, <Red High>, <Green Low (optional)>, <Green High (optional)>, <Limits Set (optional)>, <Persistence (optional)>, <Enabled (optional)>) Parameter\tDescriptionTarget Name\tName of the target of the telemetry item. Packet Name\tName of the telemetry packet of the telemetry item. Item Name\tName of the telemetry item. Red Low\tRed Low setting for this limits set. Any value below this value will be make the item red. Yellow Low\tYellow Low setting for this limits set. Any value below this value but greater than Red Low will be make the item yellow. Yellow High\tYellow High setting for this limits set. Any value above this value but less than Red High will be make the item yellow. Red High\tRed High setting for this limits set. Any value above this value will be make the item red. Green Low\tOptional. If given, any value greater than Green Low and less than Green_High will make the item blue indicating a good operational value. Green High\tOptional. If given, any value greater than Green Low and less than Green_High will make the item blue indicating a good operational value. Limits Set\tOptional. Set the limits for a specific limits set. If not given then it defaults to setting limits for the CUSTOM limits set. Persistence\tOptional. Set the number of samples this item must be out of limits before changing limits state. Defaults to no change. Note: This affects all limits settings across limits sets. Enabled\tOptional. Whether or not limits are enabled for this item. Defaults to true. Note: This affects all limits settings across limits sets. Ruby / Python Example: set_limits('INST', 'HEALTH_STATUS', 'TEMP1', -10.0, 0.0, 50.0, 60.0, 30.0, 40.0, 'TVAC', 1, true) ","version":"Next","tagName":"h3"},{"title":"get_out_of_limits","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_out_of_limits","content":" Returns an array with the target_name, packet_name, item_name, and limits_state of all items that are out of their limits ranges. Ruby / Python Syntax / Example: out_of_limits_items = get_out_of_limits() ","version":"Next","tagName":"h3"},{"title":"get_overall_limits_state","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_overall_limits_state","content":" Returns the overall limits state for the COSMOS system. Returns 'GREEN', 'YELLOW', or 'RED'. Ruby / Python Syntax: get_overall_limits_state(<Ignored Items> (optional)) Parameter\tDescriptionIgnored Items\tArray of arrays with items to ignore when determining the overall limits state. [['TARGET_NAME', 'PACKET_NAME', 'ITEM_NAME'], ...] Ruby / Python Example: overall_limits_state = get_overall_limits_state() overall_limits_state = get_overall_limits_state([['INST', 'HEALTH_STATUS', 'TEMP1']]) ","version":"Next","tagName":"h3"},{"title":"get_limits_events","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_limits_events","content":" Returns limits events based on an offset returned from the last time it was called. Ruby / Python Syntax: get_limits_event(<Offset>, count) Parameter\tDescriptionOffset\tOffset returned by the previous call to get_limits_event. Default is nil for the initial call count\tNamed parameter specifying the maximum number of limits events to return. Default is 100 Ruby / Python Example: events = get_limits_event() print(events) #[["1613077715557-0", # {"type"=>"LIMITS_CHANGE", # "target_name"=>"TGT", # "packet_name"=>"PKT", # "item_name"=>"ITEM", # "old_limits_state"=>"YELLOW_LOW", # "new_limits_state"=>"RED_LOW", # "time_nsec"=>"1", # "message"=>"message"}], # ["1613077715557-1", # {"type"=>"LIMITS_CHANGE", # "target_name"=>"TGT", # "packet_name"=>"PKT", # "item_name"=>"ITEM", # "old_limits_state"=>"RED_LOW", # "new_limits_state"=>"YELLOW_LOW", # "time_nsec"=>"2", # "message"=>"message"}]] # The last offset is the first item ([0]) in the last event ([-1]) events = get_limits_event(events[-1][0]) print(events) #[["1613077715657-0", # {"type"=>"LIMITS_CHANGE", # ... ","version":"Next","tagName":"h3"},{"title":"Targets","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#targets","content":" Methods for getting knowledge about targets. ","version":"Next","tagName":"h2"},{"title":"get_target_names","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_target_names","content":" Returns a list of the targets in the system in an array. Ruby Syntax / Example: targets = get_target_names() #=> ['INST', 'INST2', 'EXAMPLE', 'TEMPLATED'] ","version":"Next","tagName":"h3"},{"title":"get_target","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_target","content":" Returns a target hash containing all the information about the target. Ruby Syntax: get_target("<Target Name>") Parameter\tDescriptionTarget Name\tName of the target. Ruby Example: target = get_target("INST") print(target) #{"name"=>"INST", # "folder_name"=>"INST", # "requires"=>[], # "ignored_parameters"=> # ["CCSDSVER", # "CCSDSTYPE", # "CCSDSSHF", # "CCSDSAPID", # "CCSDSSEQFLAGS", # "CCSDSSEQCNT", # "CCSDSLENGTH", # "PKTID"], # "ignored_items"=> # ["CCSDSVER", # "CCSDSTYPE", # "CCSDSSHF", # "CCSDSAPID", # "CCSDSSEQFLAGS", # "CCSDSSEQCNT", # "CCSDSLENGTH", # "RECEIVED_COUNT", # "RECEIVED_TIMESECONDS", # "RECEIVED_TIMEFORMATTED"], # "limits_groups"=>[], # "cmd_tlm_files"=> # [".../targets/INST/cmd_tlm/inst_cmds.txt", # ".../targets/INST/cmd_tlm/inst_tlm.txt"], # "cmd_unique_id_mode"=>false, # "tlm_unique_id_mode"=>false, # "id"=>nil, # "updated_at"=>1613077058266815900, # "plugin"=>nil} ","version":"Next","tagName":"h3"},{"title":"get_target_interfaces","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_target_interfaces","content":" Returns the interfaces for all targets. The return value is an array of arrays where each subarray contains the target name, and a String of all the interface names. Syntax / Example: target_ints = get_target_interfaces() target_ints.each do |target_name, interfaces| puts "Target: #{target_name}, Interfaces: #{interfaces}" end ","version":"Next","tagName":"h3"},{"title":"Interfaces","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#interfaces","content":" These methods allow the user to manipulate COSMOS interfaces. ","version":"Next","tagName":"h2"},{"title":"get_interface (since 5.0.0)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_interface-since-500","content":" Returns an interface status including the as built interface and its current status (cmd/tlm counters, etc). Ruby / Python Syntax: get_interface("<Interface Name>") Parameter\tDescriptionInterface Name\tName of the interface. Ruby / Python Example: interface = get_interface("INST_INT") print(interface) #{"name"=>"INST_INT", # "config_params"=>["interface.rb"], # "target_names"=>["INST"], # "connect_on_startup"=>true, # "auto_reconnect"=>true, # "reconnect_delay"=>5.0, # "disable_disconnect"=>false, # "options"=>[], # "protocols"=>[], # "log"=>true, # "log_raw"=>false, # "plugin"=>nil, # "updated_at"=>1613076213535979900, # "state"=>"CONNECTED", # "clients"=>0, # "txsize"=>0, # "rxsize"=>0, # "txbytes"=>0, # "rxbytes"=>0, # "txcnt"=>0, # "rxcnt"=>0} ","version":"Next","tagName":"h3"},{"title":"get_interface_names","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_interface_names","content":" Returns a list of the interfaces in the system in an array. Ruby / Python Syntax / Example: interface_names = get_interface_names() #=> ['INST_INT', 'INST2_INT', 'EXAMPLE_INT', 'TEMPLATED_INT'] ","version":"Next","tagName":"h3"},{"title":"connect_interface","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#connect_interface","content":" Connects to targets associated with a COSMOS interface. Ruby / Python Syntax: connect_interface("<Interface Name>", <Interface Parameters (optional)>) Parameter\tDescriptionInterface Name\tName of the interface. Interface Parameters\tParameters used to initialize the interface. If none are given then the interface will use the parameters that were given in the server configuration file. Ruby / Python Example: connect_interface("INT1") connect_interface("INT1", hostname, port) ","version":"Next","tagName":"h3"},{"title":"disconnect_interface","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disconnect_interface","content":" Disconnects from targets associated with a COSMOS interface. Ruby / Python Syntax: disconnect_interface("<Interface Name>") Parameter\tDescriptionInterface Name\tName of the interface. Ruby / Python Example: disconnect_interface("INT1") ","version":"Next","tagName":"h3"},{"title":"start_raw_logging_interface","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#start_raw_logging_interface","content":" Starts logging of raw data on one or all interfaces. This is for debugging purposes only. Ruby / Python Syntax: start_raw_logging_interface("<Interface Name (optional)>") Parameter\tDescriptionInterface Name\tName of the Interface to command to start raw data logging. Defaults to 'ALL' which causes all interfaces that support raw data logging to start logging raw data. Ruby / Python Example: start_raw_logging_interface("int1") ","version":"Next","tagName":"h3"},{"title":"stop_raw_logging_interface","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stop_raw_logging_interface","content":" Stops logging of raw data on one or all interfaces. This is for debugging purposes only. Ruby / Python Syntax: stop_raw_logging_interface("<Interface Name (optional)>") Parameter\tDescriptionInterface Name\tName of the Interface to command to stop raw data logging. Defaults to 'ALL' which causes all interfaces that support raw data logging to stop logging raw data. Ruby / Python Example: stop_raw_logging_interface("int1") ","version":"Next","tagName":"h3"},{"title":"get_all_interface_info","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_interface_info","content":" Returns information about all interfaces. The return value is an array of arrays where each subarray contains the interface name, connection state, number of connected clients, transmit queue size, receive queue size, bytes transmitted, bytes received, command count, and telemetry count. Ruby Syntax / Example: interface_info = get_all_interface_info() interface_info.each do |interface_name, connection_state, num_clients, tx_q_size, rx_q_size, tx_bytes, rx_bytes, cmd_count, tlm_count| puts "Interface: #{interface_name}, Connection state: #{connection_state}, Num connected clients: #{num_clients}" puts "Transmit queue size: #{tx_q_size}, Receive queue size: #{rx_q_size}, Bytes transmitted: #{tx_bytes}, Bytes received: #{rx_bytes}" puts "Cmd count: #{cmd_count}, Tlm count: #{tlm_count}" end Python Syntax / Example: interface_info = get_all_interface_info() for interface in interface_info(): # [interface_name, connection_state, num_clients, tx_q_size, rx_q_size, tx_bytes, rx_bytes, cmd_count, tlm_count] print(f"Interface: {interface[0]}, Connection state: {interface[1]}, Num connected clients: {interface[2]}") print(f"Transmit queue size: {interface[3]}, Receive queue size: {interface[4]}, Bytes transmitted: {interface[5]}, Bytes received: {interface[6]}") print(f"Cmd count: {interface[7]}, Tlm count: {interface[8]}") ","version":"Next","tagName":"h3"},{"title":"map_target_to_interface","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#map_target_to_interface","content":" Map a target to an interface allowing target commands and telemetry to be processed by that interface. Ruby / Python Syntax: map_target_to_interface("<Target Name>", "<Interface Name>", cmd_only, tlm_only, unmap_old) Parameter\tDescriptionTarget Name\tName of the target Interface Name\tName of the interface cmd_only\tNamed parameter whether to map target commands only to the interface (default: false) tlm_only\tNamed parameter whether to map target telemetry only to the interface (default: false) unmap_old\tNamed parameter whether remove the target from all existing interfaces (default: true) Ruby Example: map_target_to_interface("INST", "INST_INT", unmap_old: false) Python Example: map_target_to_interface("INST", "INST_INT", unmap_old=False) ","version":"Next","tagName":"h3"},{"title":"interface_cmd","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#interface_cmd","content":" Send a command directly to an interface. This has no effect in the standard COSMOS interfaces but can be implemented by a custom interface to change behavior. Ruby / Python Syntax: interface_cmd("<Interface Name>", "<Command Name>", "<Command Parameters>") Parameter\tDescriptionInterface Name\tName of the interface Command Name\tName of the command to send Command Parameters\tAny parameters to send with the command Ruby / Python Example: interface_cmd("INST", "DISABLE_CRC") ","version":"Next","tagName":"h3"},{"title":"interface_protocol_cmd","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#interface_protocol_cmd","content":" Send a command directly to an interface protocol. This has no effect in the standard COSMOS protocols but can be implemented by a custom protocol to change behavior. Ruby / Python Syntax: interface_protocol_cmd("<Interface Name>", "<Command Name>", "<Command Parameters>") Parameter\tDescriptionInterface Name\tName of the interface Command Name\tName of the command to send Command Parameters\tAny parameters to send with the command read_write\tWhether command gets send to read or write protocols. Must be one of READ, WRITE, or READ_WRITE (Ruby symbols, Python strings). The default is READ_WRITE. index\tWhich protocol in the stack the command should apply to. The default is -1 which applies the command to all. Ruby Example: interface_protocol_cmd("INST", "DISABLE_CRC", read_write: :READ_WRITE, index: -1) Python Example: interface_protocol_cmd("INST", "DISABLE_CRC", read_write='READ_WRITE', index=-1) ","version":"Next","tagName":"h3"},{"title":"Routers","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#routers","content":" These methods allow the user to manipulate COSMOS routers. ","version":"Next","tagName":"h2"},{"title":"connect_router","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#connect_router","content":" Connects a COSMOS router. Ruby / Python Syntax: connect_router("<Router Name>", <Router Parameters (optional)>) Parameter\tDescriptionRouter Name\tName of the router. Router Parameters\tParameters used to initialize the router. If none are given then the router will use the parameters that were given in the server configuration file. Ruby / Python Example: connect_ROUTER("INST_ROUTER") connect_router("INST_ROUTER", 7779, 7779, nil, 10.0, 'PREIDENTIFIED') ","version":"Next","tagName":"h3"},{"title":"disconnect_router","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disconnect_router","content":" Disconnects a COSMOS router. Ruby / Python Syntax: disconnect_router("<Router Name>") Parameter\tDescriptionRouter Name\tName of the router. Ruby / Python Example: disconnect_router("INT1_ROUTER") ","version":"Next","tagName":"h3"},{"title":"get_router_names","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_router_names","content":" Returns a list of the routers in the system in an array. Ruby / Python Syntax / Example: router_names = get_router_names() #=> ['ROUTER_INT'] ","version":"Next","tagName":"h3"},{"title":"get_router (since 5.0.0)","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_router-since-500","content":" Returns a router status including the as built router and its current status (cmd/tlm counters, etc). Ruby / Python Syntax: get_router("<Router Name>") Parameter\tDescriptionRouter Name\tName of the router. Ruby / Python Example: router = get_router("ROUTER_INT") print(router) #{"name"=>"ROUTER_INT", # "config_params"=>["router.rb"], # "target_names"=>["INST"], # "connect_on_startup"=>true, # "auto_reconnect"=>true, # "reconnect_delay"=>5.0, # "disable_disconnect"=>false, # "options"=>[], # "protocols"=>[], # "log"=>true, # "log_raw"=>false, # "plugin"=>nil, # "updated_at"=>1613076213535979900, # "state"=>"CONNECTED", # "clients"=>0, # "txsize"=>0, # "rxsize"=>0, # "txbytes"=>0, # "rxbytes"=>0, # "txcnt"=>0, # "rxcnt"=>0} ","version":"Next","tagName":"h3"},{"title":"get_all_router_info","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_router_info","content":" Returns information about all routers. The return value is an array of arrays where each subarray contains the router name, connection state, number of connected clients, transmit queue size, receive queue size, bytes transmitted, bytes received, packets received, and packets sent. Ruby Syntax / Example: router_info = get_all_router_info() router_info.each do |router_name, connection_state, num_clients, tx_q_size, rx_q_size, tx_bytes, rx_bytes, pkts_rcvd, pkts_sent| puts "Router: #{router_name}, Connection state: #{connection_state}, Num connected clients: #{num_clients}" puts "Transmit queue size: #{tx_q_size}, Receive queue size: #{rx_q_size}, Bytes transmitted: #{tx_bytes}, Bytes received: #{rx_bytes}" puts "Packets received: #{pkts_rcvd}, Packets sent: #{pkts_sent}" end Python Syntax / Example: router_info = get_all_router_info() # router_name, connection_state, num_clients, tx_q_size, rx_q_size, tx_bytes, rx_bytes, pkts_rcvd, pkts_sent for router in router_info: print(f"Router: {router[0]}, Connection state: {router[1]}, Num connected clients: {router[2]}") print(f"Transmit queue size: {router[3]}, Receive queue size: {router[4]}, Bytes transmitted: {router[5]}, Bytes received: {router[6]}") print(f"Packets received: {router[7]}, Packets sent: {router[8]}") ","version":"Next","tagName":"h3"},{"title":"start_raw_logging_router","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#start_raw_logging_router","content":" Starts logging of raw data on one or all routers. This is for debugging purposes only. Ruby / Python Syntax: start_raw_logging_router("<Router Name (optional)>") Parameter\tDescriptionRouter Name\tName of the Router to command to start raw data logging. Defaults to 'ALL' which causes all routers that support raw data logging to start logging raw data. Ruby / Python Example: start_raw_logging_router("router1") ","version":"Next","tagName":"h3"},{"title":"stop_raw_logging_router","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stop_raw_logging_router","content":" Stops logging of raw data on one or all routers. This is for debugging purposes only. Ruby / Python Syntax: stop_raw_logging_router("<Router Name (optional)>") Parameter\tDescriptionRouter Name\tName of the Router to command to stop raw data logging. Defaults to 'ALL' which causes all routers that support raw data logging to stop logging raw data. Ruby / Python Example: stop_raw_logging_router("router1") ","version":"Next","tagName":"h3"},{"title":"router_cmd","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#router_cmd","content":" Send a command directly to a router. This has no effect in the standard COSMOS routers but can be implemented by a custom router to change behavior. Ruby / Python Syntax: router_cmd("<Router Name>", "<Command Name>", "<Command Parameters>") Parameter\tDescriptionRouter Name\tName of the router Command Name\tName of the command to send Command Parameters\tAny parameters to send with the command Ruby / Python Example: router_cmd("INST", "DISABLE_CRC") ","version":"Next","tagName":"h3"},{"title":"router_protocol_cmd","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#router_protocol_cmd","content":" Send a command directly to an router protocol. This has no effect in the standard COSMOS protocols but can be implemented by a custom protocol to change behavior. Ruby / Python Syntax: router_protocol_cmd("<Router Name>", "<Command Name>", "<Command Parameters>", read_write, index) Parameter\tDescriptionRouter Name\tName of the router Command Name\tName of the command to send Command Parameters\tAny parameters to send with the command read_write\tWhether command gets send to read or write protocols. Must be one of READ, WRITE, or READ_WRITE (Ruby symbols, Python strings). The default is READ_WRITE. index\tWhich protocol in the stack the command should apply to. The default is -1 which applies the command to all. Ruby Example: router_protocol_cmd("INST", "DISABLE_CRC", read_write: :READ_WRITE, index: -1) Python Example: router_protocol_cmd("INST", "DISABLE_CRC", read_write='READ_WRITE', index=-1) ","version":"Next","tagName":"h3"},{"title":"Stashing Data","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stashing-data","content":" These methods allow the user to store temporary data into COSMOS and retrieve it. The storage is implemented as a key / value storage (Ruby hash or Python dict). This can be used in scripts to store information that applies across multiple scripts or multiple runs of a single script. ","version":"Next","tagName":"h2"},{"title":"stash_set","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stash_set","content":" Sets a stash item. Ruby / Python Syntax: stash_set("<Stash Key>", <Stash Value>) Parameter\tDescriptionStash Key\tName of the stash key to set Stash Value\tValue to set Ruby / Python Example: stash_set('run_count', 5) stash_set('setpoint', 23.4) ","version":"Next","tagName":"h3"},{"title":"stash_get","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stash_get","content":" Returns the specified stash item. Ruby / Python Syntax: stash_get("<Stash Key>") Parameter\tDescriptionStash Key\tName of the stash key to return Ruby / Python Example: stash_get('run_count') #=> 5 ","version":"Next","tagName":"h3"},{"title":"stash_all","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stash_all","content":" Returns all the stash items as a Ruby hash or Python dict. Ruby Syntax / Example: stash_all() #=> ['run_count' => 5, 'setpoint' => 23.4] Python Syntax / Example: stash_all() #=> ['run_count': 5, 'setpoint': 23.4] ","version":"Next","tagName":"h3"},{"title":"stash_keys","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stash_keys","content":" Returns all the stash keys. Ruby / Python Syntax / Example: stash_keys() #=> ['run_count', 'setpoint'] ","version":"Next","tagName":"h3"},{"title":"stash_delete","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#stash_delete","content":" Deletes a stash item. Note this actions is permanent! Ruby / Python Syntax: stash_delete("<Stash Key>") Parameter\tDescriptionStash Key\tName of the stash key to delete Ruby / Python Example: stash_delete("run_count") ","version":"Next","tagName":"h3"},{"title":"Executing Other Procedures","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#executing-other-procedures","content":" These methods allow the user to bring in files of subroutines and execute other test procedures. ","version":"Next","tagName":"h2"},{"title":"start","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#start","content":" Starts execution of another high level test procedure. No parameters can be given to high level test procedures. If parameters are necessary, then consider using a subroutine. Syntax: start("<Procedure Filename>") Parameter\tDescriptionProcedure Filename\tName of the test procedure file. These files are normally in the procedures folder but may be anywhere in the Ruby search path. Additionally, absolute paths are supported. Example: start("test1.rb") ","version":"Next","tagName":"h3"},{"title":"load_utility","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#load_utility","content":" Reads in a script file that contains useful subroutines for use in your test procedure. When these subroutines run in ScriptRunner or TestRunner, their lines will be highlighted. If you want to import subroutines but do not want their lines to be highlighted in ScriptRunner or TestRunner, use the standard Ruby 'load' or 'require' statement or Python 'import' statement. Ruby / Python Syntax: load_utility("TARGET/lib/<Utility Filename>") Parameter\tDescriptionUtility Filename\tName of the script file containing subroutines including the .rb or .py extension. You need to include the full target name and path such as TARGET/lib/utility.rb Example: load_utility("TARGET/lib/mode_changes.rb") # Ruby load_utility("TARGET/lib/mode_changes.py") # Python ","version":"Next","tagName":"h3"},{"title":"Opening, Closing & Creating Telemetry Screens","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#opening-closing--creating-telemetry-screens","content":" These methods allow the user to open, close or create unique telemetry screens from within a test procedure. ","version":"Next","tagName":"h2"},{"title":"display_screen","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#display_screen","content":" Opens a telemetry screen at the specified position. Ruby / Python Syntax: display_screen("<Target Name>", "<Screen Name>", <X Position (optional)>, <Y Position (optional)>) Parameter\tDescriptionTarget Name\tTelemetry screen target name Screen Name\tScreen name within the specified target X Position\tX coordinate for the upper left hand corner of the screen Y Position\tY coordinate for the upper left hand corner of the screen Ruby / Python Example: display_screen("INST", "ADCS", 100, 200) ","version":"Next","tagName":"h3"},{"title":"clear_screen","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#clear_screen","content":" Closes an open telemetry screen. Ruby / Python Syntax: clear_screen("<Target Name>", "<Screen Name>") Parameter\tDescriptionTarget Name\tTelemetry screen target name Screen Name\tScreen name within the specified target Ruby / Python Example: clear_screen("INST", "ADCS") ","version":"Next","tagName":"h3"},{"title":"clear_all_screens","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#clear_all_screens","content":" Closes all open screens. Ruby / Python Syntax / Example: clear_all_screens() ","version":"Next","tagName":"h3"},{"title":"delete_screen","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#delete_screen","content":" Deletes an existing Telemetry Viewer screen. Ruby / Python Syntax: delete_screen("<Target Name>", "<Screen Name>") Parameter\tDescriptionTarget Name\tTelemetry screen target name Screen Name\tScreen name within the specified target Ruby / Python Example: delete_screen("INST", "ADCS") ","version":"Next","tagName":"h3"},{"title":"get_screen_list","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_screen_list","content":" The get_screen_list returns a list of available telemetry screens. Ruby / Python Syntax / Example: get_screen_list() #=> ['INST ADCS', 'INST COMMANDING', ...] ","version":"Next","tagName":"h3"},{"title":"get_screen_definition","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_screen_definition","content":" The get_screen_definition returns the text file contents of a telemetry screen definition. Syntax: get_screen_definition("<Target Name>", "<Screen Name>") Parameter\tDescriptionTarget Name\tTelemetry screen target name Screen Name\tScreen name within the specified target Ruby / Python Example: screen_definition = get_screen_definition("INST", "HS") ","version":"Next","tagName":"h3"},{"title":"create_screen","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#create_screen","content":" The create_screen allows you to create a screen directly from a script. This screen is saved to Telemetry Viewer for future use in that application. Python / Ruby Syntax: create_screen("<Target Name>", "<Screen Name>" "<Definition>") Parameter\tDescriptionTarget Name\tTelemetry screen target name Screen Name\tScreen name within the specified target Definition\tThe entire screen definition as a String Ruby Example: screen_def = ' SCREEN AUTO AUTO 0.1 FIXED VERTICAL TITLE "New Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END END ' # Here we pass in the screen definition as a string create_screen("INST", "LOCAL", screen_def) Python Example: screen_def = ' SCREEN AUTO AUTO 0.1 FIXED VERTICAL TITLE "New Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END END ' # Here we pass in the screen definition as a string create_screen("INST", "LOCAL", screen_def) ","version":"Next","tagName":"h3"},{"title":"local_screen","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#local_screen","content":" The local_screen allows you to create a local screen directly from a script which is not permanently saved to the Telemetry Viewer screen list. This is useful for one off screens that help users interact with scripts. Python / Ruby Syntax: local_screen("<Screen Name>" "<Definition>", <X Position (optional)>, <Y Position (optional)>) Parameter\tDescriptionScreen Name\tScreen name within the specified target Definition\tThe entire screen definition as a String X Position\tX coordinate for the upper left hand corner of the screen Y Position\tY coordinate for the upper left hand corner of the screen NOTE: It is possible to specify a X, Y location off the visible display. If you do so and try to re-create the screen it will not display (because it is already displayed). Try issuing a clear_all_screens() first to clear any screens off the visible display space. Ruby Example: screen_def = ' SCREEN AUTO AUTO 0.1 FIXED VERTICAL TITLE "Local Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END END ' # Here we pass in the screen definition as a string local_screen("TESTING", screen_def, 600, 75) Python Example: screen_def = """ SCREEN AUTO AUTO 0.1 FIXED VERTICAL TITLE "Local Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END END """ # Here we pass in the screen definition as a string local_screen("TESTING", screen_def, 600, 75) ","version":"Next","tagName":"h3"},{"title":"Script Runner Settings","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#script-runner-settings","content":" These methods allow the user to control various Script Runner settings. ","version":"Next","tagName":"h2"},{"title":"set_line_delay","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_line_delay","content":" This method sets the line delay in script runner. Ruby / Python Syntax: set_line_delay(<Delay>) Parameter\tDescriptionDelay\tThe amount of time script runner will wait between lines when executing a script, in seconds. Should be ≥ 0.0 Ruby / Python Example: set_line_delay(0.0) ","version":"Next","tagName":"h3"},{"title":"get_line_delay","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_line_delay","content":" The method gets the line delay that script runner is currently using. Ruby / Python Syntax / Example: curr_line_delay = get_line_delay() ","version":"Next","tagName":"h3"},{"title":"set_max_output","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_max_output","content":" This method sets the maximum number of characters to display in Script Runner output before truncating. Default is 50,000 characters. Ruby / Python Syntax: set_max_output(<Characters>) Parameter\tDescriptionCharacters\tNumber of characters to output before truncating Ruby / Python Example: set_max_output(100) ","version":"Next","tagName":"h3"},{"title":"get_max_output","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_max_output","content":" The method gets the maximum number of characters to display in Script Runner output before truncating. Default is 50,000 characters. Ruby / Python Syntax / Example: print(get_max_output()) #=> 50000 ","version":"Next","tagName":"h3"},{"title":"disable_instrumentation","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disable_instrumentation","content":" Disables instrumentation for a block of code (line highlighting and exception catching). This is especially useful for speeding up loops that are very slow if lines are instrumented. Consider breaking code like this into a separate file and using either require/load to read the file for the same effect while still allowing errors to be caught by your script. Use with Caution Disabling instrumentation will cause any error that occurs while disabled to cause your script to completely stop. Ruby Syntax / Example: disable_instrumentation do 1000.times do # Don't want this to have to highlight 1000 times end end Python Syntax / Example: with disable_instrumentation(): for x in range(1000): # Don't want this to have to highlight 1000 times ","version":"Next","tagName":"h3"},{"title":"Script Runner Suites","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#script-runner-suites","content":" Creating Script Runner suites utilizes APIs to add groups to the defined suites. For more information please see running script suites. ","version":"Next","tagName":"h2"},{"title":"add_group, add_group_setup, add_group_teardown, add_script","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#add_group-add_group_setup-add_group_teardown-add_script","content":" Adds a group's methods to the suite. The add_group method adds all the group methods including setup, teardown, and all the methods starting with 'script_' or 'test_'. The add_group_setup method adds just the setup method defined in the group class. The add_group_teardown method adds just the teardown method defined in the group class. The add_script method adds an individual method to the suite. NOTE: add_script can add any method including those not named with 'script_' or 'test_'. Ruby / Python Syntax: add_group(<Group Class>) add_group_setup(<Group Class>) add_group_teardown(<Group Class>) add_script(<Group Class>, <Method>) Parameter\tDescriptionGroup Class\tName of the previously defined class which inherits from the OpenC3 Group class. The Ruby API passes a String with the name of the group. The Python API passes the Group class directly. Method\tName of the method in the OpenC3 Group class. The Ruby API passes a String with the name of the method. The Python API passes the Group class directly. Ruby Example: load 'openc3/script/suite.rb' class ExampleGroup < OpenC3::Group def script_1 # Insert test code here ... end end class WrapperGroup < OpenC3::Group def setup # Insert test code here ... end def my_method # Insert test code here ... end def teardown # Insert test code here ... end end class MySuite < OpenC3::Suite def initialize super() add_group('ExampleGroup') add_group_setup('WrapperGroup') add_script('WrapperGroup', 'my_method') add_group_teardown('WrapperGroup') end end Python Example: from openc3.script import * from openc3.script.suite import Group, Suite class ExampleGroup(Group): def script_1(self): # Insert test code here ... pass class WrapperGroup(Group): def setup(self): # Insert test code here ... pass def my_method(self): # Insert test code here ... pass def teardown(self): # Insert test code here ... pass class MySuite(Suite): def __init__(self): super().__init__() self.add_group(ExampleGroup) self.add_group_setup(WrapperGroup) self.add_script(WrapperGroup, 'my_method') self.add_group_teardown(WrapperGroup) ","version":"Next","tagName":"h3"},{"title":"Script Runner Debugging","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#script-runner-debugging","content":" These methods allow the user to debug scripts with ScriptRunner. ","version":"Next","tagName":"h2"},{"title":"step_mode","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#step_mode","content":" Places ScriptRunner into step mode where Go must be hit to proceed to the next line. Ruby / Python Syntax / Example: step_mode() ","version":"Next","tagName":"h3"},{"title":"run_mode","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#run_mode","content":" Places ScriptRunner into run mode where the next line is run automatically. Ruby / Python Syntax / Example: run_mode() ","version":"Next","tagName":"h3"},{"title":"disconnect_script","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#disconnect_script","content":" Puts scripting into disconnect mode. In disconnect mode, commands are not sent to targets, checks are all successful, and waits expire instantly. Requests for telemetry (tlm()) typically return 0. Disconnect mode is useful for dry-running scripts without having connected targets. Ruby / Python Syntax / Example: disconnect_script() ","version":"Next","tagName":"h3"},{"title":"Metadata","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata","content":" Metadata allows you to mark the regular target / packet data logged in COSMOS with your own fields. This metadata can then be searched and used to filter data when using other COSMOS tools. ","version":"Next","tagName":"h2"},{"title":"metadata_all","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata_all","content":" Returns all the metadata that was previously set Ruby / Python Syntax: metadata_all() Parameter\tDescriptionlimit\tAmount of metadata items to return. Default is 100. Ruby Example: metadata_all(limit: 500) Python Example: metadata_all(limit='500') ","version":"Next","tagName":"h3"},{"title":"metadata_get","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata_get","content":" Returns metadata that was previously set Ruby / Python Syntax: metadata_get(start) Parameter\tDescriptionstart\tNamed parameter, time at which to retrieve metadata as integer seconds from epoch Ruby Example: metadata_get(start: 500) Python Example: metadata_get(start='500') ","version":"Next","tagName":"h3"},{"title":"metadata_set","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata_set","content":" Returns metadata that was previously set Ruby / Python Syntax: metadata_set(<Metadata>, start, color) Parameter\tDescriptionMetadata\tHash or dict of key value pairs to store as metadata. start\tNamed parameter, time at which to store metadata. Default is now. color\tNamed parameter, color to display metadata in the calendar. Default is #003784. Ruby Example: metadata_set({ 'key' => 'value' }) metadata_set({ 'key' => 'value' }, color: '#ff5252') Python Example: metadata_set({ 'key': 'value' }) metadata_set({ 'key': 'value' }, color='ff5252') ","version":"Next","tagName":"h3"},{"title":"metadata_update","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata_update","content":" Updates metadata that was previously set Ruby / Python Syntax: metadata_update(<Metadata>, start, color) Parameter\tDescriptionMetadata\tHash or dict of key value pairs to update as metadata. start\tNamed parameter, time at which to update metadata. Default is latest metadata. color\tNamed parameter, color to display metadata in the calendar. Default is #003784. Ruby Example: metadata_update({ 'key' => 'value' }) Python Example: metadata_update({ 'key': 'value' }) ","version":"Next","tagName":"h3"},{"title":"metadata_input","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#metadata_input","content":" Prompts the user to set existing metadata values or create new a new one. Ruby / Python Syntax / Example: metadata_input() ","version":"Next","tagName":"h3"},{"title":"Settings","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#settings","content":" COSMOS has several settings typically accessed through the Admin Settings tab. These APIs allow programmatic access to those same settings. ","version":"Next","tagName":"h2"},{"title":"list_settings","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#list_settings","content":" Return all the current COSMOS setting name. These are the names that should be used in the other APIs. Ruby Syntax / Example: puts list_settings() #=> ["pypi_url", "rubygems_url", "source_url", "version"] Python Syntax / Example: print(list_settings()) #=> ['pypi_url', 'rubygems_url', 'source_url', 'version'] ","version":"Next","tagName":"h3"},{"title":"get_all_settings","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_all_settings","content":" Return all the current COSMOS settings along with their values. Ruby Syntax / Example: puts get_all_settings() #=> # { "version"=>{"name"=>"version", "data"=>"5.11.4-beta0", "updated_at"=>1698074299509456507}, # "pypi_url"=>{"name"=>"pypi_url", "data"=>"https://pypi.org/simple", "updated_at"=>1698026776574347007}, # "rubygems_url"=>{"name"=>"rubygems_url", "data"=>"https://rubygems.org", "updated_at"=>1698026776574105465}, # "source_url"=>{"name"=>"source_url", "data"=>"https://github.com/OpenC3/cosmos", "updated_at"=>1698026776573904132} } Python Syntax / Example: print(get_all_settings()) #=> # { 'version': {'name': 'version', 'data': '5.11.4-beta0', 'updated_at': 1698074299509456507}, # 'pypi_url': {'name': 'pypi_url', 'data': 'https://pypi.org/simple', 'updated_at': 1698026776574347007}, # 'rubygems_url': {'name': 'rubygems_url', 'data': 'https://rubygems.org', 'updated_at': 1698026776574105465}, # 'source_url': {'name': 'source_url', 'data': 'https://github.com/OpenC3/cosmos', 'updated_at': 1698026776573904132} } ","version":"Next","tagName":"h3"},{"title":"get_setting, get_settings","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#get_setting-get_settings","content":" Return the data from the given COSMOS setting. Returns nil (Ruby) or None (Python) if the setting does not exist. Ruby / Python Syntax: get_setting(<Setting Name>) get_settings(<Setting Name1>, <Setting Name2>, ...) Parameter\tDescriptionSetting Name\tName of the setting to return Ruby Example: puts get_setting('version') #=> "5.11.4-beta0" puts get_settings('version', 'rubygems_url') #=> ["5.11.4-beta0", "https://rubygems.org"] Python Example: print(get_setting('version')) #=> '5.11.4-beta0' print(get_setting('version', 'rubygems_url')) #=> ['5.11.4-beta0', 'https://rubygems.org'] ","version":"Next","tagName":"h3"},{"title":"set_setting","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#set_setting","content":" Sets the given setting value. Admin Passwork Required This API is only accessible externally (not within Script Runner) and requires the admin password. Ruby / Python Syntax: set_setting(<Setting Name>, <Setting Value>) Parameter\tDescriptionSetting Name\tName of the setting to change Setting Value\tSetting value to set Ruby Example: set_setting('rubygems_url', 'https://mygemserver') puts get_settings('rubygems_url') #=> "https://mygemserver" Python Example: set_setting('pypi_url', 'https://mypypiserver') print(get_settings('pypi_url')) #=> 'https://mypypiserver' ","version":"Next","tagName":"h3"},{"title":"Configuration","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#configuration","content":" Many COSMOS tools have the ability to load and save a configuration. These APIs allow you to programmatically load and save the configuration. ","version":"Next","tagName":"h2"},{"title":"config_tool_names","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#config_tool_names","content":" List all the configuration tool names which are used as the first parameter in the other APIs. Ruby Syntax / Example: names = config_tool_names() pp names #=> ["telemetry_grapher", "data_viewer"] Python Syntax / Example: names = config_tool_names() print(names) #=> ['telemetry_grapher', 'data_viewer'] ","version":"Next","tagName":"h3"},{"title":"list_configs","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#list_configs","content":" List all the saved configuration names under the given tool name. Ruby / Python Syntax: list_configs(<Tool Name>) Parameter\tDescriptionTool Name\tName of the tool to retrieve configuration names from Ruby Example: configs = list_configs('telemetry_grapher') pp configs #=> ['adcs', 'temps'] Python Example: configs = list_configs('telemetry_grapher') print(configs) #=> ['adcs', 'temps'] ","version":"Next","tagName":"h3"},{"title":"load_config","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#load_config","content":" Load a particular tool configuration. Tool Configuration Tool configurations are not fully documented and subject to change between releases. Only modify values returned by load_config and do not change any keys. Ruby / Python Syntax: load_config(<Tool Name>, <Configuration Name>) Parameter\tDescriptionTool Name\tName of the tool Configuration Name\tName of the configuration Ruby / Python Example: config = load_config('telemetry_grapher', 'adcs') print(config) #=> # [ { # "items": [ # { # "targetName": "INST", # "packetName": "ADCS", # "itemName": "CCSDSVER", # ... ","version":"Next","tagName":"h3"},{"title":"save_config","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#save_config","content":" Save a particular tool configuration. Ruby / Python Syntax: save_config(<Tool Name>, <Configuration Name>, local_mode) Parameter\tDescriptionTool Name\tName of the tool Configuration Name\tName of the configuration local_mode\tWhether to save the configuration in local mode Ruby / Python Example: save_config('telemetry_grapher', 'adcs', config) ","version":"Next","tagName":"h3"},{"title":"delete_config","type":1,"pageTitle":"Scripting API Guide","url":"/docs/guides/scripting-api#delete_config","content":" Delete a particular tool configuration. Ruby / Python Syntax: delete_config(<Tool Name>, <Configuration Name>, local_mode) Parameter\tDescriptionTool Name\tName of the tool Configuration Name\tName of the configuration local_mode\tWhether to delete the configuration in local mode Ruby / Python Example: delete_config('telemetry_grapher', 'adcs') ","version":"Next","tagName":"h3"}],"options":{"id":"default"}}