openc3-cosmos-demo 6.0.2 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 231e6075158197e5c69a00c65a7104fb68adba7088dd0a9ae8c23f566a6d514f
4
- data.tar.gz: b1b38d14dbc759655936764f6a35adfbed12ae3875dedd05b5bc9b78174ec664
3
+ metadata.gz: c888a30f0d6951c4b7c2c10f8868e8c80569e09eac181b6998777c79d824b4a0
4
+ data.tar.gz: 9d7ec85c58a58937720cb368059bca004544cd1d8f6227c65c7fba83dc75d96a
5
5
  SHA512:
6
- metadata.gz: '081623a648d0e9c52127c31d8a57af6efb179d1831d7bb25635d4d88baf2cd8db4409be3395131a6e4fc81a557e23db1ce26a32962e87cec7d78dced7f155831'
7
- data.tar.gz: 32691c50f96230d8dddcd2f820ac47a05f7e00516e5f740679c19ad742ee505d69f7c4b0277b3dc7d9efe46a616a8884131a8e3bf2ff91451fa3928307431945
6
+ metadata.gz: e818d703ee7703d87cd5796da6efb4aa83b1f17a934ebd0aa25a3dc89af83640464a2193d40c45d054d82543e899291bfb3732498362dc5fed8c95f7b2f40fe3
7
+ data.tar.gz: 466106a6e5effdf51249e8ad0cd7780b66350fd94450498020331b591a8f1fc4209d9d0878b8f4045b4bfe0385238dc488065985e8ab30ea0d5e726af159b58b
@@ -97,6 +97,8 @@ COMMAND <%= target_name %> TIME_OFFSET BIG_ENDIAN "Subtract the packet time by t
97
97
  VALIDATOR inst_cmd_validator.rb
98
98
  <%= render "_ccsds_cmd.txt", locals: {id: 12} %>
99
99
  APPEND_PARAMETER SECONDS 32 UINT MIN MAX 0 "Seconds to subtract from packet time"
100
+ APPEND_PARAMETER IP_ADDRESS 32 UINT MIN MAX "127.0.0.1" "IP address"
101
+ WRITE_CONVERSION ip_write_conversion.rb
100
102
 
101
103
  COMMAND <%= target_name %> HIDDEN BIG_ENDIAN "Hidden command to bump the hidden packet"
102
104
  VALIDATOR inst_cmd_validator.rb
@@ -73,6 +73,14 @@ TELEMETRY <%= target_name %> HEALTH_STATUS BIG_ENDIAN "Health and status from th
73
73
  GENERIC_READ_CONVERSION_START FLOAT 32
74
74
  packet.read('TEMP1') * 1_000_000
75
75
  GENERIC_READ_CONVERSION_END
76
+ # Enable to test the ARRAYPLOT widget with array of array data [[x1,x2,...],[y1,y2,...]]
77
+ # ITEM POINTS 0 0 DERIVED
78
+ # GENERIC_READ_CONVERSION_START UINT 800
79
+ # return [
80
+ # Array.new(800) { |i| i * 0.1 },
81
+ # (0...800).map { |i| Math.sin(2 * Math::PI * i / 800) }
82
+ # ]
83
+ # GENERIC_READ_CONVERSION_END
76
84
  PROCESSOR TEMP1STAT statistics_processor.rb TEMP1 100
77
85
  PROCESSOR TEMP1WATER watermark_processor.rb TEMP1
78
86
 
@@ -127,6 +135,7 @@ TELEMETRY <%= target_name %> PARAMS BIG_ENDIAN "Params set by SETPARAMS command"
127
135
  STATE GOOD 0 GREEN
128
136
  STATE BAD 1 RED
129
137
  <% end %>
138
+ APPEND_ITEM IP_ADDRESS 32 UINT "Encoded IP Address"
130
139
  APPEND_ITEM P_2.2,2 32 UINT "Test weird characters"
131
140
  APPEND_ITEM P-3+3=3 32 UINT "Test weird characters"
132
141
  APPEND_ITEM P4!@#$%^&*? 32 UINT "Test weird characters"
@@ -160,6 +169,7 @@ TELEMETRY <%= target_name %> MECH BIG_ENDIAN "Mechanism status ©®"
160
169
  UNITS DEGREES DEG
161
170
  APPEND_ITEM CURRENT 32 FLOAT "Device current"
162
171
  UNITS micro-Ampères µA
172
+ APPEND_ITEM STRING 0 STRING "String"
163
173
  ITEM PACKET_TIME 0 0 DERIVED "Ruby time based on TIMESEC and TIMEUS"
164
174
  READ_CONVERSION unix_time_conversion.rb TIMESEC TIMEUS
165
175
 
@@ -22,6 +22,7 @@ class InstCmdValidator < OpenC3::CommandValidator
22
22
  def pre_check(command)
23
23
  # Record the current value of CMD_ACPT_CNT for comparison in post_check
24
24
  @cmd_acpt_cnt = tlm("<%= target_name %> HEALTH_STATUS CMD_ACPT_CNT")
