cosmos 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +5 -0
  3. data/appveyor.yml +2 -0
  4. data/autohotkey/tools/replay.ahk +45 -45
  5. data/autohotkey/tools/script_runner.ahk +3 -9
  6. data/cosmos.gemspec +1 -1
  7. data/data/config/interface_modifiers.yaml +23 -0
  8. data/data/config/screen.yaml +1 -1
  9. data/data/crc.txt +20 -18
  10. data/demo/config/targets/INST/cmd_tlm_server.txt +1 -1
  11. data/lib/cosmos/config/config_parser.rb +8 -3
  12. data/lib/cosmos/gui/dialogs/exception_dialog.rb +20 -5
  13. data/lib/cosmos/interfaces/protocols/burst_protocol.rb +13 -3
  14. data/lib/cosmos/interfaces/protocols/crc_protocol.rb +27 -3
  15. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +4 -2
  16. data/lib/cosmos/interfaces/protocols/length_protocol.rb +4 -2
  17. data/lib/cosmos/interfaces/protocols/override_protocol.rb +2 -2
  18. data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +3 -2
  19. data/lib/cosmos/interfaces/protocols/protocol.rb +16 -4
  20. data/lib/cosmos/interfaces/protocols/template_protocol.rb +7 -2
  21. data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +4 -2
  22. data/lib/cosmos/packets/packet_config.rb +19 -859
  23. data/lib/cosmos/packets/packet_item.rb +56 -201
  24. data/lib/cosmos/packets/parsers/xtce_converter.rb +440 -0
  25. data/lib/cosmos/packets/parsers/xtce_parser.rb +682 -0
  26. data/lib/cosmos/tools/config_editor/config_editor.rb +143 -5
  27. data/lib/cosmos/tools/tlm_viewer/screen.rb +1 -1
  28. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +5 -3
  29. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +40 -27
  30. data/lib/cosmos/version.rb +4 -4
  31. data/spec/config/config_parser_spec.rb +39 -2
  32. data/spec/install/config/targets/INST/screens/hs.txt +42 -0
  33. data/spec/install/config/targets/INST/target.txt +2 -0
  34. data/spec/interfaces/protocols/burst_protocol_spec.rb +18 -0
  35. data/spec/interfaces/protocols/length_protocol_spec.rb +49 -0
  36. data/spec/interfaces/udp_interface_spec.rb +0 -9
  37. data/spec/packets/packet_config_spec.rb +21 -144
  38. data/spec/packets/packet_item_spec.rb +68 -4
  39. data/spec/packets/parsers/packet_item_parser_spec.rb +12 -0
  40. data/spec/packets/parsers/xtce_parser_spec.rb +398 -0
  41. data/spec/tools/tlm_viewer/tlm_viewer_config_spec.rb +401 -0
  42. metadata +9 -10
@@ -288,39 +288,51 @@ module Cosmos
288
288
  packet.buffer = "\x00\x00\x00\x01" * 16
289
289
  expect(packet.get_item("ITEM1").range).to eql (1..2)
290
290
  expect(packet.get_item("ITEM1").default).to eql 3
291
+ expect(packet.get_item("ITEM1").id_value).to eql 3
291
292
  expect(packet.read("ITEM1")).to eql 0x01000000
292
293
  expect(packet.get_item("ITEM2").range).to eql (4..5)
293
294
  expect(packet.get_item("ITEM2").default).to eql 6
295
+ expect(packet.get_item("ITEM2").id_value).to eql nil
294
296
  expect(packet.read("ITEM2")).to eql 0x01000000
295
297
  expect(packet.get_item("ITEM3").range).to be_nil
296
298
  expect(packet.get_item("ITEM3").default).to eql []
299
+ expect(packet.get_item("ITEM3").id_value).to eql nil
297
300
  expect(packet.read("ITEM3")).to eql [0x01000000, 0x01000000]
298
301
  expect(packet.get_item("ITEM4").range).to eql (7..8)
299
302
  expect(packet.get_item("ITEM4").default).to eql 9
303
+ expect(packet.get_item("ITEM4").id_value).to eql 9
300
304
  expect(packet.read("ITEM4")).to eql 0x01000000
301
305
  expect(packet.get_item("ITEM5").range).to eql (10..11)
302
306
  expect(packet.get_item("ITEM5").default).to eql 12
307
+ expect(packet.get_item("ITEM5").id_value).to eql nil
303
308
  expect(packet.read("ITEM5")).to eql 0x01000000
304
309
  expect(packet.get_item("ITEM6").range).to be_nil
305
310
  expect(packet.get_item("ITEM6").default).to eql []
311
+ expect(packet.get_item("ITEM6").id_value).to eql nil
306
312
  expect(packet.read("ITEM6")).to eql [0x01000000, 0x01000000]
307
313
  expect(packet.get_item("ITEM10").range).to eql (13..14)
308
314
  expect(packet.get_item("ITEM10").default).to eql 15
315
+ expect(packet.get_item("ITEM10").id_value).to eql 15
309
316
  expect(packet.read("ITEM10")).to eql 0x00000001
310
317
  expect(packet.get_item("ITEM20").range).to eql (16..17)
311
318
  expect(packet.get_item("ITEM20").default).to eql 18
