Ball Aerospace COSMOS 5.0.5 Released

I’m happy to announce the release of COSMOS 5.0.5!

This release updates dependencies, has some important bug fixes, and improves overall performance. It also simplifies the init container design down to a single init container.

What’s Changed

  • Allow Script Runner to render UTF-8 chars by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1661
  • New github action container_scans in https://github.com/BallAerospace/COSMOS/pull/1656
  • Metadata constraint by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1665
  • Init and minio by @ryanmelt in https://github.com/BallAerospace/COSMOS/pull/1662
  • update_metadata merge existing by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1663
  • Change ${PWD} to . in compose.yaml by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1668
  • Add milliseconds to temp script name by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1672
  • Remove v-text on vuetify components by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1671
  • Add cosmos validate to check plugins by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1675
  • Graph legend position by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1679
  • Config stream by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1682
  • Table report by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1683
  • Add run_script method for buttons by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1688
  • Remove old interface code for inject_tlm by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1689
  • Handbooks by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1696
  • Xtce support by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1699
  • Create hash of screen def as key by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1702
  • set needs_dependencies if there is a top level lib folder by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1703
  • Admin updates by @ryanmelt in https://github.com/BallAerospace/COSMOS/pull/1707
  • Table Manager upload / download support by @jmthomas in https://github.com/BallAerospace/COSMOS/pull/1704
  • Logging Optimizations by @ryanmelt in https://github.com/BallAerospace/COSMOS/pull/1714

Migration Notes:

If you are upgrading and already have a local compose.yaml file, then you will need to the init container services, like it is defined in the compose.yaml file in the release.

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain Docker or Podman also works on linux. We actively develop and run with Docker Desktop on Mac/Windows, and Linux on Raspberry Pi, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 4GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. Run: docker-compose up -d
  4. Connect a web browser to http://localhost:2900
  5. Have fun running COSMOS 5!

We will be actively updating documentation on https://ballaerospace.github.io/cosmos-website/ to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Full Changelog: https://github.com/BallAerospace/COSMOS/compare/v5.0.4…v5.0.5

Ball Aerospace COSMOS 5.0.4 Released

I’m happy to announce the release of COSMOS 5.0.4! This release updates dependencies, has some important bug fixes, and improves overall performance.

The most obvious change from this release is that the Redis process has been broken into two. We now run a cosmos-redis service and a cosmos-redis-ephemeral service. This allows us to configure Redis to only backup configuration data, and not streaming target data, greatly reducing the cost of redis persistence and greatly improving performance.

What’s Changed

Tickets

Pull Requests

  • Take microservice name from ENV, fix topics by @jasonatball in https://github.com/BallAerospace/COSMOS/pull/1628
  • ERB should support minus sign at end trim mode to suppress blank lines by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1637
  • Split redis by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1643
  • add mutex to metric by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1644
  • Add codecov.yml by @jasonatball in https://github.com/BallAerospace/COSMOS/pull/1651
  • Metadata by @jasonatball in https://github.com/BallAerospace/COSMOS/pull/1642
  • Initial package audit script. by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1649
  • fix s3 file cache sharing temp folder across processes by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1650
  • Allow button widget vars and fix radio groups by @jasonatball in https://github.com/BallAerospace/COSMOS/pull/1652
  • Data extractor disconnects by @ryanatball in https://github.com/BallAerospace/COSMOS/pull/1653
  • Bump alpine build, move ruby-dev to cosmos-ruby by @jasonatball in https://github.com/BallAerospace/COSMOS/pull/1655

Migration Notes:

If you are upgrading and already have a local compose.yaml file, then you will need to manually add the cosmos-redis-ephemeral service, like it is defined in the compose.yaml file in the release.

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain Docker or Podman also works on linux. We actively develop and run with Docker Desktop on Mac/Windows, and Linux on Raspberry Pi, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 4GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. Run: docker-compose up -d
  4. Connect a web browser to http://localhost:2900
  5. Have fun running COSMOS 5!

We will be actively updating documentation on cosmosc2.com to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Full Changelog: https://github.com/BallAerospace/COSMOS/compare/v5.0.3…v5.0.4

Ball Aerospace COSMOS 5.0.3 Released

I’m happy to announce the release of COSMOS 5.0.3! This release updates dependencies, has a few bug fixes, and improves UI performance. Most importantly, the user interface better handles having many thousands of telemetry points. Everyone is encouraged to upgrade and start running off of the prebuilt containers on Docker Hub.

What’s Changed

  • Script file chooser dialogs added
  • Cypress Integration Tests Fully Removed (Replaced with Playwright)
  • Redis Aof persistence removed (Helps Raspberry Pi a lot)
  • TlmGrapher right click Improvements
  • Fix get_packet API
  • Disallow bracket in target, packet, packet item names
  • Fix Redis command tab
  • Fix Environment Variables in Test Runner
  • Allow util save and load script to take version
  • TargetPacketItemChooser performance improvements
  • Fix Test Suite results parsing
  • Paginate CmdTlmServer and PacketViewer
  • inject_tlm enhancements
  • Rework cleanup to be configurable and default to off
  • Added Ruby block support to wait_check by @andyp13
  • Lots of dependency versions updated to latest

Migration Notes:

If upgrading from an earlier version, you will need to go the Admin -> Microservices tab and manually delete the DEFAULT__CLEANUP__S3 microservice.

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain Docker or Podman also works on linux. We actively develop and run with Docker Desktop on Mac/Windows, and Linux on Raspberry Pi, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 4GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. Run: docker-compose up -d
  4. Connect a web browser to http://localhost:2900
  5. Have fun running COSMOS 5!

We will be actively updating documentation on cosmosc2.com to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Full Changelog: https://github.com/BallAerospace/COSMOS/compare/v5.0.2…v5.0.3

Ball Aerospace COSMOS 5.0.2 Released

I’m happy to announce the release of COSMOS 5.0.2! This release brings new tools, lots of bug fixes, and a focus on stability. Everyone is encouraged to upgrade and start running off of the prebuilt containers on Docker Hub.

New Tools

TableManager - Edit your binary configuration tables from COSMOS Autonomic (Beta) - Configurable Automation and Reactions Calendar (Beta) - Timeline now has a familiar calendar based interface and supports metadata entry

CI/CD Improvements

Tons of great stuff in this release, and it’s been far too long with 647 commits since the 5.0.1 release. Fortunately infrequent releases are over now that our unit test / integration test / and release process have been implemented into the Github Actions CI/CD pipeline.

Additionally we have changed from using Cypress for integration test to Playwright. With this our integration tests are now less flaky, and we are testing both Chrome and Firefox automatically.

We’ve also been doing a lot of development against an internal Git server, but will now be switching back to fully open development on Github to make maximum use of this CI/CD environment.

Release Artifacts

A full set of release artifacts is now being pushed for every release.

  • Full set of containers to Docker Hub (No more need to build yourself)
  • Main ruby gem and all plugin tools pushed to Rubygems.org
  • @cosmosc2/tool-common npm package

Significant Changes

  • Initial Version of Automated Data Reduction
  • Added IframeWidget
  • Limits sets now supported
  • Add execute selection to script runner
  • Add ImageviewerWidget
  • Implement script edit locks
  • Add menu for find/replace to ScriptRunner
  • Colorblind Mode
  • Upgrade ACE Editor
  • Add Redis command tab to admin
  • Add SR run from cursor functionality
  • Add open/save config to limits monitor
  • Add spacer widget
  • Allow get_tlm_values to return nil if item not yet set
  • Update all of our dependency versions to latest
  • Add matrix to gemspec to support Ruby 3.1
  • Deploy UNKNOWN packet loggers
  • Partially sandbox ScriptRunner
  • Add completed script history table
  • Erb support during plugin install. Asynchronous plugin install. 3rd Party Gem Support.
  • Scriptrunner breakpoints
  • Easy Install In Offline Environments
  • Add Mnemonic Checker to ScriptRunner
  • Fix build on M1 macs
  • Upgrade vue cli v5
  • Add target file methods
  • Support Browsers Going Back 2 Years
  • Remove privileged host setup commands
  • Update Interface Reconnect Logic to Work the Same as COSMOS 4

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain Docker or Podman also works on linux. We actively develop and run with Docker Desktop on Mac/Windows, and Linux on Raspberry Pi, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 4GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. Run: docker-compose up -d
  4. Connect a web browser to http://localhost:2900
  5. Have fun running COSMOS 5!

We will be actively updating documentation on cosmosc2.com to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Full Changelog: https://github.com/BallAerospace/COSMOS/compare/v5.0.1…v5.0.2

Ball Aerospace COSMOS 4.5.2 Released

COSMOS 4.5.2

This is primarily a bug fix release. All users are recommended to update. Please see the migration notes below for necessary changes when upgrading from 4.4.x.

Bug Fixes:

  • #1438 Remove all reserved item names from system cmd meta

Maintenance:

  • #1440 Remove ruby23 support

Migration Notes from COSMOS 4.4.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Modify you system.txt files to:

  1. Make sure you have a X_CSRF_TOKEN line with a unique value (anything will do, just change it)
  2. Change all LISTEN_HOST settings to 127.0.01 unless you need connections from external hosts
  3. If you know only specific external hosts will be connecting, add ALLOW_ACCESS lines for each
  4. Only add ALLOW_ROUTER_COMMANDING if you are chaining CmdTlmServers (that need to send commands), or you are receiving commands through routers
  5. Only add ALLOW_ORIGIN <Address of webpage>if you expect COSMOS to be accessed from a webpage
  6. Add ALLOW_HOST :7777, etc if you expect the COSMOS APIs to be accessed from external computers. Otherwise it will only accept connections that have a HOST header set to localhost

Ball Aerospace COSMOS 5.0.1 Released

This is the first patch release of COSMOS 5 Open Source Edition.

Significant Changes:

  • Added new notification system to frontend
  • ScriptRunner now supports mnemonic autocomplete for cmd() and tlm() keywords
  • Fixed redis streams that were not properly trimmed and leaking memory
  • All example telemetry screens from COSMOS 4 now working in COSMOS 5
  • Added ability to directly edit screens in TlmViewer
  • Added save and restore configuration to TlmViewer
  • Updated to use docker compose as much as possible
  • Greatly improved error reporting
  • Lots and Lots of Minor bug fixes and improvements

Known Things That Aren’t Done/Fully Working Yet:

  • Automatic data reduction for long term trending isn’t complete yet
  • Limits sets are not fully implemented

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain docker should work on linux. We’re currently only developing / running with Docker Desktop on Windows, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 8GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. The COSMOS 5 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. If you don’t need this, then please ignore, but if you see any SSL errors, this is probably why.
  4. Run cosmos-control.bat start (Windows), or ./cosmos-control.sh start (linux/Mac)
  5. COSMOS 5 will be built and when ready should be running (~10 mins for first run, ~3 for subsequent)
  6. Connect a web browser to http://localhost:2900
  7. Have fun running COSMOS 5!

We will be actively updating documentation on cosmosc2.com to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Ball Aerospace COSMOS 4.5.1 Released

COSMOS 4.5.1

This is primarily a security and bug fix release. All users are recommended to update. Please see the migration notes below for necessary changes when upgrading from 4.4.x.

Security Updates:

  • #1357 Fix fortify issues in C ext
  • #1361 Incorporate Fortify findings

Bug Fixes:

  • #1363 Synchronize packet and limits so that inject_tlm works as expected
  • #1314 Time#sys breaks with frozen timestamps
  • #1300 Read only files should not be editable
  • #1336 Sort Files in CRC File
  • #1330 xtce_converter: uninitialized constant USERPATH

New Features:

  • #1299 Stay on top command line option for tools

Maintenance:

  • #1242 Update installer link
  • #1252 Check for absolute path in installer
  • #1362 Ahk issues

Migration Notes from COSMOS 4.4.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Modify you system.txt files to:

  1. Make sure you have a X_CSRF_TOKEN line with a unique value (anything will do, just change it)
  2. Change all LISTEN_HOST settings to 127.0.01 unless you need connections from external hosts
  3. If you know only specific external hosts will be connecting, add ALLOW_ACCESS lines for each
  4. Only add ALLOW_ROUTER_COMMANDING if you are chaining CmdTlmServers (that need to send commands), or you are receiving commands through routers
  5. Only add ALLOW_ORIGIN <Address of webpage>if you expect COSMOS to be accessed from a webpage
  6. Add ALLOW_HOST :7777, etc if you expect the COSMOS APIs to be accessed from external computers. Otherwise it will only accept connections that have a HOST header set to localhost

Ball Aerospace COSMOS 5.0.0 Released

I am proud to announce the first production release of COSMOS 5.0.0 Open Source Edition!

COSMOS 5 is a highly-scalable, cloud-native, containerized, web-interfaced, command and control software system. This first production release is ready for general use.

What’s New from Coming from COSMOS 4:

  • The COSMOS user interface is now a web application instead of a desktop application - That means you can install COSMOS once, and all users just need to open a web browser to interact with the system. It also means COSMOS is a first class citizen when running in cloud environments like AWS and Azure.
  • Long term data archiving and trending is now always present and is a core feature of COSMOS. The DART tool has been retired, and equivalent functionality is now built right in.
  • COSMOS is now distributed as a collection of Docker containers orchestrated by docker-compose. The only prerequisite for running COSMOS is Docker, making it super easy to get up and running, and providing a consistent experience across host operating systems.
  • COSMOS 5 is built around a new plugin system that provides a highly modular way to add targets, interfaces, routers, procedures, microservices, and tools to the COSMOS framework. COSMOS can now easily be the base for your entire system, and should spawn an entire ecosystem of ready to use plugins for various pieces of hardware and software.

COSMOS 5 Technologies:

  • Docker - COSMOS 5 runs across a set of containers managed by Docker
  • Redis - Redis is used as a key-value store, and streaming data server
  • Minio - Minio provides an S3 compatible file storage server
  • Vue.js - Javascript technology used to build the new COSMOS user interface

Functional versions of the following COSMOS tools are included in this release:

  • Command and Telemetry Server
  • Command Sender
  • Packet Viewer
  • Telemetry Viewer
  • Telemetry Grapher
  • Script Runner (Test Runner now built in)
  • Limits Monitor
  • Data Extractor (Both Command and Telemetry)
  • Data Viewer
  • Timeline
  • Admin Interface

Known Things That Aren’t Done/Fully Working Yet:

  • Automatic data reduction for long term trending is being performed but is not selectable in tools yet

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain docker should work on linux. We’re currently only developing / running with Docker Desktop on Windows, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 8GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. The COSMOS 5 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. If you don’t need this, then please ignore, but if you see any SSL errors, this is probably why.
  4. Run cosmos-control.bat start (Windows), or ./cosmos-control.sh start (linux/Mac)
  5. COSMOS 5 will be built and when ready should be running (~20 mins for first run, ~3 for subsequent)
  6. Connect a web browser to http://localhost:2900
  7. Have fun running COSMOS 5!

We will be actively updating documentation on cosmosc2.com to capture all the details on COSMOS 5. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets, or any generic feedback to COSMOS@ball.com.

Thanks!

Ball Aerospace COSMOS 5.0.0 beta 2 Released

I am proud to announce the release of COSMOS 5 Beta 2!

COSMOS 5 is a highly scalable, cloud native, command and control software system. This second beta release is intended for users to begin to experiment with and prepare for the production COSMOS 5 release scheduled for June.

Changes from the Beta 1 Release:

  • COSMOS tools are now modular and can be added with plugins
  • Improved Stability and Testing
  • Improved API support from COSMOS 4
  • Improved Project Organization and Naming Consistency
  • New DataViewer Tool
  • New Notifications System
  • Streaming API now supports streaming raw packet data
  • Improved Admin Functionality
  • Improved TlmViewer Widget support
  • Classification Banner Support
  • Support for Raw Logging
  • Open source license changed from GPLv3 to AGPLv3
  • Removed EFK stack from running by default

COSMOS 5 Technologies:

  • Docker - COSMOS 5 runs across a set of containers managed by Docker
  • Redis - Redis is used as a key-value store, and streaming data server
  • Minio - Minio provides an S3 compatible file storage server
  • Vue.js - Javascript technology used to build the new COSMOS user interface

Functional versions of the following COSMOS tools are included in this release:

  • Command and Telemetry Server
  • Command Sender
  • Packet Viewer
  • Telemetry Viewer
  • Telemetry Grapher
  • Script Runner (Test Runner now built in)
  • Limits Monitor
  • Extractor
  • Data Viewer
  • Admin Interface

Known Things That Aren’t Done/Fully Working Yet:

  • Data Reduction
  • The LATEST telemetry packet
  • Serial Interface Support (probably would work on a linux host with the cosmos-operator container running with –privileged)
  • New Timeline Feature

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain docker should work on linux. We’re currently only developing / running with Docker Desktop on Windows, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 8GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here (bottom of page under Assets) https://github.com/BallAerospace/COSMOS/tags
  2. Extract the archive somewhere on your host computer
  3. The COSMOS 5 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. If you don’t need this, then please ignore, but if you see any SSL errors, this is probably why.
  4. Run cosmos-control.bat start (Windows), or ./cosmos-control.sh start (linux/Mac)
  5. COSMOS 5 will be built and when ready should be running (~20 mins for first run, ~3 for subsequent)
  6. Connect a web browser to http://localhost:2900
  7. Have fun trying out COSMOS 5!

We will be actively updating documentation on cosmosc2.com throughout the month of April. So if it isn’t documented yet, we’re getting there! The biggest new documentation is on the new plugin system.

Please try it out and let us know what you think! Please submit any issues as Github tickets.

Note that this release is not recommended for production use, but at this point you are encouraged to start migrating and working through any initial issues.

Thanks!

Ball Aerospace COSMOS 5.0.0 beta 1 Released

I am proud to announce the release of COSMOS 5 Beta 1!

COSMOS 5 is a highly scalable, cloud native, command and control software system. This is a beta release meant for COSMOS users to start experimenting with and providing feedback on the COSMOS 5 architecture and tools.

Changes from the Alpha 1 Release:

  • Extractor - Combines the TlmExtractor and CmdExtractor tools from COSMOS 4
  • Test Runner Support - Script Runner will now treat any file with _suite.rb in the filename as a test runner suite
  • Plugin System - One of the most exciting features coming in COSMOS 5 are plugins that allow plugging in targets / tools / and microservices into COSMOS
  • Admin Interface - Allows adding/removing plugins and changing configuration
  • Fully functional ethernet based interfaces and routers
  • Functional Limits Monitor
  • Lots of fixes and improvements

COSMOS 5 Technologies:

  • Docker - COSMOS 5 runs across a set of containers managed by Docker
  • Redis - Redis is used as a key-value store, and streaming data server
  • Minio - Minio provides an S3 compatible file storage server
  • EFK Stack - Elasticsearch, Fluentd, Kibana - Provide a distributed logging solution
  • Vue.js - Javascript technology used to build the new COSMOS user interface

Functional versions of the following COSMOS tools are included in this release:

  • Command and Telemetry Server
  • Command Sender
  • Packet Viewer
  • Telemetry Viewer
  • Telemetry Grapher
  • Script Runner (Test Runner now built in)
  • Limits Monitor
  • Extractor
  • Admin Interface

Known Things That Aren’t Done/Fully Working Yet:

  • Limits Sets and Limits Groups
  • The LATEST telemetry packet
  • Data Viewer
  • Handbook Creator
  • Replay
  • Per-Target Cmd/Tlm Counters
  • Plugin Tool Support
  • Serial Interface Support (probably would work on a linux host with the cosmos-operator container running with –privileged)
  • subscribe_ API calls
  • Some lesser used API calls

Prerequisites:

Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain docker should work on linux. We’re currently only developing / running with Docker Desktop on Windows, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 8GB RAM, 1 CPU, 80GB Disk Recommended Resources allocated to Docker: 16GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here (bottom of page under Assets)
  2. Extract the archive somewhere on your host computer
  3. The COSMOS 5 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. If you don’t need this, then please ignore, but if you see any SSL errors, this is probably why.
  4. Run cosmos_start.bat (Windows), or cosmos_start.sh (linux/Mac)
  5. COSMOS 5 will be built and when ready should be running (~15 mins for first run, ~2 for subsequent)
  6. Connect a web browser to http://localhost:8080
  7. Have fun trying out COSMOS 5!

We will be actively updating documentation on cosmosc2.com throughout the month of January. So if it isn’t documented yet, we’re getting there!

Please try it out and let us know what you think! Please submit any issues as Github tickets.

Note that this release is not recommended for production use. We will have a release candidate release in a few months.

Thanks!

Ball Aerospace COSMOS 4.5.0 Released

COSMOS 4.5.0

This is a security and bug fix release. All users are recommended to update. Please see the migration notes below for necessary changes when upgrading from 4.4.x.

Security Updates:

  • #672 Secure COSMOS API with Shared Secret
  • #1227 Prevent a Malicious Website From Sending Commands

Bug Fixes:

  • #1135 Command Sequence Tool Overriding String Parameter
  • #1151 CmdSender not setting description
  • #1158 Loss of 1 us precision on CCSDS time when using Time.ccsds2sec method
  • #1164 CmdTlmServer#reload always uses default system.txt
  • #1167 Serial Driver Initialization Bug
  • #1196 COSMOS windows stuck offscreen at Startup
  • #1200 Handbook PDF Generation wkhtmltopdf ProtocolUnknownError
  • #1210 Move CheckError definition to ApiShared

New Features:

  • #1141 Enable setting arbitrary bits in the serial drivers

Maintenance:

  • #1136 Telemetry Extractor delimiter on last item

Migration Notes from COSMOS 4.4.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Modify you system.txt files to:

  1. Make sure you have a X_CSRF_TOKEN line with a unique value (anything will do, just change it)
  2. Change all LISTEN_HOST settings to 127.0.01 unless you need connections from external hosts
  3. If you know only specific external hosts will be connecting, add ALLOW_ACCESS lines for each
  4. Only add ALLOW_ROUTER_COMMANDING if you are chaining CmdTlmServers (that need to send commands), or you are receiving commands through routers
  5. Only add ALLOW_ORIGIN <Address of webpage>if you expect COSMOS to be accessed from a webpage
  6. Add ALLOW_HOST :7777, etc if you expect the COSMOS APIs to be accessed from external computers. Otherwise it will only accept connections that have a HOST header set to localhost

Packet Time

It’s been said that there are only two hard things in programming. I think a corollary to that is time is hard. So I wanted to write a post about some of the various things COSMOS does with time and what you need to be aware of.

Received Time

If you’ve used COSMOS for a while you’ve noticed that COSMOS automatically creates several telemetry items on every packet: PACKET_TIMESECONDS, PACKET_TIMEFORMATTED, RECEIVED_COUNT, RECEIVED_TIMEFORMATTED, and RECEIVED_TIMESECONDS. While RECEIVED_COUNT is fairly self-explanatory (number of times the packet has been received) it might not be obvious why there are 4! ways to get the time.

So what’s the difference between RECEIVED_TIME vs PACKET_TIME. First of all they both have a TIMEFORMATTED and TIMESECONDS version. The formatted telemetry item returns the date and time in a YYYY/MM/DD HH:MM:SS.sss format in the local timezone. This is useful for human readable output like in Telemetry Extractor. They also can return TIMESECONDS which is the floating point UTC time in seconds from the Unix epoch.

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 is a recent (4.3.0) concept introduced by a change to support stored telemetry. The Packet class has a new method called packet_time that by default simply returns the received time as set by COSMOS. But if you define a telemetry item called ‘PACKET_TIME’, that item will be used instead.