25
+ @cmd_acpt_cnt ||= 0 # If the telemetry value is nil, set it to 0
25
26
  return [true, nil]
26
27
  end
27
28
 
@@ -152,6 +152,7 @@ module OpenC3
152
152
  @last_temp2 = 0
153
153
  @quiet = false
154
154
  @time_offset = 0
155
+ @ip_address = 0
155
156
  end
156
157
 
157
158
  def set_rates
@@ -238,6 +239,7 @@ module OpenC3
238
239
  when 'TIME_OFFSET'
239
240
  hs_packet.cmd_acpt_cnt += 1
240
241
  @time_offset = packet.read('seconds')
242
+ @ip_address = packet.read('ip_address')
241
243
  when 'HIDDEN'
242
244
  # Deliberately do not increment cmd_acpt_cnt
243
245
  @tlm_packets['HIDDEN'].count = packet.read('count')
@@ -378,6 +380,7 @@ module OpenC3
378
380
  packet.timesec = time.tv_sec - @time_offset
379
381
  packet.timeus = time.tv_usec
380
382
  packet.ccsdsseqcnt += 1
383
+ packet.ip_address = @ip_address
381
384
 
382
385
  when 'IMAGE'
383
386
  packet.timesec = time.tv_sec - @time_offset
@@ -1,43 +1,68 @@
1
- tl = create_timeline("Mine")
2
- puts tl #=> {"name"=>"Mine", "color"=>"#ae2d1b", "scope"=>"DEFAULT", "updated_at"=>1698763720728596964}
1
+ tl = create_timeline("RubyTL")
2
+ puts tl #=> {"name"=>"RubyTL", "color"=>"#cdce42", "execute"=>true, "shard"=>0, "scope"=>"DEFAULT", "updated_at"=>1737128664493258134}
3
3
  tls = list_timelines()
4
- check_expression("#{tls.length} == 1")
5
- puts tls[0] #=> {"name"=>"Mine", "color"=>"#ae2d1b", "scope"=>"DEFAULT", "updated_at"=>1698763720728596964}
6
- delete_timeline("Mine")
7
- check_expression("#{list_timelines().length} == 0")
4
+ names = tls.map { |tl| tl['name'] }
5
+ check_expression("#{names.include?('RubyTL')} == true")
6
+ puts tls[0] #=> {"name"=>"RubyTL", "color"=>"#cdce42", "execute"=>true, "shard"=>0, "scope"=>"DEFAULT", "updated_at"=>1737128664493258134}
8
7
 
9
- create_timeline("Mine")
10
- set_timeline_color("Mine", "#4287f5")
11
- puts get_timeline("Mine") #=> {"name"=>"Mine", "color"=>"#4287f5", "scope"=>"DEFAULT", "updated_at"=>1698763720728596964}
8
+ set_timeline_color("RubyTL", "#4287f5")
9
+ puts get_timeline("RubyTL") #=> {"name"=>"RubyTL", "color"=>"#4287f5", "execute"=>true, "shard"=>0, "scope"=>"DEFAULT", "updated_at"=>1737128689586673173}
12
10
 
13
11
  now = Time.now()
14
12
  start = now + 3600
15
- stop = start + 3600 # Stop plus 1hr
16
- act = create_timeline_activity("Mine", kind: "reserve", start: start, stop: stop)
13
+ stop = start + 3600
14
+ act1 = create_timeline_activity("RubyTL", kind: "RESERVE", start: start, stop: stop)
15
+ puts act1 #=>
16
+ # { "name"=>"RubyTL", "updated_at"=>1737128705034982375, "start"=>1737132303, "stop"=>1737135903,
17
+ # "kind"=>"reserve", "data"=>{"username"=>"operator"},
18
+ # "scope"=>"DEFAULT", "fulfillment"=>false, "uuid"=>"5f373846-eb6c-43cd-97bd-cca19a8ffb04",
19
+ # "events"=>[{"time"=>1737128705, "event"=>"created"}], "recurring"=>{}}
20
+ act2 = create_timeline_activity("RubyTL", kind: "COMMAND", start: start, stop: stop,
21
+ data: {command: "INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10"})
22
+ puts act2 #=>
23
+ # { "name"=>"RubyTL", "updated_at"=>1737128761316084471, "start"=>1737132303, "stop"=>1737135903,
24
+ # "kind"=>"command", "data"=>{"command"=>"INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10", "username"=>"operator"},
25
+ # "scope"=>"DEFAULT", "fulfillment"=>false, "uuid"=>"cdb661b4-a65b-44e7-95e2-5e1dba80c782",
26
+ # "events"=>[{"time"=>1737128761, "event"=>"created"}], "recurring"=>{}}
27
+ start = now + 7200
28
+ stop = start + 3600
29
+ act3 = create_timeline_activity("RubyTL", kind: "SCRIPT", start: start, stop: stop,
30
+ data: {environment: [{key: "USER", value: "JASON"}], script: "INST/procedures/checks.rb"})
31
+ puts act3 #=>
32
+ # { "name"=>"RubyTL", "updated_at"=>1737128791047885970, "start"=>1737135903, "stop"=>1737139503,
33
+ # "kind"=>"script", "data"=>{"environment"=>[{"key"=>"USER", "value"=>"JASON"}], "script"=>"INST/procedures/checks.rb", "username"=>"operator"},
34
+ # "scope"=>"DEFAULT", "fulfillment"=>false, "uuid"=>"70426e3d-6313-4897-b159-6e5cd94ace1d",
35
+ # "events"=>[{"time"=>1737128791, "event"=>"created"}], "recurring"=>{}}
36
+
37
+ act = get_timeline_activity("RubyTL", act2['start'], act2['uuid'])
17
38
  puts act #=>
