Skip to content

Commit

Permalink
Merge pull request #1454 from OpenC3/item_offset
Browse files Browse the repository at this point in the history
Fix offset when appending items
  • Loading branch information
ryanmelt authored Aug 14, 2024
2 parents 0e4bfc3 + 46cb701 commit d42a5ad
Show file tree
Hide file tree
Showing 18 changed files with 382 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ VARIABLE reduced_log_retain_time 2592000

<% if include_inst %>
TARGET INST <%= inst_target_name %>
# If we're in the CI pipeline shorten the log file creation time
<% if ENV["CI"] %>
TLM_LOG_CYCLE_TIME 60
<% else %>
TLM_LOG_CYCLE_TIME 300
<% end %>
LOG_RETAIN_TIME <%= log_retain_time %>
REDUCED_LOG_RETAIN_TIME <%= reduced_log_retain_time %>
TLM_LOG_CYCLE_TIME 300
# Allow the reducer microservice to take 50% of the cpu (default 30%)
REDUCER_MAX_CPU_UTILIZATION 50
<% end %>
Expand Down
7 changes: 6 additions & 1 deletion openc3/lib/openc3/conversions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@
# All changes Copyright 2022, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

module OpenC3
autoload(:Conversion, 'openc3/conversions/conversion.rb')
autoload(:BitReverseConversion, 'openc3/conversions/bit_reverse_conversion.rb')
autoload(:GenericConversion, 'openc3/conversions/generic_conversion.rb')
autoload(:IpReadConversion, 'openc3/conversions/ip_read_conversion.rb')
autoload(:IpWriteConversion, 'openc3/conversions/ip_write_conversion.rb')
autoload(:ObjectReadConversion, 'openc3/conversions/object_read_conversion.rb')
autoload(:ObjectWriteConversion, 'openc3/conversions/object_write_conversion.rb')
autoload(:PacketTimeFormattedConversion, 'openc3/conversions/packet_time_formatted_conversion.rb')
autoload(:PacketTimeSecondsConversion, 'openc3/conversions/packet_time_seconds_conversion.rb')
autoload(:PolynomialConversion, 'openc3/conversions/polynomial_conversion.rb')
Expand Down
60 changes: 60 additions & 0 deletions openc3/lib/openc3/conversions/bit_reverse_conversion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# encoding: ascii-8bit

# Copyright 2024 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

require 'openc3/conversions/conversion'

module OpenC3
class BitReverseConversion < Conversion
def initialize(converted_type, converted_bit_size)
@converted_type = converted_type.to_s.upcase.intern
@converted_bit_size = converted_bit_size.to_i
@converted_array_size = nil
if @converted_data_type == :FLOAT
raise "Float Bit Reverse Not Yet Supported"
end
end

# Perform the conversion on the value.
#
# @param value [Object] The value to convert
# @param packet [Packet] The packet which contains the value. This can
# be useful to reach into the packet and use other values in the
# conversion.
# @param buffer [String] The packet buffer
# @return The converted value
def call(value, _packet, _buffer)
reversed = 0
@converted_bit_size.times do
reversed = (reversed << 1) | (value & 1)
value >>= 1
end
return reversed & ((2 ** @converted_bit_size) - 1)
end

# @return [String] The conversion class
def to_s
"#{self.class.to_s.split('::')[-1]}.new(#{@converted_type}, #{@converted_bit_size})"
end

# @param read_or_write [String] Either 'READ' or 'WRITE'
# @return [String] Config fragment for this conversion
def to_config(read_or_write)
" #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename} #{@converted_type} #{@converted_bit_size}\n"
end
end
end
59 changes: 59 additions & 0 deletions openc3/lib/openc3/conversions/ip_read_conversion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# encoding: ascii-8bit

# Copyright 2024 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

require 'openc3/conversions/conversion'

module OpenC3
class IpReadConversion < Conversion
def initialize
@converted_type = :STRING
@converted_bit_size = 120
@converted_array_size = nil
end

# Perform the conversion on the value.
#
# @param value [Object] The value to convert
# @param packet [Packet] The packet which contains the value. This can
# be useful to reach into the packet and use other values in the
# conversion.
# @param buffer [String] The packet buffer
# @return The converted value
def call(value, _packet, _buffer)
byte4 = (value & 0xFF)
value = value >> 8
byte3 = (value & 0xFF)
value = value >> 8
byte2 = (value & 0xFF)
value = value >> 8
byte1 = (value & 0xFF)
return "#{byte1}.#{byte2}.#{byte3}.#{byte4}"
end