This was done to support processing ‘stored’ telemetry data which isn’t coming into COSMOS in real-time. Previously if you created an interface to process stored telemetry, COSMOS would set the received_time as fast as it processed the files and all your stored telemetry would effective have a timestamp of ‘now’. This would have also updated the current value table in COSMOS which affect scripts, screens, etc. With COSMOS 4.3.0 and later you can set the ‘stored’ flag in your interface and the current value table is unaffected. Also if you define a ‘PACKET_TIME’ item in your packet, this item will be used to calculate the time.

Example

COSMOS provides a Unix time conversion class which returns a Ruby time object based on the number of seconds and (optionally) microseconds since the Unix epoch. Note: This returns a Ruby Time object and not a float or string!

  ITEM PACKET_TIME 0 0 DERIVED "Ruby time based on TIMESEC and TIMEUS"
    READ_CONVERSION unix_time_conversion.rb TIMESEC TIMEUS

Definining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time that COSMOS receives the packet.

If you have a question, find a bug, or want a feature please use our Github Issues.

Ball Aerospace COSMOS 5.0.0 alpha 1 Released

I am proud to announce the release of COSMOS 5 Alpha 1!

COSMOS 5 is a highly scalable, cloud native, command and control software system. This is a technology preview release meant to introduce all of the new technologies debuting in COSMOS 5.

New Technologies:

  • Docker - COSMOS 5 runs across a set of containers managed by Docker
  • Redis - Redis is used as a key-value store, and streaming data server
  • Minio - Minio provides an S3 compatible file storage server
  • EFK Stack - Elasticsearch, Fluentd, Kibana - Provide a distributed logging solution
  • Vue.js - Javascript technology used to build the new COSMOS user interface

Basic versions of the following COSMOS tools are included in this release:

  • Command and Telemetry Server
  • Command Sender
  • Packet Viewer
  • Telemetry Viewer
  • Telemetry Grapher
  • Script Runner
  • Limits Monitor

Prerequisites:

  • Docker - Running COSMOS 5 requires a working Docker installation. Typically Docker Desktop on Windows / Mac. Plain docker should work on linux. We’re currently only developing / running with Docker Desktop on Windows, so if you have any issues on another platform, please let us know by submitting a ticket!

Minimum Resources allocated to Docker: 4GB RAM, 1 CPU, 60GB Disk Recommended Resources allocated to Docker: 8GB RAM, 2+ CPUs, 100GB Disk

To Run:

  1. Download one of the archives (.zip or .tar.gz from the Github release page) Download Release Here
  2. Extract the archive somewhere on your host computer
  3. The COSMOS 5 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. If you don’t need this, then please ignore, but if you see any SSL errors, this is probably why.
  4. Run cosmos_start.bat (Windows), or cosmos_start.sh (linux/Mac)
  5. COSMOS 5 will be built and when ready should be running (~15 mins for first run, ~2 for subsequent)
  6. Connect a web browser to http://localhost:8080
  7. Have fun trying out COSMOS 5!

Identifying Packets

COSMOS goes through a multi-stage process to turn raw bits into identified Packets belonging to a target. Understanding these steps are helpful when writing your own custom interface.

Packet Identification Process

The CmdTlmServer creates a new thread for each interface that was defined by the configuration text files. It calls connect() and then continuously calls the interface’s read() method which returns a packet. Typically the packets are unidentified meaning they don’t have an assigned target or packet name. At that point the interface thread loops through all the targets assigned to the interface to identify the packet. More on that later.

The implementation of the interface’s read() method first calls read_interface() which subclasses must implement to return raw data. Once it has the raw data, read_interface() should call read_interface_base(data) which updates internal counters. The read() method then loops through all the defined protocols for that interface which can add or subtract data and/or modify the packet. Ultimately a Packet instance is returned.

The packet identification process is implemented in System.telemetry.identify!(). The identify!() method loops through all the given targets looking to identify the data. There are two ways to identify a packet. The new way, which was implemented in COSMOS 4.4, utilizes a lookup hash which is created for each target. This requires that every packet in the target has the same ID_ITEMS (same type, size, location) defined for each packet which is generally good practice. If you have hundreds of small packets associated with a single target it’s especially important to utilize this new lookup method. The old identification method is still available if you put TLM_UNIQUE_ID_MODE in the target’s target.txt file. In this mode, each packet’s ID_ITEMS are read and individually checked for a match.

Custom Interfaces

The implication of this process for custom interfaces is how and when packets are identified. If your custom interface can determine the target, you would want to identify the packet before returning it to save processing time. This may also be required if you map multiple targets to a single interface and have identification collisions. Identification collisions occur if two packets in different targets with the same ID_ITEMS are mapped to the same interface. In this case a custom interface would first have to properly identify the target and then override the read() method to identify the packet before returning it.

An example of a custom interface implementing this might look something like this:

require 'cosmos/interfaces/interface'
module Cosmos
  class MyInterface < Interface
    # ... various other methods

    def read_interface
      # Implement something to get the raw data and return it
      # ...
      # This is probably where you determine which target the data belongs to
      @target_name = "TARGETX"
      read_interface_base(data)
      return data
    end

    def read
      packet = super() # Ensure the base class implementation is called
      # Call the identify! method to identify the packet using the given target
      return System.telemetry.identify!(packet.buffer, [@target_name]).dup # Copy the identified packet before returning it
    end
  end
end

At this point the interface thread will receive an identified packet and can quickly update the current value table with the packet data.

If you have a question, find a bug, or want a feature please use our Github Issues.

Protocol Rate

Protocols were introduced into COSMOS in version 4.0.0 and were previously discussed in this post. We recently had a question at Ball about how to reduce the telemetry rate of a high speed target so I thought I would walk through the problem and solution.

The Problem

One COSMOS server was connected to a high speed telemetry target that was generating telemetry at 10Hz. Another COSMOS server was chained to this and did not need this high speed data. How do you reduce the data rate coming into the chained server?

The Solution

We can first model the chaining using the COSMOS demo. The format for the cmd_tlm_server.txt file is given in the chaining documentation and already exists in the COSMOS demo. The demo also includes a deconflicting port definition file in system_alt_ports.txt. To start the two server instances from the command line we can type:

ruby demo\tools\CmdTlmServer

And in another terminal start the chained server:

ruby demo\tools\CmdTlmServer --system system_alt_ports.txt --config cmd_tlm_server_chain.txt

Now we need to implement a custom protocol to slow down the telemetry rate on the chained server. Note that the built-in protocols are fully described on the Protocols page and also mentioned on the Interfaces page.

Custom Protocols

Let’s assume we want to slow down the INST ADCS packet which the demo generates at 10Hz. First create a new file called config/targets/INST/lib/drop_protocol.rb. This protocol will drop data until we get the rate we want. It looks like this:

require 'cosmos/interfaces/protocols/protocol'
module Cosmos
  # Limit a specific packet by dropping packets
  class DropProtocol < Protocol
    def initialize(target_name, packet_name, drop, allow_empty_data = nil)
      super(allow_empty_data)
      System.telemetry.packet(target_name, packet_name)
      @target_name = target_name
      @packet_name = packet_name
      @drop = drop.to_i
      @count = 0
    end

    def read_packet(packet)
      target_names = nil
      target_names = @interface.target_names if @interface
      identified_packet = System.telemetry.identify_and_define_packet(packet, target_names)
      if identified_packet
        if identified_packet.target_name == @target_name && identified_packet.packet_name == @packet_name
          if @count < @drop
            @count += 1
            STDOUT.puts "DROP count:#{@count}" # Debugging statement
            return :STOP
          else
            @count = 0
            STDOUT.puts "SEND" # Debugging statement
          end
        end
      end
      return super(packet)
    end
  end
end

The constructor takes the target and packet names as well as the number of packets to drop. The read_packet method first identifies the incoming packet and then determines if it is the packet we’re interested in. At that point I simply increment a counter until we get to the required number of drop packets and return :STOP to let COSMOS know not to return the packet. Once we want to actually send the packet we reset the counter and and simply fall through to super(packet).

Note I included some debugging lines to show how you can debug your own custom protocols. When you run the CmdTlmServer from the command line the STDOUT.puts will write to the terminal output.

Now we can add this protocol to the cmd_tlm_server_chain.txt definition as follows:

INTERFACE CHAININT tcpip_client_interface.rb localhost 7779 7779 10 5 PREIDENTIFIED
  TARGET INST
  TARGET INST2
  TARGET EXAMPLE
  TARGET TEMPLATED
  TARGET SYSTEM
  TARGET DART
  PROTOCOL READ DropProtocol INST ADCS 9 # Drop 9 ADCS packets to force 1Hz

Finally stop and relaunch the chained server:

ruby demo\tools\CmdTlmServer --system system_alt_ports.txt --config cmd_tlm_server_chain.txt

You should now see the following in your terminal output:

DROP count:1
DROP count:2
DROP count:3
DROP count:4
DROP count:5
DROP count:6
DROP count:7
DROP count:8
DROP count:9
SEND
DROP count:1
DROP count:2
DROP count:3
DROP count:4
DROP count:5
DROP count:6
DROP count:7
DROP count:8
DROP count:9
SEND

And the server “Tlm Packets” tab should show the ADCS count incrementing at 1Hz. Server Tlm Packets
Chained Server Tlm Packets tab

This protocol is extremely simple but it accomplishes the task at hand. Remember protocols can be layered and operate in order so keeping them simple helps with debugging and reusability.

For example, to also reduce the rate of INST2 ADCS you’d simply add another PROTOCOL line to the cmd_tlm_server_chain.txt file:

INTERFACE CHAININT tcpip_client_interface.rb localhost 7779 7779 10 5 PREIDENTIFIED
  TARGET INST
  TARGET INST2
  TARGET EXAMPLE
  TARGET TEMPLATED
  TARGET SYSTEM
  TARGET DART
  PROTOCOL READ DropProtocol INST ADCS 9 # Drop 9 ADCS packets to force 1Hz
  PROTOCOL READ DropProtocol INST2 ADCS 9 # Drop 9 ADCS packets to force 1Hz

If you have a question, find a bug, or want a feature please use our Github Issues.

Ball Aerospace COSMOS 4.4.2 Released

COSMOS 4.4.2! A minor bug fix release.

Enjoy and see below for the full list of changes.

New Features:

None

Maintenance:

  • #1117 Include name in TcpipServerInteface log messages
  • #1128 wkhtmltopdf has old comment

Bug Fixes:

  • #1126 Packets with identically named items fail checks

Migration Notes from COSMOS 4.3.0:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

The faster identification in ticket #911 does come with a potentially breaking change. The improvement requires that all packets for a given target be identified using the same fields (bit offset, bit_size, and type). This is the typical configuration, and breaking this pattern is typically a dangerous/bad choice for interfaces anyways, but previously COSMOS did default to handling packets being potentially identified using different fields in the same target. If you have a target that still requires that functionality, you need to declare CMD_UNIQUE_ID_MODE, and/or TLM_UNIQUE_ID_MODE in the target’s target.txt file to indicate it should use the slower identification method.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Ball Aerospace COSMOS 4.4.1 Released

Onward to COSMOS 4.4.1! 27 tickets have been incorporated including 6 new features, 13 bug fixes and 8 general maintenance changes.

Mainly a stability bug fix release, but there are a few cool changes. There is an new keyword for marking that bit overlaps are intentional in packet definition files. This can get rid of those annoying warnings when you do this intentionally. There is also a new DELETE_ITEM keyword to get rid of items potentially added by auto generation. Tlm Extractor and Tlm Grapher can now pull more than 10,000 data points from DART. Also, there is now the ability to package multiple targets into one gem.

Enjoy and see below for the full list of changes.

New Features:

  • #817 Allow for intentional bit overlaps in definition
  • #821 Support DART queries larger than 10000 samples in TlmExtractor / TlmGrapher
  • #922 DELETE_ITEM
  • #1028 Support Multiple Targets Packaged into Single Gem
  • #1040 Config Editor new system config wizard
  • #1104 Create releases from Docker

Maintenance:

  • #1016 Make JSON RPC API Command Methods Case Insensitive
  • #1030 Scrolling in config editor can cause issues
  • #1039 Config Editor performance enhancements
  • #1056 AppVeyer broken
  • #1074 For BLOCK parameters, suggest 0x0 as default value
  • #1080 DART stream server docs
  • #1090 DART Reduction unreliable with file imported data
  • #1101 Windows 10 Install Error?

Bug Fixes:

  • #883 DART meta filter not populating
  • #944 DART data retrievals not per packet_time
  • #1012 Screens can’t call display when launched with –screen
  • #1031 Graphing a telemetry member whose name includes brackets fails
  • #1036 TestRunner: ABORT_TESTING_AFTER_ERROR ignored for test cases added indivually to testsuite
  • #1037 telemetry#all_item_strings support undeclared target names
  • #1051 Windows serial port hangs on write
  • #1061 Excel can’t open a blank worksheet
  • #1063 Length Protocol does not handle 0 length
  • #1064 Command Sequence Repeating Write_Conversion
  • #1081 Ruby Syntax Error Checker Hangs Test Runner
  • #1087 COSMOS Installation failure in building puma_http11
  • #1092 Typo in Odd Parity

Migration Notes from COSMOS 4.3.0:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

The faster identification in ticket #911 does come with a potentially breaking change. The improvement requires that all packets for a given target be identified using the same fields (bit offset, bit_size, and type). This is the typical configuration, and breaking this pattern is typically a dangerous/bad choice for interfaces anyways, but previously COSMOS did default to handling packets being potentially identified using different fields in the same target. If you have a target that still requires that functionality, you need to declare CMD_UNIQUE_ID_MODE, and/or TLM_UNIQUE_ID_MODE in the target’s target.txt file to indicate it should use the slower identification method.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

AMOS 2019

Ryan recently attended the Advanced Maui Optical and Space Surveillance Technologies Conference (AMOS) in September. He was selected for a poster presentation based on the paper entitled “An open source long term archiving and trending solution for SSA”. It was based on the COSMOS DART tool which supports long term storage and trending of command and telemetry data. If you look at the official AMOS Summary you might also spot him (hint: Thursday)!

Ryan at AMOS
Ryan at the Poster Session, AMOS 2019

Jason atteneded the conference back in 2017 and was able to present a talk about COSMOS based on another paper entitled “A Cloud-based, Open-Source, Command-and-Control Software Paradigm for Space Situational Awareness (SSA)”.

If you have a question, find a bug, or want a feature please use our Github Issues.

Ball Aerospace COSMOS 4.4.0 Released

Here’s COSMOS 4.4.0! 52 tickets have been incorporated including 18 new features, 19 bug fixes and 15 general maintenance changes.

Overall this is just a stability bug fix release, but there are a few interesting changes. For one, max packet reception speed has been greatly increased due to ticket #911. CmdExtractor can now output in a CSV format. ScriptRunner has a recently opened file menu section, and the show_backtrace feature is now a menu option as well. There is much better support for giving absolute paths to config files on the command line. There is also a new LED type widget to display boolean telemetry.

Enjoy and see below for the full list of changes.

Breaking Changes:

The faster identification in ticket #911 does come with a potentially breaking change. The improvement requires that all packets for a given target be identified using the same fields (bit offset, bit_size, and type). This is the typical configuration, and breaking this pattern is typically a dangerous/bad choice for interfaces anyways, but previously COSMOS did default to handling packets being potentially identified using different fields in the same target. If you have a target that still requires that functionality, you need to declare CMD_UNIQUE_ID_MODE, and/or TLM_UNIQUE_ID_MODE in the target’s target.txt file to indicate it should use the slower identification method.

New Features:

  • #822 CmdExtractor CSV Output Option
  • #854 ScriptRunner open multiple files from File->Open
  • #877 Graph in PktViewer during Replay should open TlmGrapher in Replay
  • #878 Debugger enhancements
  • #886 Add show_backtrace menu option to ScriptRunner/TestRunner
  • #891 Ability for protocol write methods to write send commands to the interface that owns it
  • #893 Canvas image ease of use
  • #895 prompt should take color and font options
  • #911 Fast Identification
  • #918 Limits bar widget display specified range
  • #934 Recent Files list in Script Runner File menu
  • #938 Test Runner disable start buttons
  • #956 Templated Protocol Limited to One Target per Interface
  • #964 Improve error message when accessing packets during initialization
  • #986 Script Runner should note Disconnect mode in log
  • #987 Tools should support absolute paths on the command line
  • #990 Add Boolean Telemetry Widget
  • #1017 Data Viewer component for colored text items

Maintenance:

  • #880 tmp output not capitalizing targets
  • #884 Documentation updates
  • #913 Workaround Travis accept failures
  • #914 Increase json_drb start timeout
  • #925 Script syntax highlighting improvements
  • #930 Update COSMOS Travis builds
  • #940 Update keyword documentation
  • #953 Simplify Launcher.bat files
  • #955 Document tool command line options
  • #995 Test Runner should use LOAD_UTILITY to better match scripting
  • #998 Enable raw logging when LOG_RAW used
  • #1000 Add IgnorePacketProtocol to defaults
  • #1005 Celsius is misspelled
  • #1008 Move handbook assets out of outputs
  • #1010 Widget documentation and cleanup

Bug Fixes:

  • #870 TlmViewer Block Widget exhibits weird scrolling issue
  • #874 Demo commanding screen can’t run scripts
  • #882 Demo background task unable to be restarted
  • #889 FixedProtocol does not identify packets when leading bytes discarded
  • #908 Bad Hex String Conversion in Command Sender
  • #909 Replay doesn’t work with TlmGrapher when loading saved_config
  • #916 Allow FORMAT_STRING before STATES
  • #919 Limits Checking Enabled Status on Properties Dialog not accurate
  • #920 Gemfile may be too strict in ruby-termios version requirement
  • #927 Error if DECLARE_TARGET with no SYSTEM target folder
  • #945 Screenshotting on Macs may not work
  • #948 Unable to connect limits monitor to replay server
  • #966 OpenGL Builder is Expecting “EarthMap1024x512.gif”, but Packaged GIF is “Earthmap1024x512.gif”
  • #975 Multiple Errors in a chain of ScriptRunner Methods
  • #978 ScriptRunner breakpoints don’t get set on the correct line
  • #980 Include target REQUIRE files in marshal
  • #983 Line number discrepancy in TestRunner Report/ScriptRunner output
  • #992 missing method in xtce_converter; process_xtce
  • #1022 Table Manager TABLEFILE doesn’t support subdirectories

Migration Notes from COSMOS 4.3.0:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Protocols

Protocols were introduced into COSMOS in version 4.0.0. Protocols consist of the code that make sense of the incoming byte stream before it is turned into packets. They work hand in hand with the COSMOS interface that connects to the target, whether it is TCP/IP, UDP, or serial. The new COSMOS protocol system makes it possible to add and layer protocols into a COSMOS interface.

Built-in Protocols

COSMOS comes with a number of built-in protocols that are used directly with the COSMOS provided interfaces. In fact, when you declare your interface you’re required to specify a protocol. For example, the following code declares a TCP/IP client with a LENGTH protocol.

INTERFACE INTERFACE_NAME tcpip_client_interface.rb localhost 8080 8081 10.0 nil LENGTH 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11

The built-in protocols are fully described on the Protocols page and also mentioned on the Interfaces page.

Custom Protocols

The built-in protocols are enough to support almost all of the data streams that you’ll encounter from a target. However, sometimes you need to massage the data a little by stripping off data or adding headers. This is when you should create a custom protocol. Custom protocols have 4 methods they can override to modify the incoming telemetry data or outgoing command data. They are read_data(data), write_data(data) and read_packet(packet) write_packet(packet). The ‘data’ methods operate on the raw binary data and are used when adding or removing raw bytes from the stream. The ‘packet’ methods operate on the data after it has been identified and converted to a COSMOS Packet.

Removing Data

A recent program was interfacing to a particular device that was sending the ASCII ETX character (0x03) at the end of the data. This character wasn’t needed and was confusing a legacy application that was parsing the raw data. A custom protocol was created to simply strip off this byte from the data stream.

In the target’s lib directory the strip_etx_protocol.rb file was created. Since the protocol had to simply strip off a single byte, it overrides the read_data(data) method.

require 'cosmos/interfaces/protocols/protocol'
class StripEtxProtocol < Protocol
  def read_data(data)
    if data[-1] == "\x03"
      return super(data[0..-2])
    else
      return super(data)
    end
  end
end

Ruby can index from the back of the array with -1, -2, etc. Thus if the last byte (-1) is a binary 0x03, the protocol returns the data from 0 up to and including the second to last byte (-2). This was added to the interface by declaring it as a READ protocol since it is only modifying the incoming telemetry data.

INTERFACE DEV_INT <interface params>
  PROTOCOL READ StripEtxProtocol

Adding Data

If you need to add framing data or other bits of protocol to your outgoing data you can create a custom protocol.

In the target’s lib directory create a file called framing_protocol.rb. Since the protocol is adding data to the outgoing stream, we override the write_data(data) method.

require 'cosmos/interfaces/protocols/protocol'
class FramingProtocol < Protocol
  HEADER = "\xDE\xAD\xBE\xEF" # Binary header data
  def write_data(data)
    super(HEADER + data)
  end
end

If you have a question, find a bug, or want a feature please use our Github Issues.

Little Endian Packet Data

APPEND does not work with little endian bitfields.

Defining little endian bitfields is a little weird but does work in COSMOS.

Rules on how COSMOS handles LITTLE_ENDIAN data:

  1. 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.

  2. 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.

  3. 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.

  4. 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

Using system.txt and target.txt

system.txt

The COSMOS system configuration is performed by system.txt in the config/system directory. This file declares all the targets that will be used by COSMOS as well as top level configuration information which is primarily used by the Command and Telemetry Server.

By default, all COSMOS tools use the config/system/system.txt file. However, all tools can take a custom system configuration file by passing the “–system " option to the tool when it starts. This is typically done in the Launcher script as shown in the COSMOS demo. Here's an excerpt which shows how we're passing system2.txt using the --system option.

TOOL "Command and Telemetry Server" "LAUNCH CmdTlmServer --system system2.txt" "cts.png" --config cmd_tlm_server2.txt

Using Multiple system.txt Files

So when would you want to create and use multiple system.txt files? Since system.txt defines the targets used by the system, you can use two different system.txt files to create two configurations which contain most but not all the same targets. For example, you have a test bench with 5 different test equipment targets but different test box targets: BOX1 and BOX2. You can create one COSMOS configuration for both test benches and create two different launcher files with different lists of targets.

target.txt

The parsing of a COSMOS target is controlled by the target.txt file found at the root of the target directory. The COMMANDS and TELEMETRY keywords tell COSMOS which Command and Telemetry files to parse. For example from the COSMOS demo INST target.txt

COMMANDS inst_cmds.txt
TELEMETRY inst_tlm.txt

Since we can tell COSMOS exactly which command and telemetry files to parse we can control how the target cmd/tlm definitions get built. This is useful if you have a target with slightly different command and telemetry definitions. This can happen for varous reasons like connecting to slightly different hardware revisions. The advantage of using a single target folder in this case (vs just copying and renaming the target folder) is that you can (potentially) reuse screens and target library code. Obviously this only works if the command and telemetry definitions are only slightly different between revisions.

