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 +4 -4
- data/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
- data/targets/INST/cmd_tlm/inst_tlm.txt +10 -0
- data/targets/INST/lib/inst_cmd_validator.rb +1 -0
- data/targets/INST/lib/sim_inst.rb +3 -0
- data/targets/INST/procedures/calendar.rb +52 -27
- data/targets/INST/procedures/checks.rb +1 -1
- data/targets/INST/procedures/disconnect.rb +1 -1
- data/targets/INST/procedures/scripting.rb +88 -0
- data/targets/INST/screens/graphs.txt +28 -23
- data/targets/INST2/cmd_tlm/inst_cmds.txt +5 -1
- data/targets/INST2/cmd_tlm/inst_tlm.txt +10 -1
- data/targets/INST2/lib/sim_inst.py +3 -0
- data/targets/INST2/procedures/calendar.py +53 -38
- data/targets/INST2/procedures/disconnect.py +1 -1
- data/targets/INST2/procedures/scripting.py +84 -0
- data/targets/INST2/screens/graphs.txt +28 -23
- data/tools/widgets/BigWidget/BigWidget.umd.min.js +98 -98
- data/tools/widgets/BigWidget/BigWidget.umd.min.js.map +1 -1
- data/tools/widgets/DataviewerquaternionWidget/DataviewerquaternionWidget.umd.min.js +114 -114
- data/tools/widgets/DataviewerquaternionWidget/DataviewerquaternionWidget.umd.min.js.map +1 -1
- data/tools/widgets/DataviewertimeWidget/DataviewertimeWidget.umd.min.js +98 -98
- data/tools/widgets/DataviewertimeWidget/DataviewertimeWidget.umd.min.js.map +1 -1
- data/tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js +98 -98
- data/tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js.map +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c888a30f0d6951c4b7c2c10f8868e8c80569e09eac181b6998777c79d824b4a0
|
4
|
+
data.tar.gz: 9d7ec85c58a58937720cb368059bca004544cd1d8f6227c65c7fba83dc75d96a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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("
|
2
|
-
puts tl #=> {"name"=>"
|
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
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
10
|
-
|
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
|
16
|
-
|
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"=>"
|
19
|
-
# "
|
20
|
-
# "
|
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("
|
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("
|
26
|
-
check_expression("#{tlas.length} ==
|
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("
|
32
|
-
tlas = get_timeline_activities("
|
33
|
-
check_expression("#{tlas.length} ==
|
34
|
-
delete_timeline_activity("
|
35
|
-
tlas = get_timeline_activities("
|
36
|
-
check_expression("#{tlas.length} ==
|
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("
|
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("
|
64
|
+
delete_timeline("RubyTL", force: true)
|
65
|
+
# Verify the timeline no longer exists
|
42
66
|
tls = list_timelines()
|
43
|
-
|
67
|
+
names = tls.map { |tl| tl['name'] }
|
68
|
+
check_expression("#{names.include?('RubyTL')} == 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("
|
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
|
-
|
4
|
-
TITLE "<%= target_name %> Instrument Graphs"
|
3
|
+
TITLE "<%= target_name %> Instrument Graphs"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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("
|
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
|
-
|
10
|
-
check_expression(f"{
|
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
|
-
|
18
|
-
|
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)
|
26
|
-
|
27
|
-
print(
|
28
|
-
# {
|
29
|
-
#
|
30
|
-
#
|
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("
|
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("
|
38
|
-
check_expression(f"{len(tlas)} ==
|
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("
|
44
|
-
tlas = get_timeline_activities("
|
45
|
-
check_expression(f"{len(tlas)} ==
|
46
|
-
delete_timeline_activity("
|
47
|
-
tlas = get_timeline_activities("
|
48
|
-
check_expression(f"{len(tlas)} ==
|
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("
|
69
|
+
delete_timeline("PythonTL", force=True)
|
56
70
|
tls = list_timelines()
|
57
|
-
|
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("
|
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")
|