# @return [String] The conversion class
def to_s
"#{self.class.to_s.split('::')[-1]}.new"
end

# @param read_or_write [String] Either 'READ' or 'WRITE'
# @return [String] Config fragment for this conversion
def to_config(read_or_write)
" #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename}\n"
end
end
end
61 changes: 61 additions & 0 deletions openc3/lib/openc3/conversions/ip_write_conversion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# encoding: ascii-8bit

# Copyright 2024 OpenC3, Inc.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

require 'openc3/conversions/conversion'

module OpenC3
class IpWriteConversion < Conversion
def initialize
@converted_type = :UINT
@converted_bit_size = 32
@converted_array_size = nil
end

# Perform the conversion on the value.
#
# @param value [Object] The value to convert
# @param packet [Packet] The packet which contains the value. This can
# be useful to reach into the packet and use other values in the
# conversion.
# @param buffer [String] The packet buffer
# @return The converted value
def call(value, _packet, _buffer)
bytes = value.split('.')
result = 0
result += Integer(bytes[0])
result = result << 8
result += Integer(bytes[1])
result = result << 8
result += Integer(bytes[2])
result = result << 8
result += Integer(bytes[3])
return result
end

# @return [String] The conversion class
def to_s
"#{self.class.to_s.split('::')[-1]}.new"
end

# @param read_or_write [String] Either 'READ' or 'WRITE'
# @return [String] Config fragment for this conversion
def to_config(read_or_write)
" #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename}\n"
end
end
end
38 changes: 29 additions & 9 deletions openc3/lib/openc3/conversions/object_read_conversion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,65 @@
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

require 'openc3/config/config_parser'
require 'openc3/conversions/conversion'

module OpenC3
class ObjectReadConversion < Conversion
def initialize(cmd_or_tlm, target_name, packet_name)
super()
@cmd_or_tlm = cmd_or_tlm.to_s.upcase.intern
raise ArgumentError, "Unknown type: #{cmd_or_tlm}" unless %i(CMD TLM).include?(@cmd_or_tlm)
cmd_or_tlm = ConfigParser.handle_nil(cmd_or_tlm)
if cmd_or_tlm
@cmd_or_tlm = cmd_or_tlm.to_s.upcase.intern
raise ArgumentError, "Unknown type: #{cmd_or_tlm}" unless %i(CMD TLM COMMAND TELEMETRY).include?(@cmd_or_tlm)
else
# Unknown - Will need to search
@cmd_or_tlm = nil
end
@target_name = target_name.to_s.upcase
@packet_name = packet_name.to_s.upcase
@converted_type = :OBJECT
@converted_bit_size = 0
end

def lookup_packet
if @cmd_or_tlm
if @cmd_or_tlm == :CMD or @cmd_or_tlm == :COMMAND
return System.commands.packet(@target_name, @packet_name)
else
return System.telemetry.packet(@target_name, @packet_name)
end
else
# Always searches commands first
begin
return System.commands.packet(@target_name, @packet_name)
rescue
return System.telemetry.packet(@target_name, @packet_name)
end
end
end

# Perform the conversion on the value.
#
# @param value [String] The BLOCK data to make into a packet
# @param packet [Packet] Unused
# @param buffer [String] The packet buffer
# @return The converted value
def call(value, _packet, buffer)
if @cmd_or_tlm == :CMD
fill_packet = System.commands.packet(@target_name, @packet_name)
else
fill_packet = System.telemetry.packet(@target_name, @packet_name)
end
fill_packet = lookup_packet()
fill_packet.buffer = value
return fill_packet.read_all(:CONVERTED, buffer, true).to_h
end

# @return [String] The conversion class
def to_s
"#{self.class.to_s.split('::')[-1]} #{@cmd_or_tlm} #{@target_name} #{@packet_name}"
"#{self.class.to_s.split('::')[-1]} #{@cmd_or_tlm ? @cmd_or_tlm : "nil"} #{@target_name} #{@packet_name}"
end

# @param read_or_write [String] Not used
# @return [String] Config fragment for this conversion
def to_config(read_or_write)
" READ_CONVERSION #{self.class.name.class_name_to_filename} #{@cmd_or_tlm} #{@target_name} #{@packet_name}\n"
" #{read_or_write}_CONVERSION #{self.class.name.class_name_to_filename} #{@cmd_or_tlm ? @cmd_or_tlm : "nil"} #{@target_name} #{@packet_name}\n"
end