Combining system.txt and target.txt

When we combine the ability in system.txt to specify a specific target.txt file and the ability in target.txt to specify the command and telemetry definitions, we can create specific configurations for different environments.

This example is losely based on the COSMOS demo. First create two separate system.txt files called system1.txt and system2.txt:

Partial system1.txt:

DECLARE_TARGET INST nil target1.txt

Partial system2.txt

DECLARE_TARGET INST nil target2.txt

The target1.txt file in the INST target calls out one set of cmd/tlm files:

COMMANDS inst1_cmds.txt
TELEMETRY inst1_tlm.txt

The target2.txt file in the INST target calls out another set:

COMMANDS inst2_cmds.txt
TELEMETRY inst2_tlm.txt

You also have to ensure your Launcher scripts specify the correct system.txt file when launching the tools:

Partial launcher1.txt:

TOOL "Command and Telemetry Server" "LAUNCH CmdTlmServer --system system1.txt" "cts.png" --config cmd_tlm_server.txt

Partial launcher2.txt:

TOOL "Command and Telemetry Server" "LAUNCH CmdTlmServer --system system2.txt" "cts.png" --config cmd_tlm_server.txt

Once you have your launcher configurations in place you can create a simple Batch file or shell script to launch COSMOS.

Launcher1.bat:

call tools\Launcher.bat --config launcher1.txt

Launcher2.bat:

call tools\Launcher.bat --config launcher2.txt

With correct usage of system.txt and target.txt you can consolidate your COSMOS configurations and avoid copying and pasting. This makes your COSMOS configuration easier to test and maintain.

Overriding Cmd/Tlm Definitions

Another way to modify a target is to override the target command and telemetry definitions. This is a useful practice if your target’s command and telemetry files are generated from a database or from some other system and you want to add COSMOS specific features. It is also handy to add custom conversions and formatting for displays.

Create a file in the target’s cmd_tlm folder named after the original file but with an extension like _override.txt. For example, you have the following telemetry definition file named inst_tlm.txt:

TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status from the target"
  APPEND_ITEM COLLECTS         16 UINT     "Number of collects"
  APPEND_ITEM TEMP1            16 UINT     "Temperature #1"

Create another file called inst_tlm_override.txt and start overriding telemetry using the SELECT_TELEMETRY and SELECT_ITEM keywords. Note that the filename is important because by default COSMOS processes cmd/tlm definition files in alphabetical order. For example, if you have a telemetry file named “telemetry.txt” and created a file called “override.txt”, you would get an error because the telemetry file will not be processed before the override.

SELECT_TELEMETRY INST HEALTH_STATUS
  SELECT_ITEM COLLECTS
    FORMAT_STRING "0x%0X"

Note that you can include these override files as needed based on the target.txt file as described above.

If you have a question, find a bug, or want a feature please use our Github Issues.

COSMOS at DockerCon 2018

Ball Aerospace COSMOS has been featured in a presentation by Chris Heistand from John Hopkins Applied Physics Laboratory. He’s working on the Double Asteroid Redirection Test (DART) not to be confused with COSMOS DART. They have setup COSMOS to run in a Docker container which X fowards to a X11Server VNC container which they then use a VNC Client to connect to. Pretty cool stuff which we we will hopefully have more out of the box support for in the future. Stay tuned!

Ball Aerospace COSMOS 4.3.0 Released

Welcome to COSMOS 4.3.0!

The highlight of this release is built in support for differentiating between stored telemetry and realtime telemetry. If your system downlinks stored telemetry that you don’t want to interfere with the COSMOS realtime current value table, your interface/protocol code can set the stored flag on a packet before returning it to COSMOS to have COSMOS log the packet, but not update the current telemetry values.

Lots of other new features as well, and a few bug fixes including fixing running on the latest version of Mac OSX. See below for the full list.

Breaking Changes: The COSMOS log file format and predentified protocol formats have changed to support stored telemetry. COSMOS 4.3 is backwards compatible with earlier formats, but older versions of COSMOS won’t be able to read files from COSMOS 4.3+.

New Features:

  • #780 Search bar support for Command Sequence
  • #785 Adjust font size
  • #804 Add classification bar to all tools
  • #808 Add CANVASELLIPSE widget
  • #814 Changes to support stored telemetry
  • #815 Create a temporary screen from a script
  • #818 Catch all state for any undefined state values
  • #819 Ensure x values added in incrementing order in TlmGrapher
  • #823 Add protocol to ignore any packet
  • #826 Allow hash style access to Excel
  • #829 Add STAY_ON_TOP feature to telemetry screens
  • #851 Ensure step_mode displays Step button
  • #859 Change Script Runner highlight color when paused

Maintenance:

  • #796 Handle Command Sequence Export Issues
  • #807 Revert Items with STATE cannot define FORMAT_STRING
  • #812 Ruby 2.5 Instrumented Code outside of methods in a class
  • #855 Remove Qt warning message on Windows 10
  • #858 Fix JRuby build issues

Bug Fixes:

  • #837 Packet Viewer’s “Hide Ignored Items” Incorrectly Persists Across Change of Packet
  • #840 Latest version of COSMOS crashing
  • #845 Support get_tlm_details in disconnect mode

Migration Notes from COSMOS 4.2.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Ball Aerospace COSMOS 4.2.4 Released

This is the second patch release for 4.2. It greatly improves the ingest speed for DART (100x), improves decom speed, reduces database size, and fixes some bugs. If you are using DART, please upgrade and follow the migration directions at the end of these release notes.

The highlight of COSMOS 4.2 is a new tool called the Data Archival and Retrieval Tool (DART). DART is a long term trending database built on top of the PostgreSql database. It integrates directly with TlmGrapher, TlmExtractor, CmdExtractor, DataViewer, and Replay, allowing you to do historical queries of logged telemetry (and commands) by specifying a time range. Queries are super fast and it performs automatic data reduction at minute/hour/day granularity. Consider setting it up for your project and start data mining today!

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

New Features:

  • #787 No way to control data bits on serial interface
  • #788 ROUTERS should support PROTOCOL keyword

Maintenance:

  • #784 Comparable and spaceship operator behavior changing
  • #791 Table Manager doesn’t expose top level layout

Bug Fixes:

  • #779 Dart updates for ingest speed, correct time zone, TlmGrapher crash
  • #786 Status tab crash on Ruby 2.5
  • #790 Telemetry check doesn’t support strings with multiple spaces

Migration Notes from COSMOS 4.1.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

If you already setup DART for your program please follow the following additional steps: In a terminal in your COSMOS project folder run:

rake db:migrate
rake db:seed

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Ball Aerospace COSMOS 4.2.3 Released

COSMOS 4.2 is here! This is the first true patch release for 4.2. The highlight of COSMOS 4.2 is a new tool called the Data Archival and Retrieval Tool (DART). DART is a long term trending database built on top of the PostgreSql database. It integrates directly with TlmGrapher, TlmExtractor, CmdExtractor, DataViewer, and Replay, allowing you to do historical queries of logged telemetry (and commands) by specifying a time range. Queries are super fast and it performs automatic data reduction at minute/hour/day granularity. Consider setting it up for your project and start data mining today!

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

New Features:

  • #767 Support Ruby 2.5
  • #771 Add CmdSender Search

Maintenance:

  • #772 OpenGL gem isn’t supported in Ruby 2.5

Bug Fixes:

  • #769 TIMEGRAPH widget non-functional
  • #775 Toggle disconnect broken in TestRunner

Migration Notes from COSMOS 4.1.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Ball Aerospace COSMOS 4.2.2 Released

COSMOS 4.2 is here! Thirty four tickets went into this release, but the highlight is a new tool called the Data Archival and Retrieval Tool (DART). DART is a long term trending database built on top of the PostgreSql database. It integrates directly with TlmGrapher, TlmExtractor, CmdExtractor, DataViewer, and Replay, allowing you to do historical queries of logged telemetry (and commands) by specifying a time range. Queries are super fast and it performs automatic data reduction at minute/hour/day granularity. Consider setting it up for your project and start data mining today!

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

New Features:

  • #698 Initial DART Release
  • #650 Gracefully handle large array items
  • #673 Button widget should spawn thread to avoid blocking GUI
  • #676 Allow individual interfaces to be disconnect mode
  • #699 Test cases added to TestRunner should be ordered in drop down
  • #705 Cmd line arg for ScriptRunner to start in disconnect mode
  • #706 Warn if ITEMs or PARAMETERs are redefined
  • #711 Allow ERB to know the target name
  • #715 Allow individual Limits Monitor items to be removed (not ignored)
  • #719 Warn if limits_group doesn’t exist in limits_groups_background_task
  • #729 CmdSender production mode to disable MANUALLY ENTERED
  • #734 Support DERIVED with APPEND
  • #737 Implement single stepping with the F10 key
  • #754 Add Replay Mode to Include All Routers
  • #765 TlmGrapher sampled analysis

Maintenance:

  • #682 Fix Ruby interpreter warnings
  • #687 Add ConfigEditor AHK tests
  • #688 Windows 10 Installation Error - RDoc parsing failure in qtruby4.rb
  • #692 Fix METADATA usage in demo
  • #738 PacketViewer scroll to item on search
  • #748 Syntax highlighting prioritizes string over comment
  • #750 TestRunner hides syntax errors with broad rescue
  • #752 Demo INST commanding screen broken
  • #757 Increase TlmGrapher timeout to better support Replay
  • #759 Allow underscores and dashes in log filename labels

Bug Fixes:

  • #690 Automatic SYSTEM META definition doesn’t include RECEIVED_XX
  • #691 tools/mac apps won’t open
  • #701 XTCE String types should not have ByteOrderList
  • #709 Can’t set breakpoint in subscript
  • #713 Launcher crashes if newline in crc.txt
  • #723 crc_protocol needs better input validation
  • #727 Install issue on Windows 10
  • #732 losing/gaining data when routing at different incoming rates
  • #735 Statistics Processor doesn’t handle nil or infinite
  • #740 About dialog crashes if USER_VERSION not defined

Migration Notes from COSMOS 4.1.x:

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

See the COSMOS documentation for directions on setting up DART: http://cosmosc2.com/docs/v4/

Derived Items

COSMOS Derived Items

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 automatically defines three derived items on every packet: RECEIVED_TIMESECONDS, RECEIVED_TIMEFORMATTED, and RECEIVED_COUNT. The time items are set to the time that the COSMOS Command and Telemetry Server receives the packet. The count is a running count of the number of packets received since the Server started. Note that the count is always a relative count and should only be used accordingly.

COSMOS derived items are defined very similarly to real items except they use the special DERIVED telemetry type. Here is how the default COSMOS derived items might look in a telemetry definition.

ITEM PACKET_TIMESECONDS 0 0 DERIVED "COSMOS Received Time (UTC, Floating point, Unix epoch)"
  READ_CONVERSION packet_time_seconds_conversion.rb
  FORMAT_STRING '%0.6f'
ITEM PACKET_TIMEFORMATTED 0 0 DERIVED "COSMOS Received Time (Local time zone, Formatted string)"
  READ_CONVERSION packet_time_formatted_conversion.rb
ITEM RECEIVED_TIMESECONDS 0 0 DERIVED "COSMOS Received Time (UTC, Floating point, Unix epoch)"
  READ_CONVERSION received_time_seconds_conversion.rb
  FORMAT_STRING '%0.6f'
ITEM RECEIVED_TIMEFORMATTED 0 0 DERIVED "COSMOS Received Time (Local time zone, Formatted string)"
  READ_CONVERSION received_time_formatted_conversion.rb
ITEM RECEIVED_COUNT 0 0 DERIVED "COSMOS packet received count"
  READ_CONVERSION received_count_conversion.rb

Note the DERIVED type where real items are INT, UINT, FLOAT, STRING or BLOCK. Also note that the bit offset and bit size values are zero. This is due to the fact that these items don’t actually exist in the binary packet but are created on the fly when the packet is processed. This also has implications with playback of the data. Since these items don’t actually exist in the binary file, they are created on the fly even when doing playback through the Replay tool. Thus if your DERIVED item is aggregating multiple values such as a running average, it will take a few samples to generate a good value.

Creating a Derived Average

A common usecase is to create a derived item which averages other telemetry points. Let’s explore how to do this within the COSMOS Demo. The COSMOS Demo already declares 4 fake temperatures named TEMP1, TEMP2, TEMP3, and TEMP4. Let’s create a new derived item called TEMP_AVERAGE that averages them.

ITEM TEMP_AVERAGE 0 0 DERIVED "Average of TEMP1, TEMP2, TEMP3, TEMP4"
  GENERIC_READ_CONVERSION_START FLOAT 32
    (packet.read("TEMP1") + packet.read("TEMP2") + packet.read("TEMP3") + packet.read("TEMP4")) / 4.0
  GENERIC_READ_CONVERSION_END

The GENERIC_READ_CONVERSION_START keyword also takes two additional argument which describe the output of the conversion. Here we specify FLOAT 32 to indicate the conversion will return a 32 bit floating point value.

In the code section, note the use of the built in variable called ‘packet’. When you create a generic conversion you always have access to the ‘packet’ variable which references the packet the conversion is declared in. For more information about how to use ‘packet’ please see the Packet documentation. You also have access to ‘value’ which is the raw value of the current item. In the case of a DERIVED item the value is nil. You can also access ‘buffer’ which is the raw buffer associated with the packet.

Using a Conversion Class

While it is easy to create a simple conversion using GENERIC_READ_CONVERSION there are multiple reasons to prefer a Conversion class. Creating a separate conversion class is easier to test, easier to reuse and has better performance. Let’s create a conversion which performs averging and rewrite the previous example. First the telemetry definition will now look like this.

ITEM TEMP_AVERAGE 0 0 DERIVED "Average of TEMP1, TEMP2, TEMP3, TEMP4"
  READ_CONVERSION average_conversion.rb TEMP1 TEMP2 TEMP3 TEMP4

We now need to implement average_conversion.rb to take our arguments and generate the average. Put this new file in the target’s lib folder (in the demo this is config/targets/INST/lib).

require 'cosmos/conversions/conversion'
module Cosmos
  class AverageConversion < Conversion
    def initialize(*args)
      super()
      @items = args
      @converted_type = :FLOAT
      @converted_bit_size = 32
    end

    def call(value, packet, buffer)
      total = 0
      @items.each do |item|
        total += packet.read(item)
      end
      return total / @items.length
    end
  end
end

Here I’m using the Ruby splat operator to collect all the arguments passed into initialize and assign them to @items. I also explicitly set the @converted_type and @converted_bit_size variables (part of the Conversion base class) to :FLOAT and 32 to indicate our conversion will return a 32 bit floating point number. The call method is what actually performs the conversion. Note how it defines the same three variables I previously talked about: value, packet and buffer. I use the packet argument to read the items passed in and then divide by the total to average them.

We’re not yet done though as we need to edit the INST/target.txt file to require this new conversion.

REQUIRE average_conversion.rb

Running this in the Demo with Telemetry Grapher shows our new average value pretty clearly.

Tlm Grapher Derived

Conversions and DERIVED variables are powerful ways to add additional telemetry points based on existing data in your packet structure. Another way to add insight into your telemetry is to add Packet Processors which I’ve previously blogged about.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Limits

COSMOS Limits

COSMOS allows you to define limits for your telemetry items to provide feedback to users about how your telemetry is performing. If you define limits, COSMOS requires you to specify both red and yellow limits. Red limits are traditionally where damage may occur while yellow limits are set a certain percentage away from red to give the operator a chance to respond before the red limits are hit. COSMOS also allows the user to set “Operational” limits (blue limits) which specify a desired operational range inside the green limits. This is best illustrated in the COSMOS demo. Here is a partial screenshot of the INST HS screen in Telemetry Viewer.

Demo MetaData

The TEMP1 telemetry point is using the LABELTRENDLIMITSBAR widget in the INST HS screen definition to display both the value (the temperature), the trend (how the data has been moving over the past 60s), as well as the limits bar. The TEMP2 telemetry point is simply using the LABELVALUELIMITSBAR widget so it shows just the value and the limits bar. Notice how the scale of the yellow regions are different for TEMP1 and TEMP2. The regions are scaled according to their defined value ranges.

This type of limits bar is also used by the Limits Monitor tool to display out of limits items system wide.

Demo MetaData

Here I’ve ignored various other items to focus on the INST HEALTHSTATUS packet containing TEMP1 and TEMP2. Notice that the overall limit is yellow since TEMP1 is yellow even though TEMP2 is green. The worst case limts item is reflected in the Monitored Limits State. Also note that TEMP2 appears above TEMP1 because it happened to go out of limits first while I was running the demo. Items appear in Limits Monitor as they go out of limits. Also note that even though TEMP2 is green it still shows up in Limits Monitor because it _previously went out of limits. If you switch to the Log tab you can see exactly when an item went out of limits and when it went back to green.

Scripting Limits

You can get this same information from a script by executing the following script in Script Runner.

puts "Overall limits state: #{get_overall_limits_state}"
get_out_of_limits.each do |item|
  tgt, pkt, item, state = item
  puts "tgt:#{tgt} pkt:#{pkt} item:#{item} state:#{state}"
end

Note that the get_out_of_limits call returns the items which are out of limits at the exact instant of the API call. Thus it doesn’t provide history like the Limits Monitor tool.

You can also disable and enable limits on individual telemetry items using the API. The following script will disable limits on TEMP1 and then after 5 seconds it re-enables limits. Run this with the Limits Monitor open and you’ll notice the text for the INST HEALTH_STATUS TEMP1 telemetry point turns black when limits are disabled. Note that this disables limits events logging in the Command and Telemetry Server for this telemetry point.

puts "TEMP1 limits enable:#{limits_enabled?("INST", "HEALTH_STATUS", "TEMP1")}"
disable_limits("INST", "HEALTH_STATUS", "TEMP1")
puts "TEMP1 limits enable:#{limits_enabled?("INST", "HEALTH_STATUS", "TEMP1")}"
wait 5
enable_limits("INST", "HEALTH_STATUS", "TEMP1")
puts "TEMP1 limits enable:#{limits_enabled?("INST", "HEALTH_STATUS", "TEMP1")}"

Limits Sets

COSMOS requires the first item after the LIMITS keyword to be the name of the limits set. Limits sets are system wide sets of limits which can be applied depending on the environment you’re testing in. Perhaps you have a “Test” set of limits which are different from your “Operational” limits. At Ball Aerospace, we frequently define cyrogentic limits when testing spacecraft in a vacuum chamber at cyrogenic temperatures. COSMOS requires at least one limits definition to belong to “DEFAULT” which is used when COSMOS starts. If you forget to define a DEFAULT limits set, you’ll get this error when you start the COSMOS Command and Telemetry Server.

Demo MetaData

Once you’ve defined your limits sets how do you use them? The COSMOS Command and Telemetry Server has a Status tab which allows you to manually change the limits set using a drop down.

Demo MetaData

Notice the log contains “INFO: Limits Set Changed to: TVAC”. This happened immediately after I manually changed the Limits Set drop down from DEFAULT to TVAC. This message is automatically generated whenever the limits set is changed either manually or from the API.

Scripting Limits Sets

You can also manipulate the limits sets programatically from a script.

get_limits_sets.each { |set| puts "Limits Set:#{set}" }
puts "Current Set:#{get_limits_set()}" # Currently selected limits set
set_limits_set("DEFAULT") # Change to DEFAULT
set_limits_set("TVAC") # Change to TVAC

Limits Groups

COSMOS also has the concept of limits groups. Limits groups are used to group together telemetry items so they can be enabled and disabled together. For example, if you have several physical devices in your system, you can group together items from each device and enable their limits when they power on and disable them when they power off. This is useful to avoid limits violations on items which are currently off and returning zeros.

Limits groups are defined by the LIMITS_GROUP keyword. Typically this is a separate file in your target’s cmd_tlm folder. If you’re creating a group which combines items from multiple targets we recommend to define this in the SYSTEM target’s cmd_tlm folder. This is how the COSMOS demo is configured with a limits_groups.txt file in SYSTEM/cmd_tlm.

Items are assigned to a group using the LIMITS_GROUP_ITEM keyword. Here is the definition in the COSMOS demo.

LIMITS_GROUP INST2_TEMP2
  LIMITS_GROUP_ITEM INST2 HEALTH_STATUS TEMP2

LIMITS_GROUP INST2_GROUND
  LIMITS_GROUP_ITEM INST2 HEALTH_STATUS GROUND1STATUS
  LIMITS_GROUP_ITEM INST2 HEALTH_STATUS GROUND2STATUS

Scripting Limits Groups

You can also manipulate the limits groups programatically from a script.

get_limits_groups.each { |group| puts "Limits Group:#{group}" }
enable_limits_group("INST2_TEMP2")
disable_limits_group("INST2_GROUND")

Automating Limits Groups

COSMOS also has the ability to automatically enable and disable limits groups based on user configurable conditions. For example, you can automatically enable the group for a particular device when the power supply voltage for that device goes high (the device is powered on). The COSMOS demo has an example of this in the SYSTEM/lib/limits_groups.rb file.

require 'cosmos/tools/cmd_tlm_server/limits_groups_background_task'

module Cosmos
  # Inheriting from the LimitsGroupsBackgroundTask provides a framework for
  # automatically enabling and disabling limits groups based on telemetry.
  class LimitsGroups < LimitsGroupsBackgroundTask
    # Initial delay upon starting the server before staring the group checks
    # followed by the background task delay between check iterations
    def initialize(initial_delay = 0, task_delay = 0.5)
      super(initial_delay, task_delay)
      # Creating a Proc allows for arbitrary code to be executed when a group is enabled or disabled
      @temp2_enable_code = Proc.new do
        enable_limits_group('INST2_GROUND') # Enable the INST2_GROUND group
      end
      @temp2_disable_code = Proc.new do
        disable_limits_group('INST2_GROUND') # Disable the INST2_GROUND group
      end
    end
  end
end

You first must require the COSMOS base class and inherit from LimitsGroupsBackgroundTask. The constructor (initialize) takes two delay parameters. The first is the initial delay after starting the Command and Telemetry Server before the task starts checking your logical conditions. The second is the delay between doing the checks (it controls the rate of the task). After calling super (important!) a Proc is created to run arbitrary code when a particular group is enabled or disabled. Note this is entirely optional but in this case we wanted to enable the INST2_GROUND group when the INST2_TEMP2 group got enabled. The @temp2_enable_code and @temp2_disable_code names don’t really matter but they must be unique and have the ‘@’ symbol to make them Ruby instance variables (rather than locals).

After the constructor is configured the method to perform the check is implemented.

def check_inst2_temp2
  process_group(0, @temp2_enable_code, @temp2_disable_code) do
    val = tlm("INST2 HEALTH_STATUS TEMP2")
    return (!val.nan? && !val.infinite?)
  end
end

The method name is very important. It must begin with ‘check_’ and end with the name of a Limits Group defined by the LIMITS_GROUP keyword. In the demo, LIMITS_GROUP(s) are defined in config/targets/SYSTEM/cmd_tlm/limits_groups.txt. Since there is a LIMITS_GROUP INST2_TEMP2 we have a match (the method name should be lower case while the LIMITS_GROUP is typically defined to be uppercase).