18
- # { "name"=>"Mine", "updated_at"=>1698763721927799173, "fulfillment"=>false, "duration"=>3600,
19
- # "start"=>1698764400, "stop"=>1698768000, "kind"=>"reserve",
20
- # "events"=>[{"time"=>1698763721, "event"=>"created"}], "data"=>{"username"=>""} }
39
+ # { "name"=>"RubyTL", "updated_at"=>1737128761316084471, "start"=>1737132303, "stop"=>1737135903,
40
+ # "kind"=>"command", "data"=>{"command"=>"INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10", "username"=>"operator"},
41
+ # "scope"=>"DEFAULT", "fulfillment"=>false, "uuid"=>"cdb661b4-a65b-44e7-95e2-5e1dba80c782",
42
+ # "events"=>[{"time"=>1737128761, "event"=>"created"}], "recurring"=>{}}
43
+
21
44
  # Get activities in the past ... should be none
22
- tlas = get_timeline_activities("Mine", start: Time.now() - 3600, stop: Time.now())
45
+ tlas = get_timeline_activities("RubyTL", start: Time.now() - 3600, stop: Time.now())
23
46
  check_expression("#{tlas.length} == 0")
24
- # Get all activities
25
- tlas = get_timeline_activities("Mine")
26
- check_expression("#{tlas.length} == 1")
47
+ # Get all activities at plus and minus 1 week
48
+ tlas = get_timeline_activities("RubyTL")
49
+ check_expression("#{tlas.length} == 3")
27
50
 
28
51
  # Create and delete a new activity
29
52
  start = start + 7200
30
53
  stop = start + 300
31
- act = create_timeline_activity("Mine", kind: "reserve", start: start, stop: stop)
32
- tlas = get_timeline_activities("Mine")
33
- check_expression("#{tlas.length} == 2")
34
- delete_timeline_activity("Mine", act['start'], act['uuid'])
35
- tlas = get_timeline_activities("Mine")
36
- check_expression("#{tlas.length} == 1")
54
+ act = create_timeline_activity("RubyTL", kind: "reserve", start: start, stop: stop)
55
+ tlas = get_timeline_activities("RubyTL")
56
+ check_expression("#{tlas.length} == 4")
57
+ delete_timeline_activity("RubyTL", act['start'], act['uuid'])
58
+ tlas = get_timeline_activities("RubyTL")
59
+ check_expression("#{tlas.length} == 3")
37
60
 
38
61
  # delete fails since the timeline has activities
39
- delete_timeline("Mine") #=> RuntimeError : Failed to delete timeline due to timeline contains activities, must force remove
62
+ delete_timeline("RubyTL") #=> RuntimeError : Failed to delete timeline due to timeline contains activities, must force remove
40
63
  # Force delete since the timeline has activities
41
- delete_timeline("Mine", force: true)
64
+ delete_timeline("RubyTL", force: true)
65
+ # Verify the timeline no longer exists
42
66
  tls = list_timelines()
43
- check_expression("#{tls.length} == 0")
67
+ names = tls.map { |tl| tl['name'] }
68
+ check_expression("#{names.include?('RubyTL')} == false")
@@ -1,4 +1,4 @@
1
- # Display all environment variables
1
+ # Display the environment variables
2
2
  puts ENV.inspect
3
3
  # Print the TYPE env var which is set in the INST COMMANDING screen
4
4
  puts "ENV['TYPE']:#{ENV['TYPE']}"
@@ -17,5 +17,5 @@ wait_expression("true == false", 5)
17
17
  wait_packet("<%= target_name %>","ADCS", 2, 5)
18
18
  wait_check("<%= target_name %> ADCS BIASX == 100", 5)
19
19
  wait_check_tolerance("<%= target_name %> ADCS BIASX", 5, 0.5, 5)
20
- wait_check_expression("true == false", 5)
20
+ wait_check_expression("tlm('<%= target_name %> HEALTH_STATUS TEMP1') < 101", 5, 0.25)
21
21
  wait_check_packet("<%= target_name %>","ADCS", 2, 5)
