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.