cosmos 3.1.2 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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