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