BallAerospace / COSMOS

Ball Aerospace COSMOS
https://ballaerospace.github.io/cosmos-website/
Other
360 stars 129 forks source link

Behaviour of Packet's Stored Property #1721

Closed jeffstjean closed 2 years ago

jeffstjean commented 2 years ago

I'm trying to write a protocol that processes old telemetry and replays it to COSMOS to store. From the documentation, it appears this can be done using the stored flag. #814 says the following:

If the stored flag is set it will cause the packet to not affect the CmdTlmServer Current Value Table

Does this include the packet viewer and telemetry viewer? It appears as if it doesn't. My protocol looks like this


require 'cosmos/interfaces/protocols/protocol'

module Cosmos
  class ReplayProtocol < Protocol
    def initialize(allow_empty_data = nil)
      super(allow_empty_data)
    end
    def read_packet(packet)
      packet.stored = true
      packet.received_time = Time.now.sys - 3000 # eventually based off of a parameter
      return packet
    end
  end
end

I can see the flag being set when I inspect the packet and I can see a new point generated on the telemetry grapher but both packet viewer and telemetry viewer still update with the new value. Is there a way to only show the most recent value in these two tools? I would like to inject these packets as if they were received when they were sent. Any thoughts?

Thanks,

Jeff

ghost commented 2 years ago

Hey Jeff, this is a bug. I'll push a quick fix in a few minutes. You'll need to run off the master branch to try it out.

ghost commented 2 years ago

merged in pr #1724 . Give it a shot now

jeffstjean commented 2 years ago

Will have to wait until Tuesday to give it a shot thanks Ryan! Needed it to make use of a replay telemetry protocol I'm working on. Will this land in 5.0.6?

ghost commented 2 years ago

Yes this will be in the next release

jeffstjean commented 2 years ago

Thanks Ryan! Just pulled down the changes and it seems to be working as expected.

I can open a new issue for this if need be but I can't find any documentation on how to actually set PACKET_TIMESECONDS. I see that it will use an item called PACKET_TIME if it exists, otherwise it will be the same as as RECEIVED_TIMESECONDS. So, I tried defining a new derived item but I keep getting errors that I don't really expect. For example, this code snippet:

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
      item = identified_packet.define_item('PACKET_TIME', 0, 0, :DERIVED)
      identified_packet.write("PACKET_TIME", Time.at(15000), :RAW)
    end
  end
  return packet
end

gives the following error ArgumentError : bit_size 0 must be positive for data types other than :STRING and :BLOCK but derived has to have bit size 0. Do you have any code examples for how to properly set PACKET_TIMESECONDS? It would be nice if it was similar to RECEIVED_TIMESECONDS and you could just call set_received_time_fast().

ghost commented 2 years ago

You can't write DERIVED items.

The idea with PACKET_TIME is that you add a DERIVED item to your packet definition named PACKET_TIME, and you have an associated READ_CONVERSION that looks at other telemetry items in the packet to make a Ruby Time object from and return.

jeffstjean commented 2 years ago

Ah that makes a lot of sense! If I create a derived item in a protocol, should that be the same as adding one to the packet definition? I added this to my telemetry definition:

ITEM PACKET_TIME 0 0 DERIVED
  GENERIC_READ_CONVERSION_START FLOAT 32
    Time.at(packet.read("TIMESTAMP"), 0).sys
  GENERIC_READ_CONVERSION_END

and everything works as expected. When I do something similar in my defined protocol:

item = identified_packet.define_item('PACKET_TIME', 0, 0, :DERIVED)
item.read_conversion = GenericConversion.new('Time.at(packet.read("TIMESTAMP"), 0).sys', :FLOAT, 32)

The PACKET_TIMESECONDS doesn't change. The whole reason I want to do this in a protocol is because there's no single place in every packet that has a timestamp - there's just a handful of packets that might be sent as stored and the only way to determine if the packet is a "stored" packet is by checking if the timestamp if far in the past. So, I figured a protocol would be the best way to KISS and only define my logic once (instead of writing that logic in each packet as required).

Is there any reason why the protocol code snippet doesn't seem to have the same effect as writing it in the telemetry definition? Thanks again Ryan!

ghost commented 2 years ago

My guess is you are running into a conversion caching effect. Conversions only run once, and then the result is cached until the packet.buffer changes.

Its either that or the data is getting copied into another packet definition somewhere that doesn't have your new PACKET_TIME item defined.