@@ -0,0 +1,88 @@
1
+ # Helper method to check for a script to change state
2
+ def wait_for_action(id, state)
3
+ i = 0
4
+ while i < 100
5
+ script = running_script_get(id)
6
+ if script['state'] == state
7
+ check_expression("'#{script['state']}' == '#{state}'")
8
+ break
9
+ end
10
+ wait 0.1
11
+ end
12
+ check_expression("'#{script['state']}' == '#{state}'")
13
+ end
14
+
15
+ SCRIPT_NAME = "INST/procedures/new_script.rb"
16
+
17
+ # Ensure it's not already there
18
+ step_mode()
19
+ script_delete(SCRIPT_NAME)
20
+ scripts = script_list()
21
+ check_expression("#{scripts.length} > 100")
22
+ run_mode()
23
+
24
+ contents = "puts('bad"
25
+ script_create(SCRIPT_NAME, contents)
26
+ body = script_body(SCRIPT_NAME)
27
+ result = script_syntax_check(body)
28
+ check_expression("#{result['success']} == false")
29
+
30
+ # Create a valid script that doesn't complete
31
+ contents = "set_line_delay(1)\nputs 'Hello from Ruby'\nputs('.')\nputs('.')\nwhile true\nputs Time.now\nwait 0.5\nwait 0.5\nend"
32
+ script_create(SCRIPT_NAME, contents)
33
+ scripts = script_list()
34
+ check_expression("#{scripts.include?(SCRIPT_NAME)} == true")
35
+
36
+ script = script_instrumented(contents)
37
+ check_expression("#{script.include?('RunningScript')} == true")
38
+
39
+ id = script_run(SCRIPT_NAME)
40
+ check_expression("#{id.to_i} > 0")
41
+ wait_for_action(id, 'running')
42
+
43
+ list = running_script_list()
44
+ started = list.select {|script| script["id"] == id}[0]
45
+ check_expression("'#{started['name']}' == SCRIPT_NAME")
46
+ script = running_script_get(id)
47
+ check_expression("'#{script['name']}' == SCRIPT_NAME")
48
+
49
+ running_script_pause(id)
50
+ wait_for_action(id, 'paused')
51
+ running_script_step(id)
52
+ wait_for_action(id, 'paused')
53
+ running_script_retry(id)
54
+ wait_for_action(id, 'paused')
55
+ running_script_go(id)
56
+ wait_for_action(id, 'running')
57
+ running_script_stop(id)
58
+ wait 1
59
+
60
+ list = running_script_list()
61
+ script = list.select {|script| script["id"] == id}[0]
62
+ # Script is stopped so it should NOT be in the running list
63
+ check_expression("#{script.nil?} == true")
64
+
65
+ list = completed_script_list()
66
+ script = list.select {|script| script["id"] == id}[0]
67
+ # Script is completed so it should be in the completed list
68
+ check_expression("#{script.nil?} == false")
69
+
70
+ id = script_run(SCRIPT_NAME)
71
+ wait_for_action(id, 'running')
72
+ running_script_delete(id) # Stop and completely remove the script
73
+ wait 1
74
+
75
+ list = running_script_list()
76
+ script = list.select {|script| script["id"] == id}[0]
77
+ # Script is deleted, so it should NOT be in the running list
78
+ check_expression("#{script.nil?} == true")
79
+ list = completed_script_list()
80
+ # Script is deleted so it should be in the completed list
81
+ script = list.select {|script| script["id"] == id}[0]
82
+ check_expression("#{script.nil?} == false")
83
+
84
+ script_lock(SCRIPT_NAME)
85
+ script_unlock(SCRIPT_NAME)
86
+ script_delete(SCRIPT_NAME)
87
+ scripts = script_list()
88
+ check_expression("#{scripts.include?(SCRIPT_NAME)} == false")
@@ -1,27 +1,32 @@
1
1
  SCREEN AUTO AUTO 1.0
2
2
 
3
- VERTICAL
4
- TITLE "<%= target_name %> Instrument Graphs"
3
+ TITLE "<%= target_name %> Instrument Graphs"
5
4
 