Inside the method you must call process_group. The first parameter is the number of seconds to delay before enabling the group when the telemetry check is true. So in this example we are waiting zero seconds to enable the group. Note that when the telemetry check is false the group is instantly disabled. The next two parameters are Proc objects which are called when the group is enabled and disabled respectively. Remember that we defined our Proc objects in the constructor to enable and disable the INST2_GROUND group. These parameters are entirely optional so you can also simply call process_group(0) with just the delay.

The code inside the process_group block (the lines after ‘do’ and before ‘end’) must return a boolean. True will enable the group and false will disable the group. In this example, the group is enabled when the value is not NaN (Not a Number) and not Infinite. If the value is NaN or Infinite the group is disabled. You can watch this happening in the demo by watching the bottom log portion of the Command and Telemetry Server.

2018/02/12 09:12:58.118  ERROR: INST HEALTH_STATUS TEMP2 = NaN is RED_LOW
2018/02/12 09:12:58.121  ERROR: INST2 HEALTH_STATUS TEMP2 = NaN is RED_LOW
2018/02/12 09:12:58.220  INFO: Disabling Limits Group: INST2_TEMP2
2018/02/12 09:12:58.220  INFO: Disabling Limits Group: INST2_GROUND

First TEMP2 transitions to NaN (this is done on purpose for the demo) which is a RED_LOW limits violation. 100ms later (due to processing time) the INST2_TEMP2 group is disabled followed by the INST2_GROUND group due to the Proc code we created.

Other Limits APIs

There are a few other APIs which are provided to work with COSMOS limits.

get_stale returns all the stale packets in the system. Stale packets are those which have not been received by the Command and Telemetry Server for the STALENESS_SECONDS setting (by default 30s).

get_limits(tgt, pkt, item) returns the limits settings for a particular telemetry item. It returns an array of the group name, persistence setting, enable setting, red low, yellow low, yellow high, red high, blue low, and blue high limits values. If no blue operational limits were set those values are nil.

set_limits(tgt, pkt, item, red_low, yellow_low, yellow_high, red_high, blue_low = nil, blue_high = nil, limits_set = :CUSTOM, persistence = nil, enabled = true) allows the user to set new values for the limits settings. Some values have defaults and some do not. Thus you must provide at least the first 7 parameters for this call to be successful. Note the order of parameters: red low, yellow low, yellow high, red high, and then blue low, blue high. By default the limits_set is :CUSTOM which is probably not a limits set you already have defined. Thus is you don’t set the limits_set parameter it may appear as if nothing has happened. To enable the new limits you have to manually change to the CUSTOM limits set: set_limits_set("CUSTOM"). Alternatively, you can specify :DEFAULT for the limits_set parameter and you will typically immediately see the change (assuming DEFAULT is the active set). If you only want to change one particular value you can call get_limits first to get the current settings and only change the value you want.

You can also use API methods to subscribe to limits events. This allows you to process all limits events in the same way the Limits Monitor application does. To start you must subscribe to limits events using subscribe_limits_events(queue_size = 1000) which returns an ID. You can then call get_limits_event(id) and pass in the ID to get limits event type and data from the server. There are three different limits event types: LIMITS_CHANGE, LIMITS_SET, and LIMITS_SETTING. LIMITS_CHANGE is when a particular item goes out of limits. This is by far the most common and probably the one you’re most interested in. LIMITS_SET events happen when the overall limits set changes. LIMITS_SETTING events are generated when the set_limits method is called to change the limits on an individual item. The get_limits_event method takes a boolean second parameter to determine whether or not to block when waiting for an event. The default is false which means it blocks waiting for an event. You can also pass true which means to not block waiting for events. However if no event is present get_limits_event will raise a ThreadError. Thus you must catch the error to allow your code to continue. Finally you call unsubscribe_limits_events(id) when shutting down.

Overflown Queues Are Deleted

By default the limits queue is 1000 events deep. If you don't call get_limits_event fast enough to keep up with the population of this queue and it overflows, COSMOS will clean up the resources and delete the queue. At this point when you call get_limits_event you will get a "RuntimeError : Packet data queue with id X not found." Note you can pass a larger queue size to the subscribe_limits_events method.

Here’s a example of using the subscription APIs.

id = subscribe_limits_events()
while true
  type, data = get_limits_event(id) # block waiting
  puts "type:#{type} data:#{data}"
  # break if XXX # Break the loop when ...
end
unsubscribe_limits_events(id)

id = subscribe_limits_events()
while true
  begin
    type, data = get_limits_event(id, true) # don't block
    puts "type:#{type} data:#{data}" # break if XXX # Break the loop when ...
  rescue ThreadError # raised if no event present
    wait 1 # Wait before checking again
  end
end
unsubscribe_limits_events(id)

Conclusion

Limits are a powerful concept in COSMOS. Sets provide for a system wide setting that affects all limits items. Groups allow limits items to be grouped to typically enable and disable them together. APIs allow the user to query and set limits across the system while subscriptions provide notifications for every limits event action.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Metadata

Metadata is data about data, i.e. information describing the data like when it was taken, version information, etc. COSMOS has explicit support for metadata, especially since the 4.0.0 release.

Metadata Overview

In versions of COSMOS prior to 4.0.0, metadata could be defined in any target / packet combination. In the COSMOS demo we defined metadata in the META target and DATA packet. You would then explicitly tell COSMOS where this metadata was defined by passing the target and packet name to the tools. Here is a example of an old (pre 4.0.0) cmd_tlm_server.txt configuration file:

PACKET_LOG_WRITER DEFAULT meta_packet_log_writer.rb META DATA config/data/meta_init.txt
COLLECT_METADATA META DATA

Here is an example of a current (post 4.0.0) cmd_tlm_server.txt configuration file:

PACKET_LOG_WRITER DEFAULT packet_log_writer.rb nil true nil 2000000000 nil false
COLLECT_METADATA

The PACKET_LOG_WRITER and COLLECT_METADATA keywords no longer have to specify where the metadata is stored because COSMOS 4.0.0 standardized the metadata definition in the SYSTEM target and META packet. You’ll notice the old cmd_tlm_server.txt file specified the location of a meta_init.txt file. This file contains the default values to use when initializing the metadata dialog. In post COSMOS 4.0.0 this file is defined in system.txt using the META_INIT keyword like so:

META_INIT config/data/meta_init.txt

Note that you do not have to define all the items in your metadata in your meta_init file. Any items not found in meta_init will simply be blank in the dialog. If you try to set any of the COSMOS reserved items (defined below) they will simply be overriden with the COSMOS defined values.

If you do not define any metadata in your system (you don’t declare the SYSTEM META packet), COSMOS will automatically define the following items:

  • SYSTEM META PKTID - Always 1 and used to identify the packet
  • SYSTEM META CONFIG - Configuration name (MD5 checksum)
  • SYSTEM META COSMOS_VERSION - COSMOS Version (e.g. 4.1.1)
  • SYSTEM META USER_VERSION - Defined by the USER_VERSION constant. Typically set in lib/user_version.rb in your configuration.
  • SYSTEM META RUBY_VERSION - Ruby Version (e.g. 2.4.2p198)

These items help identify the telemetry being collected by the currently running instance of the COSMOS Server. In fact, every time COSMOS starts a new log file it adds the SYSTEM META packet to the beginning. This behavior was possible prior to COSMOS 4.0.0 but required using the special meta_packet_log_writer in the cmd_tlm_server.txt definition as shown in the first cmd_tlm_server.txt example.

Defining Metadata

If you want to add your own fields to the COSMOS metadata you must define the standard COSMOS metadata items and then append your new values. For example, the COSMOS demo defines the following in targets/SYSTEM/cmd_tlm/meta_tlm.txt:

TELEMETRY SYSTEM META BIG_ENDIAN "System Meta Data Telemetry Packet"
  APPEND_ID_ITEM PKTID 8 UINT 1 "Packet Id"
  APPEND_ITEM CONFIG 256 STRING "Configuration Name"
  APPEND_ITEM COSMOS_VERSION 240 STRING "COSMOS Version"
    META READ_ONLY
  APPEND_ITEM USER_VERSION 240 STRING "User Project Version"
    META READ_ONLY
  APPEND_ITEM RUBY_VERSION 240 STRING "Ruby Version"
    META READ_ONLY
  APPEND_ITEM OPERATOR_NAME 512 STRING "Operator Name"

Here we see the demo defining their own new metadata item called OPERATOR_NAME after the standard COSMOS items. Note that the definition of the standard COSMOS items is important! If you misspell an item, declare the wrong data type, or have the size wrong, COSMOS will warn you that the definition is incorrect and then define the standard set of items as described above. Thus if you’re trying to create additional items and do not see them, make sure you haven’t defined the COSMOS standard items incorrectly. (Note: COSMOS 4.1.2 fixed a bug in this automatic generation of metadata items)

You can also see the use of the META READ_ONLY keyword being used in the demo configuration. This means that the metadata dialog which is opened when the COLLECT_METADATA keyword is used will display these items as read only as shown below:

Demo MetaData

Also note that you can declare metadata items with STATES and they will be displayed as dropdowns in the metadata dialog. For example if you add the following to the SYSTEM META packet:

APPEND_ITEM UUT 32 UINT "Unit under test"
  STATE ARTICLE_0 0
  STATE ARTICLE_1 1

You would see this:

MetaData Dropdown

Test Runner also has the ability to require the user to acknowledge the metadata dialog. If you add COLLECT_METADATA to the Test Runner configuration file you will see the metadata dialog upon starting any test. This is useful to force the test operator to think about anything in the metadata that might have changed prior to running the test. In addition, this forces a new telemetry file to be created with this new metadata information (remember each new binary file contains a SYSTEM META packet at the beginning).

Metadata is a useful way to add information which can’t be determined by the available hardware targets. The OPERATOR_NAME in the demo is an obvious example. Start using metadata to your advantage to help you distinguish your telemetry.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 4.1.1 Released

New Features:

  • #663 Built-in protocols to support allow_empty_data
  • #666 Add ability to create target in ConfigEditor
  • #679 TlmViewer screen audit shouldn’t count reserved item names

Maintenance:

  • #660 Update Opengl gem requirement version
  • #665 Refactor xtce parser

Bug Fixes:

  • #661 Render function bug?
  • #674 Add TlmViewerConfig spec and fix to_save

Migration Notes from COSMOS 4.0.x:

Any custom tools in other languages that use the COSMOS API will need to be updated.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

COSMOS 4.1.0 Release Notes

COSMOS 4.1 has been released and several new noteworthy features were released which weren’t fully captured by the recent release description. This post will break down the highlights from the new features, maintence items, and bug fixes from the 4.1.0 release.

Replay Tool Enhancements

