From 687f18a65a68e7f4f5fe9915d831295e7593b212 Mon Sep 17 00:00:00 2001 From: Jason Thomas Date: Sun, 15 Oct 2023 23:08:18 -0600 Subject: [PATCH 1/2] Update scripting apis --- _docs_v5/4_guides/scripting_api.md | 669 +++++++++++++++++++++++++---- scripts/verify_scripting_api.rb | 84 +++- 2 files changed, 663 insertions(+), 90 deletions(-) diff --git a/_docs_v5/4_guides/scripting_api.md b/_docs_v5/4_guides/scripting_api.md index 0e5ca82..25263f4 100644 --- a/_docs_v5/4_guides/scripting_api.md +++ b/_docs_v5/4_guides/scripting_api.md @@ -768,11 +768,18 @@ build_command(, range_check=True, raw=False) | range_check | Whether to perform range checking on the command. Default is true. | | raw | Whether to write the command arguments as RAW or CONVERTED value. Default is CONVERTED. | -Ruby / Python Example: +Ruby Example: ```ruby x = build_command("INST COLLECT with DURATION 10, TYPE NORMAL") -print(x) #=> {"id"=>"1696437370872-0", "result"=>"SUCCESS", "time"=>"1696437370872305961", "received_time"=>"1696437370872305961", "target_name"=>"INST", "packet_name"=>"COLLECT", "received_count"=>"3", "buffer"=>"\x13\xE7\xC0\x00\x00\f\x00\x01\x00\x00A \x00\x00\xAB\x00\x00\x00\x00"} +puts x #=> {"id"=>"1696437370872-0", "result"=>"SUCCESS", "time"=>"1696437370872305961", "received_time"=>"1696437370872305961", "target_name"=>"INST", "packet_name"=>"COLLECT", "received_count"=>"3", "buffer"=>"\x13\xE7\xC0\x00\x00\f\x00\x01\x00\x00A \x00\x00\xAB\x00\x00\x00\x00"} +``` + +Python Example: + +```python +x = build_command("INST COLLECT with DURATION 10, TYPE NORMAL") +print(x) #=> {'id': '1697298167748-0', 'result': 'SUCCESS', 'time': '1697298167749155717', 'received_time': '1697298167749155717', 'target_name': 'INST', 'packet_name': 'COLLECT', 'received_count': '2', 'buffer': bytearray(b'\x13\xe7\xc0\x00\x00\x0c\x00\x01\x00\x00A \x00\x00\xab\x00\x00\x00\x00')} ``` ### send_raw @@ -810,21 +817,60 @@ get_all_commands("") | ----------- | ------------------- | | Target Name | Name of the target. | -Ruby / Python Example: +Ruby Example: ```ruby cmd_list = get_all_commands("INST") -print(cmd_list) -#[{"target_name"=>"INST", -# "packet_name"=>"ABORT", -# "endianness"=>"BIG_ENDIAN", -# "description"=>"Aborts a collect on the instrument", -# "stale"=>true, -# "items"=> -# [{"name"=>"CCSDSVER", -# "bit_offset"=>0, -# "bit_size"=>3, -# ... +puts cmd_list #=> +# [{"target_name"=>"INST", +# "packet_name"=>"ABORT", +# "endianness"=>"BIG_ENDIAN", +# "description"=>"Aborts a collect on the instrument", +# "items"=> [{"name"=>"CCSDSVER", "bit_offset"=>0, "bit_size"=>3, ... }] +# ... +# }] +``` + +Python Example: + +```python +cmd_list = get_all_commands("INST") +print(cmd_list) #=> +# [{'target_name': 'INST', +# 'packet_name': 'ABORT', +# 'endianness': 'BIG_ENDIAN', +# 'description': 'Aborts a collect on the INST instrument', +# 'items': [{'name': 'CCSDSVER', 'bit_offset': 0, 'bit_size': 3, ... }] +# ... +# }] +``` + +### get_all_command_names (since 5.0.6) + +Returns an array of the command names for a particular target. + +Ruby / Python Syntax: + +```ruby +get_all_command_names("") +``` + +| Parameter | Description | +| ----------- | ------------------ | +| Target Name | Name of the target | + +Ruby Example: + +```ruby +cmd_list = get_all_command_names("INST") +puts cmd_list #=> ['ABORT', 'ARYCMD', 'ASCIICMD', ...] +``` + +Python Example: + +```python +cmd_list = get_all_command_names("INST") +print(cmd_list) #=> ['ABORT', 'ARYCMD', 'ASCIICMD', ...] ``` ### get_command (since 5.0.0) @@ -845,18 +891,29 @@ get_command("", "") Ruby / Python Example: ```ruby -cmd = get_command("INST", "ABORT") -print(cmd) -#[{"target_name"=>"INST", -# "packet_name"=>"ABORT", -# "endianness"=>"BIG_ENDIAN", -# "description"=>"Aborts a collect on the instrument", -# "stale"=>true, -# "items"=> -# [{"name"=>"CCSDSVER", -# "bit_offset"=>0, -# "bit_size"=>3, -# ... +abort_cmd = get_command("INST", "ABORT") +puts abort_cmd #=> +# [{"target_name"=>"INST", +# "packet_name"=>"ABORT", +# "endianness"=>"BIG_ENDIAN", +# "description"=>"Aborts a collect on the instrument", +# "items"=> [{"name"=>"CCSDSVER", "bit_offset"=>0, "bit_size"=>3, ... }] +# ... +# }] +``` + +Python Example: + +```python +abort_cmd = get_command("INST") +print(abort_cmd) #=> +# [{'target_name': 'INST', +# 'packet_name': 'ABORT', +# 'endianness': 'BIG_ENDIAN', +# 'description': 'Aborts a collect on the INST instrument', +# 'items': [{'name': 'CCSDSVER', 'bit_offset': 0, 'bit_size': 3, ... }] +# ... +# }] ``` ### get_parameter (since 5.0.0) @@ -875,23 +932,26 @@ get_parameter("", "", "") | Command Name | Name of the command. | | Parameter Name | Name of the parameter. | -Ruby / Python Example: +Ruby Example: ```ruby param = get_parameter("INST", "COLLECT", "TYPE") -print(param) -# {"name"=>"TYPE", -# "bit_offset"=>64, -# "bit_size"=>16, -# "data_type"=>"UINT", -# "description"=>"Collect type", -# "default"=>0, -# "minimum"=>0, -# "maximum"=>65535, -# "endianness"=>"BIG_ENDIAN", -# "required"=>true, -# "overflow"=>"ERROR", -# "states"=>{"NORMAL"=>{"value"=>0}, "SPECIAL"=>{"value"=>1, "hazardous"=>""}}} +puts param #=> +# {"name"=>"TYPE", "bit_offset"=>64, "bit_size"=>16, "data_type"=>"UINT", +# "description"=>"Collect type which can be normal or special", "default"=>0, +# "minimum"=>0, "maximum"=>65535, "endianness"=>"BIG_ENDIAN", "required"=>true, "overflow"=>"ERROR", +# "states"=>{"NORMAL"=>{"value"=>0}, "SPECIAL"=>{"value"=>1, "hazardous"=>""}}, "limits"=>{}} +``` + +Python Example: + +```python +param = get_parameter("INST", "COLLECT", "TYPE") +print(param) #=> +# {'name': 'TYPE', 'bit_offset': 64, 'bit_size': 16, 'data_type': 'UINT', +# 'description': 'Collect type which can be normal or special', 'default': 0, +# 'minimum': 0, 'maximum': 65535, 'endianness': 'BIG_ENDIAN', 'required': True, 'overflow': 'ERROR', +# 'states': {'NORMAL': {'value': 0}, 'SPECIAL': {'value': 1, 'hazardous': ''}}, 'limits': {}} ``` ### get_cmd_buffer @@ -909,11 +969,24 @@ buffer = get_cmd_buffer("", "")['buffer'] | Target Name | Name of the target. | | Packet Name | Name of the packet. | -Ruby / Python Example: +Ruby Example: ```ruby packet = get_cmd_buffer("INST", "COLLECT") -print(packet['buffer']) +puts packet #=> +# {"time"=>"1697298846752053420", "received_time"=>"1697298846752053420", +# "target_name"=>"INST", "packet_name"=>"COLLECT", "received_count"=>"20", "stored"=>"false", +# "buffer"=>"\x13\xE7\xC0\x00\x00\f\x00\x01\x00\x00@\xE0\x00\x00\xAB\x00\x00\x00\x00"} +``` + +Python Example: + +```python +packet = get_cmd_buffer("INST", "COLLECT") +print(packet) #=> +# {'time': '1697298923745982470', 'received_time': '1697298923745982470', +# 'target_name': 'INST', 'packet_name': 'COLLECT', 'received_count': '21', 'stored': 'false', +# 'buffer': bytearray(b'\x13\xe7\xc0\x00\x00\x0c\x00\x01\x00\x00@\xe0\x00\x00\xab\x00\x00\x00\x00')} ``` ### get_cmd_hazardous @@ -936,12 +1009,14 @@ Ruby Example: ```ruby hazardous = get_cmd_hazardous("INST", "COLLECT", {'TYPE' => 'SPECIAL'}) +puts hazardous #=> true ``` Python Example: ```python hazardous = get_cmd_hazardous("INST", "COLLECT", {'TYPE': 'SPECIAL'}) +print(hazardous) #=> True ``` ### get_cmd_value @@ -965,12 +1040,14 @@ Ruby Example: ```ruby value = get_cmd_value("INST", "COLLECT", "TEMP", :RAW) +puts value #=> 0.0 ``` Python Example: -```ruby +```python value = get_cmd_value("INST", "COLLECT", "TEMP", "RAW") +print(value) #=> 0.0 ``` ### get_cmd_time @@ -1291,6 +1368,26 @@ print(packets) # ... ``` +### get_all_telemetry_names (since 5.0.6) + +Returns an array of all target packet names. + +Ruby / Python Syntax: + +```ruby +get_all_telemetry_names("") +``` + +| Parameter | Description | +| ----------- | ------------------ | +| Target Name | Name of the target | + +Ruby / Python Example: + +```ruby +get_all_telemetry_names("INST") #=> ["ADCS", "HEALTH_STATUS", ...] +``` + ### get_telemetry (since 5.0.0) Returns a packet hash. @@ -1587,6 +1684,69 @@ for packet in packets: print(f"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}") ``` +### get_tlm_cnt + +Get the receive count for a telemetry packet + +Ruby / Python Syntax: + +```ruby +get_tlm_cnt("", "") +``` + +| Parameter | Description | +| --------- | ----------- | +| Target | Target name | +| Packet | Packet name | + +Ruby / Python Example: + +```ruby +get_tlm_cnt("INST", "HEALTH_STATUS") #=> 10 +``` + +### get_tlm_cnts + +Get the receive counts for an array of telemetry packets + +Ruby / Python Syntax: + +```ruby +get_tlm_cnts([["", ""], ["", ""]]) +``` + +| Parameter | Description | +| --------- | ----------- | +| Target | Target name | +| Packet | Packet name | + +Ruby / Python Example: + +```ruby +get_tlm_cnts([["INST", "ADCS"], ["INST", "HEALTH_STATUS"]]) #=> [100, 10] +``` + +### get_packet_derived_items + +Get the list of derived telemetry items for a packet + +Ruby / Python Syntax: + +```ruby +get_packet_derived_items("", "") +``` + +| Parameter | Description | +| --------- | ----------- | +| Target | Target name | +| Packet | Packet name | + +Ruby / Python Example: + +```ruby +get_packet_derived_items("INST", "HEALTH_STATUS") #=> ['PACKET_TIMESECONDS', 'PACKET_TIMEFORMATTED', ...] +``` + ## Delays These methods allow the user to pause the script to wait for telemetry to change or for an amount of time to pass. @@ -2426,7 +2586,7 @@ map_target_to_interface("INST", "INST_INT", unmap_old=False) Send a command directly to an interface. This has no effect in the standard COSMOS interfaces but can be implemented by a custom interface to change behavior. -Syntax: +Ruby / Python Syntax: ```ruby interface_cmd("", "", "") @@ -2438,7 +2598,7 @@ interface_cmd("", "", "") | Command Name | Name of the command to send | | Command Parameters | Any parameters to send with the command | -Example: +Ruby / Python Example: ```ruby interface_cmd("INST", "DISABLE_CRC") @@ -2448,23 +2608,30 @@ interface_cmd("INST", "DISABLE_CRC") Send a command directly to an interface protocol. This has no effect in the standard COSMOS protocols but can be implemented by a custom protocol to change behavior. -Syntax: +Ruby / Python Syntax: ```ruby interface_protocol_cmd("", "", "") ``` -| Parameter | Description | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------- | -| Interface Name | Name of the interface | -| Command Name | Name of the command to send | -| Command Parameters | Any parameters to send with the command | -| read_write: | Whether command gets send to read or write protocols. Must be one of :READ, :WRITE, or :READ_WRITE. (default: :READ_WRITE) | +| Parameter | Description | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Interface Name | Name of the interface | +| Command Name | Name of the command to send | +| Command Parameters | Any parameters to send with the command | +| read_write | Whether command gets send to read or write protocols. Must be one of READ, WRITE, or READ_WRITE (Ruby symbols, Python strings). The default is READ_WRITE. | +| index | Which protocol in the stack the command should apply to. The default is -1 which applies the command to all. | -Example: +Ruby Example: ```ruby -interface_protocol_cmd("INST", "DISABLE_CRC") +interface_protocol_cmd("INST", "DISABLE_CRC", read_write: :READ_WRITE, index: -1) +``` + +Python Example: + +```python +interface_protocol_cmd("INST", "DISABLE_CRC", read_write='READ_WRITE', index=-1) ``` ## Routers @@ -2631,6 +2798,150 @@ Ruby / Python Example: stop_raw_logging_router("router1") ``` +### router_cmd + +Send a command directly to a router. This has no effect in the standard COSMOS routers but can be implemented by a custom router to change behavior. + +Ruby / Python Syntax: + +```ruby +router_cmd("", "", "") +``` + +| Parameter | Description | +| ------------------ | --------------------------------------- | +| Router Name | Name of the router | +| Command Name | Name of the command to send | +| Command Parameters | Any parameters to send with the command | + +Ruby / Python Example: + +```ruby +router_cmd("INST", "DISABLE_CRC") +``` + +### router_protocol_cmd + +Send a command directly to an router protocol. This has no effect in the standard COSMOS protocols but can be implemented by a custom protocol to change behavior. + +Ruby / Python Syntax: + +```ruby +router_protocol_cmd("", "", "", read_write, index) +``` + +| Parameter | Description | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Router Name | Name of the router | +| Command Name | Name of the command to send | +| Command Parameters | Any parameters to send with the command | +| read_write | Whether command gets send to read or write protocols. Must be one of READ, WRITE, or READ_WRITE (Ruby symbols, Python strings). The default is READ_WRITE. | +| index | Which protocol in the stack the command should apply to. The default is -1 which applies the command to all. | + +Ruby Example: + +```ruby +router_protocol_cmd("INST", "DISABLE_CRC", read_write: :READ_WRITE, index: -1) +``` + +Python Example: + +```python +router_protocol_cmd("INST", "DISABLE_CRC", read_write='READ_WRITE', index=-1) +``` + +## Stashing Data + +These methods allow the user to store temporary data into COSMOS and retrieve it. The storage is implemented as a key / value storage (Ruby hash or Python dict). This can be used in scripts to store information that applies across multiple scripts or multiple runs of a single script. + +### stash_set + +Sets a stash item. + +Ruby / Python Syntax: + +```ruby +stash_set("", ) +``` + +| Parameter | Description | +| ----------- | ---------------------------- | +| Stash Key | Name of the stash key to set | +| Stash Value | Value to set | + +Ruby / Python Example: + +```ruby +stash_set('run_count', 5) +stash_set('setpoint', 23.4) +``` + +### stash_get + +Returns the specified stash item. + +Ruby / Python Syntax: + +```ruby +stash_get("") +``` + +| Parameter | Description | +| --------- | ------------------------------- | +| Stash Key | Name of the stash key to return | + +Ruby / Python Example: + +```ruby +stash_get('run_count') #=> 5 +``` + +### stash_all + +Returns all the stash items as a Ruby hash or Python dict. + +Ruby Syntax / Example: + +```ruby +stash_all() #=> ['run_count' => 5, 'setpoint' => 23.4] +``` + +Python Syntax / Example: + +```ruby +stash_all() #=> ['run_count': 5, 'setpoint': 23.4] +``` + +### stash_keys + +Returns all the stash keys. + +Ruby / Python Syntax / Example: + +```ruby +stash_keys() #=> ['run_count', 'setpoint'] +``` + +### stash_delete + +Deletes a stash item. Note this actions is permanent! + +Ruby / Python Syntax: + +```ruby +stash_delete("") +``` + +| Parameter | Description | +| --------- | ------------------------------- | +| Stash Key | Name of the stash key to delete | + +Ruby / Python Example: + +```ruby +stash_delete("run_count") +``` + ## Executing Other Procedures These methods allow the user to bring in files of subroutines and execute other test procedures. @@ -2687,19 +2998,20 @@ Opens a telemetry screen at the specified position. Ruby / Python Syntax: ```ruby -display_screen("", , ) +display_screen("", "", , ) ``` -| Parameter | Description | -| ------------ | ------------------------------------------------------------------------------------------------ | -| Display Name | Name of the telemetry screen to display. Screens are normally named by "TARGET_NAME SCREEN_NAME" | -| X Position | The X coordinate on screen where the top left corner of the telemetry screen will be placed. | -| Y Position | The Y coordinate on screen where the top left corner of the telemetry screen will be placed. | +| Parameter | Description | +| ----------- | --------------------------------------------------------- | +| Target Name | Telemetry screen target name | +| Screen Name | Screen name within the specified target | +| X Position | X coordinate for the upper left hand corner of the screen | +| Y Position | Y coordinate for the upper left hand corner of the screen | Ruby / Python Example: ```ruby -display("INST ADCS", 100, 200) +display_screen("INST", "ADCS", 100, 200) ``` ### clear_screen @@ -2709,17 +3021,18 @@ Closes an open telemetry screen. Ruby / Python Syntax: ```ruby -clear_screen("") +clear_screen("", "") ``` -| Parameter | Description | -| ------------ | ---------------------------------------------------------------------------------------------- | -| Display Name | Name of the telemetry screen to close. Screens are normally named by "TARGET_NAME SCREEN_NAME" | +| Parameter | Description | +| ----------- | --------------------------------------- | +| Target Name | Telemetry screen target name | +| Screen Name | Screen name within the specified target | Ruby / Python Example: ```ruby -clear_screen("INST ADCS") +clear_screen("INST", "ADCS") ``` ### clear_all_screens @@ -2732,6 +3045,27 @@ Ruby / Python Syntax / Example: clear_all_screens() ``` +### delete_screen + +Deletes an existing Telemetry Viewer screen. + +Ruby / Python Syntax: + +```ruby +delete_screen("", "") +``` + +| Parameter | Description | +| ----------- | --------------------------------------- | +| Target Name | Telemetry screen target name | +| Screen Name | Screen name within the specified target | + +Ruby / Python Example: + +```ruby +delete_screen("INST", "ADCS") +``` + ### get_screen_list The get_screen_list returns a list of available telemetry screens. @@ -2749,13 +3083,13 @@ The get_screen_definition returns the text file contents of a telemetry screen d Syntax: ```ruby -get_screen_definition("", "") +get_screen_definition("", "") ``` -| Parameter | Description | -| ------------------ | --------------------------------------- | -| Screen target name | Telemetry screen target name. | -| Screen name | Screen name within the specified target | +| Parameter | Description | +| ----------- | --------------------------------------- | +| Target Name | Telemetry screen target name | +| Screen Name | Screen name within the specified target | Ruby / Python Example: @@ -2765,19 +3099,19 @@ screen_definition = get_screen_definition("INST", "HS") ### create_screen -The create_screen allows you to create a screen directly from a script. +The create_screen allows you to create a screen directly from a script. This screen is saved to Telemetry Viewer for future use in that application. Python / Ruby Syntax: ```ruby -create_screen("", "" "") +create_screen("", "" "") ``` -| Parameter | Description | -| ------------------ | ---------------------------------------- | -| Screen target name | Telemetry screen target name | -| Screen name | Screen name within the specified target | -| Screen Definition | The entire screen definition as a String | +| Parameter | Description | +| ----------- | ---------------------------------------- | +| Target Name | Telemetry screen target name | +| Screen Name | Screen name within the specified target | +| Definition | The entire screen definition as a String | Ruby Example: @@ -2785,7 +3119,7 @@ Ruby Example: screen_def = ' SCREEN AUTO AUTO 0.1 FIXED VERTICAL - TITLE "Local Screen" + TITLE "New Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END @@ -2801,7 +3135,7 @@ Python Example: screen_def = ' SCREEN AUTO AUTO 0.1 FIXED VERTICAL - TITLE "Local Screen" + TITLE "New Screen" VERTICALBOX LABELVALUE INST HEALTH_STATUS TEMP1 END @@ -2811,6 +3145,57 @@ screen_def = ' create_screen("INST", "LOCAL", screen_def) ``` +### local_screen + +The local_screen allows you to create a local screen directly from a script which is not permanently saved to the Telemetry Viewer screen list. This is useful for one off screens that help users interact with scripts. + +Python / Ruby Syntax: + +```ruby +local_screen("" "", , ) +``` + +| Parameter | Description | +| ----------- | --------------------------------------------------------- | +| Screen Name | Screen name within the specified target | +| Definition | The entire screen definition as a String | +| X Position | X coordinate for the upper left hand corner of the screen | +| Y Position | Y coordinate for the upper left hand corner of the screen | + +NOTE: Is is possible to specify a X, Y location off the visible display. If you do so and try to re-create the screen it will not display (because it is already displayed). Try issuing a `clear_all_screens()` first to clear any screens off the visible display space. + +Ruby Example: + +```ruby +screen_def = ' + SCREEN AUTO AUTO 0.1 FIXED + VERTICAL + TITLE "Local Screen" + VERTICALBOX + LABELVALUE INST HEALTH_STATUS TEMP1 + END + END +' +# Here we pass in the screen definition as a string +local_screen("TESTING", screen_def, 600, 75) +``` + +Python Example: + +```python +screen_def = ' + SCREEN AUTO AUTO 0.1 FIXED + VERTICAL + TITLE "Local Screen" + VERTICALBOX + LABELVALUE INST HEALTH_STATUS TEMP1 + END + END +' +# Here we pass in the screen definition as a string +local_screen("TESTING", screen_def, 600, 75) +``` + ## Script Runner Specific Functionality These methods allow the user to interact with ScriptRunner functions. @@ -2933,3 +3318,127 @@ Ruby / Python Syntax / Example: ```ruby disconnect_script() ``` + +## Metadata + +Metadata allows you to mark the regular target / packet data logged in COSMOS with your own fields. This metadata can then be searched and used to filter data when using other COSMOS tools. + +### metadata_all + +Returns all the metadata that was previously set + +Ruby / Python Syntax: + +```ruby +metadata_all() +``` + +| Parameter | Description | +| --------- | --------------------------------------------------- | +| limit | Amount of metadata items to return. Default is 100. | + +Ruby Example: + +```ruby +metadata_all(limit: 500) +``` + +Python Example: + +```python +metadata_all(limit='500') +``` + +### metadata_get + +Returns metadata that was previously set + +Ruby / Python Syntax: + +```ruby +metadata_get(start) +``` + +| Parameter | Description | +| --------- | --------------------------------------------------------------------------------- | +| start | Named parameter, time at which to retrieve metadata as integer seconds from epoch | + +Ruby Example: + +```ruby +metadata_get(start: 500) +``` + +Python Example: + +```python +metadata_get(start='500') +``` + +### metadata_set + +Returns metadata that was previously set + +Ruby / Python Syntax: + +```ruby +metadata_set(, start, color) +``` + +| Parameter | Description | +| --------- | ------------------------------------------------------------------------------ | +| metadata | Hash or dict of key value pairs to store as metadata. | +| start | Named parameter, time at which to store metadata. Default is now. | +| color | Named parameter, color to display metadat in the calendar. Default is #003784. | + +Ruby Example: + +```ruby +metadata_set({ 'key' => 'value' }) +metadata_set({ 'key' => 'value' }, color: '#ff5252') +``` + +Python Example: + +```python +metadata_set({ 'key': 'value' }) +metadata_set({ 'key': 'value' }, color='ff5252') +``` + +### metadata_update + +Updates metadata that was previously set + +Ruby / Python Syntax: + +```ruby +metadata_update(, start, color) +``` + +| Parameter | Description | +| --------- | ------------------------------------------------------------------------------ | +| metadata | Hash or dict of key value pairs to update as metadata. | +| start | Named parameter, time at which to update metadata. Default is latest metadata. | +| color | Named parameter, color to display metadat in the calendar. Default is #003784. | + +Ruby Example: + +```ruby +metadata_update({ 'key' => 'value' }) +``` + +Python Example: + +```python +metadata_update({ 'key': 'value' }) +``` + +### metadata_input + +Prompts the user to set existing metadata values or create new a new one. + +Ruby / Python Syntax / Example: + +```ruby +metadata_input() +``` diff --git a/scripts/verify_scripting_api.rb b/scripts/verify_scripting_api.rb index ca4a29d..a76c3fa 100644 --- a/scripts/verify_scripting_api.rb +++ b/scripts/verify_scripting_api.rb @@ -1,6 +1,18 @@ def parse_file(filename, methods) File.open(filename) do |file| - file.each do |line| + data = file.read + lines = data.split("\n") + # Check for our API indicator and strip out the excess + if data.include?("START PUBLIC API") + start = 0 + end_line = -1 + lines.each_with_index do |line, index| + start = index if line.include?("START PUBLIC API") + end_line = index if line.include?("END PUBLIC API") + end + lines = lines[start..end_line] + end + lines.each do |line| if line.strip =~ /^def / next if line.include?('def _') next if line.include?('initialize') @@ -15,15 +27,32 @@ def parse_file(filename, methods) end end -api_methods = {} +ruby_api_methods = {} Dir[File.join(File.dirname(__FILE__),'../../cosmos/openc3/lib/openc3/script/*.rb')].each do |filename| next if filename.include?('extract') - parse_file(filename, api_methods) + next if filename.include?('web_socket_api') + next if filename.include?('suite_results') + next if filename.include?('suite_runner') + next if filename.include?('script_runner') + parse_file(filename, ruby_api_methods) end Dir[File.join(File.dirname(__FILE__),'../../cosmos/openc3/lib/openc3/api/*.rb')].each do |filename| - parse_file(filename, api_methods) + parse_file(filename, ruby_api_methods) +end + +python_api_methods = {} +Dir[File.join(File.dirname(__FILE__),'../../cosmos/openc3/python/openc3/script/*.py')].each do |filename| + next if filename.include?('authorization') + next if filename.include?('decorators') + next if filename.include?('server_proxy') + next if filename.include?('stream') + next if filename.include?('suite_results') + next if filename.include?('suite_runner') + parse_file(filename, python_api_methods) +end +Dir[File.join(File.dirname(__FILE__),'../../cosmos/openc3/python/openc3/api/*.py')].each do |filename| + parse_file(filename, python_api_methods) end -# api_methods.uniq! documented_methods = [] File.open(File.join(File.dirname(__FILE__),'../_docs_v5/4_guides/scripting_api.md')) do |file| @@ -50,8 +79,43 @@ def parse_file(filename, methods) end documented_methods.uniq! -DEPRECATED = %w(require_utility get_all_target_info check_tolerance_raw wait_raw wait_check_raw wait_tolerance_raw wait_check_tolerance_raw) -puts "Documented but doesn't exist:" -puts documented_methods - api_methods.keys -puts "\nExists but not documented:" -puts api_methods.keys - documented_methods - DEPRECATED +exit_code = 0 +deprecated = %w(require_utility get_all_target_info check_tolerance_raw wait_raw wait_check_raw wait_tolerance_raw wait_check_tolerance_raw) +deprecated += %w(tlm_variable play_wav_file status_bar) +deprecated += %w(method_missing self.included write puts) # shouldn't be included +deprecated += %w(get_cmd_cnts) # internal APIs +if (documented_methods - ruby_api_methods.keys - python_api_methods.keys).length > 0 + puts "Documented but doesn't exist:" + puts documented_methods - ruby_api_methods.keys - python_api_methods.keys + exit_code = -1 +end +if (ruby_api_methods.keys - documented_methods - deprecated).length > 0 + puts "\nRuby exists but not documented:" + puts ruby_api_methods.keys - documented_methods - deprecated + exit_code = -1 +end +if (python_api_methods.keys - documented_methods - deprecated).length > 0 + puts "\nPython exists but not documented:" + puts python_api_methods.keys - documented_methods - deprecated + exit_code = -1 +end +ruby_api_massaged = [] +ruby_api_methods.keys.each do |key| + # Remove ? and ! from method names as python can't use them + if key.include?('?') or key.include?('!') + ruby_api_massaged << key[0..-2] + else + ruby_api_massaged << key + end +end +if (ruby_api_massaged - python_api_methods.keys - deprecated).length > 0 + puts "\nRuby but not Python:" + puts ruby_api_massaged - python_api_methods.keys - deprecated + exit_code = -1 +end +if (python_api_methods.keys - ruby_api_massaged).length > 0 + puts "\nPython but not Ruby:" + puts python_api_methods.keys - ruby_api_massaged + exit_code = -1 +end +exit exit_code From 7e6a3a1d9461b817c280001b5abf9152d57d650c Mon Sep 17 00:00:00 2001 From: Jason Thomas Date: Mon, 16 Oct 2023 10:42:06 -0600 Subject: [PATCH 2/2] Add get_overrides and suite APIs --- _docs_v5/4_guides/scripting_api.md | 118 ++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/_docs_v5/4_guides/scripting_api.md b/_docs_v5/4_guides/scripting_api.md index 25263f4..2cfdfac 100644 --- a/_docs_v5/4_guides/scripting_api.md +++ b/_docs_v5/4_guides/scripting_api.md @@ -1607,6 +1607,38 @@ normalize_tlm("INST HEALTH_STATUS TEMP1") # clear all overrides normalize_tlm("INST HEALTH_STATUS TEMP1", type='RAW') # clear only the RAW override ``` +### get_overrides + +Returns an array of the the currently overriden values set by override_tlm. NOTE: This returns all the value types that are overriden which by default is all 4 values types when using override_tlm. + +Ruby / Python Syntax: + +```ruby +get_overrides() +``` + +Ruby Example: + +```ruby +override_tlm("INST HEALTH_STATUS TEMP1 = 5") +puts get_overrides() #=> +# [ {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"RAW", "value"=>5} +# {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"CONVERTED", "value"=>5} +# {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"FORMATTED", "value"=>"5"} +# {"target_name"=>"INST", "packet_name"=>"HEALTH_STATUS", "item_name"=>"TEMP1", "value_type"=>"WITH_UNITS", "value"=>"5"} ] +``` + +Python Example: + +```python +override_tlm("INST HEALTH_STATUS TEMP1 = 5") +print(get_overrides()) #=> +# [ {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'RAW', 'value': 5}, +# {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'CONVERTED', 'value': 5}, +# {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'FORMATTED', 'value': '5'}, +# {'target_name': 'INST', 'packet_name': 'HEALTH_STATUS', 'item_name': 'TEMP1', 'value_type': 'WITH_UNITS', 'value': '5'} ] +``` + ## Packet Data Subscriptions Methods for subscribing to specific packets of data. This provides an interface to ensure that each telemetry packet is received and handled rather than relying on polling where some data may be missed. @@ -3162,7 +3194,7 @@ local_screen("" "", , ) +add_group_setup() +add_group_teardown() +add_script(, ) +``` + +| Parameter | Description | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Group Class | Name of the previously defined class which inherits from the OpenC3 Group class. The Ruby API passes a String with the name of the group. The Python API passes the Group class directly. | +| Method | Name of the method in the OpenC3 Group class. The Ruby API passes a String with the name of the method. The Python API passes the Group class directly. | + +Ruby Example: + +```ruby +load 'openc3/script/suite.rb' + +class ExampleGroup < OpenC3::Group + def script_1 + # Insert test code here ... + end +end +class WrapperGroup < OpenC3::Group + def setup + # Insert test code here ... + end + def my_method + # Insert test code here ... + end + def teardown + # Insert test code here ... + end +end + +class MySuite < OpenC3::Suite + def initialize + super() + add_group('ExampleGroup') + add_group_setup('WrapperGroup') + add_script('WrapperGroup', 'my_method') + add_group_teardown('WrapperGroup') + end +end +``` + +Python Example: + +```python +from openc3.script import * +from openc3.script.suite import Group, Suite + +class ExampleGroup(Group): + def script_1(self): + # Insert test code here ... + pass +class WrapperGroup(Group): + def setup(self): + # Insert test code here ... + pass + def my_method(self): + # Insert test code here ... + pass + def teardown(self): + # Insert test code here ... + pass +class MySuite(Suite): + def __init__(self): + super().__init__() + self.add_group(ExampleGroup) + self.add_group_setup(WrapperGroup) + self.add_script(WrapperGroup, 'my_method') + self.add_group_teardown(WrapperGroup) +```