cosmos 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Manifest.txt +17 -1
  4. data/autohotkey/tools/test_runner2.ahk +1 -0
  5. data/autohotkey/tools/tlm_grapher.ahk +13 -1
  6. data/data/crc.txt +39 -30
  7. data/demo/config/data/crc.txt +3 -3
  8. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +3 -1
  9. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +7 -1
  10. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +6 -1
  11. data/lib/cosmos.rb +2 -2
  12. data/lib/cosmos/gui/dialogs/about_dialog.rb +18 -5
  13. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +0 -7
  14. data/lib/cosmos/gui/line_graph/overview_graph.rb +12 -2
  15. data/lib/cosmos/gui/utilities/script_module_gui.rb +11 -3
  16. data/lib/cosmos/interfaces/interface.rb +12 -0
  17. data/lib/cosmos/interfaces/stream_interface.rb +1 -21
  18. data/lib/cosmos/interfaces/tcpip_server_interface.rb +10 -0
  19. data/lib/cosmos/io/json_drb_object.rb +75 -56
  20. data/lib/cosmos/io/tcpip_server.rb +1 -11
  21. data/lib/cosmos/packet_logs.rb +1 -0
  22. data/lib/cosmos/packet_logs/ccsds_log_reader.rb +103 -0
  23. data/lib/cosmos/packets/packet.rb +70 -1
  24. data/lib/cosmos/packets/packet_config.rb +59 -611
  25. data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -0
  26. data/lib/cosmos/packets/parsers/limits_parser.rb +146 -0
  27. data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -0
  28. data/lib/cosmos/packets/parsers/macro_parser.rb +116 -0
  29. data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -0
  30. data/lib/cosmos/packets/parsers/packet_parser.rb +123 -0
  31. data/lib/cosmos/packets/parsers/processor_parser.rb +63 -0
  32. data/lib/cosmos/packets/parsers/state_parser.rb +116 -0
  33. data/lib/cosmos/packets/structure.rb +59 -22
  34. data/lib/cosmos/packets/structure_item.rb +1 -1
  35. data/lib/cosmos/script/script.rb +4 -5
  36. data/lib/cosmos/streams/serial_stream.rb +5 -0
  37. data/lib/cosmos/streams/stream.rb +8 -2
  38. data/lib/cosmos/streams/stream_protocol.rb +1 -0
  39. data/lib/cosmos/streams/tcpip_client_stream.rb +37 -7
  40. data/lib/cosmos/streams/tcpip_socket_stream.rb +9 -6
  41. data/lib/cosmos/system/target.rb +3 -6
  42. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +57 -48
  43. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +7 -3
  44. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +1 -1
  45. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +7 -1
  46. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +1 -2
  47. data/lib/cosmos/top_level.rb +22 -11
  48. data/lib/cosmos/utilities/message_log.rb +14 -9
  49. data/lib/cosmos/version.rb +5 -5
  50. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +16 -16
  51. data/spec/interfaces/linc_interface_spec.rb +3 -0
  52. data/spec/interfaces/tcpip_client_interface_spec.rb +1 -0
  53. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -0
  54. data/spec/io/json_drb_object_spec.rb +1 -1
  55. data/spec/io/serial_driver_spec.rb +0 -1
  56. data/spec/packet_logs/packet_log_writer_spec.rb +5 -3
  57. data/spec/packets/packet_config_spec.rb +22 -837
  58. data/spec/packets/packet_item_spec.rb +10 -10
  59. data/spec/packets/packet_spec.rb +239 -1
  60. data/spec/packets/parsers/format_string_parser_spec.rb +122 -0
  61. data/spec/packets/parsers/limits_parser_spec.rb +282 -0
  62. data/spec/packets/parsers/limits_response_parser_spec.rb +149 -0
  63. data/spec/packets/parsers/macro_parser_spec.rb +184 -0
  64. data/spec/packets/parsers/packet_item_parser_spec.rb +306 -0
  65. data/spec/packets/parsers/packet_parser_spec.rb +99 -0
  66. data/spec/packets/parsers/processor_parser_spec.rb +114 -0
  67. data/spec/packets/parsers/state_parser_spec.rb +156 -0
  68. data/spec/packets/structure_item_spec.rb +14 -14
  69. data/spec/packets/structure_spec.rb +162 -16
  70. data/spec/streams/fixed_stream_protocol_spec.rb +7 -4
  71. data/spec/streams/length_stream_protocol_spec.rb +3 -0
  72. data/spec/streams/preidentified_stream_protocol_spec.rb +3 -0
  73. data/spec/streams/serial_stream_spec.rb +12 -0
  74. data/spec/streams/stream_protocol_spec.rb +14 -0
  75. data/spec/streams/stream_spec.rb +1 -0
  76. data/spec/streams/tcpip_client_stream_spec.rb +3 -0
  77. data/spec/streams/tcpip_socket_stream_spec.rb +15 -3
  78. data/spec/streams/template_stream_protocol_spec.rb +5 -0
  79. data/spec/streams/terminated_stream_protocol_spec.rb +4 -0
  80. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +21 -1
  81. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +1 -1
  82. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +1 -1
  83. metadata +19 -3
