cosmos 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +5 -0
- data/appveyor.yml +2 -0
- data/autohotkey/tools/replay.ahk +45 -45
- data/autohotkey/tools/script_runner.ahk +3 -9
- data/cosmos.gemspec +1 -1
- data/data/config/interface_modifiers.yaml +23 -0
- data/data/config/screen.yaml +1 -1
- data/data/crc.txt +20 -18
- data/demo/config/targets/INST/cmd_tlm_server.txt +1 -1
- data/lib/cosmos/config/config_parser.rb +8 -3
- data/lib/cosmos/gui/dialogs/exception_dialog.rb +20 -5
- data/lib/cosmos/interfaces/protocols/burst_protocol.rb +13 -3
- data/lib/cosmos/interfaces/protocols/crc_protocol.rb +27 -3
- data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +4 -2
- data/lib/cosmos/interfaces/protocols/length_protocol.rb +4 -2
- data/lib/cosmos/interfaces/protocols/override_protocol.rb +2 -2
- data/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +3 -2
- data/lib/cosmos/interfaces/protocols/protocol.rb +16 -4
- data/lib/cosmos/interfaces/protocols/template_protocol.rb +7 -2
- data/lib/cosmos/interfaces/protocols/terminated_protocol.rb +4 -2
- data/lib/cosmos/packets/packet_config.rb +19 -859
- data/lib/cosmos/packets/packet_item.rb +56 -201
- data/lib/cosmos/packets/parsers/xtce_converter.rb +440 -0
- data/lib/cosmos/packets/parsers/xtce_parser.rb +682 -0
- data/lib/cosmos/tools/config_editor/config_editor.rb +143 -5
- data/lib/cosmos/tools/tlm_viewer/screen.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +5 -3
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +40 -27
- data/lib/cosmos/version.rb +4 -4
- data/spec/config/config_parser_spec.rb +39 -2
- data/spec/install/config/targets/INST/screens/hs.txt +42 -0
- data/spec/install/config/targets/INST/target.txt +2 -0
- data/spec/interfaces/protocols/burst_protocol_spec.rb +18 -0
- data/spec/interfaces/protocols/length_protocol_spec.rb +49 -0
- data/spec/interfaces/udp_interface_spec.rb +0 -9
- data/spec/packets/packet_config_spec.rb +21 -144
- data/spec/packets/packet_item_spec.rb +68 -4
- data/spec/packets/parsers/packet_item_parser_spec.rb +12 -0
- data/spec/packets/parsers/xtce_parser_spec.rb +398 -0
- data/spec/tools/tlm_viewer/tlm_viewer_config_spec.rb +401 -0
- metadata +9 -10
@@ -0,0 +1,42 @@
|
|
1
|
+
SCREEN AUTO AUTO 0.5
|
2
|
+
GLOBAL_SETTING LABELVALUELIMITSBAR COLORBLIND TRUE
|
3
|
+
|
4
|
+
VERTICAL
|
5
|
+
|
6
|
+
TITLE "Instrument Health and Status"
|
7
|
+
SETTING BACKCOLOR 162 181 205
|
8
|
+
SETTING TEXTCOLOR black
|
9
|
+
|
10
|
+
VERTICALBOX
|
11
|
+
SECTIONHEADER "General Telemetry"
|
12
|
+
NAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL
|
13
|
+
BUTTON 'Start Collect' 'target_name = get_target_name("INST"); cmd("#{target_name} COLLECT with TYPE NORMAL, DURATION 5")'
|
14
|
+
FORMATVALUE INST HEALTH_STATUS COLLECTS "0x%08X"
|
15
|
+
LABELVALUE INST HEALTH_STATUS COLLECT_TYPE
|
16
|
+
LABELVALUE INST HEALTH_STATUS DURATION
|
17
|
+
LABELVALUE INST HEALTH_STATUS ASCIICMD WITH_UNITS 30
|
18
|
+
END
|
19
|
+
SETTING BACKCOLOR 163 185 163
|
20
|
+
|
21
|
+
VERTICALBOX
|
22
|
+
SECTIONHEADER "Temperatures"
|
23
|
+
LABELTRENDLIMITSBAR INST HEALTH_STATUS TEMP1 WITH_UNITS 5
|
24
|
+
LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP2 CONVERTED 25
|
25
|
+
# LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP2 RAW 20 # RAW is not allowed for LIMITSBAR widgets
|
26
|
+
LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP2 FORMATTED
|
27
|
+
LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP2 WITH_UNITS
|
28
|
+
LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP3
|
29
|
+
LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP4
|
30
|
+
SETTING GRAY_TOLERANCE 0.1
|
31
|
+
END
|
32
|
+
SETTING BACKCOLOR 203 173 158
|
33
|
+
|
34
|
+
VERTICALBOX
|
35
|
+
SECTIONHEADER "Ground Station"
|
36
|
+
LABELVALUE INST HEALTH_STATUS GROUND1STATUS
|
37
|
+
LABELVALUE INST HEALTH_STATUS GROUND2STATUS
|
38
|
+
END
|
39
|
+
|
40
|
+
SETTING BACKCOLOR 207 171 169
|
41
|
+
END
|
42
|
+
SETTING BACKCOLOR 162 181 205
|
@@ -197,6 +197,24 @@ module Cosmos
|
|
197
197
|
pkt = @interface.read
|
198
198
|
expect(pkt.length).to eql 3 # sync plus one byte
|
199
199
|
end
|
200
|
+
|
201
|
+
it "handle auto allow_empty_data correctly" do
|
202
|
+
@interface.add_protocol(BurstProtocol, [0, nil, false, nil], :READ_WRITE)
|
203
|
+
expect(@interface.read_protocols[0].read_data("")).to eql :STOP
|
204
|
+
expect(@interface.read_protocols[0].read_data("A")).to eql "A"
|
205
|
+
@interface.add_protocol(BurstProtocol, [0, nil, false, nil], :READ_WRITE)
|
206
|
+
expect(@interface.read_protocols[0].read_data("")).to eql ""
|
207
|
+
expect(@interface.read_protocols[1].read_data("")).to eql :STOP
|
208
|
+
expect(@interface.read_protocols[0].read_data("A")).to eql "A"
|
209
|
+
expect(@interface.read_protocols[1].read_data("A")).to eql "A"
|
210
|
+
@interface.add_protocol(BurstProtocol, [0, nil, false, nil], :READ_WRITE)
|
211
|
+
expect(@interface.read_protocols[0].read_data("")).to eql ""
|
212
|
+
expect(@interface.read_protocols[1].read_data("")).to eql ""
|
213
|
+
expect(@interface.read_protocols[2].read_data("")).to eql :STOP
|
214
|
+
expect(@interface.read_protocols[0].read_data("A")).to eql "A"
|
215
|
+
expect(@interface.read_protocols[1].read_data("A")).to eql "A"
|
216
|
+
expect(@interface.read_protocols[2].read_data("A")).to eql "A"
|
217
|
+
end
|
200
218
|
end
|
201
219
|
|
202
220
|
describe "write" do
|
@@ -46,6 +46,55 @@ module Cosmos
|
|
46
46
|
end
|
47
47
|
|
48
48
|
describe "read" do
|
49
|
+
it "caches data for reads correctly" do
|
50
|
+
@interface.instance_variable_set(:@stream, LengthStream.new)
|
51
|
+
@interface.add_protocol(LengthProtocol, [
|
52
|
+
0, # bit offset
|
53
|
+
8, # bit size
|
54
|
+
0, # length offset
|
55
|
+
1, # bytes per count
|
56
|
+
'BIG_ENDIAN'], :READ_WRITE)
|
57
|
+
$buffer = "\x02\x03\x02\x05"
|
58
|
+
packet = @interface.read
|
59
|
+
expect(packet.buffer.length).to eql 2
|
60
|
+
expect(packet.buffer).to eql "\x02\x03"
|
61
|
+
packet = @interface.read
|
62
|
+
expect(packet.buffer.length).to eql 2
|
63
|
+
expect(packet.buffer).to eql "\x02\x05"
|
64
|
+
expect(@interface.read_protocols[0].read_data("\x03\x01\x02\x03\x04\x05")).to eql "\x03\x01\x02"
|
65
|
+
expect(@interface.read_protocols[0].read_data("")).to eql "\x03\x04\x05"
|
66
|
+
expect(@interface.read_protocols[0].read_data("")).to eql :STOP
|
67
|
+
end
|
68
|
+
|
69
|
+
# This test case uses two length protocols to verify that data flows correctly between the two protocols and that earlier data
|
70
|
+
# is removed correctly using discard leading bytes. In general it is not typical to use two different length protocols, but it could
|
71
|
+
# be useful to pull out a packet inside of a packet.
|
72
|
+
it "caches data for reads correctly with multiple protocols" do
|
73
|
+
@interface.instance_variable_set(:@stream, LengthStream.new)
|
74
|
+
@interface.add_protocol(LengthProtocol, [
|
75
|
+
0, # bit offset
|
76
|
+
8, # bit size
|
77
|
+
0, # length offset
|
78
|
+
1, # bytes per count
|
79
|
+
'BIG_ENDIAN'], :READ_WRITE)
|
80
|
+
@interface.add_protocol(LengthProtocol, [
|
81
|
+
0, # bit offset
|
82
|
+
8, # bit size
|
83
|
+
0, # length offset
|
84
|
+
1, # bytes per count
|
85
|
+
'BIG_ENDIAN',
|
86
|
+
1], :READ_WRITE) # Discard leading bytes set to 1
|
87
|
+
# The second protocol above will receive the two byte packets from the first protocol and
|
88
|
+
# then drop the length field.
|
89
|
+
$buffer = "\x02\x03\x02\x05"
|
90
|
+
packet = @interface.read
|
91
|
+
expect(packet.buffer.length).to eql 1
|
92
|
+
expect(packet.buffer).to eql "\x03"
|
93
|
+
packet = @interface.read
|
94
|
+
expect(packet.buffer.length).to eql 1
|
95
|
+
expect(packet.buffer).to eql "\x05"
|
96
|
+
end
|
97
|
+
|
49
98
|
it "reads LITTLE_ENDIAN length fields from the stream" do
|
50
99
|
@interface.instance_variable_set(:@stream, LengthStream.new)
|
51
100
|
@interface.add_protocol(LengthProtocol, [
|
@@ -100,15 +100,6 @@ module Cosmos
|
|
100
100
|
end
|
101
101
|
|
102
102
|
describe "read" do
|
103
|
-
it "stops the read thread if no read port given" do
|
104
|
-
i = UdpInterface.new('localhost','8888','nil')
|
105
|
-
i.connect
|
106
|
-
thread = Thread.new { i.read }
|
107
|
-
sleep 0.1
|
108
|
-
expect(thread.stop?).to be true
|
109
|
-
Cosmos.kill_thread(nil, thread)
|
110
|
-
end
|
111
|
-
|
112
103
|
it "stops the read thread if there is an IOError" do
|
113
104
|
read = double("read")
|
114
105
|
allow(read).to receive(:read).and_raise(IOError)
|
@@ -13,36 +13,6 @@ require 'cosmos'
|
|
13
13
|
require 'cosmos/packets/packet_config'
|
14
14
|
require 'tempfile'
|
15
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:ParameterSet>
|
30
|
-
<xtce:ContainerSet>
|
31
|
-
<xtce:SequenceContainer name="B_Base" abstract="true">
|
32
|
-
<xtce:EntryList>
|
33
|
-
<xtce:ParameterRefEntry parameterRef="A"/>
|
34
|
-
</xtce:EntryList>
|
35
|
-
</xtce:SequenceContainer>
|
36
|
-
<xtce:SequenceContainer name="B" shortDescription="B">
|
37
|
-
<xtce:EntryList/>
|
38
|
-
<xtce:BaseContainer containerRef="B_Base">
|
39
|
-
</xtce:BaseContainer>
|
40
|
-
</xtce:SequenceContainer>
|
41
|
-
</xtce:ContainerSet>
|
42
|
-
</xtce:TelemetryMetaData>
|
43
|
-
</xtce:SpaceSystem>
|
44
|
-
END
|
45
|
-
|
46
16
|
module Cosmos
|
47
17
|
|
48
18
|
describe PacketConfig do
|
@@ -52,120 +22,6 @@ module Cosmos
|
|
52
22
|
@pc = PacketConfig.new
|
53
23
|
end
|
54
24
|
|
55
|
-
describe "xtce support" do
|
56
|
-
it "processes xtce telemetry" do
|
57
|
-
tf = Tempfile.new(['unittest', '.xtce'])
|
58
|
-
tf.puts XTCE_START
|
59
|
-
tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned"/>'
|
60
|
-
tf.puts XTCE_END
|
61
|
-
tf.close
|
62
|
-
|
63
|
-
@pc.process_file(tf.path, 'TEST')
|
64
|
-
|
65
|
-
packet = @pc.telemetry['TEST']['B']
|
66
|
-
expect(packet).to_not be_nil
|
67
|
-
expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
|
68
|
-
|
69
|
-
tf.unlink
|
70
|
-
end
|
71
|
-
|
72
|
-
it "processes explicit big endian xtce telemetry" do
|
73
|
-
tf = Tempfile.new(['unittest', '.xtce'])
|
74
|
-
tf.puts XTCE_START
|
75
|
-
tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
|
76
|
-
tf.puts ' <xtce:ByteOrderList>' + "\n"
|
77
|
-
tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
|
78
|
-
tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
|
79
|
-
tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
|
80
|
-
tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
|
81
|
-
tf.puts ' </xtce:ByteOrderList>' + "\n"
|
82
|
-
tf.puts '</xtce:IntegerDataEncoding>' + "\n"
|
83
|
-
tf.puts XTCE_END
|
84
|
-
tf.close
|
85
|
-
|
86
|
-
@pc.process_file(tf.path, 'TEST')
|
87
|
-
|
88
|
-
packet = @pc.telemetry['TEST']['B']
|
89
|
-
expect(packet).to_not be_nil
|
90
|
-
expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
|
91
|
-
expect(@pc.warnings).to be_empty
|
92
|
-
|
93
|
-
tf.unlink
|
94
|
-
end
|
95
|
-
|
96
|
-
it "processes explicit little endian xtce telemetry" do
|
97
|
-
tf = Tempfile.new(['unittest', '.xtce'])
|
98
|
-
tf.puts XTCE_START
|
99
|
-
tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
|
100
|
-
tf.puts ' <xtce:ByteOrderList>' + "\n"
|
101
|
-
tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
|
102
|
-
tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
|
103
|
-
tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
|
104
|
-
tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
|
105
|
-
tf.puts ' </xtce:ByteOrderList>' + "\n"
|
106
|
-
tf.puts '</xtce:IntegerDataEncoding>' + "\n"
|
107
|
-
tf.puts XTCE_END
|
108
|
-
tf.close
|
109
|
-
|
110
|
-
@pc.process_file(tf.path, 'TEST')
|
111
|
-
|
112
|
-
packet = @pc.telemetry['TEST']['B']
|
113
|
-
expect(packet).to_not be_nil
|
114
|
-
expect(packet.get_item('A').endianness).to eql :LITTLE_ENDIAN
|
115
|
-
expect(@pc.warnings).to be_empty
|
116
|
-
|
117
|
-
tf.unlink
|
118
|
-
end
|
119
|
-
|
120
|
-
it "warn of bad byteorderlist no zero xtce telemetry" do
|
121
|
-
tf = Tempfile.new(['unittest', '.xtce'])
|
122
|
-
tf.puts XTCE_START
|
123
|
-
tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
|
124
|
-
tf.puts ' <xtce:ByteOrderList>' + "\n"
|
125
|
-
tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
|
126
|
-
tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
|
127
|
-
tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
|
128
|
-
tf.puts ' <xtce:Byte byteSignificance="4"/>' + "\n"
|
129
|
-
tf.puts ' </xtce:ByteOrderList>' + "\n"
|
130
|
-
tf.puts '</xtce:IntegerDataEncoding>' + "\n"
|
131
|
-
tf.puts XTCE_END
|
132
|
-
tf.close
|
133
|
-
|
134
|
-
@pc.process_file(tf.path, 'TEST')
|
135
|
-
|
136
|
-
packet = @pc.telemetry['TEST']['B']
|
137
|
-
expect(packet).to_not be_nil
|
138
|
-
expect(packet.get_item('A').endianness).to eql :BIG_ENDIAN
|
139
|
-
expect(@pc.warnings).to_not be_empty
|
140
|
-
|
141
|
-
tf.unlink
|
142
|
-
end
|
143
|
-
|
144
|
-
it "warn of bad byteorderlist scrambled xtce telemetry" do
|
145
|
-
tf = Tempfile.new(['unittest', '.xtce'])
|
146
|
-
tf.puts XTCE_START
|
147
|
-
tf.puts '<xtce:IntegerDataEncoding sizeInBits="32" encoding="unsigned">' + "\n"
|
148
|
-
tf.puts ' <xtce:ByteOrderList>' + "\n"
|
149
|
-
tf.puts ' <xtce:Byte byteSignificance="0"/>' + "\n"
|
150
|
-
tf.puts ' <xtce:Byte byteSignificance="2"/>' + "\n"
|
151
|
-
tf.puts ' <xtce:Byte byteSignificance="1"/>' + "\n"
|
152
|
-
tf.puts ' <xtce:Byte byteSignificance="3"/>' + "\n"
|
153
|
-
tf.puts ' </xtce:ByteOrderList>' + "\n"
|
154
|
-
tf.puts '</xtce:IntegerDataEncoding>' + "\n"
|
155
|
-
tf.puts XTCE_END
|
156
|
-
tf.close
|
157
|
-
|
158
|
-
@pc.process_file(tf.path, 'TEST')
|
159
|
-
|
160
|
-
packet = @pc.telemetry['TEST']['B']
|
161
|
-
expect(packet).to_not be_nil
|
162
|
-
expect(packet.get_item('A').endianness).to eql :LITTLE_ENDIAN
|
163
|
-
expect(@pc.warnings).to_not be_empty
|
164
|
-
|
165
|
-
tf.unlink
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
25
|
it "complains about unknown keywords" do
|
170
26
|
tf = Tempfile.new('unittest')
|
171
27
|
tf.puts("BLAH")
|
@@ -174,6 +30,27 @@ module Cosmos
|
|
174
30
|
tf.unlink
|
175
31
|
end
|
176
32
|
|
33
|
+
it "outputs parsed definitions back to a file" do
|
34
|
+
tf = Tempfile.new('unittest')
|
35
|
+
tlm = "TELEMETRY TGT1 PKT1 LITTLE_ENDIAN \"Telemetry\"\n"\
|
36
|
+
" ITEM BYTE 0 8 UINT \"Item\"\n"
|
37
|
+
tf.write tlm
|
38
|
+
cmd = "COMMAND TGT1 PKT1 LITTLE_ENDIAN \"Command\"\n"\
|
39
|
+
" PARAMETER PARAM 0 16 UINT 0 0 0 \"Param\"\n"
|
40
|
+
tf.write cmd
|
41
|
+
limits = "LIMITS_GROUP TVAC\n"\
|
42
|
+
" LIMITS_GROUP_ITEM TGT1 PKT1 ITEM1\n"
|
43
|
+
tf.write limits
|
44
|
+
tf.close
|
45
|
+
@pc.process_file(tf.path, "TGT1")
|
46
|
+
@pc.to_config(System.paths["LOGS"])
|
47
|
+
@pc.to_xtce(System.paths["LOGS"])
|
48
|
+
expect(cmd.strip).to eql File.read(File.join(System.paths["LOGS"], 'TGT1', 'cmd_tlm', 'tgt1_cmd.txt')).strip
|
49
|
+
expect(tlm.strip).to eql File.read(File.join(System.paths["LOGS"], 'TGT1', 'cmd_tlm', 'tgt1_tlm.txt')).strip
|
50
|
+
expect(limits.strip).to eql File.read(File.join(System.paths["LOGS"], 'SYSTEM', 'cmd_tlm', 'limits_groups.txt')).strip
|
51
|
+
tf.unlink
|
52
|
+
end
|
53
|
+
|
177
54
|
context "with all telemetry keywords" do
|
178
55
|
before(:all) do
|
179
56
|
# top level keywords
|
@@ -24,6 +24,7 @@ module Cosmos
|
|
24
24
|
it "sets the format_string" do
|
25
25
|
@pi.format_string = "%5.1f"
|
26
26
|
expect(@pi.format_string).to eql "%5.1f"
|
27
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match /FORMAT_STRING %5.1f/
|
27
28
|
end
|
28
29
|
|
29
30
|
it "sets the format_string to nil" do
|
@@ -47,6 +48,10 @@ module Cosmos
|
|
47
48
|
c = GenericConversion.new("value / 2")
|
48
49
|
@pi.read_conversion = c
|
49
50
|
expect(@pi.read_conversion.to_s == c.to_s).to be true
|
51
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
52
|
+
expect(config).to match /GENERIC_READ_CONVERSION_START/
|
53
|
+
expect(config).to match /value \/ 2/
|
54
|
+
expect(config).to match /GENERIC_READ_CONVERSION_END/
|
50
55
|
end
|
51
56
|
|
52
57
|
it "sets the read_conversion to nil" do
|
@@ -64,6 +69,10 @@ module Cosmos
|
|
64
69
|
c = GenericConversion.new("value / 2")
|
65
70
|
@pi.write_conversion = c
|
66
71
|
expect(@pi.write_conversion.to_s == c.to_s).to be true
|
72
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
73
|
+
expect(config).to match /GENERIC_WRITE_CONVERSION_START/
|
74
|
+
expect(config).to match /value \/ 2/
|
75
|
+
expect(config).to match /GENERIC_WRITE_CONVERSION_END/
|
67
76
|
end
|
68
77
|
|
69
78
|
it "sets the write_conversion to nil" do
|
@@ -78,14 +87,22 @@ module Cosmos
|
|
78
87
|
|
79
88
|
describe "id_value=" do
|
80
89
|
it "accepts id values according to data_type" do
|
90
|
+
@pi.range = (0..10)
|
81
91
|
@pi.id_value = 10
|
82
92
|
expect(@pi.id_value).to eql 10
|
83
93
|
@pi.data_type = :FLOAT
|
84
94
|
@pi.id_value = 10.0
|
85
95
|
expect(@pi.id_value).to eql 10.0
|
96
|
+
expect(@pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/ID_PARAMETER TEST 0 32 FLOAT 0 10 10.0/)
|
97
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/ID_ITEM TEST 0 32 FLOAT 10.0/)
|
86
98
|
@pi.data_type = :STRING
|
87
99
|
@pi.id_value = "HI"
|
88
100
|
expect(@pi.id_value).to eql "HI"
|
101
|
+
expect(@pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/ID_PARAMETER TEST 0 32 STRING "HI"/)
|
102
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/ID_ITEM TEST 0 32 STRING "HI"/)
|
103
|
+
@pi.id_value = "\xDE\xAD\xBE\xEF" # binary
|
104
|
+
expect(@pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/ID_PARAMETER TEST 0 32 STRING 0xDEADBEEF/)
|
105
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/ID_ITEM TEST 0 32 STRING 0xDEADBEEF/)
|
89
106
|
end
|
90
107
|
|
91
108
|
it "sets the id_value to nil" do
|
@@ -105,6 +122,9 @@ module Cosmos
|
|
105
122
|
states = {"TRUE"=>1, "FALSE"=>0}
|
106
123
|
@pi.states = states
|
107
124
|
expect(@pi.states).to eql states
|
125
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
126
|
+
expect(config).to match(/STATE TRUE 1/)
|
127
|
+
expect(config).to match(/STATE FALSE 0/)
|
108
128
|
end
|
109
129
|
|
110
130
|
it "sets the states to nil" do
|
@@ -122,6 +142,7 @@ module Cosmos
|
|
122
142
|
description = "this is it"
|
123
143
|
@pi.description = description
|
124
144
|
expect(@pi.description).to eql description
|
145
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/ITEM TEST 0 32 UINT "this is it"/)
|
125
146
|
end
|
126
147
|
|
127
148
|
it "sets the description to nil" do
|
@@ -156,6 +177,8 @@ module Cosmos
|
|
156
177
|
units = "V"
|
157
178
|
@pi.units = units
|
158
179
|
expect(@pi.units).to eql units
|
180
|
+
@pi.units_full = "Volts"
|
181
|
+
expect(@pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/UNITS Volts V/)
|
159
182
|
end
|
160
183
|
|
161
184
|
it "sets the units to nil" do
|
@@ -173,15 +196,25 @@ module Cosmos
|
|
173
196
|
pi = PacketItem.new("test", 0, 8, :INT, :BIG_ENDIAN, 16)
|
174
197
|
pi.default = [1, -1]
|
175
198
|
expect(pi.default).to eql [1, -1]
|
199
|
+
expect(pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/ARRAY_PARAMETER TEST 0 8 INT 16/)
|
200
|
+
expect(pi.to_config(:TELEMETRY, :BIG_ENDIAN)).to match(/ARRAY_ITEM TEST 0 8 INT 16/)
|
176
201
|
pi = PacketItem.new("test", 0, 32, :UINT, :BIG_ENDIAN, nil)
|
202
|
+
pi.range = (0..10)
|
177
203
|
pi.default = 0x01020304
|
178
204
|
expect(pi.default).to eql 0x01020304
|
205
|
+
expect(pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/PARAMETER TEST 0 32 UINT 0 10 16909060/)
|
179
206
|
pi = PacketItem.new("test", 0, 32, :FLOAT, :BIG_ENDIAN, nil)
|
207
|
+
pi.range = (-10..10)
|
180
208
|
pi.default = 5.5
|
181
209
|
expect(pi.default).to eql 5.5
|
210
|
+
expect(pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/PARAMETER TEST 0 32 FLOAT -10 10 5.5/)
|
182
211
|
pi = PacketItem.new("test", 0, 32, :STRING, :BIG_ENDIAN, nil)
|
183
212
|
pi.default = "HI"
|
184
213
|
expect(pi.default).to eql "HI"
|
214
|
+
expect(pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/PARAMETER TEST 0 32 STRING "HI"/)
|
215
|
+
pi = PacketItem.new("test", 0, 32, :STRING, :BIG_ENDIAN, nil)
|
216
|
+
pi.default = "\xDE\xAD\xBE\xEF"
|
217
|
+
expect(pi.to_config(:COMMAND, :BIG_ENDIAN)).to match(/PARAMETER TEST 0 32 STRING 0xDEADBEEF/)
|
185
218
|
end
|
186
219
|
|
187
220
|
it "sets the default to nil" do
|
@@ -269,6 +302,12 @@ module Cosmos
|
|
269
302
|
expect(@pi.hazardous).to eql hazardous
|
270
303
|
expect(@pi.hazardous["TRUE"]).to eql hazardous["TRUE"]
|
271
304
|
expect(@pi.hazardous["FALSE"]).to eql hazardous["FALSE"]
|
305
|
+
|
306
|
+
@pi.range = (0..1)
|
307
|
+
@pi.states = {"TRUE"=>1, "FALSE"=>0}
|
308
|
+
config = @pi.to_config(:COMMAND, :BIG_ENDIAN)
|
309
|
+
expect(config).to match(/STATE TRUE 1/)
|
310
|
+
expect(config).to match(/STATE FALSE 0 HAZARDOUS "NO FALSE ALLOWED"/)
|
272
311
|
end
|
273
312
|
|
274
313
|
it "sets hazardous to nil" do
|
@@ -286,6 +325,12 @@ module Cosmos
|
|
286
325
|
state_colors = {"TRUE"=>:GREEN, "FALSE"=>:RED}
|
287
326
|
@pi.state_colors = state_colors
|
288
327
|
expect(@pi.state_colors).to eql state_colors
|
328
|
+
|
329
|
+
@pi.range = (0..1)
|
330
|
+
@pi.states = {"TRUE"=>1, "FALSE"=>0}
|
331
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
332
|
+
expect(config).to match(/STATE TRUE 1 GREEN/)
|
333
|
+
expect(config).to match(/STATE FALSE 0 RED/)
|
289
334
|
end
|
290
335
|
|
291
336
|
it "sets the state_colors to nil" do
|
@@ -301,7 +346,16 @@ module Cosmos
|
|
301
346
|
describe "limits=" do
|
302
347
|
it "accepts limits as a PacketItemLimits" do
|
303
348
|
limits = PacketItemLimits.new
|
349
|
+
limits.values = {DEFAULT: [10, 20, 80, 90, 40, 50], TVAC: [100, 200, 800, 900]}
|
304
350
|
@pi.limits = limits
|
351
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
352
|
+
expect(config).to match(/LIMITS DEFAULT 1 DISABLED 10 20 80 90 40 50/)
|
353
|
+
expect(config).to match(/LIMITS TVAC 1 DISABLED 100 200 800 900/)
|
354
|
+
@pi.limits.enabled = true
|
355
|
+
@pi.limits.persistence_setting = 3
|
356
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
357
|
+
expect(config).to match(/LIMITS DEFAULT 3 ENABLED 10 20 80 90 40 50/)
|
358
|
+
expect(config).to match(/LIMITS TVAC 3 ENABLED 100 200 800 900/)
|
305
359
|
end
|
306
360
|
|
307
361
|
it "sets the limits to nil" do
|
@@ -314,10 +368,20 @@ module Cosmos
|
|
314
368
|
end
|
315
369
|
end
|
316
370
|
|
317
|
-
describe "meta" do
|
318
|
-
it "allows
|
319
|
-
@pi.meta
|
320
|
-
|
371
|
+
describe "meta=" do
|
372
|
+
it "only allows a hash" do
|
373
|
+
expect { @pi.meta = 1 }.to raise_error(ArgumentError, /must be a Hash/)
|
374
|
+
end
|
375
|
+
|
376
|
+
it "sets the meta hash" do
|
377
|
+
@pi.meta = { 'TYPE' => ['float32', 'uint8'], 'TEST' => ["test string"] }
|
378
|
+
expect(@pi.meta['TYPE']).to eql ['float32', 'uint8']
|
379
|
+
expect(@pi.meta['TEST']).to eql ["test string"]
|
380
|
+
config = @pi.to_config(:TELEMETRY, :BIG_ENDIAN)
|
381
|
+
expect(config).to match(/META TYPE float32 uint8/)
|
382
|
+
expect(config).to match(/META TEST "test string"/)
|
383
|
+
@pi.meta = nil # Clear the meta hash
|
384
|
+
expect(@pi.meta.empty?).to be true # Clearing it results in empty hash
|
321
385
|
end
|
322
386
|
end
|
323
387
|
|