6
- MATRIXBYCOLUMNS 2
7
- SPARKLINE <%= target_name %> HEALTH_STATUS TEMP1
8
- SETTING SIZE 400 50
9
- SETTING HISTORY 30s
10
- SPARKLINE <%= target_name %> HEALTH_STATUS TEMP2
11
- SETTING SIZE 400 50
12
- SETTING HISTORY 30s
13
- LABELSPARKLINE <%= target_name %> HEALTH_STATUS TEMP3
14
- LABELSPARKLINE <%= target_name %> HEALTH_STATUS TEMP4
15
- LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP1
16
- SETTING ITEM <%= target_name %> ADCS Q1
17
- LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP2 RAW
18
- SETTING SECONDSGRAPHED 60
19
- SETTING POINTSSAVED 600
20
- SETTING POINTSGRAPHED 60
21
- LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP3 CONVERTED REDUCED_MINUTE MIN
22
- SETTING SIZE 600 500 # width height
23
- SETTING HISTORY 1h
24
- LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP4
25
- SETTING HISTORY 30m
26
- END
5
+ MATRIXBYCOLUMNS 2
6
+ SPARKLINE <%= target_name %> HEALTH_STATUS TEMP1
7
+ SETTING SIZE 400 50
8
+ SETTING HISTORY 30s
9
+ SPARKLINE <%= target_name %> HEALTH_STATUS TEMP2
10
+ SETTING SIZE 400 50
11
+ SETTING HISTORY 30s
12
+ LABELSPARKLINE <%= target_name %> HEALTH_STATUS TEMP3
13
+ LABELSPARKLINE <%= target_name %> HEALTH_STATUS TEMP4
14
+ LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP1
15
+ SETTING ITEM <%= target_name %> ADCS Q1
16
+ LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP2 RAW
17
+ SETTING SECONDSGRAPHED 60
18
+ SETTING POINTSSAVED 600
19
+ SETTING POINTSGRAPHED 60
20
+ LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP3 CONVERTED REDUCED_MINUTE MIN
21
+ SETTING SIZE 600 500 # width height
22
+ SETTING HISTORY 1h
23
+ LINEGRAPH <%= target_name %> HEALTH_STATUS TEMP4
24
+ SETTING HISTORY 30m
27
25
  END
26
+
27
+ ARRAYPLOT
28
+ SETTING TITLE "Array Data"
29
+ SETTING ITEM INST HEALTH_STATUS ARY
30
+ SETTING ITEM INST HEALTH_STATUS ARY2
31
+ SETTING SIZE 600 400
32
+ SETTING X_AXIS 10 10
@@ -29,9 +29,11 @@ COMMAND <%= target_name %> SETPARAMS BIG_ENDIAN "Sets numbered parameters"
29
29
  <%= render "_ccsds_cmd.txt", locals: {id: 4} %>
30
30
  # ERB syntax:
31
31
  <% (1..5).each do |i| %>
32
- APPEND_PARAMETER VALUE<%= i %> 16 UINT 0 5 1 "Value <%= i %> setting"
32
+ # The packet is BIG_ENDIAN (CCSDS) but these fields are LITTLE_ENDIAN
33
+ APPEND_PARAMETER VALUE<%= i %> 16 UINT 0 5 1 "Value <%= i %> setting" LITTLE_ENDIAN
33
34
  RELATED_ITEM <%= target_name %> PARAMS VALUE<%= i %>
34
35
  <% end %>
36
+ SCREEN <%= target_name %> PARAMS
35
37
 
36
38
  SELECT_PARAMETER VALUE5
37
39
  POLY_WRITE_CONVERSION 0 2
@@ -95,6 +97,8 @@ COMMAND <%= target_name %> TIME_OFFSET BIG_ENDIAN "Subtract the packet time by t
95
97
  VALIDATOR inst2_cmd_validator.py
96
98
  <%= render "_ccsds_cmd.txt", locals: {id: 12} %>
97
99
  APPEND_PARAMETER SECONDS 32 UINT MIN MAX 0 "Seconds to subtract from packet time"
100
+ APPEND_PARAMETER IP_ADDRESS 32 UINT MIN MAX "127.0.0.1" "IP address"
101
+ WRITE_CONVERSION openc3/conversions/ip_write_conversion.py
98
102
 
99
103
  COMMAND <%= target_name %> HIDDEN BIG_ENDIAN "Hidden command to bump the hidden packet"
100
104
  VALIDATOR inst2_cmd_validator.py
@@ -65,6 +65,14 @@ TELEMETRY <%= target_name %> HEALTH_STATUS BIG_ENDIAN "Health and status from th
65
65
  READ_CONVERSION openc3/conversions/processor_conversion.py TEMP1STAT MEAN
66
66
  ITEM TEMP1STDDEV 0 0 DERIVED "Stddev of most recent 100 samples for TEMP1"
67
67
  READ_CONVERSION openc3/conversions/processor_conversion.py TEMP1STAT STDDEV
68
+ ITEM TEMP1_MICRO 0 0 DERIVED
69
+ GENERIC_READ_CONVERSION_START FLOAT 32
70
+ packet.read('TEMP1') / 1_000_000
71
+ GENERIC_READ_CONVERSION_END
72
+ ITEM TEMP1_MEGA 0 0 DERIVED
73
+ GENERIC_READ_CONVERSION_START FLOAT 32
74
+ packet.read('TEMP1') * 1_000_000
75
+ GENERIC_READ_CONVERSION_END
68
76
  PROCESSOR TEMP1STAT openc3/processors/statistics_processor.py TEMP1 100
69
77
  PROCESSOR TEMP1WATER openc3/processors/watermark_processor.py TEMP1
70
78
 
@@ -119,6 +127,7 @@ TELEMETRY <%= target_name %> PARAMS BIG_ENDIAN "Params set by SETPARAMS command"
119
127
  STATE GOOD 0 GREEN
120
128
  STATE BAD 1 RED
121
129
  <% end %>
130
+ APPEND_ITEM IP_ADDRESS 32 UINT "Encoded IP Address"
122
131
  APPEND_ITEM P_2.2,2 32 UINT "Test weird characters"