I think the best new feature in COSMOS 4.1.0 is the ability of the Reply tool to work side by side with the Command and Telemetry Server (#559). This change actually affects far more than just the Replay tool and the Server because a new “Replay Mode” was built into Data Viewer, Limits Monitor, Packet Viewer, Telemetry Grapher, and Telemetry Viewer.

Replay also got a cosmetic upgrade to look more like the Command and Telemetry Server. Here’s the new Replay in action:

Replay

Replay now has tabs for Targets, Cmd Packets, Tlm Packets, Routers, and Status which correspond to the same tabs in the Server. These tabs count the number of packets being processed by Replay. Thus if you rewind the file and play it back, the counts simply keep incrementing.

Here’s a screenshot of Packet Viewer displaying data in this new Replay mode:

Packet Viewer Replay

Here’s another screenshot of Telemetry Grapher displaying data in this new Replay mode:

Packet Viewer Replay

You’ll notice the tools have a new File menu option to toggle the Replay mode which displays a green “Replay Mode” bar to visually indicate the tool is no longer processing real-time data.

Zip Saved Configuration Data

Issue #579 was implemented to zip up the COSMOS saved configuration files. This makes configuration managing these saved configurations much easier since you only have to check in a single zip file instead of a folder containing dozens of files and folders.

If you’re not familiar with saved configurations, let me explain why this is important. When COSMOS starts, it parses the configuration files, calculates the MD5 sum, and puts a copy of the configuration in outputs/saved_config (by default). You should always configuration manage these files in the saved_config directory to allow COSMOS to parse old binary files created by that configuration. The only exception is during COSMOS configuration development when you’re certain you no longer need to parse old telemetry bin files.

As an example of how these saved configurations work, consider that you collect data during a test. Next you modify the configuration by adding some telemetry items to a packet which increases the packet length. If you try to parse the old binary file, COSMOS would complain that the binary packet is not long enough to match the new definition. However, if you save the old configuration, COSMOS would match the MD5 sum in the packet with the saved configuration and load the configuration to parse the packet. Note that if COSMOS can’t find the saved configuration it uses the current configuration.

Better Step Debugging

Issue #620 was to move the Script Runner Step button next to the Start, Pause, Stop buttons rather than down in the debugging pane. This should make it a lot easier to use the Step feature when debugging scripts. Here’s a screenshot of a simple script I started using the Step button (available when you enable Debugging via the Script / Toggle Debug menu).

Script Runner Debug

Issue #619 was implemented to prevent Script Runner from instrumenting comments and whitespace when running scripts. This should also make debugging scripts easier as you don’t have to step over a bunch of comments or whitespace.

API over HTTP

As Ryan mentioned in the 4.1 Release Notes, issue #510 was created to move the COSMOS API from our custom protocol to HTTP. While this change is transparent to the user, it should make it easier for other languages and tools to interface with the COSMOS system in the future.

Bug Fixes

There were a number of bug fixes as noted in the 4.1 Release Notes. #617 and #659 were both related to Ruby 2.4.2 which is the new Ruby version in COSMOS 4.0. Ruby 2.4 is the latest version of Ruby which provides performance improvements you can read about on ruby-lang.org. #616 addresses an annoying message generating by QT on Windows 10. #655 addresses an issue with using COLLECT_METADATA in the basic “install” version of COSMOS. #633 fix a bug where the prompt_vertical_message_box and prompt_combo_box scripting methods were mutating the input parameters. If you’re using those scripting methods, you should upgrade to COSMOS 4.1.

There were a number of other enhancements and bug fixes but the previous list is a compelling reason to upgrade to COSMOS 4.1 today!

Ball Aerospace COSMOS 4.1.0 Released

Welcome to COSMOS 4.1! The COSMOS API has transitioned from a custom TCP protocol to HTTP. This will make interfacing to COSMOS from programming languages other than Ruby much easier. There are also many new APIs that allows the full functionality of the CmdTlmServer and Replay to be controlled remotely. See below for the full list of changes!

New Features:

  • #531 Command sequence export option
  • #558 subscription APIs should work in disconnect mode
  • #559 Build Replay Functionality into CmdTlmServer
  • #578 Add ability to query available screens from Telemetry Viewer
  • #579 Create zip of configuration in saved config
  • #581 Make various log files readonly
  • #587 AUTO_INTERFACE_TARGETS ignore existing interfaces
  • #591 Investigate creating single COSMOS UDP socket for case where read_port == write_src_port
  • #599 Create subscription API for CTS messages
  • #601 Add background task and other status APIs
  • #606 Enhancement to Open File Script Interface - File Filter
  • #612 CSV support for strings and symbols
  • #620 Move Script Runner step button next to start/go
  • #625 Add APIs to start/stop background tasks
  • #626 Add API functions to get ignored parameters/items
  • #635 get_cmd_param_list should return the type for each command parameter
  • #642 Handle Infinity/NaN without invalid JSON

Maintenance:

  • #510 Investigate changing JsonDrb to running over HTTP
  • #603 CmdTlmServer invalid constructor argument
  • #614 Pass server message color to message subscriptions
  • #619 Script Runner instrumenting comments and whitespace
  • #630 Add ConfigEditor and CmdSequence to install launcher
  • #647 Make packet item sort consistent
  • #649 Add codecov support

Bug Fixes:

  • #562 #562 Template protocol should fill Id fields
  • #577 #577 Telemetry Viewer has fatal exception when called with JSON-RPC method display
  • #593 #593 Race condition in Cosmos.kill_thread
  • #607 #607 Support latest version of wkhtmltopdf for pdf creation and properly set working dir
  • #610 #610 target shouldn’t report error requiring file in target lib
  • #616 #616 Ignore untested Windows version message in Windows 10
  • #617 #617 Ruby 2.4’s inherent Warning class shadows Qt::MessageBox::Warning
  • #633 #633 combo_box is mutating input
  • #639 #639 Partial rendering in config parser should enforce that rendered partials start with underscore
  • #654 #654 Test Runner crashes with no config file
  • #655 #655 Metadata system triggers a nil router error in api.rb with basic setup
  • #659 #659 Hazardous commands throwing errors

Migration Notes from COSMOS 4.0.x:

Any custom tools in other languages that use the COSMOS API will need to be updated.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Require vs Load

As a COSMOS developer I often get asked about require vs load vs require_utility vs load_utility and what do they all mean. Let me explain these keywords and how they are used within Ruby and COSMOS.

Require vs Load

The Ruby programming language defines the keywords ‘require’ and ‘load’. These are actually methods on the Kernel class and you can find the full documention on ruby-doc.org for both require and load. They basically include additional Ruby source files into the current execution environment so they can be used by your code. The key difference is that require will only include a file once. If you try to require a file a second time the require method actually returns false indicating that the file has already been required. You can easily test this by opening an IRB session and requiring something twice.

irb(main):001:0> require 'cosmos'
=> true
irb(main):002:0> require 'cosmos'
=> false

This has key implications for usage in COSMOS, especially when writing scripts for use in Script Runner or Test Runner. Let’s say you have a subroutine that you want to call (and don’t want to watch the line by line execution of). You require it in your script and execute it. You realize you have a bug in this required script and edit the file. Now you re-run the top level script but notice none of your changes have been include! What gives?! The require keyword notices that you’ve already required the file and thus does not re-load it on the next execution of your script. This has led some COSMOS users to simply close and re-open Script Runner or Test Runner each time they edit something. While this solves the require problem there is a better solution: load.

The load keyword loads the specified file everytime and thus reparses any changes that may have been made to the file in question. This is almost always what you want to use when writing scripts for COSMOS as it allows you to edit files and be assured that you will be running the latest. Note the difference when using load in this IRB session.

irb(main):001:0> load 'cosmos.rb'
=> true
irb(main):002:0> load 'cosmos.rb'
=> true
irb(main):003:0> load 'cosmos'
LoadError: cannot load such file -- cosmos
        from (irb):3:in 'load'
        from (irb):3
        from C:/Ruby233p222-x64/bin/irb.cmd:19:in '<main>'
irb(main):004:0> require 'cosmos.rb'
=> true

When using the keyword load you must add the .rb Ruby extension to the file you are trying to load. Leaving this off (which is allowed with the require keyword) will result in a LoadError as shown above. Note that require works with or without the .rb Ruby extension and that the previous load of cosmos.rb did not affect the require of cosmos.rb (it still had never been required).

Load vs load_utility

Now that we’ve established how the require and load keywords work in Ruby, how does the load_utility keyword work in COSMOS? This keyword is COSMOS specific and means that COSMOS will step through the included source file when it is called. This is useful for debugging subroutines or for things that you simply want to watch execute. It is not recommended for subroutines that take an extended time to process like looping over large datasets. This will SIGNIFICANTLY slow down the execution of this code as it shows each line execute in the GUI.

Note that COSMOS also has a require_utility keyword. This keyword works exactly like load_utility which is why we recommend using load_utility going forward as it better matches the Ruby keywords in what it is doing. This keyword is effectively deprecated and may be removed in future versions of COSMOS.

Ruby Load Path

After talking aobut require and load I think this is a good place to talk a little about the Ruby Load Path since it directly affects whether a require or load will succeed. The overall Ruby load path can be found by typing $LOAD_PATH. Doing this in my IRB session running Ruby 2.3.3 results in the following.

irb(main):004:0> puts $LOAD_PATH
C:\git\cosmos\lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/did_you_mean-1.0.0/lib
C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0/x64-msvcrt
C:/Ruby233p222-x64/lib/ruby/site_ruby
C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0/x64-msvcrt
C:/Ruby233p222-x64/lib/ruby/vendor_ruby
C:/Ruby233p222-x64/lib/ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/2.3.0/x64-mingw32
=> nil

You’ll notice most of these paths are relative to my Ruby installation at C:/Ruby233p222. I also have an entry for my developer copy of COSMOS due to my environment variable of RUBYLIB=C:\git\cosmos\lib. As a COSMOS developer I have this variable set but you most likely will not. Setting the RUBYLIB environment variable is useful when developing but can interfere with loading gems since it is at the top of the $LOAD_PATH.

When you start requiring other libraries they typically add things to your LOAD_PATH. Watch what happens when I require ‘cosmos’.

irb(main):001:0> require 'cosmos'
=> true
irb(main):002:0> puts $LOAD_PATH
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/uuidtools-2.1.5/lib
C:\git\cosmos\lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/did_you_mean-1.0.0/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/bundler-1.15.4/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/json-1.8.6/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/json-1.8.6
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rack-2.0.3/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/puma-3.10.0/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/puma-3.10.0
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/uuidtools-2.1.5/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/mini_portile2-2.3.0/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/nokogiri-1.8.1-x64-mingw32/lib
C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rubyzip-1.1.7/lib
C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0/x64-msvcrt
C:/Ruby233p222-x64/lib/ruby/site_ruby
C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0/x64-msvcrt
C:/Ruby233p222-x64/lib/ruby/vendor_ruby
C:/Ruby233p222-x64/lib/ruby/2.3.0
C:/Ruby233p222-x64/lib/ruby/2.3.0/x64-mingw32
=> nil

Now a bunch of gems have added themselves to my $LOAD_PATH. These gems are the gems that cosmos has dependencies on. Note that when you require or load a file the $LOAD_PATH entries are searched in order. Thus in the above example a file in the uuidtools library will be found before a file in the rubyzip library.

You can display your $LOAD_PATH from Script Runner by simply running “puts $LOAD_PATH” from Script Runner. When I do this I get the following in my Script Output:

2017/11/13 10:58:21.815 (SCRIPTRUNNER): Starting script:
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/procedures
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/uuidtools-2.1.5/lib
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/bundler-1.15.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/ruby-prof-0.15.9/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/ruby-prof-0.15.9
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/roodi-4.1.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/reek-1.6.6/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/unparser-0.2.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rainbow-2.2.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/rainbow-2.2.2
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/procto-0.0.3/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/parser-2.2.3.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/guard-rspec-4.7.3/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rspec-3.5.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rspec-mocks-3.5.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rspec-expectations-3.5.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rspec-core-3.5.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rspec-support-3.5.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/guard-bundler-2.1.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/guard-compat-1.2.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/guard-2.14.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/notiffany-0.1.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/shellany-0.0.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/nenv-0.3.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/lumberjack-1.0.12/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/listen-2.10.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rb-inotify-0.9.10/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rb-fsevent-0.10.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/formatador-0.2.5/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/flog-4.6.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/flay-2.10.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/ruby_parser-3.10.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/sexp_processor-4.10.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/path_expander-1.0.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/ffi-1.9.18-x64-mingw32/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/erubis-2.7.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/diff-lcs-1.2.5/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/coveralls-0.8.21/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/thor-0.19.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/term-ansicolor-1.6.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/tins-1.15.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/simplecov-0.14.1/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/simplecov-html-0.10.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/docile-1.1.5/lib
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/lib
2017/11/13 10:58:22.076 (:1): C:/git/extensions/x64-mingw32/2.3.0/cosmos-0.0.0
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/uuidtools-2.1.5/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/snmp-1.2.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rubyzip-1.1.7/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rdoc-4.3.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rack-2.0.3/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/qtbindings-4.8.6.3-x64-mingw32/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/qtbindings-qt-4.8.6.3-x64-mingw32/qtlib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/puma-3.10.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/puma-3.10.0
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/pry-doc-0.6.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/yard-0.9.9/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/pry-0.10.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/slop-3.6.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/method_source-0.8.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/opengl-0.9.2-x64-mingw32/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/nokogiri-1.8.1-x64-mingw32/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/mini_portile2-2.3.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/json-1.8.6/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/json-1.8.6
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/httpclient-2.8.3/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/concord-0.1.5/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/equalizer-0.0.11/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/coderay-1.1.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/timers-4.0.4/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/hitimes-1.2.6/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/extensions/x64-mingw32/2.3.0/hitimes-1.2.6
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/benchmark-ips-2.7.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/ast-2.3.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/adamantium-0.2.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/memoizable-0.4.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/thread_safe-0.3.6/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/ice_nine-0.11.2/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/abstract_type-0.0.7/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/rake-12.1.0/lib
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/site_ruby/2.3.0/x64-msvcrt
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/site_ruby
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/vendor_ruby/2.3.0/x64-msvcrt
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/vendor_ruby
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/2.3.0
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/2.3.0/x64-mingw32
2017/11/13 10:58:22.076 (:1): C:/Ruby233p222-x64/lib/ruby/gems/2.3.0/gems/qtbindings-4.8.6.3-x64-mingw32/lib/../lib/2.3
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/config/targets/INST/lib
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/config/targets/INST/procedures
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/config/targets/EXAMPLE/lib
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/config/targets/TEMPLATED/lib
2017/11/13 10:58:22.076 (:1): C:/git/COSMOS/demo/config/targets/SYSTEM/lib
2017/11/13 10:58:22.092 (SCRIPTRUNNER): Script completed:

Wow, that is a lot of gems! COSMOS requires a lot of libraries to support how it operates including many used for development purposes like rspec and simplecov. An important thing to note is at the top of the list the following paths are listed.

C:/git/COSMOS/demo/procedures
C:/git/COSMOS/demo/lib

The first path is due to the following line in the COSMOS Demo configuration’s system.txt configuration file: PATH PROCEDURES ./procedures. This adds the procedures directory in the current COSMOS configuration (C:/git/COSMOS/demo on my machine) to the path.

The second path is added to every COSMOS configuration. The lib directory in the current COSMOS configuration (C:/git/COSMOS/demo on my machine).

You should also note the last few lines of the $LOAD_PATH.

C:/git/COSMOS/demo/config/targets/INST/lib
C:/git/COSMOS/demo/config/targets/INST/procedures
C:/git/COSMOS/demo/config/targets/EXAMPLE/lib
C:/git/COSMOS/demo/config/targets/TEMPLATED/lib
C:/git/COSMOS/demo/config/targets/SYSTEM/lib

These are added because COSMOS automatically adds the lib and procedures directory from each Target folder. Thus you are able to directly load a file in the INST/procedures directory by doing “load ‘checks.rb’” (for example). If a file is in a subdirectory like the INST/procedures/utilities directory, then you must specify the additional subpath such as “load_utility ‘utilities/clear.rb’”.

require_relative

Just for completeness note that there is also a Ruby keyword called require_relative. This works similar to require but instead of using the LOAD_PATH as described above, it looks relative to the current executing file. This should rarely be needed in COSMOS except perhaps in test files.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Config Editor

COSMOS gained a new tool in the 4.0.0 release called Configuration Editor. This tool provides contextual help when editing COSMOS configuration files and thus should make configuring COSMOS much easier than in the past.

Configuration Editor Basics

When creating a new project from from the Demo you’ll notice a new icon in the Launcher under the Utilities label:

Demo Launcher

Note that as of this post the Install Launcher does not have the new Configuration Editor or Command Sequence buttons but this will be addressed in the next release.

Clicking the Config Editor button brings up the Configuration Editor tool:

Config Editor

Configuration Editor has three vertical panes. The far left is a Windows Explorer type tree view which opens at the base of your COSMOS configuration. This makes it easy to see and navigate through all the COSMOS configuration files.

The middle pane is a file editor which opens files when they are clicked on in the left pane tree view.

The right pane is what Configuration Editor was created for. It provides contextual help for all the COSMOS keywords. As the editor cursor in the middle pane changes the contextual help changes to reflect current editor line. Here’s an example of the right pane when the Demo’s INST target’s command definition is edited:

Config Editor

The user can either edit the configuration file directly in the middle pane or use the configuration help in the right pane. Edits in the middle pane are immediately reflected in the right pane. Edits in the right pane are not reflected back in the configuration pane until the user tabs or clicks to another field. Note that tabbing through the fields is a quick way to transition from one parameter to another.

Configuration Editor contains the same Edit and Search menu options that Script Runner supports. Searching for keywords and transitioning from one to another also updates the configuration help pane which is another way to quickly check particular keywords.

If you have an older (pre-4.0) COSMOS configuration or generated a basic configuration from the install (4.0.0-4.0.3) you will not have a link to the new Configuration Editor tool in your Launcher. Follow the following steps to add this tool.

  1. Edit config/tools/launcher/launcher.txt
  2. Add the following line (typically after Utilities LABEL)
    TOOL "Config Editor" "LAUNCH ConfigEditor" "config_editor.png"
    

Restart your Launcher and you should see this new tool to help you configure COSMOS. Note that if you don’t have the Configuration Editor button then you probably also don’t have a button for the new Command Sequence tool. Add the following line after the Command Sender line to access this tool:

TOOL "Command Sequence" "LAUNCH CmdSequence" "cmd_sequence.png"

Enjoy these new COSMOS 4.0 tools!

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 4.0.3 Released

Important Bug Fix: UdpInterface was only working for locahost on earlier versions of COSMOS 4.0.x. Please upgrade to COSMOS 4.0.3 if you need support for UDP.

New Features:

  • #585 Add packet level config_name

Maintenance:

None

Bug Fixes:

  • #590 UdpReadSocket must be created before UdpWriteSocket if read_port == write_src_port

Migration Notes from COSMOS 3.x:

COSMOS 4 includes several breaking changes from the COSMOS 3.x series.

The first and simplest is that the Command and Telemetry Server now opens an additional port at 7780 by default, that provides a router that will send out each command that the system has sent. This can allow external systems to also log all commands sent by COSMOS. For most people this change will be transparent and no updates to your COSMOS configuration will be required.

The second is that the Command and Telemetry Server now always supports a meta data packet called SYSTEM META. This packet will always contain the MD5 sum for the current running COSMOS configuration, the version of COSMOS running, the version of your COSMOS Project, and the version of Ruby being used. You can also add your own requirements for meta data with things like the name of the operator currently running the system, or the name of a specific test you are currently running. In general you shouldn’t need to do anything for this change unless you were using the previous metadata functionality in COSMOS. If you were, then you will need to migrate your meta data to the new SYSTEM META packet, and change the parameters in your CmdTlmServer or TestRunner configurations regarding meta data. If you weren’t using metadata before, then you will probably just notice this new packet in your log files, and in your telemetry stream.

Finally the most exciting breaking change is in how COSMOS interfaces handle protocols. Before, the COSMOS TCP/IP and Serial interface classes each took a protocol like LENGTH, TERMINATED, etc that defined how packets were delineated by the interface. Now each interface can take a set of one or more protocols. This allows COSMOS to much more easily support nested protocols, such as the frame focused protocols of CCSDS. It also allows for creating helpful reusable protocols such as the new CRC protocol for automatically adding CRCs to outgoing commands and verifying incoming CRCs on telemetry packets. It’s a great change, but if you have any custom interface classes you have written, they will probably require some modification. See the Interfaces section at cosmosc2.com to see how the new interface classes work. We will also be writing up a blog post to help document the process of upgrading. Look for this in a week or two.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Ball Aerospace COSMOS 4.0.2 Released

Important Bug Fix: UdpInterface was only working for locahost on earlier versions of COSMOS 4.0.x. Please upgrade to COSMOS 4.0.2 if you need support for UDP.

New Features:

  • #577 LIMITSBAR widget shouldn’t allow RAW
  • #565 Template Protocol support for logging rather than disconnect on timeout

Maintenance:

  • #551 TlmViewer meta AUTO_TARGET needs parameter
  • #553 Create cosmosc2 documentation based on metadata
  • #554 TEMP1 limits getting disabled in demo is confusing

Bug Fixes:

  • #564 Items with STATES don’t respect LIMITS
  • #568 CSV shouldn’t call compact
  • #569 combo_box and vertical_message_box don’t report correct user selection
  • #580 Udp interface does not work for non-localhost

Migration Notes from COSMOS 3.8.x:

COSMOS 4 includes several breaking changes from the COSMOS 3.x series.

The first and simplest is that the Command and Telemetry Server now opens an additional port at 7780 by default, that provides a router that will send out each command that the system has sent. This can allow external systems to also log all commands sent by COSMOS. For most people this change will be transparent and no updates to your COSMOS configuration will be required.

The second is that the Command and Telemetry Server now always supports a meta data packet called SYSTEM META. This packet will always contain the MD5 sum for the current running COSMOS configuration, the version of COSMOS running, the version of your COSMOS Project, and the version of Ruby being used. You can also add your own requirements for meta data with things like the name of the operator currently running the system, or the name of a specific test you are currently running. In general you shouldn’t need to do anything for this change unless you were using the previous metadata functionality in COSMOS. If you were, then you will need to migrate your meta data to the new SYSTEM META packet, and change the parameters in your CmdTlmServer or TestRunner configurations regarding meta data. If you weren’t using metadata before, then you will probably just notice this new packet in your log files, and in your telemetry stream.

Finally the most exciting breaking change is in how COSMOS interfaces handle protocols. Before, the COSMOS TCP/IP and Serial interface classes each took a protocol like LENGTH, TERMINATED, etc that defined how packets were delineated by the interface. Now each interface can take a set of one or more protocols. This allows COSMOS to much more easily support nested protocols, such as the frame focused protocols of CCSDS. It also allows for creating helpful reusable protocols such as the new CRC protocol for automatically adding CRCs to outgoing commands and verifying incoming CRCs on telemetry packets. It’s a great change, but if you have any custom interface classes you have written, they will probably require some modification. See the Interfaces section at cosmosc2.com to see how the new interface classes work. We will also be writing up a blog post to help document the process of upgrading. Look for this in a week or two.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Deploying COSMOS to the Cloud

COSMOS is a GUI application which runs equally well on Windows, Linux, and Mac OS X due to the QT GUI framework and Ruby language it is written in. Traditionally this means you install it locally on your own workstation and you’re off and running. But can COSMOS also be deployed to the cloud? Yes! This post describes how I deployed COSMOS to Amazon Web Services (AWS) using several different technologies.

AWS

AWS consists of a lot of different services. To deploy COSMOS you need to create an AWS EC2 instance. The first step is to sign up for AWS which enables you to use their Free Tier for 12 months. This includes 750hrs each on Linux and Windows Server.

Deploying to Windows Server

Deploying to Windows Server is probably the easiest way to get COSMOS in the cloud. Simply create a Windows Server instance by selecting the following image: Windows Image

Then select the t2.micro Type which is marked “Free tier eligible”. Launch the Instance and you should see the key pair dialog: Key Pair Dialog

Create a new key pair and give the name something generic because you can use the same key pair for all the EC2 instances you create. Create the instance and then View Instance which will show the instance status. Click the Connect button at top which will bring up the Connect dialog: Connect Dialog

Click the Download Remote Desktop File and open it in Remote Desktop to connect to the Windows Server instance. Note that it does take a while for the Windows instance to boot so this won’t work until your Status Checks show a green check. Also note that many corporate firewalls may block doing a Remote Desktop outside your corporate network.

You also need to click Get Password and locate your ‘pem’ file you saved earlier to Decrypt your password. Login to the instance as Administrator with the decrypted password. Once you’ve logged in you can change the password to something a little more reasonable. Then simply follow the usual COSMOS installation instructions.

Here is a screenshot of my successful COSMOS installation running on the AWS Microsoft Server instance: COSMOS on Windows

Deploying to Red Hat Linux (with X forwarding)

Deploying to Red Hat Linux is similar to Windows. Create a Red Hat instance by selecting the following image: Red Hat Image

Use the same key pair when creating your Windows instance and create the instance. View Instance and click the Connect button which brings up the Connect dialog: Connect Dialog

SSH to the instance using the connection string provided making sure to specify the full path to your ‘pem’ file in the quoted path after the -i option. Install a GUI by issuing the following command:

sudo yum groupinstall 'Server with GUI'

Install COSMOS using the installation bash file:

bash <(\curl -sSL https://raw.githubusercontent.com/BallAerospace/COSMOS/cosmos4/vendor/installers/linux_mac/INSTALL_COSMOS.sh)

Chose the sudo option when asked how to install. To enable X forwarding edit the SSH config file:

sudo vim /etc/ssh/sshd_config

Enable the following settings:

X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost no

Close your current SSH connection and reconnect with SSH adding the -X option to enable X11 forwarding and -Y to enable trusted X11 fowarding. If you host OS is Mac OS X you’ll need to install XQuartz. Linux has X11 forward support built-in. Windows should probably install Xming which is an exercise left to the reader.

Now launch COSMOS and you should see the COSMOS windows appear on your own machine. While this approach works I found the performance to be significantly slower than VNC. Here is a screenshot of it running while I connected via a Mac OS X machine: Red Hat X

Deploying on Ubuntu (with VNC)

Deploying to Ubuntu Linux is very similar to Red Hat. Create an Ubuntu instance by selecting the following image: Ubuntu Image

Use the same key pair as when creating your Windows or Red Hat instance and create the instance. View Instance and click the Connect button which brings up the Connect dialog: Connect Dialog

Click on the instance and click the Description tab which appears below the instance. Click the link next to Security groups to open the Security Groups configuration. Click the Inbound tab and create Edit to create a new Custom TCP Rule to enable TCP traffic on Ports 5900-5910 from Anywhere. Your rule should look like the following: Security Group

SSH to the instance using the connection string provided making sure to specify the full path to your ‘pem’ file in the quoted path after the -i option. Install a GUI by issuing the following command:

sudo apt-get update
sudo apt install xfce4 xfce4-goodies tightvncserver

Run the following commands to setup the VNC server:

vncserver
vncserver -kill :1
vim ~/.vnc/xstartup

Ensure your xstartup file matches the following:

#!/bin/sh

# Uncomment the following two lines for normal desktop:
unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc
unset DBUS_SESSION_BUS_ADDRESS
startxfce4 &

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#x-window-manager &

Restart VNC:

vncserver

Install COSMOS using the installation bash file:

bash <(\curl -sSL https://raw.githubusercontent.com/BallAerospace/COSMOS/cosmos4/vendor/installers/linux_mac/INSTALL_COSMOS.sh)

Chose the sudo option when asked how to install. On your local machine install a VNC viewer such as TightVNC and connect by entering the Public DNS address of your AWS instance in the Remote Host as well as the Port number of 5901. Typically this is added by appending it to the Remote Host address with a colon. Here is a screenshot of it running while I connected via TightVNC: Red Hat X

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 4.0.1 Released

New Features:

  • #527 Editing config files should now bring up ConfigEditor
  • #528 ConfigEditor missing some keywords
  • #534 Create ConfigEditor Mac app
  • #536 Clickable canvas objects open screens
  • #542 Automatically populate COMMAND SYSTEM META
  • #543 Allow SYSTEM META items to be read only

Maintenance:

  • None

Bug Fixes:

  • #533 TestRunner strips all comments when running
  • #538 META_INIT broken
  • #540 Background task packet subscription get_packet broken
  • #547 convert_packet_to_data should copy buffer

Migration Notes from COSMOS 3.8.x:

COSMOS 4 includes several breaking changes from the COSMOS 3.x series.

The first and simplest is that the Command and Telemetry Server now opens an additional port at 7780 by default, that provides a router that will send out each command that the system has sent. This can allow external systems to also log all commands sent by COSMOS. For most people this change will be transparent and no updates to your COSMOS configuration will be required.

The second is that the Command and Telemetry Server now always supports a meta data packet called SYSTEM META. This packet will always contain the MD5 sum for the current running COSMOS configuration, the version of COSMOS running, the version of your COSMOS Project, and the version of Ruby being used. You can also add your own requirements for meta data with things like the name of the operator currently running the system, or the name of a specific test you are currently running. In general you shouldn’t need to do anything for this change unless you were using the previous metadata functionality in COSMOS. If you were, then you will need to migrate your meta data to the new SYSTEM META packet, and change the parameters in your CmdTlmServer or TestRunner configurations regarding meta data. If you weren’t using metadata before, then you will probably just notice this new packet in your log files, and in your telemetry stream.

Finally the most exciting breaking change is in how COSMOS interfaces handle protocols. Before, the COSMOS TCP/IP and Serial interface classes each took a protocol like LENGTH, TERMINATED, etc that defined how packets were delineated by the interface. Now each interface can take a set of one or more protocols. This allows COSMOS to much more easily support nested protocols, such as the frame focused protocols of CCSDS. It also allows for creating helpful reusable protocols such as the new CRC protocol for automatically adding CRCs to outgoing commands and verifying incoming CRCs on telemetry packets. It’s a great change, but if you have any custom interface classes you have written, they will probably require some modification. See the Interfaces section at cosmosc2.com to see how the new interface classes work. We will also be writing up a blog post to help document the process of upgrading. Look for this in a week or two.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Ball Aerospace COSMOS 4.0.0 Released

COSMOS 4 is here!

48 tickets have gone into this release, and it brings with it two new tools and some great under the hood improvements.

New Tools:

COSMOS now has a dedicated Configuration Editor and Command Sequence Builder.

The config editor gives you contextual help when building config files, and make it super easy to define packets and configure tools without having to have the online documentation up in front of you. It’s going to make setting up COSMOS even easier than it was before.

Command Sequence builder allows you to define series of commands that should be sent at either absolute or relative timestamps to each other. This is great for planning time specific commanding. You can execute these on the ground directly from the tool, or you can convert them to your own internal format and upload to the system you are commanding.

Highlighted changes:

  1. New protocol system allows assigning multiple protocols to each interface to support layered protocols, and common functionality like CRC checking/adding to commands.
  2. The ability to View the most recent raw data received or sent on each interface
  3. The Command and Telemetry Server can now run on JRuby in –no-gui mode (may help performance for huge projects with 50+ targets)
  4. New router provides the ability to get a copy of every command sent out from COSMOS in a stream
  5. New SYSTEM META packet output by the CmdTlmServer
  6. Lots more! See the full ticket list below

New Features:

  • #229 Gem Based Targets should support DataViewer and other tool configurations
  • #234 Add a method to system.txt to add files used in the marshall file MD5 sum calculation
  • #253 Create “generators” for targets, tools, etc
  • #258 Create COSMOS Command Sequence Tool
  • #261 Provide a method for specifying binary data in STRING and BLOCK default values
  • #278 Consider adding wait_ methods to internal API for use in Background tasks
  • #281 Add support for stretch and spacers in widget layouts
  • #319 Add the ability to grab telemetry ARRAY_ITEMs
  • #337 Support specifying default parameters to default log reader and log writer in system.txt
  • #347 COSMOS GLobal Time Zone Setting (Local/UTC)
  • #356 Interface protocols
  • #360 Add raw stream preamble and postamble data to “View Raw”
  • #381 Float Infinity and NaN as command values
  • #401 tolerance scripting calls should support array telemetry items
  • #404 Packet Viewer easy access to edit configuration files
  • #405 Telemetry Viewer easy access to edit screen definition
  • #423 Add “Cmd router” to CmdTlmServer to support external logging of all commands
  • #424 TlmViewer should call update_widget for a screen with no value items and with CmdTlmServer not running
  • #426 Standardize meta data to SYSTEM META packet
  • #432 Export processed config files
  • #442 Label value widgets should support right aligned labels
  • #459 Script Editor code completion enhancements
  • #479 Limits Monitor doesn’t detect newly connected targets
  • #489 Built in support for limits group enable and disable
  • #497 Update serial_interface.rb to support hardware flow control
  • #498 Script helper for activities that should cause an exception
  • #511 Make CmdTlmServer run on JRuby
  • #512 Create a CRC Protocol
  • #513 Create a GUI config file editor
  • #516 Recreate COSMOS C Extension Code in Pure Ruby
  • #517 Make hostname for tools to connect to CTS API configurable in system.txt
  • #519 Replay should support alternate packet log readers

Maintenance:

  • #354 Targets need to be path namespaced to avoid conflicts
  • #323 Catch Signals in CmdTlmServer
  • #341 Document COSMOS JSON API on cosmosc2.com
  • #398 Documentation, code cleanup
  • #429 Command Endianness and Parameter Endianness
  • #437 Remove CMD_TLM_VERSION from system.txt
  • #438 Cache script text as part of instrumenting script
  • #446 Windows 10 Install fails
  • #476 Separate apt and yum package install lines
  • #477 Deprecate userpath.txt
  • #484 require_file should re-raise existing exception

Bug Fixes:

  • #456 Replay doesn’t shut down properly if closed while playing
  • #481 show_backtrace not working in ScriptRunner
  • #494 Details dialog crashes for items with LATEST packet
  • #502 Target REQUIRE should also search system path
  • #506 Don’t call read_interface if data is cached in protocols for another packet

Migration Notes from COSMOS 3.8.x:

COSMOS 4 includes several breaking changes from the COSMOS 3.x series.

The first and simplest is that the Command and Telemetry Server now opens an additional port at 7780 by default, that provides a router that will send out each command that the system has sent. This can allow external systems to also log all commands sent by COSMOS. For most people this change will be transparent and no updates to your COSMOS configuration will be required.

The second is that the Command and Telemetry Server now always supports a meta data packet called SYSTEM META. This packet will always contain the MD5 sum for the current running COSMOS configuration, the version of COSMOS running, the version of your COSMOS Project, and the version of Ruby being used. You can also add your own requirements for meta data with things like the name of the operator currently running the system, or the name of a specific test you are currently running. In general you shouldn’t need to do anything for this change unless you were using the previous metadata functionality in COSMOS. If you were, then you will need to migrate your meta data to the new SYSTEM META packet, and change the parameters in your CmdTlmServer or TestRunner configurations regarding meta data. If you weren’t using metadata before, then you will probably just notice this new packet in your log files, and in your telemetry stream.

Finally the most exciting breaking change is in how COSMOS interfaces handle protocols. Before, the COSMOS TCP/IP and Serial interface classes each took a protocol like LENGTH, TERMINATED, etc that defined how packets were delineated by the interface. Now each interface can take a set of one or more protocols. This allows COSMOS to much more easily support nested protocols, such as the frame focused protocols of CCSDS. It also allows for creating helpful reusable protocols such as the new CRC protocol for automatically adding CRCs to outgoing commands and verifying incoming CRCs on telemetry packets. It’s a great change, but if you have any custom interface classes you have written, they will probably require some modification. See the Interfaces section at cosmosc2.com to see how the new interface classes work. We will also be writing up a blog post to help document the process of upgrading. Look for this in a week or two.

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Template Protocol

The Template Protocol is probably one of the more confusing protocols in the COSMOS protocol library but it is extremely helpful when implementing string based protocols such as Standard Commands for Programmable Instruments (SCPI; often pronounced “skippy”).

For this example we’ll assume we’re trying to talk to a SCPI enabled power supply such as the Keysight N6700. We start by creating a directory under our config/targets called POWER. The supply has a TCP/IP interface so we’ll use the TCP/IP Client Interface to connect to it. Thus we create our POWER/cmd_tlm_server.txt file as follows:

INTERFACE POWER_INT tcpip_client_interface.rb 127.0.0.1 5025 5025 10.0 nil TEMPLATE 0x0A 0x0A
  TARGET POWER

This definition declares an interface named POWER_INT using the TCP/IP client interface which connects to ‘127.0.0.1’ (obviously you’ll change this to your actual power supply IP addres) using a write and read port of 5025 (standard SCPI ports for Keysight instruments) with a write timeout of 10s and no read timeout (block on read). We specify the TEMPLATE protocol with both write and read termination characters of 0x0A (ASCII newline). Note the TEMPLATE protocol takes many additional parameters to allow you to work with off nominal protocol conditions.

Now you can define your target’s command and telemetry definitions. We’ll create example commands which get and set the voltage setting in our power supply. Create a POWER/cmd_tlm/cmd.txt file which has the following:

COMMAND POWER GET_VOLTAGE BIG_ENDIAN "Get voltage"
  APPEND_ID_PARAMETER CMD_ID 8 UINT 1 1 1 "Command Id" # Unique command ID
  APPEND_PARAMETER CHANNEL 8 UINT 1 4 1 "Channel"
  APPEND_PARAMETER CMD_TEMPLATE 512 STRING "MEAS:VOLT? (@<CHANNEL>)"
  APPEND_PARAMETER RSP_TEMPLATE 512 STRING "<VOLTAGE>"
  APPEND_PARAMETER RSP_PACKET 512 STRING "TLM"

COMMAND POWER SET_VOLTAGE BIG_ENDIAN "Set voltage"
  APPEND_ID_PARAMETER CMD_ID 8 UINT 2 2 2 "Command Id" # Unique command ID
  APPEND_PARAMETER CHANNEL 8 UINT 1 4 1 "Channel"
  APPEND_PARAMETER VOLTAGE 8 UINT 0 100 10 "Voltage"
  APPEND_PARAMETER CMD_TEMPLATE 512 STRING "VOLT <VOLTAGE>,(@<CHANNEL>)"
  APPEND_PARAMETER RSP_TEMPLATE 512 STRING "<SET_VOLTAGE>"
  APPEND_PARAMETER RSP_PACKET 512 STRING "TLM"

The CMD_ID parameter is defined by APPEND_ID_PARAMETER. This ID parameter is not used by the SCPI protocol but is needed for COSMOS to identify the command when it is logged. The CMD_TEMPLATE parameter is the actual SCPI command which is being sent to the target. Anything inside brackets <> will be replaced by the value in the named parameter. For example, both commands define the CHANNEL parameter and thus <CHANNEL> will be replaced by the value of that parameter when constructing the command. The RSP_TEMPLATE is the expected string response back from the target. This is parsed by pulling out values into the bracket delimited values. The RSP_PACKET defines the packet where the bracket delimited values are defined. So for our GET_VOLTAGE example we parse the VOLTAGE value and place it in the TLM packet.

Create a POWER/cmd_tlm/tlm.txt file to define the response telemetry:

TELEMETRY POWER TLM BIG_ENDIAN "Power Supply Telemetry"
  APPEND_ID_ITEM TLM_ID 32 INT 1 "Packet Identifier" # Unique telemetry ID
  APPEND_ITEM VOLTAGE 32 FLOAT "PS Measured Voltage"
    FORMAT_STRING "%0.3f"
    UNITS "Volts" "V"
  APPEND_ITEM SET_VOLTAGE 32 FLOAT "PS Set Voltage"
    FORMAT_STRING "%0.3f"
    UNITS "Volts" "V"

The TLM_ID item is defined by APPEND_ID_ITEM. This ID item is not used by the SCPI protocol but is needed by COSMOS to decode this logged telemetry packet. The packet is named TLM which matches our RSP_PACKET definition in the commands. We define VOLTAGE and SET_VOLTAGE which also match the values used in the RSP_TEMPLATE parameters in our commands.

With Keysight supplies you can string together a bunch of SCIP commands in one CMD_TEMPLATE if you delimit them with semicolons. Then in the RSP_TEMPLATE you can break the response apart and set a bunch of telemetry items at once. For example:

COMMAND POWER GET_STATUS BIG_ENDIAN "Get status"
  APPEND_ID_PARAMETER CMD_ID 8 UINT 3 3 3 "Command Id" # Unique command ID
  APPEND_PARAMETER CHANNEL 8 UINT 1 4 1 "Channel"
  APPEND_PARAMETER CMD_TEMPLATE 512 STRING "MEAS:VOLT (@<CHANNEL>);CURR (@<CHANNEL>);POW (@<CHANNEL>)"
  APPEND_PARAMETER RSP_TEMPLATE 512 STRING "<VOLTAGE>,<CURRENT>,<POWER>"
  APPEND_PARAMETER RSP_PACKET 512 STRING "TLM"

The RSP_TEMPLATE expects to have three values delimited by the comma character. For this example to be complete you would also need to declare CURRENT and POWER items in the TLM packet.

Using the TEMPLATE processor can be complex but makes working with with string based command / response protocols like SCPI much easier.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 3.9.2 Released

New Features:

  • #147 TlmExtractor Full Column Names Mode
  • #148 TlmExtractor Share individual columns
  • #189 ScriptRunner Breakpoints don’t adapt to edits
  • #233 Add Config Option to Increase Tcpip Interface Timeout to TlmGrapher
  • #280 Method for determining interface packet count
  • #313 Add command line option to automatically start ScriptRunner
  • #336 Add Log Analyze Feature to TlmExtractor/CmdExtractor
  • #395 Implement Stylesheets Throughout
  • #408 Easy way to find which targets use an interface?
  • #433 Scripting support for TlmViewer close all screens
  • #434 TlmViewer option for no resize of screens
  • #436 PacketViewer option to ignore target.txt ignored items
  • #441 PacketViewer should identify derived items in the GUI

Maintenance:

None

Bug Fixes:

  • #417 Table Manager not checking ranges
  • #419 Support multiple arrays in string based commands

Migration Notes from COSMOS 3.8.x:

The Table Manager configuration file format has changed. Documentation will updated the first week of April.

You can migrate existing config files using:

bundle exec ruby tools\TableManager --convert config\tools\table_manager\old_table_def.txt

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Packet Processors

COSMOS Packet Processors are a powerful concept that allow you to run code each time a specified packet is received. COSMOS provides a few generic Packet Processors which allows you to include statistics about individual telemetry points in your defined packets. Let’s break down how the COSMOS included processors are used and how you can implement your own Packet Processor.

First install COSMOS and start up the demo application. You’ll notice we declare a few targets of which one is called INST (for instrument). If you open up Packet Viewer and navigate to the INST target and the HEALTH_STATUS packet you can see a bunch of derived telemetry points at the top.

Packet Viewer

These points aren’t immediately obvious in the GUI (Ticket #441) but here they include all the items down to and including TEMP1STDDEV. If you right click on one of them and choose “Details” you can see that Data Type is DERVIED.

Derived

This is all controlled by the INST target’s cmd/tlm definition files. If you open the INST/cmd_tlm/inst_tlm.txt file from the demo you’ll see the following at the end of the HEALTH_STATUS packet definition:

  ITEM TEMP1HIGH 0 0 DERIVED "High-water mark for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1WATER HIGH_WATER
  ITEM TEMP1LOW 0 0 DERIVED "Low-water mark for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1WATER LOW_WATER
  ITEM TEMP1MAX 0 0 DERIVED "Maximum of most recent 100 samples for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1STAT MAX
  ITEM TEMP1MIN 0 0 DERIVED "Minimum of most recent 100 samples for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1STAT MIN
  ITEM TEMP1MEAN 0 0 DERIVED "Mean of most recent 100 samples for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1STAT MEAN
  ITEM TEMP1STDDEV 0 0 DERIVED "Stddev of most recent 100 samples for TEMP1"
    READ_CONVERSION processor_conversion.rb TEMP1STAT STDDEV
  PROCESSOR TEMP1STAT statistics_processor.rb TEMP1 100
  PROCESSOR TEMP1WATER watermark_processor.rb TEMP1

These definitions create six new telemetry ITEMs. The READ_CONVERSION line takes a conversion class and then variable parameters that are passed to the class. Here we’re using the COSMOS provided processor_conversion.rb class which pulls a result calculated by a PROCESSOR. The last two lines define the two PROCESSORs.

Currently COSMOS provides the following three processors:

  1. new_packet_log_processor.rb - This processor creates a new packet log whenever the given Packet is seen.
  2. watermark_processor.rb - This processor monitors a telemetry item and tracks the high and low water points of that item since the launch of the Command and Telemetry Server.
  3. statistics_processor.rb - This processor collects a given number of samples of a telemetry item and calculates the minimum, maximum, mean, and standard deviation over the sample.

If all you want to do is to calculate useful statistics on your telemetry items you can stop reading now. For those who want to know how this works or want to implement their own Packet Processors, let’s continue into the source code.

Processor Implementation

require 'cosmos/processors/processor'
module Cosmos
  class WatermarkProcessor < Processor
    # @param item_name [String] The name of the item to gather statistics on
    # @param value_type #See Processor::initialize
    def initialize(item_name, value_type = :CONVERTED)
      super(value_type)
      @item_name = item_name.to_s.upcase
      reset()
    end

    # See Processor#call
    def call(packet, buffer)
      value = packet.read(@item_name, @value_type, buffer)
      high_water = @results[:HIGH_WATER]
      @results[:HIGH_WATER] = value if !high_water or value > high_water
      low_water = @results[:LOW_WATER]
      @results[:LOW_WATER] = value if !low_water or value < low_water
    end

    # Reset any state
    def reset
      @results[:HIGH_WATER] = nil
      @results[:LOW_WATER] = nil
    end

    # Convert to configuration file string
    def to_config
      "  PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@item_name} #{@value_type}\n"
    end
  end
end

The initialize method gets passed the parameters from the config file. Thus our config file of: PROCESSOR TEMP1WATER watermark_processor.rb TEMP1 passes ‘TEMP1’ into ‘item_name’ of the initialize method: def initialize(item_name, value_type = :CONVERTED) Since we only pass one value, we use the default value_type of :CONVERTED.

We store the item_name into a Ruby instance variable @item_name and call reset() to initialize our @results. But how did we get a @results instance variable? If you look at the class definition we are inheriting from Processor which is the base class for all COSMOS Processors. It declares a @results instance variable and initializes @results in its initialize method which we call using super(value_type).

The call method is the most important Processor method. It is always passed the packet and buffer. The packet is the COSMOS Packet instance which contains the value you’re interested in. Buffer is the raw binary buffer which this packet is based on. The Processor base class should never be directly used as it defines but does not implement call. Instead, you inherit from Processor like we did with WatermarkProcessor and implement your own call method. WatermarkProcessor reads the item we’re interested in and then compares it with the currently stored high and low value to determine if it should be saved. Note how it is saving the value in the @results hash with the :HIGH_WATER and :LOW_WATER symbol keys.

Processor Conversion

If you then open up the processor_conversion.rb code you can see how these results are converted into new telemetry items.

require 'cosmos/conversions/conversion'
module Cosmos
  # Retrieves the result from an item processor
  class ProcessorConversion < Conversion
    # @param processor_name [String] The name of the associated processor
    # @param result_name [String] The name of the associated result in the processor
    # @param converted_type [String or nil] The datatype of the result of the processor
    # @param converted_bit_size [Integer or nil] The bit size of the result of the processor
    def initialize(processor_name, result_name, converted_type = nil, converted_bit_size = nil)
      super()
      @processor_name = processor_name.to_s.upcase
      @result_name = result_name.to_s.upcase.intern
      if ConfigParser.handle_nil(converted_type)
        @converted_type = converted_type.to_s.upcase.intern
        raise ArgumentError, "Unknown converted type: #{converted_type}" if !BinaryAccessor::DATA_TYPES.include?(@converted_type)
      end
      @converted_bit_size = Integer(converted_bit_size) if ConfigParser.handle_nil(converted_bit_size)
    end

    # @param (see Conversion#call)
    # @return [Varies] The result of the associated processor
    def call(value, packet, buffer)
      packet.processors[@processor_name].results[@result_name] || 0 # Never return nil
    end
    def to_s; end # Not shown for brevity
    def to_config(read_or_write); end # Not shown for brevity
  end
end

First of all note that ProcessorConversion inherits from the Conversion base class. This is very similar to the WatermarkProcessor inheriting from the Processor base class. Again, there is an initialize method and a call method. The initialize method requires the processor_name and result_name and takes optional parameters that help describe the converted type. Let’s see how these map together in our definition.

Our config file looked like the following: READ_CONVERSION processor_conversion.rb TEMP1WATER HIGH_WATER This passes TEMP1WATER and HIGH_WATER as processor_name and result_name into initialize: def initialize(processor_name, result_name, converted_type = nil, converted_bit_size = nil)

We store the processor name and result name into Ruby instance variables (first turning them into upper case strings). We additionally turn the result name into a Ruby symbol by calling intern on it. This allows us to match the symbol names we used in the WatermarkProcessor code.

All Conversion classes also implement the call method except with a slightly different signature. In addition to the packet and buffer being passed, the raw value is returned. The ProcessorConversion class uses the packet instance to access the processors hash by the given processor name and then accesses the results hash by the passed result name. We add a ‘|| 0’ which does a logical OR on the initial result to ensure that we don’t return a nil value as a result of the conversion.

Custom Processor

So how could we implement our own Processor? Let’s say you had some telemetry points that you wanted to average and report that averaged value as a new telemetry item. This is useful because you can then add limits to this new item and act on its value in scripts without having to constantly perform the averaging operation.

First create your new Processor class. Let’s call it MeanProcessor. This code should go into a file called mean_processor.rb and can either live in one of your target/lib folders or since it’s generic we can put it in the top level /lib directory in our project.

require 'cosmos/processors/processor'
module Cosmos
  class MeanProcessor < Processor # @param item_name [Array<String>] The names of the items to mean
    def initialize(\*item_names) # the splat operator accepts a variable length argument list
      super(:CONVERTED) # Hard code to work on converted values
      @item_names = item_names # Array of the item names
      reset()
    end

    def call(packet, buffer)
      values = []
      @item_names.each do |item|
        values << packet.read(item, :CONVERTED, buffer)
      end
      @results[:MEAN] = values.inject(0, :+).to_f / values.length
    end

    # Reset any state
    def reset
      @results[:MEAN] = []
    end

    # Convert to configuration file string
    def to_config
      "  PROCESSOR #{@name} #{self.class.name.to_s.class_name_to_filename} #{@item_names.join(' ')}\n"
    end
  end
end

This class introduces some new Ruby syntax. Since we want to accept any number of items to average we have to accept a variable number of arguments in our initialize method. The ruby splat operator (or star operator) does this and places the arguments into a Ruby array. We store these names and then use them in our call method to perform the mean. I’m using a cool feature of Ruby’s Enumerable mixin, which is part of Array, to sum up the values (starting with 0) and then dividing by the number of values we have to get the mean. Note I’m also calling to_f to ensure the numerator is a floating point number so we do floating point math during the division. Integer division would truncate the value to an integer value.

First to use this new processor you need to require it in your target’s target.txt configuration file: REQUIRE mean_processor.rb Then delcare the processing in your configuration definition as follows:

TELEMETRY INST HEALTH_STATUS BIG_ENDIAN "Health and status from the instrument"
  ... # See demo configuration
  ITEM TEMPS_MEAN 0 0 DERIVED "Mean of TEMP1, TEMP2, TEMP3, TEMP4"
    READ_CONVERSION processor_conversion.rb TEMPMEAN MEAN
  PROCESSOR TEMPMEAN mean_processor.rb TEMP1 TEMP2 TEMP3 TEMP4

We define the processor on the INST HEALTH_STATUS packet and pass in 4 items to average. We also define a new derived item called TEMPS_MEAN which uses our previously described processor_conversion to pull out the MEAN value that we calculated. The result is shown in this PacketViewer screen shot:

Packet Viewer

Creating a custom processor definitely requires you to dive into the COSMOS API and play with the underlying Ruby code. Hopefully the existing processor code and this blog post helps you to derive whatever telemetry points you need.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

WIRED Article

Ball Aerospace COSMOS has been featured in an article on WIRED.com. The article focues on the fact that COSMOS is open source and what that means for the industry. The author includes quotes from GitHub’s VP of Product Engineering, Aerospace Corporation’s Principle Director of IT, and of course Ryan Melton and Jason Thomas of Ball Aerospace.

Ball Aerospace COSMOS 3.9.1 Released

New Features:

  • #382 CmdTlmServer Start/Stop for background tasks
  • #385 Quick access to COSMOS gem code
  • #388 Legal Dialog should show COSMOS version
  • #409 Update LINC interface to support multiple targets on the same interface

Maintenance:

  • #369 Table Manager refactoring
  • #386 Batch file for offline installation

Bug Fixes:

  • #236 Test Runner doesn’t support status_bar
  • #329 Using XTCE file instead of .txt cmd_tlm file didn’t work as online docs suggest
  • #378 TlmViewer displaying partials in the screen list
  • #402 Mac installation is failed - Please help.
  • #411 xtce explicit byte order list processing isn’t correct
  • #412 subscribe_packet_data needs to validate parameters

Migration Notes from COSMOS 3.8.x:

The Table Manager configuration file format has changed. Documentation will updated the first week of April.

You can migrate existing config files using:

bundle exec ruby tools\TableManager --convert config\tools\table_manager\old_table_def.txt

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

Routers

COSMOS Routers can be a confusing topic for people new and old alike to the COSMOS system. Let’s break them down and explore how COSMOS uses them internally and how you might use them in your configuration.

A COSMOS Router is first and foremost an interface like any other COSMOS interface. In fact if you look through the source code you won’t even see a Router class because they are instances of the Interface class. As a reminder, an Interface provides the lowest level connection between COSMOS and a target (something you’re trying to get COSMOS to talk to). Thus a Router is also providing a low level connection between COSMOS and something. So what’s the difference? Normal Interfaces read the target and send data (telemetry) to COSMOS and send commands to the target. Routers do the exact opposite: they route telemetry out to clients connected to them and route commands sent to them back to a target. Thus they provide a conduit for other clients to communicate with a target.

The COSMOS Command and Telemetry Server always starts a Router called the PREIDENTIFIED_ROUTER which appears in the Routers tab of the GUI: Server Routers

The Preidentified Router is controlled by the system.txt configuration file:

# Ethernet Ports
PORT CTS_API 7777
PORT TLMVIEWER_API 7778
PORT CTS_PREIDENTIFIED 7779

This Router is called the PREIDENTIFIED router because it uses a special stream protocol which adds the packet received time, the target name, and the packet name before sending the packet. This stream is used by the Telemetry Grapher so it doesn’t have to spend additional cycles identifying packets and can directly graph the packets it is interested in. The Replay tool also creates this router for the exact same purpose.

If you look back at the picture you’ll see in our demo configuration that we also create another Router called the INST_ROUTER. This is how that Router is configured:

ROUTER INST_ROUTER tcpip_server_interface.rb 2055 2055 10.0 nil LENGTH 32 16 7
  OPTION LISTEN_ADDRESS 127.0.0.1
  ROUTE INST_INT

Basically we’re creating a Router that routes only the INST interface data. We create this Router using a TCPIP Server interface with a LENGTH protocol of bit offset 32, length field size of 16, and length value offset of 7. These values were chosen to match the INST command and telemetry which use CCSDS headers. The CCSDS standard specifies a 16 bit length field at offset 32. The CCSDS standard also specifies that the length field is the length of the packet past the length field minus 1. Thus we add 7 for the 4 bytes of offset, 2 bytes of length field, and the minus 1.

For more information about the options you can pass to a Router (and Interface) see the Interface Configuration part of the documentation.

To connect to the INST_ROUTER that we created we can write a little Ruby code using existing COSMOS interface classes and streams.

require 'cosmos'
require 'cosmos/interfaces/tcpip_client_interface'

i = Cosmos::TcpipClientInterface.new('localhost',2055,2055,nil,nil,'LENGTH',32,16,7)
i.connect
loop do
  pkt = Cosmos::System.telemetry.identify!(i.read.buffer, ['INST'])
  puts pkt.packet_name
end

Obviously we need the TCPIP Client Interface to match the port number of the TCPIP Server and we also need to match the LENGTH protocol options. Notice how we have to call the System.telemetry.identify! method to identify the raw packet stream. When I run this from a command prompt after starting the Server I see a stream of packet names similar to this:

MECH
ADCS
MECH
IMAGE
PARAMS
ADCS
HEALTH_STATUS
MECH
ADCS
...

You should see MECH and ADCS come out at 10Hz and the IMAGE, PARAMS, and HEALTH_STATUS come out at 1Hz. This matches the Packet Count ratio on the Tlm Packets tab of the Server.

We can also write some code to connect to the PREIDENTIFIED router. It looks very similar to the previous code except we do not need to identify the packets as they are pre-identified!

require 'cosmos'
require 'cosmos/interfaces/tcpip_client_interface'

i = Cosmos::TcpipClientInterface.new('localhost',7779,7779,nil,nil,'PREIDENTIFIED')
i.connect
loop do
  pkt = i.read
  puts pkt.packet_name
end

This time you should see some LIMITS_CHANGE packet names sprinkled in with the output from before. That’s because we’re accessing the ENTIRE COSMOS telemetry stream and not just the stream from the INST interface. Keep this in mind if you have performance issues when trying to process the entire telemetry stream.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 3.8.3 Released

New Features:

  • #230 Make AUTO_TARGETS ignore target folders that have already been manually referenced
  • #257 Increment received_count in packet log reader
  • #264 Validate command/telemetry conversions during startup
  • #292 Target directory for API methods
  • #314 Update .bat files to handle spaces in path
  • #316 Add option to radiobutton widget to be checked by default
  • #326 Script Runner Crash using message_box with boolean parameter
  • #339 Add ‘Help’ menu item to open cosmosc2.com -> Documentation
  • #340 Packet Viewer - Allow select cell and copy value as text
  • #357 Add support for mixed endianness within tables
  • #359 Table Manager support MIN/MAX UINTX macros

Maintenance:

  • #349 Optimize cmd() to not build commands twice
  • #362 restore_defaults should take an optional parameter to exclude specified parameters
  • #365 Windows installer can have issues if .gem files are present in same folder
  • TestRunner support for newer Bundler (Abstract error when starting)

Bug Fixes:

  • #322 Udp interface thread does not gracefully shutdown
  • #327 TlmGrapher Screenshot in Linux captures the screenshot dialog box
  • #332 ERB template local variables dont’ support strings
  • #338 Setting received_time and received_count on a packet should clear the read conversion cache
  • #342 Cut and Paste Error in top_level.rb
  • #344 CmdTlmServer connect/disconnect button doesn’t work after calling connect_interface from script
  • #359 Table Manager doesn’t support strings
  • #372 TestRunner reinstantiating TestSuite/Test objects every execution

Migration Notes from COSMOS 3.7.x:

None

To upgrade to the latest version of COSMOS, run “bundle update cosmos” in your COSMOS project folder.

SmallSat Ops

The fact that COSMOS is the only open source C2 system has made it an ideal small satellite operations platform. This is one of the reasons Ryan attended the Small Satellite Conference back in August. He gave a very well received COSMOS presentation and was able to meet with many players in the industry.

Ryan at SmallSat Ryan enjoying the moment at Small Sat 2016

I recently googled for “COSMOS Command and Control” and came across a LinkedIn article about COSMOS. We had heard from Pat Stakem during the summer of 2015 but hadn’t heard much since. He and his students created a CubeSat using the open source Core Flight System from NASA Goddard. Of course they used COSMOS for their ground system running on Ubuntu. They integrated Apache to serve up the COSMOS telemetry files generated from Telemetry Extractor to operate their satellite “lights out”. They put together a great PowerPoint presentation with screenshots of COSMOS. They also created a whitepaper detailing the entire process.

Stakem Screenshot Screenshot showing COSMOS in action

ERB Config Files

COSMOS configuration files support ERB (Embedded RuBy) which is used heavily by Ruby on Rails. I found a pretty good description of ERB here. ERB allows you to put executable Ruby code in your configuration files. The trick is to surround the Ruby code with the special markers: <% <code> %>. If you want the result of your Ruby code to be placed in the configuration file you need to add the equal sign to the first marker: <%= <code> %>

A COSMOS user recently asked if he could include environment variables in his COSMOS configuration. This is very easy using the ERB syntax. For example, you have an environment variable named “LOG_DIR” in your system which points to the path you want to store your COSMOS logs. To use this value you would modify your system.txt file as follows:

...
# Paths
PATH LOGS <%= ENV["LOG_DIR"] %>
...

When this file gets parsed by COSMOS, the value of the LOG_DIR environment variable gets inserted into the system.txt output file. Note the %= syntax to insert the value and how I’m using the ENV from the Ruby core library.

It’s recommended that you don’t put too much logic in these ERB statements to keep your configuration files readable and maintainable. If you have a complex piece of code you want to use in an ERB statement, you can create a utility in your ‘lib’ folder and define methods to use. For example, in your ‘lib’ folder create utilties.rb:

def log_path
  File.join(Cosmos::USERPATH, 'outputs', 'mylogs')
end

Now in system.txt we can use that ‘log_path’ routine after we first require ‘utilities’.

<% require 'utilities' %>
...
# Paths
PATH LOGS <%= log_path() %>
...

Notice how the first ERB statement does NOT use the %= syntax since I’m simply requiring the file I want to use. I don’t want to put anything in the template itself. Later in the PATH statement I use the %= syntax to insert the result of the log_path() method.

ERB templates are particularly useful in command and telemetry definitions as they allow you to reuse sections. We’ve added our own routine called ‘render’ (similar to Ruby on Rails) which can render a command or telemetry template. The best example of this is in the COSMOS Demo INST target. If you open the inst_cmds.txt file you’ll see this:

COMMAND INST COLLECT BIG_ENDIAN "Starts a collect on the instrument"
  <%= render "_ccsds_cmd.txt", locals: {id: 1} %>
  PARAMETER    TYPE           64  16  UINT MIN MAX 0 "Collect type"
    REQUIRED
    STATE NORMAL  0
    STATE SPECIAL 1 HAZARDOUS
  PARAMETER    DURATION       80  32  FLOAT 0.0 10.0 1.0 "Collect duration"
  PARAMETER    OPCODE        112   8  UINT 0x0 0xFF 0xAB "Collect opcode"
    FORMAT_STRING "0x%0X"
  PARAMETER    TEMP          120  32  FLOAT 0.0 25.0 0.0 "Collect temperature"
    UNITS Celsius C

COMMAND INST ABORT BIG_ENDIAN "Aborts a collect on the instrument"
  <%= render "_ccsds_cmd.txt", locals: {id: 2} %>

...

Notice the call to <%= render "_ccsds_cmd.txt", locals: {id: 1} %>. Opening the ‘_ccsds_cmd.txt’ file reveals this command template:

  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 999 "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"
    OVERFLOW TRUNCATE
  PARAMETER    CCSDSLENGTH    32  16  UINT MIN MAX 12 "CCSDS primary header packet length"
  ID_PARAMETER PKTID          48  16  UINT MIN MAX <%= id %> "Packet id"

The call to render replaces everything in the named template with the render call. We follow the Ruby on Rails convention of naming these templates (Rails calls them ‘partials’) with a leading underscore to differentiate them from full command and telemetry definitions. Notice too that we are passing local variables to the template. The ‘id: 1’ syntax is basically setting the ‘id’ variable in the template to 1. This allows us to send a different PKTID to each command.

ERB is incredibly powerful and a great way to avoid WET (Write Each Time) command and telemetry definitions. Now go DRY (Don’t Repeat Yourself) up your COSMOS configuration!

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Custom Widgets

Sometimes we receive requests to make custom COSMOS widgets or to modify existing COSMOS widgets to add certain looks or functionality. While this is a project we’re happy to perform for our customers, it’s also something that can be done by end users willing to dig into some of the Qt and COSMOS documentation. In this post, I’m going to describe how to create a custom COSMOS widget.

When asked to perform customizations like this I first bring up the COSMOS Demo. We try to include all the COSMOS features in the Demo so end users have concrete examples to follow instead of relying solely on the excellent documentation at cosmosc2.com. Obviously you must first have COSMOS installed so follow the installation instructions and then launch the Demo by running the Launcher in the Demo folder. Here is how the server appears on my Windows machine:

COSMOS Demo Server

I’m going to create a custom widget in the INST target to display some of the Array data in a table. If you first launch the Telemetry Viewer and open the INST ARRAY screen you should see the following:

COSMOS Inst Array

This screen is already using the Array widget to display this data in a text box. We will add our new widget to the top of the screen which will display the data in a table. Let’s add the line to the screen which will call our new widget. Edit demo/config/targets/INST/screens/array.txt and add the following line in the middle:

...
TITLE "Instrument Array Data"
DEMOTABLE INST HEALTH_STATUS ARY
ARRAY INST HEALTH_STATUS ARY 300 50 nil 8 FORMATTED
...

Now we need to create the DemotableWidget which will implement the actual display. Create a new file called demotable_widget.rb in demo/config/targets/INST/lib. Note that the name of the line in the config file, DEMOTABLE, must be all lowercase followed by an underscore and ‘widget’. The class name in the file must be one word with the first letter and Widget capitalized. This is how it should start:

require 'cosmos/tools/tlm_viewer/widgets/widget'

module Cosmos
  class DemotableWidget < Qt::TableWidget
  include Widget
    def initialize(parent_layout, target_name, packet_name, item_name, value_type = :WITH_UNITS)
      super(target_name, packet_name, item_name, value_type)
    end
  end
end

We’re extending the closest widget that Qt offers to what we’re trying to achieve. In this case it’s pretty obvious but you can get documentation on all the Qt classes. In many cases it might be easier to extend an existing COSMOS widget.

Note that our initialize method takes the parent_layout as the first value. All COSMOS widgets make the first parameter the parent_layout so they can be added. The next four paramaters are typically the target_name, packet_name, item_name and value_type. Additional parameters can follow the value_type parameter. The first thing we do in the initialize method is call super which calls the Widget initialize method. If you run this code you should see that the screen displays but doesn’t look any different. That’s because we haven’t actually added our new widget to the parent_layout. Before adding widgets to the layout you typically want to configure them. For our table, we need to set the number of rows and columns. First I grab the telemetry value from the server using the System.telemetry.value method defined in telemetry.rb. Since this is an array value I call length to determine how many rows to display in the table. I then use the Qt methods setRowCount and setColumnCount to initialize the table. You can find these methods in the Qt::TableWidget documentation. Finally I call the addWidget method which is a part of all the Qt::Layout classes.

def initialize(parent_layout, target_name, packet_name, item_name, value_type = :WITH_UNITS)
  super(target_name, packet_name, item_name, value_type)
  value = System.telemetry.value(target_name, packet_name, item_name) # Get the value
  @rows = value.length # Store the rows
  setRowCount(@rows)
  setColumnCount(1)
  parent_layout.addWidget(self) if parent_layout
end

Now if you stop and restart the Telemetry Viewer (so it can re-require the new widget code) it should display an empty table:

COSMOS Inst Array

To actually populate it with data we must follow the Cosmos Widget conventions. First of all by including Widget you include all the Widget code which creates two key class methods: layout_manager? and takes_value?. These must be overridden to return true if your widget is either a layout or takes a value respectively. Since our widget will be taking the array data as a value we must override takes_value?:

require 'cosmos/tools/tlm_viewer/widgets/widget'

module Cosmos
  class DemotableWidget < Qt::TableWidget
  include Widget
    def self.takes_value?
      return true
    end
  end
end

Typically class methods are defined at the top of the source file and begin with self. You can also type out the class name but this is less robust as changing the class name requires changing the method name. Implementing this class method allows Telemetry Viewer to call the value=(data) method with new telemetry data. The value method implementation should look like this:

def value=(data)
  (0...@rows).each do |row| # Note the extra 'dot' which means up to but not including
    setItem(row, 0, Qt::TableWidgetItem.new(data[row].to_s))
  end
end

The data value passed to the method is the same target, packet, and item used in the screen definition. In our value= method we are using our stored instance variable @rows to index into the array data and create new Qt::TableWidgetItem instances to store the data. TableWidgetItems expect Strings to be passed so I call to_s on the data item to ensure it is a String. If you now re-launch Telemetry Viewer you should see the values populated in the table:

COSMOS Inst Array

At this point you could be done. But wait! The Array widget below the table fades darker to implement “aging”, showing the user the values haven’t changed. How do we implement “aging” in our new widget? To start we require the aging_widget and include the AgingWidget module. Then we must call the setup_aging method in our initialize method as well as redefine the process_settings method:

require 'cosmos/tools/tlm_viewer/widgets/widget'
require 'cosmos/tools/tlm_viewer/widgets/aging_widget'

module Cosmos
  class DemotableWidget < Qt::TableWidget
    include Widget
    include AgingWidget

    def initialize(parent_layout, target_name, packet_name, item_name, value_type = :WITH_UNITS)
      super(target_name, packet_name, item_name, value_type)
      setup_aging()
      value = System.telemetry.value(target_name, packet_name, item_name) # Get the value
      @rows = value.length # Store the rows
      setRowCount(@rows)
      setColumnCount(1)
      parent_layout.addWidget(self) if parent_layout
    end

    def process_settings
      super
      process_aging_settings
    end
  end
end

Note that we were able to remove the class method self.takes_value? because AgingWidget already implements it. This is all required to setup aging but we must still modify the value= method to do the work. First in value= we call super to call the AgingWidget’s value= method. This method returns a string representation of the data with the correct foreground color and text character indicating the color, e.g. G=Green, Y=Yellow, R=Red. This is important for values with limits settings but since our array value doesn’t have limits I’m going to igore the return value and simply allow the aging routine to age the data. Interally this updates the @background instance variable with the current ‘aged’ background color. I then set the TableWidgetItem’s background color to this color before adding it to the table:

def value=(data)
  super(data)
  (0...@rows).each do |row|
    item = Qt::TableWidgetItem.new(data[row])
    item.setBackgroundColor(@background)
    setItem(row, 0, item)
  end
end

The end result is aging:

COSMOS Inst Array

Note that if you have a widget that implements aging and limits you’ll want to keep the value returned by super and use it in your widget. If you don’t want the aging routine to directly use your data value you can pass a string as the second parameter, e.g. super(data, text). This text string will be modified with the color blind settings. Basically that means that whatever the calculated @foreground color string is, a corresponding text character is added (R=Red, G=Green, etc) to aid people who can’t distinguish colors. See aging_widget.rb for more details.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Custom COSMOS Interface

Interfaces were changed dramatically in COSMOS 4.0.0

This article only applies to pre-4.0.0 COSMOS releases. For current COSMOS releases please see the new Interface and Protocol documentation.

One of our Ball Aerospace engineers asked how they could add a checksum to an existing COSMOS interface when talking to their target. COSMOS does not support this directly so it requires creating a custom interface. While this might sound daunting, the COSMOS interfaces were designed just for this type of extension and provide hooks for customization.

In this example we will assume the original interface is the COSMOS Serial Interface. In your target’s lib folder create a new interface called checksum_serial_interface.rb:

require 'cosmos' # always require cosmos
require 'cosmos/interfaces/serial_interface' # original interface being extended

module Cosmos
  class ChecksumSerialInterface < SerialInterface
    def pre_write_packet(packet)
      data = packet.buffer
      checksum = 0xFFFF
      data.each_byte {|x| checksum += x }
      checksum &= 0xFFFF
      data << [checksum].pack("n") # Pack as 16 bit unsigned bit endian
      return data
    end

    def post_read_data(packet_data)
      len = packet_data.length
      calc_checksum = 0xFFFF
      packet_data[0..(len - 3)].each_byte {|x| calc_checksum += x }
      calc_checksum &= 0xFFFF
      rx_checksum = packet_data[-2..-1].unpack("n") # Unpack as 16 bit unsigned big endian
      if calc_checksum == rx_checksum
        return packet_data
      else
        puts "Bad checksum detected. Calculated: 0x#{calc_checksum.to_s(16)} Received: 0x#{rx_checksum.to_s(16)}. Dropping packet."
        return "" # Also can return nil to break the connection and reconnect to the target
      end
    end
  end
end

What we’re doing is overriding pre_write_packet in StreamInterface to allow us to modify the data before it is written to the packet and sent over the interface. We also override post_read_data to operate on data received before it is sent back to the COSMOS server and thus the tools. Note there is also a post_read_packet(packet) method which is called after post_read_data is called and after the COSMOS Packet has been created. All Interfaces inheriting from StreamInterface includes these callback methods, including SerialInterface, TcpipServerInterface, and TcpipClientInterface. Note that UdpInterface inherits directly from Interface and thus does NOT include these callbacks.

Then in your cmd_tlm_server.txt file for your target you use your new interface:

#         interface name  file name                    write read baud   parity stop timeouts stream
INTERFACE UART_INTERFACE  checksum_serial_interface.rb COM1  COM1 115200 NONE   1    nil nil  BURST

I added a comment line above the definition which describes the settings. For more information see the Serial Interface documentation.

This same technique can obviously be used to extend the the other TCPIP interfaces and can be used with all the various Streams COSMOS defines.

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

COSMOS Cmd/Tlm Naming

Recently a user asked if they could add exclamation points and question marks to their command and telemetry items. Absolutely! COSMOS provides great flexibility in command and telemetry naming conventions. (See Command). For example, adding an exclamation point to a command to denote a more severe version of the same command:

COMMAND TGT ABORT BIG_ENDIAN "Tries to abort a collect on the instrument"
COMMAND TGT ABORT! BIG_ENDIAN "Force aborts a collect on the instrument"

While it doesn’t make sense to define a command with a question mark, it works well with telemetry points. For example, there is a telemetry point which indicates whether a mechanism is deployed or not. It is an analog value that indicates deployed if the value is above zero. To view both the raw value and the deployed status, define a derived telemetry point which indicates a TRUE or FALSE status:

APPEND_ITEM DEPLOYED 16 UINT "Deployed raw value"
ITEM DEPLOYED? 0 0 DERIVED "Deployed status"
  STATE FALSE 0
  STATE TRUE 1
  GENERIC_READ_CONVERSION_START UINT 8
    myself.read('DEPLOYED') > 0 ? 1 : 0
  GENERIC_READ_CONVERSION_END

Note that this is probably overkill in this case because the conversion could just as easily be applied directly to the item. The raw value could then be obtained by calling tlm_raw(“TGT PKT DEPLOYED”) (see tlm_raw).

These practices are similar to the Ruby convention of using methods with an exclamation point (bang) to indicate a dangerous method which typically directly modifies its caller. Ruby also has a convention of methods with question marks returning a boolean true or false value. Read more in the Ruby documentation.

Ball Aerospace COSMOS 3.8.2 Released

New Features:

Maintenance:

  • COSMOS Downloads graph rake task updates

Bug Fixes:

  • #303 Need to clear read conversion cache on Packet#clone
  • #304 Win32 Serial Driver clean disconnect
  • #309 Fix Script Runner insert_return when not running

Migration Notes from COSMOS 3.7.x:

None

Ball Aerospace COSMOS 3.8.1 Released

New Features:

  • #184 Limits Monitor show green for blue limits items
  • #190 Simpler MIN MAX syntax for command definitions
  • #254 Get buffer from commands
  • #259 Proper support for user selected text editor on linux
  • #262 PackerViewer option for listing derived items last
  • #271 Time.formatted option for no microseconds
  • #288 check_tolerance should enforce a positive tolerance
  • #301 Update use of COSMOS_DEVEL

Maintenance:

  • #268 xtce_converter doesn’t support byte order list
  • #277 Test Runner support for Script Runner options
  • #285 xtce converter doesn’t support LocationInContainerInBits

Bug Fixes:

  • #256 Defining initialize method in Cosmos::Test class breaks the class when using Test Selection in TestRunner
  • #273 Wrap Qt::Application.instance in main_thread
  • #287 Installer issue on newer versions of Ubuntu and Debian related to libssl
  • #293 Units applied after a read_conversion that returns a string modifies cached conversion value
  • #294 String#convert_to_value should always just return the starting string if the conversion fails
  • #298 COSMOS IoMultiplexer breaks gems that invoke stream operator on STDOUT/ERR

Migration Notes from COSMOS 3.7.x:

None

Sparkfun Blog Post

Ball Aerospace COSMOS has been featured in a blog post on SparkFun. SparkFun is an online retail store that sells electronics primarily for hobbyists. Ball recently purchased a Raspberry Pi, Arduino, and various other parts to interface to COSMOS. We think hobbyists will find COSMOS a great way to interface to their embedded projects and SparkFun agrees! Get started with COSMOS now!

A Ball engineer wrote a Wiki on how he configured COSMOS to talk to his Arduino Uno. It’s a little old but it gives a nice step by step tutorial on how to use COSMOS with an Arduino.

XTCE Support

Ball Aerospace COSMOS now has support for the XTCE Command and Telemetry Definition Standard. This is an open standard designed to allow command and telemetry definitions to be transferred between different ground systems. COSMOS can run directly using the .xtce files, or can convert them into the COSMOS configuration file format.

See the docs for more information: XTCE Support

Fukuoka Special Award Winner

Ball Aerospace COSMOS has been honored by the Ruby community by receiving one of the three Fukuoka Special Awards handed out this year! This is a great honor with the contest judging being led by Matz himself (the creator of the Ruby programming language).

Ball Aerospace COSMOS 3.8.0 Released

With this release COSMOS now has initial support for the XTCE Command and Telemetry Definition standard.

New Features:

  • #251 Create COSMOS XTCE Converter
  • #252 Add polling rate command line option to PacketViewer

Bug Fixes:

  • #245 TlmGrapher Crashes on Inf
  • #248 Can’t script commands containing ‘with’ in the name

Migration Notes from COSMOS 3.7.x:

None

COSMOS Simulated Target

Creating a COSMOS Simulated Target

Sometimes you have a need to create a simulated target in COSMOS. This simulated target is not a physical target producing data and accepting commands but a software target which generates data and sends it to COSMOS. This is exactly how the COSMOS Demo operates within the INST target that it creates. While this is a very full featured example its complexity can be a little overwhelming. In this post I’m going to break down a much simpler simulated target so you can create your own.

First of all create a new COSMOS target directory in config/targets. I called mine INST (instrument) to match the COSMOS demo. Create the ‘cmd_tlm’ and ‘lib’ subdirectories. For my demo I created a simple ‘cmd.txt’ file which contains a single command:

COMMAND INST SET_STATUS BIG_ENDIAN "Set status"
  APPEND_PARAMETER STATUS 0 STRING "STATUS" "Status"
    STATE "OK" "OK"
    STATE "ERROR" "ERROR"

I created a ‘tlm.txt’ file which contains two different telemetry packets:

TELEMETRY INST STATUS BIG_ENDIAN "Status from the instrument"
  APPEND_ID_ITEM ID 16 UINT 1 "Packet ID"
  APPEND_ITEM COUNTER 16 UINT "Packet counter"
  APPEND_ITEM STATUS 0 STRING "Most recent ASCIICMD string"
    STATE "OK" "OK"
    STATE "ERROR" "ERROR"

TELEMETRY INST DATA BIG_ENDIAN "Data from the instrument"
  APPEND_ID_ITEM ID 16 UINT 2 "Packet ID"
  APPEND_ITEM COUNTER 16 UINT "Packet counter"
  APPEND_ITEM TIMESEC 32 UINT "Seconds since epoch (January 1st, 1970, midnight)"
  APPEND_ITEM TIMEUS  32 UINT "Microseconds of second"
  APPEND_ITEM TEMP1 32 INT "Temperature #1"
    UNITS CELSIUS C
    FORMAT_STRING "%0.3f"
    LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0

The cmd_tlm_server.txt file is very simple:

INTERFACE INST_INT simulated_target_interface.rb sim_inst.rb
  TARGET INST

The real work is in implementing how your simulated target is going to behave. This is done in the lib/sim_inst.rb file. Note that whatever you name your simulated target file must match the last parameter of the INTERFACE in the cmd_tlm_server.rb as shown above.

I’ll break down my sim_inst.rb piece by piece and then list it in its entirety. First you must inherit from the Cosmos::SimulatedTarget.

require 'cosmos'
module Cosmos
  class SimInst < SimulatedTarget

Next you can initialize any of your packets in the initialize method. This is entirely optional but I show how to use the @tlm_packets hash to access all the defined packets. This hash is created automatically by the SimulatedTarget based on all the packets you have defined in your cmd_tlm/tlm.txt file. Note that there is NOT a corresponding @cmd_packets.

def initialize(target_name)
  super(target_name)

  # We grab the STATUS packet to set initial values
  packet = @tlm_packets['STATUS']
  packet.enable_method_missing # required to use packet.<item> = value
  packet.status = "NONE"
end

We then have to configure the telemetry packet rates of our target. That is, how fast do the packets get sent out. This is handled by implementing the set_rates method and by calling set_rate for each packet defined in your system. If you do not call set_rate the packet will not be send out periodically (which may be desirable for event based packets).

def set_rates
  # The SimulatedTarget operates on a 101Hz clock
  # Thus the rates are determined by dividing this rate
  # by the set rate to get the output rate of the packet
  set_rate('STATUS', 100) # 100 / 100 = 1Hz
  set_rate('DATA', 10) # 100 / 10 = 10Hz
end

If your target will accept command you need to implemented the write(packet) method. My write method is simple in that I only have a single command that directly sets a value in one of my telemetry packets.

def write(packet)
  # We directly set the telemetry value from the only command
  # If you have more than one command you'll need to switch
  # on the packet.packet_name to determine what command it is
  @tlm_packets['STATUS'].status = packet.read("status")
end

Your target must implement the read(count_100hz, time) method to return telemetry packets back to COSMOS. You’ll call the get_pending_packets(count_100hz) method implemented by SimulatedTarget and then perform whatever operations you want on the packets before returning the array of packets back to COSMOS. Note my use of the cycle_tlm_item method to automatically cycle the telemetry item as each packet is sent out. This is used heavily in the COSMOS Demo.

def read(count_100hz, time)
  # The SimulatedTarget implements get_pending_packets to return
  # packets at the correct time interval based on their rates
  pending_packets = get_pending_packets(count_100hz)

  pending_packets.each do |packet|
    case packet.packet_name
    when 'STATUS'
      packet.counter += 1
    when 'DATA'
      # This method in SimulatedTarget cycles the specified telemetry
      # point between the two given values by the given increment for
      # each packet sent out.
      cycle_tlm_item(packet, 'temp1', -95.0, 95.0, 1.0)

      packet.timesec = time.tv_sec
      packet.timeus  = time.tv_usec
      packet.counter += 1
    end
  end
  pending_packets
end

Hopefully that a little easier to understand than the full COSMOS Demo which has much more complex command and telemetry definitions and simulated targets in order to better exercise the various COSMOS tools. While there are other ways to simulate COSMOS targets they can get you into trouble if you’re not careful about properly cloning packets sending back updated data. Additionally, using the SimulatedTargetInterface in your Interface makes it very clear to other developers that this target is indeed simulated.

Without further ado, here is my sim_inst.rb in its entirety:

require 'cosmos'
module Cosmos
  class SimInst < SimulatedTarget
    def initialize(target_name)
      super(target_name)

      # We grab the STATUS packet to set initial values
      packet = @tlm_packets['STATUS']
      packet.enable_method_missing # required to use packet.<item> = value
      packet.status = "NONE"
    end

    def set_rates
      # The SimulatedTarget operates on a 100Hz clock
      # Thus the rates are determined by dividing this rate
      # by the set rate to get the output rate of the packet
      set_rate('STATUS', 100) # 100 / 100 = 1Hz
      set_rate('DATA', 10) # 100 / 10 = 10Hz
    end

    def write(packet)
      # We directly set the telemetry value from the only command
      # If you have more than one command you'll need to switch
      # on the packet.packet_name to determine what command it is
      @tlm_packets['STATUS'].status = packet.read("status")
    end

    def read(count_100hz, time)
      # The SimulatedTarget implements get_pending_packets to return
      # packets at the correct time interval based on their rates
      pending_packets = get_pending_packets(count_100hz)

      pending_packets.each do |packet|
        case packet.packet_name
        when 'STATUS'
          packet.counter += 1
        when 'DATA'
          # This method in SimulatedTarget cycles the specified telemetry
          # point between the two given values by the given increment for
          # each packet sent out.
          cycle_tlm_item(packet, 'temp1', -95.0, 95.0, 1.0)

          packet.timesec = time.tv_sec
          packet.timeus  = time.tv_usec
          packet.counter += 1
        end
      end
      pending_packets
    end
  end
end

Happy simulated target programming!

If you have a question which would benefit the community or find a possible bug please use our Github Issues.

Ball Aerospace COSMOS 3.7.1 Released

Bug Fixes:

  • #228 Fix typo in udp_interface
  • #231 MACRO_APPEND with multiple items not working
  • #235 Improve IntegerChooser and FloatChooser Validation
  • #236 TestRunner doesn’t support status_bar
  • #240 Make sure super() is called in all bundled conversion classes
  • #241 Don’t reformat BLOCK data types with a conversion in Structure#formatted

Migration Notes from COSMOS 3.6.x:

  1. Background task arguments are now broken out instead of being received as a single array
  2. udp_interface now takes an optional argument for bind_address
  3. line_graph_script has been significantly updated to support modifying plots from the script.

Ball Aerospace COSMOS 3.7.0 Released

New Features:

  • #213 Vertical Limits Bar
  • #214 TlmGrapher show full date for plotted points
  • #219 State Color Widget
  • #225 Set Bind Address in UDP interface

Maintenance:

  • #223 C Extension Improvements

Bug Fixes:

  • #199 Investigate TlmGrapher Formatted Time Item
  • #211 Background task with arguments not working
  • #217 Graph Right Margin Too Small

Migration Notes from COSMOS 3.6.x:

  1. Background task arguments are now broken out instead of being received as a single array
  2. udp_interface now takes an optional argument for bind_address
  3. line_graph_script has been significantly updated to support modifying plots from the script.

Ball Aerospace COSMOS 3.6.3 Released

New Features:

  • #200 ScriptRunner Find Dialog Does Not Cross Windows
  • #201 Table Manager to support arbitrary inputs on State Fields
  • #209 Add UTS Timestamp Flag to TlmGrapher Plots

Maintenance:

  • #194 Allow up to one minute for TlmViewer to start when calling display() from a script
  • #203 load_utility should raise LoadError like load and require
  • #205 Add testing for array and matrix

Bug Fixes:

  • #191 Installing COSMOS Issue on Windows 7
  • #193 Fix ask() on linux and qt 4.6.2
  • #197 Improve linc interface

Migration Notes from COSMOS 3.5.x:

None

Ball Aerospace COSMOS 3.6.2 Released

Huge new feature in this release: All COSMOS configuration files are now interpreted with the ERB preprocessor! This allows you to use Ruby code within the configuration files to help build them. You can also render partials of common information such as packet headers so you only have to define them once. See the INST target in the updated Demo project for examples.

Bug Fixes:

  • #187 Must require tempfile in config_parser.rb on non-windows systems

Migration Notes from COSMOS 3.5.x:

None

Ball Aerospace COSMOS 3.6.0 Released

Huge new feature in this release: All COSMOS configuration files are now interpreted with the ERB preprocessor! This allows you to use Ruby code within the configuration files to help build them. You can also render partials of common information such as packet headers so you only have to define them once. See the INST target in the updated Demo project for examples.

Bug Fixes:

  • #168 Select unreliably unblocks when closing sockets on linux
  • #177 MACRO_APPEND in descending order is broken
  • #179 ScriptRunnerFrame Context Menu Crash
  • #182 Overriding LOG_WRITERS in cmd_tlm_server.txt can cause issues

New Features:

  • #170 Consider supporting a preprocessor over COSMOS config files
  • #171 Script Runner should have file open and save GUI dialogs
  • #174 Add View in Command Sender in Server

Maintenance:

  • #80 Investigate performance of nonblocking IO without exceptions

Migration Notes from COSMOS 3.5.x:

None

Ball Aerospace COSMOS 3.5.3 Released

Bug Fixes:

  • #169 Make windows bat files support running outside of the current directory

New Features:

  • N/A

Maintenance:

  • N/A

Migration Notes from COSMOS 3.4.2:

The launcher scripts and .bat files that live in the COSMOS project tools folder have been updated to be easier to maintain and to ensure that the user always sees some sort of error message if a problem occurs starting a tool. All users should copy the new files from the tools folder in the COSMOS demo folder into their projects as part of the upgrade to COSMOS 3.5.1

COSMOS now disables reverse DNS lookups by default because they can take a long time in some environments. If you still want to see hostnames when someone connects to a TCP/IP server interface/router then you will need to add ENABLE_DNS to your system.txt file.

Ball Aerospace COSMOS 3.5.2 Released

Bug Fixes:

  • #167 Use updated url for wkhtmltopdf downloads

New Features:

  • #166 Add install script for Ubuntu

Maintenance:

  • N/A

Migration Notes from COSMOS 3.4.2:

The launcher scripts and .bat files that live in the COSMOS project tools folder have been updated to be easier to maintain and to ensure that the user always sees some sort of error message if a problem occurs starting a tool. All users should copy the new files from the tools folder in the COSMOS demo folder into their projects as part of the upgrade to COSMOS 3.5.1

COSMOS now disables reverse DNS lookups by default because they can take a long time in some environments. If you still want to see hostnames when someone connects to a TCP/IP server interface/router then you will need to add ENABLE_DNS to your system.txt file.

Ball Aerospace COSMOS 3.5.1 Released

This release fixes a bug and completes the installation scripts for linux/mac.

Bug Fixes:

  • #165 Change launch_tool to tool_launch in Launcher

New Features:

  • N/A

Maintenance:

  • #102 Create Installation Scripts

Migration Notes from COSMOS 3.4.2:

The launcher scripts and .bat files that live in the COSMOS project tools folder have been updated to be easier to maintain and to ensure that the user always sees some sort of error message if a problem occurs starting a tool. All users should copy the new files from the tools folder in the COSMOS demo folder into their projects as part of the upgrade to COSMOS 3.5.1

COSMOS now disables reverse DNS lookups by default because they can take a long time in some environments. If you still want to see hostnames when someone connects to a TCP/IP server interface/router then you will need to add ENABLE_DNS to your system.txt file.

Ball Aerospace COSMOS 3.5.0 Released

This release contains a lot of new functionality and a key new feature: The ability to create new COSMOS targets and tools as reusable gems! This will hopefully allow the open source community to create sharable configuration for a large amount of hardware and allow for community generated tools to be easily integrated.

Bug Fixes:

  • #153 set_tlm should support settings strings with spaces using the normal syntax
  • #155 Default to not performing DNS lookups

New Features:

  • #25 Warn users if reading a packet log uses the latest instead of the version specified in the file header
  • #106 Allow the server to run headless
  • #109 Cmd value api
  • #129 Script Runner doesn’t syntax highlight module namespacing
  • #133 Add sound to COSMOS alerts
  • #138 Limits Monitor should show what is stale
  • #142 Support gem based targets and tools
  • #144 Never have nothing happen when trying to launch a tool
  • #152 Provide a method to retrieve current suite/group/case in TestRunner
  • #157 Launcher support command line options in combobox
  • #163 Allow message_box to display buttons vertically

Maintenance:

  • #131 Consolidate Find/Replace logic in the FindReplaceDialog
  • #137 Improve Server message log performance
  • #142 Improve Windows Installer bat file
  • #146 Need support for additional non-standard serial baud rates
  • #150 Improve Win32 serial driver performance

Migration Notes from COSMOS 3.4.2:

The launcher scripts and .bat files that live in the COSMOS project tools folder have been updated to be easier to maintain and to ensure that the user always sees some sort of error message if a problem occurs starting a tool. All users should copy the new files from the tools folder in the COSMOS demo folder into their projects as part of the upgrade to COSMOS 3.5.0

COSMOS now disables reverse DNS lookups by default because they can take a long time in some environments. If you still want to see hostnames when someone connects to a TCP/IP server interface/router then you will need to add ENABLE_DNS to your system.txt file.

Ball Aerospace COSMOS 3.4.2 Released

Issues:

  • #123 TestRunner command line option to launch a test automatically
  • #125 Fix COSMOS issues for qtbindings 4.8.6.2
  • #126 COSMOS GUI Chooser updates

Migration Notes from COSMOS 3.3.x or 3.4.x:

COSMOS 3.4.2 requires qtbindings 4.8.6.2. You must also update qtbindings when installing this release. Also note that earlier versions of COSMOS will not work with qtbindings 4.8.6.2. All users are strongly recommended to update both gems.

Ball Aerospace COSMOS 3.4.1 Released

Issues:

  • #121 BinaryAccessor write crashes with negative bit sizes

Migration Notes from COSMOS 3.3.x:

None

Note: COSMOS 3.4.0 has a serious regression when writing to variably sized packets. Please upgrade to 3.4.1 immediately if you are using 3.4.0.

Ball Aerospace COSMOS 3.4.0 Released

Issues:

  • #23 Handbook Creator User’s Guide Mode
  • #72 Refactor binary_accessor
  • #101 Support Ruby 2.2 and 64-bit Ruby on Windows
  • #104 CmdTlmServer Loading Tmp & SVN Conflict Files
  • #107 Remove truthy and falsey from specs
  • #110 Optimize TlmGrapher
  • #111 Protect Interface Thread Stop from AutoReconnect
  • #114 Refactor Cosmos::Script module
  • #118 Allow PacketViewer to hide ignored items

Migration Notes from COSMOS 3.3.x:

None

COSMOS BinaryAccessor#write C Extension

How I created a COSMOS C Extension

The COSMOS framework has several C extensions created to increase performance. One critical piece that was created early on is the extension to the BinaryAccessor class. This allows for increased performance when reading items from binary packets which is the most common operation in the COSMOS system. I created a COSMOS performance configuration which spawns 30 fake targets and attempts to send commands to them as fast as possible. Sending commands exercies the write portion of BinaryAccessor and profiling showed this was now becoming a bottleneck. Therefore I set out to port the write method to the existing C extension.

The fact that Ryan had already implemented the read method as a C extension gave me a huge head start. I first copied all the Ruby code directly into the C extension so I could try to translate it line by line. Initially if I didn’t know how to do the translation I would just comment it out and see how much I could compile. A nice way to do this in C code is use #if 0 ... #endif. I also copied the read method signature and locals since the methods are similar. Before I get to far into the guts I should note that this effort relied on a very comprehensive spec or I would have had no idea if I was successful.

Once I implemented the initial parameter checking I dove into the String and Block (binary string) handling portion of the write method. The write method modifies the given buffer by writing a String or Block into it. I started with Google and found Chris Lalancette’s post and this excellent write-up on The Ruby C API. I also cloned ruby itself and went directly to the code. I found the code a little difficult to follow but the important thing to remember is if the method is NOT delcared static then you can use it in your C extension. I ended up using rb_str_concat to add to the buffer and rb_str_update to directly modify the buffer.

Modifying Ruby strings

If you directly modify the Ruby string buffer in a C extension with memcpy, memmove, or memset (after getting a pointer with RSTRING_PTR), you need to tell the Ruby runtime with the rb_str_modify method. Calling Ruby's methods like rb_str_update automatically handles this for you.

Another issue I ran into was the existing Ruby code was calling to_s on the input value to ensure it was a String. In the C extension you can check for a type using RB_TYPE_P(value, T_STRING) where value is a unknown Ruby VALUE instance and T_STRING can be any number of Ruby types. If the value was not a Ruby String I used rb_funcall to directly call the Ruby runtime and call the to_s method. If you are unable to find an appropriate method in the C library to do what you want, this is the way to use Ruby from within your C extension.

Next I started to tackle the writing of signed and unsigned integers. COSMOS supports overflow of integers by either truncating a passed in value, saturating to the high or low, or raising an error. So I implemented a check_overflow method in C to handle this logic. This code was very difficult to get right because of the size of the values involved. Since COSMOS handles integers of any size, I had to create Ruby Bignum constants to perform the comparisons. This involved another dive into the Ruby source to understand bignum.c. One of the tricks was to create Ruby Constants up front in the Initialization routine so I wasn’t constantly recalulating Bignums for comparison. COSMOS also handles bitfields so those values I generate dynamically using rb_big_pow and rb_bit_minus. I also created a TO_BIGNUM macro which converts Fixnum to Bignum so all the math uses Bignum methods. I could then use the rb_big_cmp to compare the given value with the appropriate minimum and maximum values.

The bitfield logic was the most complex to convert to C. This required a lot of C printfs and Ruby puts at each step of the way to ensure all the intermediary calculations were matching up. COSMOS supports big and little endian data buffers so I had to ensure the bytes were reversed and shifted as necessary before finally writing them back to the buffer. Again the rb_str_modify function is called to notify the Ruby runtime that the buffer has been changed.

The floating point values were probably the easiest because I simply called RFLOAT_VALUE(value) to get the double value of the passed in Ruby value. At this point I was able to successfully run the full spec. However, once I ran the entire COSMOS spec suite I hit a failure on a simple write call in api_spec.rb. I determined the spec was trying to send an integer value where there was a floating point value defined. The old Ruby code simply converted this value inline but I was calling RFLOAT_VALUE(value) which ASSUMES the value is a float. I updated the binary_accessor_spec.rb to capture this failure and also noted a similar issue in the integer logic. The Ruby code was calling value = Integer(value) for integers and value = Float(value) for floats. This not only handles the case of passing an integer value when you want to write a float, it also handles truncating a float to an integer and even handles parsing a String which contains a numeric value. When you have a tremendous amount of work being done by Ruby you are best to fall back to rb_funcall. But how to call the Integer() method which doesn’t appear to have a receiver. Remember that if a method doesn’t appear to have a receiver it’s probably being called on Kernel which is exactly the case. Thus I call it with value = rb_funcall(rb_mKernel, rb_intern("Float"), 1, value);. (Note: I also discovered I could call the method passing ‘self’ instead of rb_mKernel but using Kernel felt more explicit).

At this point I refactored to combine some of the functionality in the read method with the new write method. I probably could have done more refactoring but refactoring C code just isn’t as much fun as refactoring Ruby code. Once I completed the refactor I wanted to benchmark my new C extension to determine how much faster (or slower?) I made it. I love the benchmark-ips gem as it benchmarks iterations per second and automatically determines how many times to run the code to get good data. But I didn’t want to re-write our existing specs to support using this gem so I looked into how to integrate it with RSpec. It turns out this is all that was needed in our spec_helper.rb:

if ENV.key?("BENCHMARK")
  c.around(:each) do |example|
    Benchmark.ips do |x|
      x.report(example.metadata[:full_description]) do
        example.run
      end
    end
  end
end

Benchmark-ips works by calculating the number of runs to get interesting data and then running the code in question. Thus defining BENCHMARK in the environment makes the specs run EXTREMELY slow. I used the ability of RSpec to filter only the examples I wanted to benchmark with the -e option:

rspec spec/packets/binary_accesor_spec.rb -e "write only"

Running this in master and then in my C-extension branch I calculated the difference in iterations and then filtered out all the “complains” (raise an exception) and “overflow” test cases to focus on just the tests which write values. The average improvement was 1.3x. Not quite as awesome as I was hoping for but an improvement in an area that is performance sensitive. I suspected I could get additional performance if I optimized the check_overflow method to not always use Bignums and to do Fixnum comparisons if possible. However, this did not yield any optimizations so I backed out the change.

At this point I submitted the pull request which broke the Travis build. Ryan then added a patch that corrected all my issues and the build passed. I re-benchmarked his changes and overall the results were actually slightly faster on average so the pull request was merged.

Enjoy a faster COSMOS write routine!

Ball Aerospace COSMOS 3.3.3 Released

Issues:

  • #93 Derived items that return arrays are not formatted to strings bug
  • #94 JsonDRb retry if first attempt hits a closed socket bug
  • #96 Make max lines written to output a variable in ScriptRunnerFrame enhancement
  • #99 Increase Block Count in DataViewer

Migration Notes from COSMOS 3.2.x:

System.telemetry.target_names and System.commands.target_names no longer contain the ‘UNKNOWN’ target.

Ball Aerospace COSMOS 3.3.1 - Startup Cheetah

COSMOS first-time startup speed is now 16 times faster - hence this release is codenamed “Startup Cheetah”. Enjoy!

Issues:

  • #91 Add mutex around creation of System.instance
  • #89 Reduce maximum block count from 10000 to 100 everywhere
  • #87 MACRO doesn’t support more than one item
  • #85 Replace use of DL with Fiddle
  • #82 Improve COSMOS startup speed
  • #81 UNKNOWN target identifies all buffers before other targets have a chance
  • #78 Reduce COSMOS memory usage
  • #76 Fix specs to new expect syntax and remove ‘should’
  • #74 Server requests/sec and utilization are incorrect

Migration Notes from COSMOS 3.2.x:

System.telemetry.target_names and System.commands.target_names no longer contain the ‘UNKNOWN’ target.

Ball Aerospace COSMOS 3.2.1 Released

Issues:

  • #61 Don’t crash TestRunner if there is an error during require_utilities()
  • #63 Creating interfaces with the same name does not cause an error
  • #64 Launcher RUBYW substitution broken by refactor
  • #65 CmdTlmServer ensure log messages start scrolled to bottom on Linux
  • #66 Improve graceful shutdown on linux and prevent continuous exceptions from InterfaceThread
  • #70 ask() should take a default

Migration Notes from COSMOS 3.1.x:

No significant updates to existing code should be needed. The primary reason for update to 3.2.x is fixing the slow shutdown present in all of 3.1.x.

Ball Aerospace COSMOS 3.2.0 Released

Issues:

  • #34 Refactor packet_config
  • #43 Add ccsds_log_reader.rb as an example of alternative log readers
  • #45 Slow shutdown of CTS and TlmViewer with threads trying to connect
  • #46 Add mutex protection to Cosmos::MessageLog
  • #47 TlmGrapher RangeError in Overview Graph
  • #49 Make about dialog scroll
  • #55 Automatic require of stream_protocol fix and cleanup
  • #57 Add OPTION keyword to support passing arbitrary options to interfaces/routers
  • #59 Add password mode to ask and ask_string

Migration Notes from COSMOS 3.1.x:

No significant updates to existing code should be needed. The primary reason for update to 3.2.x is fixing the slow shutdown present in all of 3.1.x.

Ball Aerospace COSMOS 3.1.2 Released

Issues:

  • #20 Handbook Creator should output relative paths
  • #21 Improve code metrics
  • #26 Dynamically created file for Mac launchers should not be included in CRC calculation
  • #27 TestRunner build_test_suites destroys CustomTestSuite if underlying test procedures change
  • #28 TlmGrapher - Undefined method nan? for 0:Fixnum
  • #35 Race condition starting new binary log
  • #36 TlmDetailsDialog non-functional
  • #37 Remaining TlmGrapher regression
  • #38 Allow INTERFACE_TARGET to work with target name substitutions

Migration Notes from COSMOS 3.0.x:

The definition of limits persistence has changed. Before it only applied when changing to a bad state (yellow or red). Now persistence applies for all changes including from stale to a valid state and from bad states back to green.

Ball Aerospace COSMOS 3.1.1 Released

Issues:

  • #10 Simulated Targets Button only works on Windows
  • #11 Mac application folders not working
  • #12 Persistence should be applied even if changing from stale
  • #14 Allow information on logging page to be copied
  • #16 Ensure read conversion cache cannot be cleared mid-use
  • #17 NaNs in telemetry graph causes scaling crash

Migration Notes from COSMOS 3.0.x:

The definition of limits persistence has changed. Before it only applied when changing to a bad state (yellow or red). Now persistence applies for all changes including from stale to a valid state and from bad states back to green.

Ball Aerospace COSMOS Open Sourced

Ball Aerospace & Technologies Corp. has launched Ball Aerospace COSMOS, the company’s second open source software project.

Ball Aerospace COSMOS brings an exciting set of functionality to Operations and Integration & Test that had previously only been available in proprietary and expensive COTS solutions or not available in any commercial product. A full set of 15 applications provide features including automated test procedures, realtime and offline telemetry display and graphing, post-test analysis and CSV extraction, limits monitoring, command and telemetry handbook creation, and binary file editing.

Automated test procedures written for COSMOS offer the full power of the Ruby programming language allowing operators to send commands, verify telemetry, read and write files, access the network, and even send an email on completion. Additional features include automated test report generation, standardized meta data collection (unit serial number, operator name), and loop testing (executing the same test repeatedly to wring out timing and other issues). Advanced debugging functionality allows for single-stepping through procedures, setting breakpoints, and complete logging of all script and user interaction with the system under test.

Detailed data visualization allows for custom screen creation, line and x-y plotting of realtime data, easy creation of custom 3d visualizations, and the ability to quickly view any data provided by an embedded system. Post-test analysis and data extraction capabilities make narrowing down anomalies easy and allow for data to be quickly imported into outside data analysis systems such as Matlab.

“Ball Aerospace’s COSMOS enables an amazing amount of functionality and can provide a standard interface for interacting with anything that contains embedded software”, said Ryan Melton, COSMOS’s creator and open source evangelist. “By open sourcing this software we hope to change the whole playing field of Operations, Integration, and Test”.