@@ -0,0 +1,58 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ module Cosmos
12
+
13
+ class FormatStringParser
14
+ # @param parser [ConfigParser] Configuration parser
15
+ # @param item [Packet] The current item
16
+ def self.parse(parser, item)
17
+ @parser = FormatStringParser.new(parser)
18
+ @parser.verify_parameters()
19
+ @parser.create_format_string(item)
20
+ end
21
+
22
+ # @param parser [ConfigParser] Configuration parser
23
+ def initialize(parser)
24
+ @parser = parser
25
+ end
26
+
27
+ def verify_parameters
28
+ @usage = "FORMAT_STRING <PRINTF STYLE STRING>"
29
+ @parser.verify_num_parameters(1, 1, @usage)
30
+ end
31
+
32
+ # @param item [PacketItem] The item the limits response should be added to
33
+ def create_format_string(item)
34
+ item.format_string = @parser.parameters[0]
35
+ # Only test the format string if there is not a read conversion because
36
+ # read conversion can return any type
37
+ test_format_string(item) unless item.read_conversion
38
+ end
39
+
40
+ private
41
+
42
+ def test_format_string(item)
43
+ case item.data_type
44
+ when :INT, :UINT
45
+ sprintf(item.format_string, 0)
46
+ when :FLOAT
47
+ sprintf(item.format_string, 0.0)
48
+ when :STRING, :BLOCK
49
+ sprintf(item.format_string, 'Hello')
50
+ else
51
+ # Nothing to do
52
+ end
53
+ rescue Exception
54
+ raise @parser.error("Invalid FORMAT_STRING specified for type #{item.data_type}: #{@parser.parameters[0]}", @usage)
55
+ end
56
+
57
+ end
58
+ end # module Cosmos
@@ -0,0 +1,146 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ module Cosmos
12
+
13
+ class LimitsParser
14
+ # @param parser [ConfigParser] Configuration parser
15
+ # @param packet [Packet] The current packet
16
+ # @param cmd_or_tlm [String] Whether this is a command or telemetry packet
17
+ # @param item [PacketItem] The packet item to create limits on
18
+ # @param warnings [Array<String>] Array of string warnings which will be
19
+ # appended with any warnings found when parsing the limits
20
+ def self.parse(parser, packet, cmd_or_tlm, item, warnings)
21
+ @parser = LimitsParser.new(parser)
22
+ @parser.verify_parameters(cmd_or_tlm)
23
+ @parser.create_limits(packet, item, warnings)
24
+ end
25
+
26
+ def initialize(parser)
27
+ @parser = parser
28
+ end
29
+
30
+ # @param cmd_or_tlm [String] Whether this is a command or telemetry packet
31
+ def verify_parameters(cmd_or_tlm)
32
+ if cmd_or_tlm == PacketConfig::COMMAND
33
+ raise @parser.error("LIMITS only applies to telemetry items")
34
+ end
35
+ @usage = "LIMITS <LIMITS SET> <PERSISTENCE> <ENABLED/DISABLED> <RED LOW LIMIT> <YELLOW LOW LIMIT> <YELLOW HIGH LIMIT> <RED HIGH LIMIT> <GREEN LOW LIMIT (Optional)> <GREEN HIGH LIMIT (Optional)>"
36
+ @parser.verify_num_parameters(7, 9, @usage)
37
+ end
38
+
39
+ # @param packet [Packet] The packet the item should be added to
40
+ def create_limits(packet, item, warnings)
41
+ limits_set = get_limits_set()
42
+ initialize_limits_values(packet, item)
43
+ ensure_consistency_with_default(packet, item, warnings)
44
+
45
+ item.limits.values[limits_set] = get_values()
46
+ item.limits.enabled = get_enabled()
47
+ item.limits.persistence_setting = get_persistence()
48
+ item.limits.persistence_count = 0
49
+
50
+ packet.update_limits_items_cache
51
+ limits_set
52
+ end
53
+
54
+ private
55
+
56
+ def initialize_limits_values(packet, item)
57
+ limits_set = get_limits_set()
58
+ # Values must be initialized with a :DEFAULT key
59
+ if !item.limits.values
60
+ if limits_set == :DEFAULT
61
+ item.limits.values = {:DEFAULT => []}
62
+ else
63
+ raise @parser.error("DEFAULT limits set must be defined for #{packet.target_name} #{packet.packet_name} #{item.name} before setting limits set #{limits_set}")
64
+ end
65
+ end
66
+ end
67
+
68
+ def ensure_consistency_with_default(packet, item, warnings)
69
+ # Nothing to do if we're already :DEFAULT
70
+ return if get_limits_set() == :DEFAULT
71
+
72
+ msg = "TELEMETRY Item #{packet.target_name} #{packet.packet_name} #{item.name} #{get_limits_set()} limits _TYPE_ setting conflict with DEFAULT"
73
+ # XOR our setting with the items current setting
74
+ # If it returns true then we have a mismatch and log the error
75
+ if (get_enabled() ^ item.limits.enabled)
76
+ warnings << msg.sub('_TYPE_', 'enable')
77
+ Logger.instance.warn warnings[-1]
78
+ end
79
+ if item.limits.persistence_setting != get_persistence()
80
+ warnings << msg.sub('_TYPE_', 'persistence')
81
+ Logger.instance.warn warnings[-1]
82
+ end
83
+ end
84
+
85
+ def get_limits_set
86
+ @parser.parameters[0].upcase.to_sym
87
+ end
88
+
89
+ def get_persistence
90
+ Integer(@parser.parameters[1])
91
+ rescue
92
+ raise @parser.error("Persistence must be an integer.", @usage)
93
+ end
94
+
95
+ def get_enabled
96
+ enabled = @parser.parameters[2].upcase
97
+ if enabled != 'ENABLED' and enabled != 'DISABLED'
98
+ raise @parser.error("Initial LIMITS state must be ENABLED or DISABLED.", @usage)
99
+ end
100
+ enabled == 'ENABLED' ? true : false
101
+ end
102
+
103
+ def get_values
104
+ values = get_red_yellow_values()
105
+ values += get_green_values(values[1], values[2])
106
+ values
107
+ end
108
+
109
+ def get_red_yellow_values
110
+ params = @parser.parameters
111
+ err = nil
112
+ red_low = Float(params[3]) rescue err = "red low"
113
+ yellow_low = Float(params[4]) rescue err = "yellow low"
114
+ yellow_high = Float(params[5]) rescue err = "yellow high"
115
+ red_high = Float(params[6]) rescue err = "red high"
116
+ raise @parser.error("Invalid #{err} limit value. Limits can be integers or floats.", @usage) if err
117
+
118
+ # Verify valid limits are specified
119
+ if (red_low > yellow_low) or (yellow_low >= yellow_high) or (yellow_high > red_high)
120
+ raise @parser.error("Invalid limits specified. Ensure yellow limits are within red limits.", @usage)
121
+ end
122
+ [red_low, yellow_low, yellow_high, red_high]
123
+ end
124
+
125
+ def get_green_values(yellow_low, yellow_high)
126
+ params = @parser.parameters
127
+ # Since our initial parameter check verifies between 7 and 9 we do a
128
+ # special check for 8 parameters which is an error
129
+ if params.length == 8
130
+ raise @parser.error("Must give both a green low and green high value.", @usage)
131
+ end
132
+ return [] unless params.length == 9
133
+
134
+ err = nil
135
+ green_low = Float(params[7]) rescue err = "green low"
136
+ green_high = Float(params[8]) rescue err = "green high"
137
+ raise @parser.error("Invalid #{err} limit value. Limits can be integers or floats.", @usage) if err
138
+
139
+ if (yellow_low > green_low) or (green_low >= green_high) or (green_high > yellow_high)
140
+ raise @parser.error("Invalid limits specified. Ensure green limits are within yellow limits.", @usage)
141
+ end
142
+ [green_low, green_high]
143
+ end
144
+
145
+ end
146
+ end # module Cosmos
@@ -0,0 +1,52 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ module Cosmos
12
+
13
+ class LimitsResponseParser
14
+ # @param parser [ConfigParser] Configuration parser
15
+ # @param item [Packet] The current item
16
+ # @param cmd_or_tlm [String] Whether this is a command or telemetry packet
17
+ def self.parse(parser, item, cmd_or_tlm)
18
+ @parser = LimitsResponseParser.new(parser)
19
+ @parser.verify_parameters(cmd_or_tlm)
20
+ @parser.create_limits_response(item)
21
+ end
22
+
23
+ # @param parser [ConfigParser] Configuration parser
24
+ def initialize(parser)
25
+ @parser = parser
26
+ end
27
+
28
+ # @param cmd_or_tlm [String] Whether this is a command or telemetry packet
29
+ def verify_parameters(cmd_or_tlm)
30
+ if cmd_or_tlm == PacketConfig::COMMAND
31
+ raise @parser.error("LIMITS_RESPONSE only applies to telemetry items")
32
+ end
33
+ @usage = "LIMITS_RESPONSE <RESPONSE CLASS FILENAME> <RESPONSE SPECIFIC OPTIONS>"
34
+ @parser.verify_num_parameters(1, nil, @usage)
35
+ end
36
+
37
+ # @param item [PacketItem] The item the limits response should be added to
38
+ def create_limits_response(item)
39
+ # require should be performed in target.txt
40
+ klass = @parser.parameters[0].filename_to_class_name.to_class
41
+ raise @parser.error("#{@parser.parameters[0].filename_to_class_name} class not found. Did you require the file in target.txt?", @usage) unless klass
42
+ if @parser.parameters[1]
43
+ item.limits.response = klass.new(*@parser.parameters[1..(@parser.parameters.length - 1)])
44
+ else
45
+ item.limits.response = klass.new
46
+ end
47
+ rescue Exception => err
48
+ raise @parser.error(err, @usage)
49
+ end
50
+
51
+ end
52
+ end # module Cosmos
@@ -0,0 +1,116 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'ostruct'
12
+
13
+ module Cosmos
14
+ class MacroParser
15
+ # Adds a new item to the Macro
16
+ def self.new_item
17
+ return unless @macro
18
+ @macro.new_item
19
+ end
20
+
21
+ # Starts a new Macro
22
+ #
23
+ # @param parser [ConfigParser] Configuration Parser
24
+ def self.start(parser)
25
+ if @macro
26
+ @macro = nil
27
+ raise parser.error("First close the previous MACRO_APPEND_START with a MACRO_APPEND_END")
28
+ else
29
+ @macro = MacroParser.new(parser)
30
+ end
31
+ end
32
+
33
+ # Ends the Macro and adds all the items to the packet
34
+ #
35
+ # @param parser [ConfigParser] Configuration Parser
36
+ # @param packet [Packet] Packet to add the macro items to
37
+ def self.end(parser, packet)
38
+ raise parser.error("First start a macro with MACRO_APPEND_START") unless @macro
39
+ @macro.complete(packet)
40
+ ensure
41
+ # Ensure this class instance variable gets cleared so we can process the
42
+ # next call to start
43
+ @macro = nil
44
+ end
45
+
46
+ # @param parser [ConfigParser] Configuration Parser
47
+ def initialize(parser)
48
+ @parser = parser
49
+ @usage = '#{keyword} <FIRST INDEX> <LAST INDEX> [NAME FORMAT]'
50
+ parser.verify_num_parameters(2, 3, @usage)
51
+ @macro = OpenStruct.new(:started => true, :list => [])
52
+ first_index = parser.parameters[0].to_i
53
+ last_index = parser.parameters[1].to_i
54
+ if first_index < last_index
55
+ @macro.indices = (first_index..last_index).to_a
56
+ else
57
+ @macro.indices = (last_index..first_index).to_a
58
+ end
59
+ @macro.format = parser.parameters[2] ? parser.parameters[2] : '%s%d'
60
+ @macro.format_order = get_format_order()
61
+ end
62
+
63
+ def new_item
64
+ if @parser.keyword.include?('APPEND')
65
+ @macro.list << @parser.parameters[0].upcase
66
+ end
67
+ end
68
+
69
+ def complete(packet)
70
+ @parser.verify_num_parameters(0, 0, @parser.keyword)
71
+ raise @parser.error("Missing MACRO_APPEND_START before this config.line.", @parser.keyword) unless @macro
72
+ raise @parser.error("No items appended in MACRO_APPEND list", @parser.keyword) if @macro.list.empty?
73
+
74
+ create_new_packet_items(packet)#, new_item_names)
75
+ end
76
+
77
+ private
78
+
79
+ def format_item_name(name, index)
80
+ if @macro.format_order == 'sd'
81
+ sprintf(@macro.format, name, index)
82
+ else
83
+ sprintf(@macro.format, index, name)
84
+ end
85
+ end
86
+
87
+ def create_new_packet_items(packet)
88
+ @macro.list.each do |name|
89
+ original_item_name = name
90
+ # Shift off the macro indices because since the first item already
91
+ # exists we just rename it
92
+ new_name = format_item_name(name, @macro.indices.shift)
93
+ item = packet.rename_item(name, new_name)
94
+
95
+ # The renaming indices create new items
96
+ @macro.indices.each do |index|
97
+ new_item = item.clone
98
+ new_item.name = format_item_name(original_item_name, index)
99
+ packet.append(new_item)
100
+ end
101
+ end
102
+ end
103
+
104
+ def get_format_order()
105
+ string_index = @macro.format.index(/%\d*s/)
106
+ num_index = @macro.format.index(/%\d*d/)
107
+ raise parser.error("Invalid NAME FORMAT (#{@macro.format}) for MACRO_APPEND_START", @usage) unless string_index && num_index
108
+ if string_index < num_index
109
+ @macro.format_order = 'sd'
110
+ else
111
+ @macro.format_order = 'ds'
112
+ end
113
+ end
114
+
115
+ end
116
+ end # module Cosmos
@@ -0,0 +1,215 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos/packets/packet_config'
12
+ require 'cosmos/packets/packet_item'
13
+
14
+ module Cosmos
15
+
16
+ class PacketItemParser
17
+ # @param parser [ConfigParser] Configuration parser
18
+ # @param packet [Packet] The packet the item should be added to
19
+ # @param cmd_or_tlm [String] Whether this is :bn
20
+ def self.parse(parser, packet, cmd_or_tlm)
21
+ parser = PacketItemParser.new(parser)
22
+ parser.verify_parameters(cmd_or_tlm)
23
+ parser.create_packet_item(packet, cmd_or_tlm)
24
+ end
25
+
26
+ # @param parser [ConfigParser] Configuration parser
27
+ def initialize(parser)
28
+ @parser = parser
29
+ @usage = get_usage()
30
+ end
31
+
32
+ def verify_parameters(cmd_or_tlm)
33
+ if @parser.keyword.include?('ITEM') && cmd_or_tlm == PacketConfig::COMMAND
34
+ raise @parser.error("ITEM types are only valid with TELEMETRY", @usage)
35
+ elsif @parser.keyword.include?('PARAMETER') && cmd_or_tlm == PacketConfig::TELEMETRY
36
+ raise @parser.error("PARAMETER types are only valid with COMMAND", @usage)
37
+ end
38
+ # The usage is formatted with brackets <XXX> around each option so
39
+ # count the number of open brackets to determine the number of options
40
+ max_options = @usage.count("<")
41
+ # The last two options (description and endianness) are optional
42
+ @parser.verify_num_parameters(max_options-2, max_options, @usage)
43
+ end
44
+
45
+ def create_packet_item(packet, cmd_or_tlm)
46
+ item = PacketItem.new(@parser.parameters[0],
47
+ get_bit_offset(),
48
+ get_bit_size(),
49
+ get_data_type(),
50
+ get_endianness(packet),
51
+ get_array_size(),
52
+ :ERROR) # overflow
53
+ if cmd_or_tlm == PacketConfig::COMMAND
54
+ item.range = get_range()
55
+ item.default = get_default()
56
+ end
57
+ item.id_value = get_id_value()
58
+ item.description = get_description()
59
+ if append?
60
+ item = packet.append(item)
61
+ else
62
+ item = packet.define(item)
63
+ end
64
+ item
65
+ rescue => err
66
+ raise @parser.error(err, @usage)
67
+ end
68
+
69
+ private
70
+
71
+ def append?
72
+ @parser.keyword.include?("APPEND")
73
+ end
74
+
75
+ def get_data_type
76
+ index = append? ? 2 : 3
77
+ @parser.parameters[index].upcase.to_sym
78
+ end
79
+
80
+ def get_bit_offset
81
+ return 0 if append?
82
+ Integer(@parser.parameters[1])
83
+ rescue => err # In case Integer fails
84
+ raise @parser.error(err, @usage)
85
+ end
86
+
87
+ def get_bit_size
88
+ index = append? ? 1 : 2
89
+ Integer(@parser.parameters[index])
90
+ rescue => err
91
+ raise @parser.error(err, @usage)
92
+ end
93
+
94
+ def get_array_size
95
+ return nil unless (@parser.keyword.include?('ARRAY'))
96
+ index = append? ? 3 : 4
97
+ Integer(@parser.parameters[index])
98
+ rescue => err
99
+ raise @parser.error(err, @usage)
100
+ end
101
+
102
+ def get_endianness(packet)
103
+ params = @parser.parameters
104
+ max_options = @usage.count("<")
105
+ if params[max_options-1]
106
+ endianness = params[max_options-1].to_s.upcase.intern
107
+ if endianness != :BIG_ENDIAN and endianness != :LITTLE_ENDIAN
108
+ raise @parser.error("Invalid endianness #{endianness}. Must be BIG_ENDIAN or LITTLE_ENDIAN.", @usage)
109
+ end
110
+ else
111
+ endianness = packet.default_endianness
112
+ end
113
+ endianness
114
+ end
115
+
116
+ def get_range
117
+ return nil if @parser.keyword.include?('ARRAY')
118
+ data_type = get_data_type()
119
+ return nil if data_type == :STRING or data_type == :BLOCK
120
+
121
+ index = append? ? 3 : 4
122
+ (ConfigParser.handle_defined_constants(@parser.parameters[index].convert_to_value))..(ConfigParser.handle_defined_constants(@parser.parameters[index+1].convert_to_value))
123
+ end
124
+
125
+ def get_default
126
+ return [] if @parser.keyword.include?('ARRAY')
127
+
128
+ index = append? ? 3 : 4
129
+ data_type = get_data_type()
130
+ if data_type == :STRING or data_type == :BLOCK
131
+ return @parser.parameters[index]
132
+ else
133
+ return ConfigParser.handle_defined_constants(@parser.parameters[index+2].convert_to_value)
134
+ end
135
+ end
136
+
137
+ def get_id_value
138
+ return nil unless @parser.keyword.include?('ID_')
139
+ data_type = get_data_type
140
+ if @parser.keyword.include?('ITEM')
141
+ index = append? ? 3 : 4
142
+ else # PARAMETER
143
+ index = append? ? 5 : 6
144
+ # STRING and BLOCK PARAMETERS don't have min and max values
145
+ index -= 2 if data_type == :STRING || data_type == :BLOCK
146
+ end
147
+ if data_type == :DERIVED
148
+ raise @parser.error("DERIVED data type not allowed for Identifier")
149
+ end
150
+ @parser.parameters[index]
151
+ end
152
+
153
+ def get_description
154
+ max_options = @usage.count("<")
155
+ @parser.parameters[max_options-2] if @parser.parameters[max_options-2]
156
+ end
157
+
158
+ # There are many different usages of the ITEM and PARAMETER keywords so
159
+ # parse the keyword and parameters to generate the correct usage information.
160
+ def get_usage
161
+ keyword = @parser.keyword
162
+ params = @parser.parameters
163
+ usage = "#{keyword} <ITEM NAME> "
164
+ usage << "<BIT OFFSET> " unless keyword.include?("APPEND")
165
+ usage << bit_size_usage()
166
+ usage << type_usage()
167
+ usage << "<TOTAL ARRAY BIT SIZE> " if keyword.include?("ARRAY")
168
+ usage << id_usage()
169
+ usage << "<DESCRIPTION (Optional)> <ENDIANNESS (Optional)>"
170
+ usage
171
+ end
172
+
173
+ def bit_size_usage
174
+ if @parser.keyword.include?("ARRAY")
175
+ "<ARRAY ITEM BIT SIZE> "
176
+ else
177
+ "<BIT SIZE> "
178
+ end
179
+ end
180
+
181
+ def type_usage
182
+ keyword = @parser.keyword
183
+ # Item type usage is simple so just return it
184
+ return "<TYPE: INT/UINT/FLOAT/STRING/BLOCK/DERIVED> " if keyword.include?("ITEM")
185
+
186
+ # Build up the parameter type usage based on the keyword
187
+ usage = "<TYPE: "
188
+ params = @parser.parameters
189
+ # ARRAY types don't have min or max or default values
190
+ if keyword.include?("ARRAY")
191
+ usage << "INT/UINT/FLOAT/STRING/BLOCK> "
192
+ else
193
+ # STRING and BLOCK types do not have min or max values
194
+ if get_data_type() == :STRING || get_data_type() == :BLOCK
195
+ usage << "STRING/BLOCK> "
196
+ else
197
+ usage << "INT/UINT/FLOAT> <MIN VALUE> <MAX VALUE> "
198
+ end
199
+ # ID Values do not have default values
200
+ usage << "<DEFAULT_VALUE> " unless keyword.include?("ID")
201
+ end
202
+ usage
203
+ end
204
+
205
+ def id_usage
206
+ return '' unless @parser.keyword.include?("ID")
207
+ if @parser.keyword.include?("PARAMETER")
208
+ "<DEFAULT AND ID VALUE> "
209
+ else
210
+ "<ID VALUE> "
211
+ end
212
+ end
213
+
214
+ end
215
+ end # module Cosmos