def as_json(*a)
Expand Down
12 changes: 1 addition & 11 deletions openc3/lib/openc3/conversions/object_write_conversion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,12 @@ class ObjectWriteConversion < ObjectReadConversion
# @param buffer [String] The packet buffer
# @return Raw BLOCK data
def call(value, _packet, buffer)
if @cmd_or_tlm == :CMD
fill_packet = System.commands.packet(@target_name, @packet_name)
else
fill_packet = System.telemetry.packet(@target_name, @packet_name)
end
fill_packet = lookup_packet()
fill_packet.restore_defaults()
value.each do |key, write_value|
fill_packet.write(key, write_value)
end
return fill_packet.buffer
end

# @param read_or_write [String] Not used
# @return [String] Config fragment for this conversion
def to_config(read_or_write)
" WRITE_CONVERSION #{self.class.name.class_name_to_filename} #{@cmd_or_tlm} #{@target_name} #{@packet_name}\n"
end
end
end
2 changes: 1 addition & 1 deletion openc3/lib/openc3/packets/packet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,7 @@ def to_config(cmd_or_tlm)
config << " HAZARDOUS #{@hazardous_description.to_s.quote_if_necessary}\n" if @hazardous
config << " DISABLE_MESSAGES\n" if @messages_disabled
if @virtual
config << " VIRTUAL"
config << " VIRTUAL\n"
elsif @disabled
config << " DISABLED\n"
elsif @hidden
Expand Down
5 changes: 5 additions & 0 deletions openc3/lib/openc3/packets/packet_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ def to_config(cmd_or_tlm, default_endianness)
config << " #{self.endianness}" if self.endianness != default_endianness && self.data_type != :STRING && self.data_type != :BLOCK
config << "\n"

config << " VARIABLE_BIT_SIZE '#{self.variable_bit_size['length_item_name']}' #{self.variable_bit_size['length_bits_per_count']} #{self.variable_bit_size['length_value_bit_offset']}\n" if self.variable_bit_size
config << " REQUIRED\n" if self.required
config << " FORMAT_STRING #{self.format_string.to_s.quote_if_necessary}\n" if self.format_string
config << " UNITS #{self.units_full.to_s.quote_if_necessary} #{self.units.to_s.quote_if_necessary}\n" if self.units
Expand Down Expand Up @@ -510,6 +511,9 @@ def as_json(*a)
end

config['meta'] = @meta if @meta
if @variable_bit_size
config['variable_bit_size'] = @variable_bit_size
end
config
end

Expand Down Expand Up @@ -571,6 +575,7 @@ def self.from_json(hash)
item.limits.values = values if values.length > 0
end
item.meta = hash['meta']
item.variable_bit_size = hash['variable_bit_size']
item
end

Expand Down
5 changes: 5 additions & 0 deletions openc3/lib/openc3/packets/structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,12 @@ def append(item)
if item.data_type == :DERIVED
item.bit_offset = 0
else
# We're appending a new item so set the bit_offset
item.bit_offset = @defined_length_bits
# Also set original_bit_offset because it's currently 0
# due to PacketItemParser::create_packet_item
# get_bit_offset() returning 0 if append
item.original_bit_offset = @defined_length_bits
end
return define(item)
end
Expand Down
6 changes: 5 additions & 1 deletion openc3/lib/openc3/packets/structure_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class StructureItem
# Will reflect the bit offset with all variable sized items at their
# minimum size
# @return [Integer] 0 based bit offset
attr_reader :original_bit_offset
attr_accessor :original_bit_offset

# The number of bits which represent this StructureItem in the binary buffer.
# @return [Integer] Size in bits
Expand Down Expand Up @@ -329,6 +329,7 @@ def self.from_json(hash)
si = StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
endianness, hash['array_size'], overflow)
si.key = hash['key'] || hash['name']
si.variable_bit_size = hash['variable_bit_size']
si
end

Expand All @@ -342,6 +343,9 @@ def as_json(*a)
hash['endianness'] = self.endianness
hash['array_size'] = self.original_array_size
hash['overflow'] = self.overflow
if @variable_bit_size
hash['variable_bit_size'] = @variable_bit_size
end
hash
end

Expand Down
Loading

0 comments on commit d42a5ad

Please sign in to comment.