319
+ expect(packet.get_item("ITEM20").id_value).to eql nil
312
320
  expect(packet.read("ITEM20")).to eql 0x00000001
313
321
  expect(packet.get_item("ITEM30").range).to be_nil
314
322
  expect(packet.get_item("ITEM30").default).to eql []
323
+ expect(packet.get_item("ITEM30").id_value).to eql nil
315
324
  expect(packet.read("ITEM30")).to eql [0x00000001, 0x00000001]
316
325
  expect(packet.get_item("ITEM40").range).to eql (19..20)
317
326
  expect(packet.get_item("ITEM40").default).to eql 21
327
+ expect(packet.get_item("ITEM40").id_value).to eql 21
318
328
  expect(packet.read("ITEM40")).to eql 0x00000001
319
329
  expect(packet.get_item("ITEM50").range).to eql (22..23)
320
330
  expect(packet.get_item("ITEM50").default).to eql 24
331
+ expect(packet.get_item("ITEM50").id_value).to eql nil
321
332
  expect(packet.read("ITEM50")).to eql 0x00000001
322
333
  expect(packet.get_item("ITEM60").range).to be_nil
323
334
  expect(packet.get_item("ITEM60").default).to eql []
335
+ expect(packet.get_item("ITEM60").id_value).to eql nil
324
336
  expect(packet.read("ITEM60")).to eql [0x00000001, 0x00000001]
325
337
  tf.unlink
326
338
  end