123
132
  APPEND_ITEM P-3+3=3 32 UINT "Test weird characters"
124
133
  APPEND_ITEM P4!@#$%^&*? 32 UINT "Test weird characters"
@@ -137,7 +146,7 @@ TELEMETRY <%= target_name %> IMAGE BIG_ENDIAN "Packet with image data"
137
146
  ITEM PACKET_TIME 0 0 DERIVED "Python time based on TIMESEC and TIMEUS"
138
147
  READ_CONVERSION openc3/conversions/unix_time_conversion.py TIMESEC TIMEUS
139
148
 
140
- TELEMETRY <%= target_name %> MECH BIG_ENDIAN "Mechanism status"
149
+ TELEMETRY <%= target_name %> MECH BIG_ENDIAN "Mechanism status ©®"
141
150
  <%= render "_ccsds_tlm.txt", locals: {apid: 5} %>
142
151
  APPEND_ITEM EXTRA 32 FLOAT "Extra item to be deleted"
143
152
  APPEND_ITEM SLRPNL1 32 FLOAT "Solar panel 1 angle"
@@ -148,6 +148,7 @@ class SimInst(SimulatedTarget):
148
148
  self.last_temp2 = 0
149
149
  self.quiet = False
150
150
  self.time_offset = 0
151
+ self.ip_address = 0
151
152
 
152
153
  def set_rates(self):
153
154
  self.set_rate("ADCS", 10)
@@ -213,6 +214,7 @@ class SimInst(SimulatedTarget):
213
214
  case "TIME_OFFSET":
214
215
  hs_packet.write("cmd_acpt_cnt", hs_packet.read("cmd_acpt_cnt") + 1)
215
216
  self.time_offset = packet.read("seconds")
217
+ self.ip_address = packet.read("ip_address")
216
218
  case "HIDDEN":
217
219
  # Deliberately do not increment cmd_acpt_cnt
218
220
  self.tlm_packets["HIDDEN"].count = packet.read("count")
@@ -382,6 +384,7 @@ class SimInst(SimulatedTarget):
382
384
  packet.write("timesec", int(time - self.time_offset))
383
385
  packet.write("timeus", int((time % 1) * 1000000))
384
386
  packet.write("ccsdsseqcnt", packet.read("ccsdsseqcnt") + 1)
387
+ packet.write("ip_address", self.ip_address)
385
388
 
386
389
  case "IMAGE":
387
390
  packet.write("timesec", int(time - self.time_offset))
@@ -1,57 +1,72 @@
1
1
  from datetime import datetime, timezone, timedelta
2
2
 
3
- tl = create_timeline("Mine")
4
- print(
5
- tl
6
- ) # => {"name":"Mine", "color":"#ae2d1b", "scope":"DEFAULT", "updated_at":1698763720728596964}
3
+ tl = create_timeline("PythonTL", color="#FF0000")
4
+ print(tl) #=> {'name': 'PythonTL', 'color': '#FF0000', 'execute': True, 'shard': 0, 'scope': 'DEFAULT', 'updated_at': 1737129062249843763}
7
5
  tls = list_timelines()
8
- print(tls)
9
- print(type(tls))
10
- check_expression(f"{len(tls)} == 1")
11
- print(
12
- tls[0]
13
- ) # => {"name":"Mine", "color":"#ae2d1b", "scope":"DEFAULT", "updated_at":1698763720728596964}
14
- delete_timeline("Mine")
15
- check_expression(f"{len(list_timelines())} == 0")
6
+ print(tls) #=> [{'name': 'PythonTL', 'color': '#FF0000', 'execute': True, 'shard': 0, 'scope': 'DEFAULT', 'updated_at': 1737129062249843763}]
7
+ names = [tl["name"] for tl in tls]
8
+ check_expression(f"{'PythonTL' in names} == True")
9
+ print(tls[0]) #=> {'name': 'PythonTL', 'color': '#FF0000', 'execute': True, 'shard': 0, 'scope': 'DEFAULT', 'updated_at': 1737129436186473255}
16
10
 
17
- create_timeline("Mine")
18
- set_timeline_color("Mine", "#4287f5")
19
- print(
20
- get_timeline("Mine")
21
- ) # => {"name":"Mine", "color":"#4287f5", "scope":"DEFAULT", "updated_at":1698763720728596964}
11
+ set_timeline_color("PythonTL", "#4287f5")
12
+ print(get_timeline("PythonTL")) #=> {'name': 'PythonTL', 'color': '#4287f5', 'execute': True, 'shard': 0, 'scope': 'DEFAULT', 'updated_at': 1737129508391137136}
22
13
 
23
14
  now = datetime.now(timezone.utc)
24
15
  start = now + timedelta(hours=1)