@@ -0,0 +1,398 @@
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 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/packets/packet_config'
14
+ require 'tempfile'
15
+
16
+ XTCE_START =<<END
17
+ <?xml version="1.0" encoding="UTF-8"?>
18
+ <xtce:SpaceSystem xmlns:xtce="http://www.omg.org/space/xtce" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="INST" xsi:schemaLocation="http://www.omg.org/space/xtce http://www.omg.org/spec/XTCE/20061101/06-11-06.xsd">
19
+ <xtce:TelemetryMetaData>
20
+ <xtce:ParameterTypeSet>
21
+ <xtce:IntegerParameterType name="A_Type" shortDescription="A" signed="false">
22
+ <xtce:UnitSet/>
23
+ END
24
+ XTCE_END =<<END
25
+ </xtce:IntegerParameterType>
26
+ </xtce:ParameterTypeSet>
27
+ <xtce:ParameterSet>
28
+ <xtce:Parameter name="A" parameterTypeRef="A_Type">
29
+ <xtce:UnitSet/>
30
+ </xtce:Parameter>
31
+ </xtce:ParameterSet>
32
+ <xtce:ContainerSet>
33
+ <xtce:SequenceContainer name="B_Base" abstract="true">
34
+ <xtce:EntryList>
35
+ <xtce:ParameterRefEntry parameterRef="A"/>
36
+ </xtce:EntryList>
37
+ </xtce:SequenceContainer>
38
+ <xtce:SequenceContainer name="B" shortDescription="B">
39
+ <xtce:EntryList/>
40
+ <xtce:BaseContainer containerRef="B_Base">
41
+ </xtce:BaseContainer>
42
+ </xtce:SequenceContainer>
43
+ </xtce:ContainerSet>
44
+ </xtce:TelemetryMetaData>
45
+ </xtce:SpaceSystem>
46
+ END
47
+
48
+ module Cosmos
49
+
50
+ describe XtceParser do
51
+ after(:all) do
52
+ #clean_config()
53
+ end
54
+
55
+ def xml_file(target)
56
+ tf = Tempfile.new(['unittest', '.xtce'])
57
+ tf.puts '<?xml version="1.0" encoding="UTF-8"?>'
58
+ tf.puts "<xtce:SpaceSystem xmlns:xtce=\"http://www.omg.org/space/xtce\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"#{target}\" xsi:schemaLocation=\"http://www.omg.org/space/xtce http://www.omg.org/spec/XTCE/20061101/06-11-06.xsd\">"
59
+ yield tf
60
+ tf.puts '</xtce:SpaceSystem>'
61
+ tf.close
62
+ tf
63
+ end
64
+
65
+ def telemetry_file(target)
66
+ xml_file(target) do |tf|
67
+ tf.puts ' <xtce:TelemetryMetaData>'
68
+ yield tf
69
+ tf.puts ' </xtce:TelemetryMetaData>'
70
+ end
71
+ end
72
+
73
+ def add_tlm_packet_item(tf, packet, item)
74
+ tf.puts "<xtce:ParameterTypeSet>"
75
+ tf.puts " <xtce:IntegerParameterType name=\"#{item}_Type\" shortDescription=\"#{item} Description\" signed=\"false\">"
76
+ tf.puts " <xtce:IntegerDataEncoding sizeInBits=\"8\" encoding=\"unsigned\"/>"
77
+ yield tf
78
+ tf.puts " </xtce:IntegerParameterType>"
79
+ tf.puts "</xtce:ParameterTypeSet>"
80
+ tf.puts "<xtce:ParameterSet>"
81
+ tf.puts " <xtce:Parameter name=\"#{item}\" parameterTypeRef=\"#{item}_Type\"/>"
82
+ tf.puts "</xtce:ParameterSet>"
83
+ tf.puts "<xtce:ContainerSet>"
84
+ tf.puts " <xtce:SequenceContainer name=\"#{packet}_Base\" abstract=\"true\">"
85
+ tf.puts " <xtce:EntryList>"
86
+ tf.puts " <xtce:ParameterRefEntry parameterRef=\"#{item}\"/>"
87
+ tf.puts " </xtce:EntryList>"
88
+ tf.puts " </xtce:SequenceContainer>"
89
+ tf.puts " <xtce:SequenceContainer name=\"#{packet}\" shortDescription=\"Telemetry\">"
90
+ tf.puts " <xtce:EntryList/>"
91
+ tf.puts " <xtce:BaseContainer containerRef=\"#{packet}_Base\"/>"
92
+ tf.puts " </xtce:SequenceContainer>"
93
+ tf.puts "</xtce:ContainerSet>"
94
+ end
95
+
96
+ def command_file(target)
97
+ xml_file(target) do |tf|
98
+ tf.puts ' <xtce:CommandMetaData>'
99
+ yield tf
100
+ tf.puts ' </xtce:CommandMetaData>'
101
+ end
102
+ end
103
+
104
+ def add_cmd_packet_item(tf, packet, item)
105
+ tf.puts "<xtce:ArgumentTypeSet>"
106
+ tf.puts " <xtce:IntegerArgumentType name=\"#{item}_Type\" initialValue=\"0\" shortDescription=\"#{item} description\" signed=\"false\">"
107
+ tf.puts " <xtce:ByteOrderList>"
108
+ tf.puts " <xtce:Byte byteSignificance=\"0\"/>"
109
+ tf.puts " <xtce:Byte byteSignificance=\"1\"/>"
110
+ tf.puts " </xtce:ByteOrderList>"
111
+ tf.puts " <xtce:UnitSet/>"
112
+ tf.puts " <xtce:IntegerDataEncoding sizeInBits=\"16\" encoding=\"unsigned\"/>"
113
+ tf.puts " <xtce:ValidRange minInclusive=\"0\" maxInclusive=\"0\"/>"
114
+ tf.puts " </xtce:IntegerArgumentType>"
115
+ tf.puts "</xtce:ArgumentTypeSet>"
116
+ tf.puts "<xtce:MetaCommandSet>"
117
+ tf.puts " <xtce:MetaCommand name=\"#{packet}_Base\" abstract=\"true\">"
118
+ tf.puts " <xtce:ArgumentList>"
119
+ tf.puts " <xtce:Argument name=\"#{item}\" argumentTypeRef=\"#{item}_Type\"/>"
120
+ tf.puts " </xtce:ArgumentList>"
121
+ tf.puts " <xtce:CommandContainer name=\"#{packet}_CommandContainer\">"
122
+ tf.puts " <xtce:EntryList>"
123
+ tf.puts " <xtce:ArgumentRefEntry argumentRef=\"#{item}\"/>"
124
+ tf.puts " </xtce:EntryList>"
125
+ tf.puts " </xtce:CommandContainer>"
126
+ tf.puts " </xtce:MetaCommand>"
127
+ tf.puts " <xtce:MetaCommand name=\"#{packet}\" shortDescription=\"#{packet} description\">"
128
+ tf.puts " <xtce:BaseMetaCommand metaCommandRef=\"#{packet}_Base\"/>"
129
+ tf.puts " </xtce:MetaCommand>"
130
+ tf.puts "</xtce:MetaCommandSet>"
131
+ end
132
+
133
+ describe "process_file" do
134
+ before(:each) do
135
+ @pc = PacketConfig.new
136
+ end
137
+
138
+ it "processes xtce telemetry" do
139
+ tf = Tempfile.new(['unittest', '.xtce'])
140
+ tf.puts XTCE_START
141
+ tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned"/>'
142
+ tf.puts XTCE_END
143
+ tf.close
144
+
145
+ @pc.process_file(tf.path, 'TEST')
146
+ packet = @pc.telemetry['TEST']['B']
147
+ expect(packet).to_not be_nil
148
+ expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
149
+ tf.unlink
150
+ end
151
+
152
+ it "processes xtce commands" do
153
+ tf = Tempfile.new(['unittest', '.xtce'])
154
+ tf = command_file("TGT") do |tf|
155
+ add_cmd_packet_item(tf, "PKT", "PARAM1")
156
+ end
157
+
158
+ @pc.process_file(tf.path, 'TGT')
159
+ packet = @pc.commands['TGT']['PKT']
160
+ expect(packet).to_not be_nil
161
+ expect(packet.get_item('PARAM1').bit_offset).to eql 0
162
+ expect(packet.get_item('PARAM1').bit_size).to eql 16
163
+ expect(packet.get_item('PARAM1').data_type).to eql :UINT
164
+ expect(packet.get_item('PARAM1').endianness).to eql :LITTLE_ENDIAN
165
+ tf.unlink
166
+ end
167
+
168
+ context "with units" do
169
+ it "processes description and value" do
170
+ tf = telemetry_file("TGT") do |tf|
171
+ add_tlm_packet_item(tf, "PKT", "TEMP1") do |tf|
172
+ tf.puts '<xtce:UnitSet>'
173
+ tf.puts '<xtce:Unit description="Volts">V</xtce:Unit>'
174
+ tf.puts '</xtce:UnitSet>'
175
+ end
176
+ end
177
+
178
+ @pc.process_file(tf.path, 'TGT')
179
+ packet = @pc.telemetry['TGT']['PKT']
180
+ expect(packet).to_not be_nil
181
+ expect(packet.get_item('TEMP1').units).to eql 'V'
182
+ expect(packet.get_item('TEMP1').units_full).to eql 'Volts'
183
+ tf.unlink
184
+ end
185
+
186
+ it "processes description only" do
187
+ tf = telemetry_file("TGT") do |tf|
188
+ add_tlm_packet_item(tf, "PKT", "TEMP1") do |tf|
189
+ tf.puts '<xtce:UnitSet>'
190
+ tf.puts '<xtce:Unit description="Volts"/>'
191
+ tf.puts '</xtce:UnitSet>'
192
+ end
193
+ end
194
+
195
+ @pc.process_file(tf.path, 'TGT')
196
+ packet = @pc.telemetry['TGT']['PKT']
197
+ expect(packet).to_not be_nil
198
+ expect(packet.get_item('TEMP1').units).to eql 'Volts'
199
+ expect(packet.get_item('TEMP1').units_full).to eql 'Volts'
200
+ tf.unlink
201
+ end
202
+
203
+ it "processes value only" do
204
+ tf = telemetry_file("TGT") do |tf|
205
+ add_tlm_packet_item(tf, "PKT", "TEMP1") do |tf|
206
+ tf.puts '<xtce:UnitSet>'
207
+ tf.puts '<xtce:Unit>V</xtce:Unit>'
208
+ tf.puts '</xtce:UnitSet>'
209
+ end
210
+ end
211
+
212
+ @pc.process_file(tf.path, 'TGT')
213
+ packet = @pc.telemetry['TGT']['PKT']
214
+ expect(packet).to_not be_nil
215
+ expect(packet.get_item('TEMP1').units).to eql 'V'
216
+ expect(packet.get_item('TEMP1').units_full).to eql 'V'
217
+ tf.unlink
218
+ end
219
+
220
+ it "processes multiple units" do
221
+ tf = telemetry_file("TGT") do |tf|
222
+ add_tlm_packet_item(tf, "PKT", "TEMP1") do |tf|
223
+ tf.puts '<xtce:UnitSet>'
224
+ tf.puts '<xtce:Unit description="Volts">V</xtce:Unit>'
225
+ tf.puts '<xtce:Unit description="Mega">M</xtce:Unit>'
226
+ tf.puts '</xtce:UnitSet>'
227
+ end
228
+ end
229
+
230
+ @pc.process_file(tf.path, 'TGT')
231
+ packet = @pc.telemetry['TGT']['PKT']
232
+ expect(packet).to_not be_nil
233
+ expect(packet.get_item('TEMP1').units).to eql 'V/M'
234
+ expect(packet.get_item('TEMP1').units_full).to eql 'Volts/Mega'
235
+ tf.unlink
236
+ end
237
+ end
238
+
239
+ it "processes explicit big endian xtce telemetry" do
240
+ tf = Tempfile.new(['unittest', '.xtce'])
241
+ tf.puts XTCE_START
242
+ tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
243
+ tf.puts ' <xtce:ByteOrderList>' + "\n"
244
+ tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
245
+ tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
246
+ tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
247
+ tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
248
+ tf.puts ' </xtce:ByteOrderList>' + "\n"
249
+ tf.puts '</xtce:IntegerDataEncoding>' + "\n"
250
+ tf.puts XTCE_END
251
+ tf.close
252
+
253
+ @pc.process_file(tf.path, 'TEST')
254
+
255
+ packet = @pc.telemetry['TEST']['B']
256
+ expect(packet).to_not be_nil
257
+ expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
258
+ expect(@pc.warnings).to be_empty
259
+
260
+ tf.unlink
261
+ end
262
+
263
+ it "processes explicit little endian xtce telemetry" do
264
+ tf = Tempfile.new(['unittest', '.xtce'])
265
+ tf.puts XTCE_START
266
+ tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
267
+ tf.puts '
268
+ <xtce:ByteOrderList>' + "\n"
269
+ tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
270
+ tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
271
+ tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
272
+ tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
273
+ tf.puts ' </xtce:ByteOrderList>' + "\n"
274
+ tf.puts '</xtce:IntegerDataEncoding>' + "\n"
275
+ tf.puts XTCE_END
276
+ tf.close
277
+
278
+ @pc.process_file(tf.path, 'TEST')
279
+
280
+ packet = @pc.telemetry['TEST']['B']
281
+ expect(packet).to_not be_nil
282
+ expect(packet.get_item('A').endianness).to eql :LITTLE_ENDIAN
283
+ expect(@pc.warnings).to be_empty
284
+
285
+ tf.unlink
286
+ end
287
+
288
+ it "warns of bad byteorderlist no zero xtce telemetry" do
289
+ tf = Tempfile.new(['unittest', '.xtce'])
290
+ tf.puts XTCE_START
291
+ tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
292
+ tf.puts ' <xtce:ByteOrderList>' + "\n"
293
+ tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
294
+ tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
295
+ tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
296
+ tf.puts ' <xtce:Byte byteSignificance="4"/>' + "\n"
297
+ tf.puts ' </xtce:ByteOrderList>' + "\n"
298
+ tf.puts '</xtce:IntegerDataEncoding>' + "\n"
299
+ tf.puts XTCE_END
300
+ tf.close
301
+
302
+ @pc.process_file(tf.path, 'TEST')
303
+
304
+ packet = @pc.telemetry['TEST']['B']
305
+ expect(packet).to_not be_nil
306
+ expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
307
+ expect(@pc.warnings).to_not be_empty
308
+
309
+ tf.unlink
310
+ end
311
+
312
+ it "warns of bad byteorderlist scrambled xtce telemetry" do
313
+ tf = Tempfile.new(['unittest', '.xtce'])
314
+ tf.puts XTCE_START
315
+ tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
316
+ tf.puts ' <xtce:ByteOrderList>' + "\n"
317
+ tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
318
+ tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
319
+ tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
320
+ tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
321
+ tf.puts ' </xtce:ByteOrderList>' + "\n"
322
+ tf.puts '</xtce:IntegerDataEncoding>' + "\n"
323
+ tf.puts XTCE_END
324
+ tf.close
325
+
326
+ @pc.process_file(tf.path, 'TEST')
327
+
328
+ packet = @pc.telemetry['TEST']['B']
329
+ expect(packet).to_not be_nil
330
+ expect(packet.get_item('A').endianness).to eql :LITTLE_ENDIAN
331
+ expect(@pc.warnings).to_not be_empty
332
+
333
+ tf.unlink
334
+ end
335
+
336
+ it "outputs parsed definitions back to a file" do
337
+ tf = Tempfile.new('unittest')
338
+ cmd = "COMMAND TGT1 CMDPKT LITTLE_ENDIAN \"Command\"\n"\
339
+ " ID_PARAMETER CMD_OPCODE 0 16 UINT 0 0 0 \"Opcode\"\n"\
340
+ " PARAMETER CMD_UNSIGNED 16 16 UINT 0 65535 1 \"Unsigned\"\n"\
341
+ " STATE FALSE 0\n"\
342
+ " STATE TRUE 1\n"\
343
+ " PARAMETER CMD_SIGNED 32 16 INT -100 100 0 \"Signed\"\n"\
344
+ " UNITS Kilos K\n"\
345
+ " ARRAY_PARAMETER CMD_ARRAY 48 64 FLOAT 640 \"Array of 10 64bit floats\"\n"\
346
+ " PARAMETER CMD_FLOAT 688 32 FLOAT MIN MAX 10.0 \"Float\"\n"\
347
+ " POLY_WRITE_CONVERSION 10.0 0.5 0.25\n"\
348
+ " PARAMETER CMD_DOUBLE 720 64 FLOAT MIN MAX 0.0 \"Double\"\n"\
349
+ " PARAMETER CMD_STRING 784 32 STRING \"DEAD\" \"String\"\n"\
350
+ " PARAMETER CMD_STRING2 816 32 STRING 0xDEAD \"Binary\"\n"\
351
+ " PARAMETER CMD_BLOCK 848 32 BLOCK 0xBEEF \"Block\"\n"
352
+ tf.puts cmd
353
+ tlm1 = "TELEMETRY TGT1 TLMPKT BIG_ENDIAN \"Telemetry\"\n"\
354
+ " ID_ITEM TLM_OPCODE 0 8 UINT 1 \"Opcode\"\n"\
355
+ " ITEM UNSIGNED 8 8 UINT \"Unsigned\"\n"\
356
+ " STATE FALSE 0\n"\
357
+ " STATE TRUE 1\n"\
358
+ " ITEM SIGNED 16 8 INT \"Signed\"\n"\
359
+ " UNITS Kilos K\n"\
360
+ " ARRAY_ITEM ARRAY 24 8 UINT 80 \"Array\"\n"\
361
+ " ITEM FLOAT 104 32 FLOAT \"Float\"\n"\
362
+ " POLY_READ_CONVERSION 10.0 0.5 0.25\n"\
363
+ " ITEM DOUBLE 136 64 FLOAT \"Double\"\n"\
364
+ " LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0\n"\
365
+ " ITEM STRING 200 32 STRING \"String\"\n"\
366
+ " ITEM BLOCK 232 32 BLOCK \"Block\"\n"\
367
+ " ITEM NOT_PACKED 300 8 UINT \"Not packed\"\n"
368
+ tf.puts tlm1
369
+ tlm2 = "TELEMETRY TGT1 TLMPKT2 BIG_ENDIAN \"Telemetry\"\n"\
370
+ " ID_ITEM TLM_OPCODE2 0 8 UINT 1 \"Opcode\"\n"\
371
+ " ITEM UNSIGNED2 8 32 UINT \"Little endian\" LITTLE_ENDIAN\n"\
372
+ " UNITS Kilos K\n"\
373
+ " ITEM SIGNED2 40 8 INT \"Signed\"\n"\
374
+ " LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0\n"\
375
+ " ITEM SIGNED3 48 8 INT \"Signed3\"\n"
376
+ tf.puts tlm2
377
+ limits = "LIMITS_GROUP TVAC\n"\
378
+ " LIMITS_GROUP_ITEM TGT1 TLMPKT UNSIGNED\n"
379
+ tf.puts limits
380
+ tf.close
381
+ @pc.process_file(tf.path, "TGT1")
382
+ @pc.to_xtce(System.paths["LOGS"])
383
+ xml_path = File.join(System.paths["LOGS"], "TGT1", "cmd_tlm", "tgt1.xtce")
384
+ expect(File.exist?(xml_path)).to be true
385
+ @pc.process_file(xml_path, "TGT1")
386
+ @pc.to_config(System.paths["LOGS"])
387
+ cmd_config_path = File.join(System.paths["LOGS"], "TGT1", "cmd_tlm", "tgt1_cmd.txt")
388
+ expect(File.read(cmd_config_path)).to include(cmd)
389
+ tlm_config_path = File.join(System.paths["LOGS"], "TGT1", "cmd_tlm", "tgt1_tlm.txt")
390
+ tlm = File.read(tlm_config_path)
391
+ expect(tlm).to include(tlm1)
392
+ expect(tlm).to include(tlm2)
393
+ tf.unlink
394
+ end
395
+
396
+ end # describe "process_file"
397
+ end
398
+ end
@@ -0,0 +1,401 @@
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 'spec_helper'
12
+ require 'cosmos'
13
+ require 'cosmos/tools/tlm_viewer/tlm_viewer_config'
14
+ require 'tempfile'
15
+ require 'ostruct'
16
+
17
+ module Cosmos
18
+
19
+ describe TlmViewerConfig do
20
+ before(:all) do
21
+ # Allow the require widget to work
22
+ Cosmos.add_to_search_path(File.join(Cosmos::USERPATH,'../../lib/cosmos/tools/tlm_viewer/widgets'))
23
+ end
24
+
25
+ describe "initialize" do
26
+ it "checks for a given filename" do
27
+ expect { TlmViewerConfig.new('blah_file.txt') }.to raise_error("Configuration file blah_file.txt does not exist.")
28
+ end
29
+
30
+ it "raises on unknown parameters" do
31
+ tf = Tempfile.new('mylauncher.txt')
32
+ tf.puts "UNKNOWN"
33
+ tf.close
34
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
35
+ tf.unlink
36
+ end
37
+
38
+ describe 'NEW_COLUMN' do
39
+ it "creates a new column in the configuration" do
40
+ tf = Tempfile.new('mylauncher.txt')
41
+ tf.puts "NEW_COLUMN"
42
+ tf.close
43
+
44
+ tvc = TlmViewerConfig.new(tf.path)
45
+ expect(tvc.columns.length).to eq 2 # Starts with 1 by default
46
+ tf.unlink
47
+
48
+ tf = Tempfile.new('mylauncher.txt')
49
+ tf.puts "NEW_COLUMN"
50
+ tf.puts "NEW_COLUMN"
51
+ tf.close
52
+
53
+ tvc = TlmViewerConfig.new(tf.path)
54
+ expect(tvc.columns.length).to eq 3
55
+ tf.unlink
56
+ end
57
+
58
+ it "raises with parameters" do
59
+ tf = Tempfile.new('mylauncher.txt')
60
+ tf.puts "NEW_COLUMN 2"
61
+ tf.close
62
+
63
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
64
+ tf.unlink
65
+ end
66
+ end
67
+
68
+ describe 'AUTO_TARGETS' do
69
+ it "automatically parses all target screen directories" do
70
+ tf = Tempfile.new('mylauncher.txt')
71
+ tf.puts "AUTO_TARGETS"
72
+ tf.close
73
+
74
+ tvc = TlmViewerConfig.new(tf.path)
75
+ expect(tvc.screen_infos.include?("INST HS")).to be true
76
+ expect(tvc.screen_infos.include?("SYSTEM STATUS")).to be true
77
+ tf.unlink
78
+ end
79
+
80
+ it "raises with parameters" do
81
+ tf = Tempfile.new('mylauncher.txt')
82
+ tf.puts "AUTO_TARGETS TRUE"
83
+ tf.close
84
+
85
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
86
+ tf.unlink
87
+ end
88
+ end
89
+
90
+ describe 'AUTO_TARGET' do
91
+ it "automatically parses the target screen directories" do
92
+ tf = Tempfile.new('mylauncher.txt')
93
+ tf.puts "AUTO_TARGET INST"
94
+ tf.close
95
+
96
+ tvc = TlmViewerConfig.new(tf.path)
97
+ expect(tvc.screen_infos.include?("INST HS")).to be true
98
+ expect(tvc.screen_infos.include?("SYSTEM STATUS")).to be false
99
+ tf.unlink
100
+ end
101
+
102
+ it "raises with parameters" do
103
+ tf = Tempfile.new('mylauncher.txt')
104
+ tf.puts "AUTO_TARGET"
105
+ tf.close
106
+
107
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
108
+ tf.unlink
109
+ end
110
+
111
+ it "raises with more than one parameter" do
112
+ tf = Tempfile.new('mylauncher.txt')
113
+ tf.puts "AUTO_TARGET INST TRUE"
114
+ tf.close
115
+
116
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
117
+ tf.unlink
118
+ end
119
+
120
+ it "raises with an unknown target" do
121
+ tf = Tempfile.new('mylauncher.txt')
122
+ tf.puts "AUTO_TARGET BLAH"
123
+ tf.close
124
+
125
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
126
+ tf.unlink
127
+ end
128
+ end
129
+
130
+ describe 'TARGET' do
131
+ it "raises with no parameters" do
132
+ tf = Tempfile.new('mylauncher.txt')
133
+ tf.puts "TARGET"
134
+ tf.close
135
+
136
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
137
+ tf.unlink
138
+ end
139
+
140
+ it "raises with more than one parameter" do
141
+ tf = Tempfile.new('mylauncher.txt')
142
+ tf.puts "TARGET INST TRUE"
143
+ tf.close
144
+
145
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
146
+ tf.unlink
147
+ end
148
+
149
+ it "raises with an unknown target" do
150
+ tf = Tempfile.new('mylauncher.txt')
151
+ tf.puts "TARGET BLAH"
152
+ tf.close
153
+
154
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
155
+ tf.unlink
156
+ end
157
+ end
158
+
159
+ describe "SCREEN" do
160
+ it "parses a specified target, screen and position" do
161
+ tf = Tempfile.new('mylauncher.txt')
162
+ tf.puts "TARGET INST"
163
+ tf.puts "SCREEN hs.txt 100 200"
164
+ tf.close
165
+
166
+ tvc = TlmViewerConfig.new(tf.path)
167
+ expect(tvc.screen_infos.include?("INST HS")).to be true
168
+ expect(tvc.screen_infos["INST HS"].x_pos).to eql 100
169
+ expect(tvc.screen_infos["INST HS"].y_pos).to eql 200
170
+ tf.unlink
171
+ end
172
+
173
+ it "raises unless preceeded by TARGET" do
174
+ tf = Tempfile.new('mylauncher.txt')
175
+ tf.puts "SCREEN hs.txt"
176
+ tf.close
177
+
178
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
179
+ tf.unlink
180
+ end
181
+
182
+ it "raises with no parameters" do
183
+ tf = Tempfile.new('mylauncher.txt')
184
+ tf.puts "TARGET INST"
185
+ tf.puts "SCREEN"
186
+ tf.close
187
+
188
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
189
+ tf.unlink
190
+ end
191
+
192
+ it "raises with more than 3 parameters" do
193
+ tf = Tempfile.new('mylauncher.txt')
194
+ tf.puts "TARGET INST"
195
+ tf.puts "SCREEN hs.txt 100 200 300"
196
+ tf.close
197
+
198
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
199
+ tf.unlink
200
+ end
201
+ end
202
+
203
+ describe "SHOW_ON_STARTUP" do
204
+ it "indicates a screen should be shown when TlmViewer launches" do
205
+ tf = Tempfile.new('mylauncher.txt')
206
+ tf.puts "TARGET INST"
207
+ tf.puts "SCREEN hs.txt 100 200"
208
+ tf.puts "SHOW_ON_STARTUP"
209
+ tf.close
210
+
211
+ tvc = TlmViewerConfig.new(tf.path)
212
+ expect(tvc.screen_infos.include?("INST HS")).to be true
213
+ expect(tvc.screen_infos["INST HS"].show_on_startup).to be true
214
+ tf.unlink
215
+ end
216
+
217
+ it "raises unless preceeded by SCREEN" do
218
+ tf = Tempfile.new('mylauncher.txt')
219
+ tf.puts "SHOW_ON_STARTUP"
220
+ tf.close
221
+
222
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
223
+ tf.unlink
224
+ end
225
+
226
+ it "raises with parameters" do
227
+ tf = Tempfile.new('mylauncher.txt')
228
+ tf.puts "TARGET INST"
229
+ tf.puts "SCREEN hs.txt"
230
+ tf.puts "SHOW_ON_STARTUP TRUE"
231
+ tf.close
232
+
233
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
234
+ tf.unlink
235
+ end
236
+ end
237
+
238
+ describe "ADD_SHOW_ON_STARTUP" do
239
+ it "indicates a screen should be shown when TlmViewer launches" do
240
+ tf = Tempfile.new('mylauncher.txt')
241
+ tf.puts "AUTO_TARGETS"
242
+ tf.puts "ADD_SHOW_ON_STARTUP INST HS 100 200"
243
+ tf.close
244
+
245
+ tvc = TlmViewerConfig.new(tf.path)
246
+ expect(tvc.screen_infos.include?("INST HS")).to be true
247
+ expect(tvc.screen_infos["INST HS"].show_on_startup).to be true
248
+ tf.unlink
249
+ end
250
+
251
+ it "raises if the screen wasn't previously defined" do
252
+ tf = Tempfile.new('mylauncher.txt')
253
+ tf.puts "ADD_SHOW_ON_STARTUP INST HS 100 200"
254
+ tf.close
255
+
256
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
257
+ tf.unlink
258
+ end
259
+
260
+ it "raises with less than 2 parameters" do
261
+ tf = Tempfile.new('mylauncher.txt')
262
+ tf.puts "ADD_SHOW_ON_STARTUP INST"
263
+ tf.close
264
+
265
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
266
+ tf.unlink
267
+ end
268
+
269
+ it "raises with more than 4 parameters" do
270
+ tf = Tempfile.new('mylauncher.txt')
271
+ tf.puts "ADD_SHOW_ON_STARTUP INST hs.txt 100 200 300"
272
+ tf.close
273
+
274
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
275
+ tf.unlink
276
+ end
277
+ end
278
+
279
+ describe "GROUP" do
280
+ it "defines a new group in TlmViewer" do
281
+ tf = Tempfile.new('mylauncher.txt')
282
+ tf.puts "GROUP Tester"
283
+ tf.close
284
+
285
+ tvc = TlmViewerConfig.new(tf.path)
286
+ expect(tvc.columns[0].keys.include?("Tester")).to be true
287
+ tf.unlink
288
+ end
289
+
290
+ it "raises with no parameters" do
291
+ tf = Tempfile.new('mylauncher.txt')
292
+ tf.puts "GROUP"
293
+ tf.close
294
+
295
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
296
+ tf.unlink
297
+ end
298
+
299
+ it "raises with more than 1 parameter" do
300
+ tf = Tempfile.new('mylauncher.txt')
301
+ tf.puts "GROUP Tester Tester"
302
+ tf.close
303
+
304
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
305
+ tf.unlink
306
+ end
307
+ end
308
+
309
+ describe "GROUP_SCREEN" do
310
+ it "defines a screen in a group" do
311
+ tf = Tempfile.new('mylauncher.txt')
312
+ #tf.puts "AUTO_TARGETS"
313
+ tf.puts "TARGET INST"
314
+ tf.puts "SCREEN hs.txt"
315
+ tf.puts "GROUP Tester"
316
+ tf.puts "GROUP_SCREEN INST HS 100 200"
317
+ tf.close
318
+
319
+ tvc = TlmViewerConfig.new(tf.path)
320
+ expect(tvc.columns[0]["Tester"]["INST_HS"].group).to eql "Tester"
321
+ tf.unlink
322
+ end
323
+
324
+ it "raises with less than 2 parameters" do
325
+ tf = Tempfile.new('mylauncher.txt')
326
+ tf.puts "GROUP_SCREEN INST"
327
+ tf.close
328
+
329
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
330
+ tf.unlink
331
+ end
332
+
333
+ it "raises with more than 4 parameter" do
334
+ tf = Tempfile.new('mylauncher.txt')
335
+ tf.puts "GROUP_SCREEN INST HS 100 200 300"
336
+ tf.close
337
+
338
+ expect { TlmViewerConfig.new(tf.path) }.to raise_error(Cosmos::ConfigParser::Error)
339
+ tf.unlink
340
+ end
341
+ end
342
+
343
+ describe "to_save" do
344
+ it "saves AUTO_TARGETS as TARGET/SCREEN" do
345
+ tf = Tempfile.new('mylauncher.txt')
346
+ tf.puts "AUTO_TARGETS"
347
+ tf.close
348
+
349
+ tvc = TlmViewerConfig.new(tf.path)
350
+ config_file = File.join(Cosmos::USERPATH, "test_config.txt")
351
+ tvc.save(config_file)
352
+ tf.unlink
353
+
354
+ config = File.read(config_file)
355
+ expect(config).to match /TARGET "INST"/
356
+ expect(config).to match /SCREEN "hs.txt"/
357
+ expect(config).to match /TARGET "SYSTEM"/
358
+ expect(config).to match /SCREEN "status.txt"/
359
+ end
360
+
361
+ it "saves the configuration" do
362
+ tf = Tempfile.new('mylauncher.txt')
363
+ inst_hs = "TARGET \"INST\"\n"\
364
+ " SCREEN \"hs.txt\"\n"\
365
+ " SHOW_ON_STARTUP\n"
366
+ tf.puts inst_hs
367
+ tf.puts "NEW_COLUMN"
368
+ test_group = "GROUP \"Test\"\n"\
369
+ " GROUP_SCREEN SYSTEM STATUS 100 200\n"\
370
+ " GROUP_SCREEN INST HS\n"\
371
+ " SHOW_ON_STARTUP\n"
372
+ tf.puts test_group
373
+ another_group = "GROUP \"2Another\"\n"\
374
+ " GROUP_SCREEN INST HS\n"\
375
+ " GROUP_SCREEN SYSTEM STATUS 300 400\n"\
376
+ " SHOW_ON_STARTUP\n"
377
+ tf.puts another_group
378
+ tf.puts "NEW_COLUMN"
379
+ tf.puts "TARGET SYSTEM"
380
+ tf.puts " SCREEN status.txt"
381
+ tf.puts "ADD_SHOW_ON_STARTUP SYSTEM STATUS 500 600"
382
+ tf.close
383
+
384
+ tvc = TlmViewerConfig.new(tf.path)
385
+ config_file = File.join(Cosmos::USERPATH, "test_config.txt")
386
+ tvc.save(config_file)
387
+ tf.unlink
388
+
389
+ config = File.read(config_file)
390
+ expect(config).to include(inst_hs)
391
+ expect(config).to include(test_group)
392
+ expect(config).to include(test_group)
393
+ expect(config).to include("TARGET \"SYSTEM\"\n SCREEN \"status.txt\" 500 600\n SHOW_ON_STARTUP")
394
+ expect(config.scan(/NEW_COLUMN/).count).to eql 2
395
+ end
396
+ end
397
+
398
+ end
399
+ end
400
+ end
401
+