25
- stop = start + timedelta(hours=1) # Stop plus 1hr
26
- act = create_timeline_activity("Mine", kind="reserve", start=start, stop=stop)
27
- print(act) # =>
28
- # { "name"=>"Mine", "updated_at"=>1698763721927799173, "fulfillment"=>false, "duration"=>3600,
29
- # "start"=>1698764400, "stop"=>1698768000, "kind"=>"reserve",
30
- # "events"=>[{"time"=>1698763721, "event"=>"created"}], "data"=>{"username"=>""} }
16
+ stop = start + timedelta(hours=1)
17
+ act1 = create_timeline_activity("PythonTL", kind="reserve", start=start, stop=stop)
18
+ print(act1) # =>
19
+ # {'name': 'PythonTL', 'updated_at': 1737129305507111708, 'start': 1737132902, 'stop': 1737136502,
20
+ # 'kind': 'reserve', 'data': {'username': 'operator'},
21
+ # 'scope': 'DEFAULT', 'fulfillment': False, 'uuid': '46328378-ed78-4719-ad70-e84951a196fd',
22
+ # 'events': [{'time': 1737129305, 'event': 'created'}], 'recurring': {}}
23
+ act2 = create_timeline_activity("PythonTL", kind="COMMAND", start=start, stop=stop,
24
+ data={'command': "INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10"})
25
+ print(act2) #=>
26
+ # {'name': 'PythonTL', 'updated_at': 1737129508886643928, 'start': 1737133108, 'stop': 1737136708,
27
+ # 'kind': 'command', 'data': {'command': 'INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10', 'username': 'operator'},
28
+ # 'scope': 'DEFAULT', 'fulfillment': False, 'uuid': 'cddbf034-ccdd-4c36-91c2-2653a39b06a5',
29
+ # 'events': [{'time': 1737129508, 'event': 'created'}], 'recurring': {}}
30
+ start = now + timedelta(hours=2)
31
+ stop = start + timedelta(hours=1)
32
+ act3 = create_timeline_activity("PythonTL", kind="SCRIPT", start=start, stop=stop,
33
+ data={'environment': [{'key': "USER", 'value': "JASON"}], 'script': "INST2/procedures/checks.py"})
34
+ print(act3) #=>
35
+ # {'name': 'PythonTL', 'updated_at': 1737129509288571345, 'start': 1737136708, 'stop': 1737140308,
36
+ # 'kind': 'script', 'data': {'environment': [{'key': 'USER', 'value': 'JASON'}], 'script': 'INST2/procedures/checks.py', 'username': 'operator'},
37
+ # 'scope': 'DEFAULT', 'fulfillment': False, 'uuid': '4f8d791b-b138-4383-b5ec-85c28b2bea20',
38
+ # 'events': [{'time': 1737129509, 'event': 'created'}], 'recurring': {}}
39
+
40
+ act = get_timeline_activity("PythonTL", act2['start'], act2['uuid'])
41
+ print(act) #=>
42
+ # { "name"=>"RubyTL", "updated_at"=>1737128761316084471, "start"=>1737132303, "stop"=>1737135903,
43
+ # "kind"=>"command", "data"=>{"command"=>"INST COLLECT with TYPE NORMAL, DURATION 5, TEMP 10", "username"=>"operator"},
44
+ # "scope"=>"DEFAULT", "fulfillment"=>false, "uuid"=>"cdb661b4-a65b-44e7-95e2-5e1dba80c782",
45
+ # "events"=>[{"time"=>1737128761, "event"=>"created"}], "recurring"=>{}}
46
+
31
47
  # Get activities in the past ... should be none
32
- tlas = get_timeline_activities("Mine", start=start - timedelta(hours=2), stop=now)
48
+ tlas = get_timeline_activities("PythonTL", start=now - timedelta(hours=2), stop=now)
33
49
  print(tlas)
34
50
  print(type(tlas))
35
51
  check_expression(f"{len(tlas)} == 0")
36
- # Get all activities
37
- tlas = get_timeline_activities("Mine")
38
- check_expression(f"{len(tlas)} == 1")
52
+ # Get all activities at plus and minus 1 week
53
+ tlas = get_timeline_activities("PythonTL")
54
+ check_expression(f"{len(tlas)} == 3")
39
55
 
40
56
  # Create and delete a new activity
41
57
  start = start + timedelta(hours=2)
42
58
  stop = start + timedelta(minutes=30)
43
- act = create_timeline_activity("Mine", kind="reserve", start=start, stop=stop)
44
- tlas = get_timeline_activities("Mine")
45
- check_expression(f"{len(tlas)} == 2")
46
- delete_timeline_activity("Mine", act["start"], act["uuid"])
47
- tlas = get_timeline_activities("Mine")
48
- check_expression(f"{len(tlas)} == 1")
59
+ act = create_timeline_activity("PythonTL", kind="reserve", start=start, stop=stop)
60
+ tlas = get_timeline_activities("PythonTL")
61
+ check_expression(f"{len(tlas)} == 4")
62
+ delete_timeline_activity("PythonTL", act["start"], act["uuid"])
63
+ tlas = get_timeline_activities("PythonTL")
64
+ check_expression(f"{len(tlas)} == 3")
49
65
 
50
66
  # delete fails since the timeline has activities
51
- delete_timeline(
52
- "Mine"
53
- ) #: RuntimeError : Failed to delete timeline due to timeline contains activities, must force remove
67
+ delete_timeline("PythonTL")
54
68
  # Force delete since the timeline has activities
55
- delete_timeline("Mine", force=True)
69
+ delete_timeline("PythonTL", force=True)
56
70
  tls = list_timelines()
57
- check_expression(f"{len(tls)} == 0")
71
+ names = [tl["name"] for tl in tls]
72
+ check_expression(f"{'PythonTL' in names} == False")
@@ -17,5 +17,5 @@ wait_expression("True == False", 5)
17
17
  wait_packet("<%= target_name %>", "ADCS", 2, 5)
18
18
  wait_check("<%= target_name %> ADCS BIASX == 100", 5)
19
19
  wait_check_tolerance("<%= target_name %> ADCS BIASX", 5, 0.5, 5)
20
- wait_check_expression("True == False", 5)
20
+ wait_check_expression(f"tlm('<%= target_name %> HEALTH_STATUS TEMP1') < 101", 5, 0.25, globals())
21
21
  wait_check_packet("<%= target_name %>", "ADCS", 2, 5)
@@ -0,0 +1,84 @@
1
+ # Helper method to check for a script to change state
2
+ def wait_for_action(id, state):
3
+ i = 0
4
+ while i < 100:
5
+ script = running_script_get(id)
6
+ if script['state'] == state:
7
+ check_expression(f"'{script['state']}' == '{state}'")
8
+ break
9
+ wait(0.1)
10
+ check_expression(f"'{script['state']}' == '{state}'")
11
+
12
+ SCRIPT_NAME = "INST2/procedures/new_script.py"
13
+
14
+ # Ensure it's not already there
15
+ step_mode()
16
+ script_delete(SCRIPT_NAME)
17
+ scripts = script_list()
18
+ check_expression(f"{len(scripts)} > 100")
19
+ run_mode()
20
+
21
+ contents = "print('bad"
22
+ script_create(SCRIPT_NAME, contents)
23
+ body = script_body(SCRIPT_NAME)
24
+ result = script_syntax_check(body)
25
+ check_expression(f"{result['success']} == False")
26
+
27
+ contents = 'set_line_delay(1)\nprint("Hello from Python")\nprint(".")\nprint(".")\nwhile True:\n print(".")\n wait(0.5)\n wait(0.5)\n'
28
+ result = script_create(SCRIPT_NAME, contents)
29
+ scripts = script_list()
30
+ check_expression(f"{SCRIPT_NAME in scripts} == True")
31
+
32
+ script = script_instrumented(contents)
33
+ check_expression(f"{'RunningScript.instance' in script} == True")
34
+
35
+ id = script_run(SCRIPT_NAME)
36
+ check_expression(f"{int(id)} > 0")
37
+ wait_for_action(id, 'running')
38
+
39
+ list = running_script_list()
40
+ started = [script for script in list if script["id"] == id][0]
41
+ check_expression(f"'{started['name']}' == '{SCRIPT_NAME}'")
42
+ script = running_script_get(id)
43
+ check_expression(f"'{script['name']}' == '{SCRIPT_NAME}'")
44
+
45
+ running_script_pause(id)
46
+ wait_for_action(id, 'paused')
47
+ running_script_step(id)
48
+ wait_for_action(id, 'paused')
49
+ running_script_retry(id)
50
+ wait_for_action(id, 'paused')
51
+ running_script_go(id)
52
+ wait_for_action(id, 'running')
53
+ running_script_stop(id)
54
+ wait(1)
55
+
56
+ list = running_script_list()
57
+ script = [script for script in list if script["id"] == id]
58
+ # Script is stopped so it should NOT be in the running list
59
+ check_expression(f"{len(script)} == 0")
60
+
61
+ list = completed_script_list()
62
+ script = [script for script in list if script["id"] == id]
63
+ # Script is completed so it should be in the completed list
64
+ check_expression(f"{len(script)} == 1")
65
+
66
+ id = script_run(SCRIPT_NAME)
67
+ wait_for_action(id, 'running')
68
+ running_script_delete(id) # Stop and completely remove the script
69
+ wait(1)
70
+
71
+ list = running_script_list()
72
+ script = [script for script in list if script["id"] == id]
73
+ # Script is deleted, so it should NOT be in the running list
74
+ check_expression(f"{len(script)} == 0")
75
+ list = completed_script_list()
76
+ # Script is deleted so it should be in the completed list
77
+ script = [script for script in list if script["id"] == id]
78
+ check_expression(f"{len(script)} == 1")
79
+
80
+ script_lock(SCRIPT_NAME)
81
+ script_unlock(SCRIPT_NAME)
82
+ script_delete(SCRIPT_NAME)
83
+ scripts = script_list()
84
+ check_expression(f"{SCRIPT_NAME not in scripts} == True")