diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml
new file mode 100644
index 0000000000..a1867c3ee8
--- /dev/null
+++ b/.github/workflows/spelling.yml
@@ -0,0 +1,20 @@
+name: Check Spelling
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ spelling:
+ name: Codespell
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: codespell-project/actions-codespell@v2
+ with:
+ # Skip generated code as well as cstol_converter which has false
+ # positivies on ADN and Adn
+ skip: ./docs,*.map,*.min.js,*.pem,*.bin,cstol_converter
+ ignore_words_file: .whitelist
\ No newline at end of file
diff --git a/.whitelist b/.whitelist
new file mode 100644
index 0000000000..120cdf2349
--- /dev/null
+++ b/.whitelist
@@ -0,0 +1,3 @@
+assertin
+xdescribe
+xit
\ No newline at end of file
diff --git a/INSTALL.md b/INSTALL.md
index efec8e348c..bd5d3d0bd0 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -22,7 +22,7 @@ The most commands can also take arguments. The current argument options when run
## Setup
-To build you can use an environment variable `SSL_CERT_FILE` or it will default to use a public curl ca file. When you run setup it copys the `SSL_CERT_FILE` and will place a copy in the root of the openc3 repo as `cacert.pem`. These are needed to build the docker containers.
+To build you can use an environment variable `SSL_CERT_FILE` or it will default to use a public curl ca file. When you run setup it copies the `SSL_CERT_FILE` and will place a copy in the root of the openc3 repo as `cacert.pem`. These are needed to build the docker containers.
If you're building and want to use a private Rubygems, NPM or APK server (e.g. Nexus) you can update the following environment variables: RUBYGEMS_URL, NPM_URL, APK_URL, and more in the .env file. Example values:
diff --git a/README.md b/README.md
index 26b6b100c4..f0cfe542f2 100644
--- a/README.md
+++ b/README.md
@@ -27,13 +27,13 @@ After configuring OpenC3 COSMOS to talk to your hardware, you immediately can us
1. **Command Sender**
- - Command Sender allows you to manually send one-off commands with conventient drop downs and descriptions of each command and command parameter.
+ - Command Sender allows you to manually send one-off commands with convenient drop downs and descriptions of each command and command parameter.
1. **Script Runner**
- Script Runner allows for running OpenC3 COSMOS test procedures or any other Ruby code from a graphical environment that highlights each line as it executes. At anytime during execution, the script can be paused or stopped. If a telemetry check fails or any other exception occurs, the script is immediately stopped and the user notified.
- - Script Runner also allows you to break your operational or test procedures down into discreet test cases that each complete with either SUCCESS or FAILURE. After running, a script report is automatically created for you. Convenient features such as the ability to loop testing help get the kinks out of your system before formal runs.
+ - Script Runner also allows you to break your operational or test procedures down into discret test cases that each complete with either SUCCESS or FAILURE. After running, a script report is automatically created for you. Convenient features such as the ability to loop testing help get the kinks out of your system before formal runs.
1. **Packet Viewer**
diff --git a/docs.openc3.com/docs/configuration/_command.md b/docs.openc3.com/docs/configuration/_command.md
index d6e735944b..d2849ec7ba 100644
--- a/docs.openc3.com/docs/configuration/_command.md
+++ b/docs.openc3.com/docs/configuration/_command.md
@@ -7,7 +7,7 @@ title: Commands
## Command Definition Files
-Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
+Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters.
diff --git a/docs.openc3.com/docs/configuration/_table.md b/docs.openc3.com/docs/configuration/_table.md
index a5a7390fa0..c679557d24 100644
--- a/docs.openc3.com/docs/configuration/_table.md
+++ b/docs.openc3.com/docs/configuration/_table.md
@@ -8,7 +8,7 @@ title: Tables
## Table Definition Files
Table definition files define the binary tables that can be displayed in COSMOS [Table Manager](../tools/table-manager.md)
-. Table definitions are defined in the target's tables/config directory and are typically named after the table such as `PPSSelectionTable_def.txt`. The `_def.txt` extention helps to identify the file as a table definition. Table definitions can be combined using the `TABLEFILE` keyword. This allows you to build individual table components into a larger binary.
+. Table definitions are defined in the target's tables/config directory and are typically named after the table such as `PPSSelectionTable_def.txt`. The `_def.txt` extension helps to identify the file as a table definition. Table definitions can be combined using the `TABLEFILE` keyword. This allows you to build individual table components into a larger binary.
The Table definition files share a lot of similarity with the [Command Configuration](command.md). You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data.
diff --git a/docs.openc3.com/docs/configuration/_telemetry.md b/docs.openc3.com/docs/configuration/_telemetry.md
index 1c70df56be..c577b29dfd 100644
--- a/docs.openc3.com/docs/configuration/_telemetry.md
+++ b/docs.openc3.com/docs/configuration/_telemetry.md
@@ -7,7 +7,7 @@ title: Telemetry
## Telemetry Definition Files
-Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
+Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
When defining telemetry items you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. Within COSMOS, the only difference between a STRING and BLOCK is when COSMOS reads a STRING type it stops reading when it encounters a null byte (0). This shows up when displaying the value in Packet Viewer or Tlm Viewer and in the output of Data Extractor. You should strive to store non-ASCII data inside BLOCK items and ASCII strings in STRING items.
@@ -62,7 +62,7 @@ ITEM PACKET_TIME 0 0 DERIVED "Python time based on TIMESEC and TIMEUS"
READ_CONVERSION openc3/conversions/unix_time_conversion.py TIMESEC TIMEUS
```
-Definining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
+Defining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
diff --git a/docs.openc3.com/docs/configuration/command.md b/docs.openc3.com/docs/configuration/command.md
index 9837134787..67ea270435 100644
--- a/docs.openc3.com/docs/configuration/command.md
+++ b/docs.openc3.com/docs/configuration/command.md
@@ -7,7 +7,7 @@ title: Commands
## Command Definition Files
-Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
+Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters.
@@ -125,7 +125,7 @@ META TEST "This parameter is for test purposes only"
#### OVERLAP
(Since 4.4.1)
**This item is allowed to overlap other items in the packet**
-If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
#### KEY
@@ -345,7 +345,7 @@ APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0
#### OVERFLOW
**Set the behavior when writing a value overflows the type**
-By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value.
+By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value.
| Parameter | Description | Required |
|-----------|-------------|----------|
diff --git a/docs.openc3.com/docs/configuration/interfaces.md b/docs.openc3.com/docs/configuration/interfaces.md
index fd69809bf2..15a4b4f25c 100644
--- a/docs.openc3.com/docs/configuration/interfaces.md
+++ b/docs.openc3.com/docs/configuration/interfaces.md
@@ -175,7 +175,7 @@ See [INTERFACE](plugins.md#interface) for a description of the INTERFACE keyword
## Streams
-Streams are low level classes that implement read, read_nonblock, write, connect, connected? and disconnect methods. The build-in Stream classes are SerialStream, TcpipSocketStream and TcpipClientStream and they are automatically used when creating a Serial Interface, TCP/IP Server Interface, or TCP/IP Client Interface.
+Streams are low level classes that implement read, read_nonblock, write, connect, connected? and disconnect methods. The built-in Stream classes are SerialStream, TcpipSocketStream and TcpipClientStream and they are automatically used when creating a Serial Interface, TCP/IP Server Interface, or TCP/IP Client Interface.
## Protocols
diff --git a/docs.openc3.com/docs/configuration/plugins.md b/docs.openc3.com/docs/configuration/plugins.md
index b7f3bf5420..02c8b99e05 100644
--- a/docs.openc3.com/docs/configuration/plugins.md
+++ b/docs.openc3.com/docs/configuration/plugins.md
@@ -58,7 +58,7 @@ The VARIABLE keyword defines a variable that will be requested for the user to e
## NEEDS_DEPENDENCIES
(Since 5.5.0)
**Indicates the plugin needs dependencies and sets the GEM_HOME environment variable**
-If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kuberentes pod.
+If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kubernetes pod.
## INTERFACE
@@ -153,7 +153,7 @@ If DONT_RECONNECT is not present the Server will try to reconnect to an interfac
### DISABLE_DISCONNECT
**Disable the Disconnect button on the Interfaces tab in the Server**
-Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertantly disconnect from a target.
+Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertently disconnect from a target.
### LOG_RAW
@@ -807,7 +807,7 @@ Defines a custom widget that can be used in Telemetry Viewer screens.
| Parameter | Description | Required |
|-----------|-------------|----------|
-| Widget Name | The name of the widget wil be used to build a path to the widget implementation. For example, `WIDGET HELLOWORLD` will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the [Custom Widgets](../guides/custom-widgets.md) guide for more details. | True |
+| Widget Name | The name of the widget will be used to build a path to the widget implementation. For example, `WIDGET HELLOWORLD` will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the [Custom Widgets](../guides/custom-widgets.md) guide for more details. | True |
Example Usage:
```ruby
diff --git a/docs.openc3.com/docs/configuration/protocols.md b/docs.openc3.com/docs/configuration/protocols.md
index c74aefea79..1fa867ef2f 100644
--- a/docs.openc3.com/docs/configuration/protocols.md
+++ b/docs.openc3.com/docs/configuration/protocols.md
@@ -303,7 +303,7 @@ The base class disconnect_reset implementation just calls the reset method to en
The read_data method is used to analyze and potentially modify any raw data read by an Interface. It takes one parameter as the current state of the data to be analyzed. It can return either a string of data, STOP, or DISCONNECT. If it returns a string, then it believes that data may be ready to be a full packet, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes it needs more data to complete a full packet. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected).
-Base class Ruby implemenation:
+Base class Ruby implementation:
```ruby
def read_data(data)
@@ -320,7 +320,7 @@ def read_data(data)
end
```
-Base class Python implemenation:
+Base class Python implementation:
```python
def read_data(self, data, extra=None):
diff --git a/docs.openc3.com/docs/configuration/table.md b/docs.openc3.com/docs/configuration/table.md
index 9307880389..770ef81e45 100644
--- a/docs.openc3.com/docs/configuration/table.md
+++ b/docs.openc3.com/docs/configuration/table.md
@@ -8,7 +8,7 @@ title: Tables
## Table Definition Files
Table definition files define the binary tables that can be displayed in COSMOS [Table Manager](../tools/table-manager.md)
-. Table definitions are defined in the target's tables/config directory and are typically named after the table such as `PPSSelectionTable_def.txt`. The `_def.txt` extention helps to identify the file as a table definition. Table definitions can be combined using the `TABLEFILE` keyword. This allows you to build individual table components into a larger binary.
+. Table definitions are defined in the target's tables/config directory and are typically named after the table such as `PPSSelectionTable_def.txt`. The `_def.txt` extension helps to identify the file as a table definition. Table definitions can be combined using the `TABLEFILE` keyword. This allows you to build individual table components into a larger binary.
The Table definition files share a lot of similarity with the [Command Configuration](command.md). You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data.
@@ -131,7 +131,7 @@ META TEST "This parameter is for test purposes only"
#### OVERLAP
(Since 4.4.1)
**This item is allowed to overlap other items in the packet**
-If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
#### KEY
@@ -351,7 +351,7 @@ APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0
#### OVERFLOW
**Set the behavior when writing a value overflows the type**
-By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value.
+By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value.
| Parameter | Description | Required |
|-----------|-------------|----------|
@@ -406,7 +406,7 @@ When Data Type is STRING, BLOCK the remaining parameters are:
| Parameter | Description | Required |
|-----------|-------------|----------|
-| Table | The name of the existin table | True |
+| Table | The name of the existing table | True |
## DEFAULT
**Specify default values for a SINGLE row in a multi-column table**
diff --git a/docs.openc3.com/docs/configuration/telemetry-screens.md b/docs.openc3.com/docs/configuration/telemetry-screens.md
index 45e752a5e6..37c9291200 100644
--- a/docs.openc3.com/docs/configuration/telemetry-screens.md
+++ b/docs.openc3.com/docs/configuration/telemetry-screens.md
@@ -104,7 +104,7 @@ SETTING and SUBSETTING applies only to the widget defined immediately before it.
GLOBAL_SETTING and GLOBAL_SUBSETTING applies to all widgets.
Common wiget settings are defined here. Some widgets define their own
-unqiue settings which are documented under that specific widget.
+unique settings which are documented under that specific widget.
@@ -277,7 +277,7 @@ END
## NAMED_WIDGET
**Name a widget to allow access to it via the getNamedWidget method**
-To programatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets.
+To programmatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets.
:::warning
getNamedWidget returns the widget itself and thus must be operated on using methods native to that widget
@@ -429,7 +429,7 @@ END
| Parameter | Description | Required |
|-----------|-------------|----------|
-| Tab text | Text to diplay in the tab | True |
+| Tab text | Text to display in the tab | True |
Example Usage:
```ruby
@@ -1109,6 +1109,14 @@ IMAGEVIEWER INST IMAGE IMAGE jpg
### PROGRESSBAR
**Displays a progress bar that is useful for displaying percentages**
+| Parameter | Description | Required |
+|-----------|-------------|----------|
+| Target name | The target name | True |
+| Packet name | The packet name | True |
+| Item name | The item name | True |
+| Scale factor | Value to multiple the telemetry item by before displaying the in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0. | False |
+| Width | Width of the progress bar (default = 100 pixels) | False |
+| Value type | The type of the value to display. Default is CONVERTED.
Valid Values: RAW, CONVERTED, FORMATTED, WITH_UNITS | False |
Example Usage:
```ruby
diff --git a/docs.openc3.com/docs/configuration/telemetry.md b/docs.openc3.com/docs/configuration/telemetry.md
index 2a3c9fb687..02e412daed 100644
--- a/docs.openc3.com/docs/configuration/telemetry.md
+++ b/docs.openc3.com/docs/configuration/telemetry.md
@@ -7,7 +7,7 @@ title: Telemetry
## Telemetry Definition Files
-Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
+Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the [ASCII Table](http://www.asciitable.com/) is structured, files beginning with capital letters are processed before lower case letters.
When defining telemetry items you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. Within COSMOS, the only difference between a STRING and BLOCK is when COSMOS reads a STRING type it stops reading when it encounters a null byte (0). This shows up when displaying the value in Packet Viewer or Tlm Viewer and in the output of Data Extractor. You should strive to store non-ASCII data inside BLOCK items and ASCII strings in STRING items.
@@ -62,7 +62,7 @@ ITEM PACKET_TIME 0 0 DERIVED "Python time based on TIMESEC and TIMEUS"
READ_CONVERSION openc3/conversions/unix_time_conversion.py TIMESEC TIMEUS
```
-Definining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
+Defining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
@@ -159,7 +159,7 @@ META TEST "This parameter is for test purposes only"
#### OVERLAP
(Since 4.4.1)
**This item is allowed to overlap other items in the packet**
-If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
#### KEY
diff --git a/docs.openc3.com/docs/development/developing.md b/docs.openc3.com/docs/development/developing.md
index ac7ee931b9..b9a7180570 100644
--- a/docs.openc3.com/docs/development/developing.md
+++ b/docs.openc3.com/docs/development/developing.md
@@ -147,4 +147,4 @@ openc3-cosmos-cmd-tlm-api % bundle install
openc3-cosmos-cmd-tlm-api % bundle exec rails s
```
-1. Once the `bundle exec rails s` command returns you should see API requests coming from interations in the frontend code. If you add code (like Ruby debugging statements) to the cmd-tlm-api code you need to stop the server (CTRL-C) and restart it to see the effect.
+1. Once the `bundle exec rails s` command returns you should see API requests coming from interactions in the frontend code. If you add code (like Ruby debugging statements) to the cmd-tlm-api code you need to stop the server (CTRL-C) and restart it to see the effect.
diff --git a/docs.openc3.com/docs/getting-started/generators.md b/docs.openc3.com/docs/getting-started/generators.md
index d1e1044dec..322f639b62 100644
--- a/docs.openc3.com/docs/getting-started/generators.md
+++ b/docs.openc3.com/docs/getting-started/generators.md
@@ -203,7 +203,7 @@ WIDGET Helloworld
## Tool Generator
-The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelt. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see [Running a Frontend Application](../development/developing#running-a-frontend-application).
+The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelte. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see [Running a Frontend Application](../development/developing#running-a-frontend-application).
```bash
openc3-cosmos-gse % openc3.sh cli generate tool
@@ -225,7 +225,7 @@ This creates the following files and directories:
| src/tools/datavis/datavis.vue | Fully functional tool which displays a simple button. This can be expanded using existing COSMOS Vue.js code to create any tool imaginable. |
| package.json | Build and dependency definition file. Used by npm or yarn to build the tool. |
| vue.config.js | Vue configuration file used to serve the application in development and build the application. |
-| \ | Various dotfiles which help configure formatters and tools for Javascript frontend developemnt |
+| \ | Various dotfiles which help configure formatters and tools for Javascript frontend development |
It also updates the plugin.txt file to add the new tool. The icon can be changed to any of the material design icons found [here](https://pictogrammers.com/library/mdi/).
diff --git a/docs.openc3.com/docs/getting-started/gettingstarted.md b/docs.openc3.com/docs/getting-started/gettingstarted.md
index b381a09089..e2cabca37d 100644
--- a/docs.openc3.com/docs/getting-started/gettingstarted.md
+++ b/docs.openc3.com/docs/getting-started/gettingstarted.md
@@ -63,7 +63,7 @@ The cli runs as the default COSMOS container user which is the recommended pract
```
:::info Generators
-There are a number of generators available. Run `openc3.bat cli generate` to see all the avilable options.
+There are a number of generators available. Run `openc3.bat cli generate` to see all the available options.
:::
1. The target generator creates a single target named BOB. Best practice is to create a single target per plugin to make it easier to share targets and upgrade them individually. Lets see what the target generator created for us. Open the openc3-cosmos-bob/targets/BOB/cmd_tlm/cmd.txt:
@@ -88,7 +88,7 @@ There are a number of generators available. Run `openc3.bat cli generate` to see
- Then we APPEND_PARAMETER a third parameter called BOOL which is a 8-bit unsigned integer (UINT) with a minimum value of MIN (meaning the smallest value a UINT supports, e.g 0), a maximum value of MAX (largest value a UINT supports, e.g. 255), and a default value of 0. BOOL has two states which are just a fancy way of giving meaning to the integer values 0 and 1. The STATE FALSE has a value of 0 and the STATE TRUE has a value of 1.
- Finally we APPEND_PARAMETER called LABEL which is a 0-bit (meaning it takes up all the remaining space in the packet) string (STRING) with a default value of "OpenC3". Strings don't have minimum or maximum values as that doesn't make sense for STRING types.
- Check out the full [Command](../configuration/command.md) documention for more.
+ Check out the full [Command](../configuration/command.md) documentation for more.
1. Now open the openc3-cosmos-bob/targets/BOB/cmd_tlm/tlm.txt:
@@ -107,7 +107,7 @@ There are a number of generators available. Run `openc3.bat cli generate` to see
- We start by defininig an ID_ITEM called ID that is a 16-bit signed integer (INT) with an id value of 1 and described as "Identifier". Id items are used to take unidentified blobs of bytes and determine which packet they are. In this case if a blob comes in with a value of 1, at bit offset 0 (since we APPEND this item first), interpreted as a 16-bit integer, then this packet will be "identified" as STATUS. Note the first packet defined without any ID_ITEMS is a "catch-all" packet that matches all incoming data (even if the data lengths don't match).
- Next we define three items similar to the command definition above.
- Check out the full [Telemetry](../configuration/telemetry.md) documention for more.
+ Check out the full [Telemetry](../configuration/telemetry.md) documentation for more.
1. COSMOS has defined an example command and telemetry packet for our target. Most targets will obviously have more than one command and telemetry packet. To add more simply create additional COMMAND and TELEMETRY lines in your text files. Actual packets should match the structure of your command and telemetry. Be sure to add at least one unique [ID_PARAMETER](../configuration/command.md#id_parameter) and [ID_ITEM](../configuration/telemetry.md#id_item) so your packets can be distinguished from each other.
@@ -147,7 +147,7 @@ In a plugin that you plan to reuse you should make things like hostnames and por
File: openc3-cosmos-bob-1.0.0.20210618174517.gem
```
- - Note that the VERSION is required to specify the version to build. We recommend [sematic versioning](https://semver.org/) when building your plugin so people using your plugin (including you) know when there are breaking changes.
+ - Note that the VERSION is required to specify the version to build. We recommend [semantic versioning](https://semver.org/) when building your plugin so people using your plugin (including you) know when there are breaking changes.
1. Once our plugin is built we need to upload it to COSMOS. Go back to the Admin page and click the Plugins Tab. Click on "Click to install plugin" and select the openc3-cosmos-bob-1.0.0.20210618174517.gem file. Then click Upload. Go back to the CmdTlmServer and you should see the plugin being deployed at which point the BOB_INT interface should appear and try to connect. Go ahead and click 'Cancel' because unless you really have something listening on port 8080 this will never connect. At this point you can explore the other CmdTlmServer tabs and other tools to see your newly defined BOB target.
diff --git a/docs.openc3.com/docs/getting-started/installation.md b/docs.openc3.com/docs/getting-started/installation.md
index 6415f6e69c..a75168d618 100644
--- a/docs.openc3.com/docs/getting-started/installation.md
+++ b/docs.openc3.com/docs/getting-started/installation.md
@@ -25,7 +25,7 @@ Install [Docker](https://docs.docker.com/get-docker/) and install [Docker Compos
swap=0
:::warning Important: Modify Docker Connection Timeouts
-Docker by default will break idle (no data) connections after a period of 5 minutes. This "feature" will eventually cause you problems if you don't adjust the Docker settings. This may manifest as idle connections dropping or simplying failing to resume after data should have started flowing again. Find the file at C:\\Users\\username\\AppData\\Roaming\\Docker\\settings.json on Windows or ~/Library/Group Containers/group.com.docker/settings.json on MacOS. Modify the value `vpnKitMaxPortIdleTime` to change the timeout (recommend setting to 0). **Note:** 0 means no timeout (idle connections not dropped)
+Docker by default will break idle (no data) connections after a period of 5 minutes. This "feature" will eventually cause you problems if you don't adjust the Docker settings. This may manifest as idle connections dropping or simply failing to resume after data should have started flowing again. Find the file at C:\\Users\\username\\AppData\\Roaming\\Docker\\settings.json on Windows or ~/Library/Group Containers/group.com.docker/settings.json on MacOS. Modify the value `vpnKitMaxPortIdleTime` to change the timeout (recommend setting to 0). **Note:** 0 means no timeout (idle connections not dropped)
:::
**Note:** As of December 2021 the COSMOS Docker containers are based on the Alpine Docker image.
diff --git a/docs.openc3.com/docs/getting-started/key_concepts.md b/docs.openc3.com/docs/getting-started/key_concepts.md
index cd00f187e2..7a144c48c2 100644
--- a/docs.openc3.com/docs/getting-started/key_concepts.md
+++ b/docs.openc3.com/docs/getting-started/key_concepts.md
@@ -24,7 +24,7 @@ The COSMOS Open Source containers consist of the following:
| Name | Description |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| cosmos-openc3-cosmos-init-1 | Copies files to Minio and configures COSMOS then exits |
-| cosmos-openc3-operator-1 | Main COSMOS container that runs the interfaces and target mircoservices |
+| cosmos-openc3-operator-1 | Main COSMOS container that runs the interfaces and target microservices |
| cosmos-openc3-cosmos-cmd-tlm-api-1 | Rails server that provides all the COSMOS API endpoints |
| cosmos-openc3-cosmos-script-runner-api-1 | Rails server that provides the Script API endpoints |
| cosmos-openc3-redis-1 | Serves the static target configuration |
@@ -59,11 +59,11 @@ COSMOS Enterprise also provides [Terraform](https://www.terraform.io/) scripts t
### Vue.js
-The COSMOS frontend is fully browser native and is implented in the Vue.js framework. Per [Vue.js](https://vuejs.org/guide/introduction.html), "Vue is a JavaScript framework for building user interfaces. It builds on top of standard HTML, CSS, and JavaScript and provides a declarative and component-based programming model that helps you efficiently develop user interfaces, be they simple or complex." COSMOS utilizes Vue.js and the [Vuetify](https://vuetifyjs.com/en/) Component Framework UI library to build all the COSMOS tools which run in the browser of your choice.
+The COSMOS frontend is fully browser native and is implemented in the Vue.js framework. Per [Vue.js](https://vuejs.org/guide/introduction.html), "Vue is a JavaScript framework for building user interfaces. It builds on top of standard HTML, CSS, and JavaScript and provides a declarative and component-based programming model that helps you efficiently develop user interfaces, be they simple or complex." COSMOS utilizes Vue.js and the [Vuetify](https://vuetifyjs.com/en/) Component Framework UI library to build all the COSMOS tools which run in the browser of your choice.
### Single-Spa
-While COSMOS itself is written in Vue.js, we utilize a technology called [single-spa](https://single-spa.js.org/) to allow COSMOS developers to create applications in any javascript framework they choose. Single-spa is a micro frontend framework and acts as a top level router to render the application being requested. COSMOS provides sample applications ready to plug into single-spa in Angular, React, Svelt, and Vue.
+While COSMOS itself is written in Vue.js, we utilize a technology called [single-spa](https://single-spa.js.org/) to allow COSMOS developers to create applications in any javascript framework they choose. Single-spa is a micro frontend framework and acts as a top level router to render the application being requested. COSMOS provides sample applications ready to plug into single-spa in Angular, React, Svelte, and Vue.
### Astro UX
diff --git a/docs.openc3.com/docs/getting-started/requirements.md b/docs.openc3.com/docs/getting-started/requirements.md
index 40879c37a1..3ba4a67825 100644
--- a/docs.openc3.com/docs/getting-started/requirements.md
+++ b/docs.openc3.com/docs/getting-started/requirements.md
@@ -65,7 +65,7 @@ COSMOS 5 is a cloud native, containerized, microservice oriented command and con
| COSMOS-3 | The COSMOS user interface shall be accessible from the Firefox web browser | Open COSMOS in Firefox |
| COSMOS-4 | COSMOS shall log all commands sent | |
| COSMOS-5 | COSMOS shall log all telemetry received | |
-| COSMOS-6 | COSMOS shall decommutate all telemetry packets recieved | |
+| COSMOS-6 | COSMOS shall decommutate all telemetry packets received | |
| COSMOS-7 | COSMOS shall support autonomously attempting to connect to targets. | Verify targets are connected upon starting the CTS. |
| COSMOS-8 | COSMOS shall time stamp telemetry packets upon receipt. | Verify logged packets are timestamped. |
| COSMOS-9 | COSMOS shall time stamp telemetry packets to a resolution of 1 millisecond or better. Note: This requirement only refers to resolution. COSMOS does not run on real-time operating systems and accuracy cannot be guaranteed. | View time stamps in log. |
@@ -151,12 +151,12 @@ Script Runner now also provides a structured methodology for designing system le
| SR-5 | Script Runner shall highlight the currently executing line of the script. | Verify that lines are highlighted as a test script executes. |
| SR-6 | Script Runner shall allow pausing an executing script. | Press pause button and verify script is paused. Press start to resume. |
| SR-7 | Script Runner shall allow stopping an executing script. | Press stop and verify script stops. |
-| SR-8 | Script Runner shall pause an executing script upon the occurance of an error. | Create a script with a statement that is guaranteed to fail and verify that the script is paused. |
+| SR-8 | Script Runner shall pause an executing script upon the occurrence of an error. | Create a script with a statement that is guaranteed to fail and verify that the script is paused. |
| SR-9 | Script Runner shall log commands sent. | Execute a script that sends a command and verify it is logged. |
| SR-10 | Script Runner shall log text written to STDOUT. Note: Typically through the puts method. | Execute a script that uses puts to write a message and verify it is logged. |
| SR-11 | Script Runner shall log wait times. | Execute a script that includes a wait method and verify wait time is logged. |
| SR-12 | Script Runner shall log errors that occur while the script is executing. | Create a script with a check statement that is guaranteed to fail and verify it is logged. |
-| SR-13 | Script Runner shall log check statement success and failure. | Create a script with a check statement that is guaranteed to fail and one that is guaranteed to succeeed. Verify both the success and failure are logged. |
+| SR-13 | Script Runner shall log check statement success and failure. | Create a script with a check statement that is guaranteed to fail and one that is guaranteed to succeed. Verify both the success and failure are logged. |
| SR-14 | Script Runner shall support executing selected lines. | Select a set of lines and execute them using Script->Execute Selected Lines. |
| SR-15 | Script Runner shall support executing selected lines while paused. | Select a set of lines and execute them from the right-click context menu. |
| SR-16 | Script Runner shall support starting a script from any line. | Place the mouse cursor at the desired first line and then select Script->Execute From Cursor. |
diff --git a/docs.openc3.com/docs/guides/custom-widgets.md b/docs.openc3.com/docs/guides/custom-widgets.md
index bbc1f329e1..974337a46c 100644
--- a/docs.openc3.com/docs/guides/custom-widgets.md
+++ b/docs.openc3.com/docs/guides/custom-widgets.md
@@ -2,7 +2,7 @@
title: Custom Widgets
---
-COSMOS allows you to build custom widgets which can be deployed with your [plugin](../configuration/plugins.md) and used in [Telemetry Viewer](../tools/tlm-viewer.md). Building custom widgets can utilitize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the [Widget Generator](../getting-started/generators#widget-generator) guide for information about generating the scaffolding for a custom widget.
+COSMOS allows you to build custom widgets which can be deployed with your [plugin](../configuration/plugins.md) and used in [Telemetry Viewer](../tools/tlm-viewer.md). Building custom widgets can utilize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the [Widget Generator](../getting-started/generators#widget-generator) guide for information about generating the scaffolding for a custom widget.
## Custom Widgets
diff --git a/docs.openc3.com/docs/guides/script-writing.md b/docs.openc3.com/docs/guides/script-writing.md
index b5d51834f7..65f217cfc1 100644
--- a/docs.openc3.com/docs/guides/script-writing.md
+++ b/docs.openc3.com/docs/guides/script-writing.md
@@ -213,7 +213,7 @@ def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp):
Use comments when what you are doing is unclear or there is a higher-level purpose to a set of lines. Try to avoid putting numbers or other details in a comment as they can become out of sync with the underlying code. Ruby and Python comments start with a # pound symbol and can be anywhere on a line.
```ruby
-# This line sends an abort command - BAD COMMENT, UNNECCESSARY
+# This line sends an abort command - BAD COMMENT, UNNECESSARY
cmd("INST ABORT")
# Rotate the gimbal to look at the calibration target - GOOD COMMENT
cmd("INST ROTATE with ANGLE 180.0") # Rotate 180 degrees - BAD COMMENT
@@ -317,7 +317,7 @@ def script_1_heater_zone_control():
### Using Classes vs Unscoped Methods
-Classes in object-oriented programing allow you to organize a set of related methods and some associated state. The most important aspect is that the methods work on some shared state. For example, if you have code that moves a gimbal around, and need to keep track of the number of moves, or steps, performed across methods, then that is a wonderful place to use a class. If you just need a helper method to do something that happens multiple times in a script without copy and pasting, it probably does not need to be in a class.
+Classes in object-oriented programming allow you to organize a set of related methods and some associated state. The most important aspect is that the methods work on some shared state. For example, if you have code that moves a gimbal around, and need to keep track of the number of moves, or steps, performed across methods, then that is a wonderful place to use a class. If you just need a helper method to do something that happens multiple times in a script without copy and pasting, it probably does not need to be in a class.
NOTE: The convention in COSMOS is to have a TARGET/lib/target.\[rb/py\] file which is named after the TARGET name and contains a class called Target. This discussion refers to scripts in the TARGET/procedures directory.
@@ -533,7 +533,7 @@ else:
When running suites, there is a checkbox at the top of the tool called “Manual” that affects this $manual variable directly.
-### Outputing Extra Information to a Report
+### Outputting Extra Information to a Report
COSMOS Script Runner operating on a script suite automatically generates a report that shows the PASS/FAILED/SKIPPED state for each script. You can also inject arbitrary text into this report using the example as follows. Alternatively, you can simply use print text into the Script Runner message log.
@@ -588,7 +588,7 @@ id, packets = get_packets(id)
packets.each do |packet|
puts "#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}"
end
-# Wait for some time later and re-use the last returned ID
+# Wait for some time later and reuse the last returned ID
id, packets = get_packets(id)
```
@@ -600,7 +600,7 @@ wait(1.5)
id, packets = get_packets(id)
for packet in packets:
print(f"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}")
-# Wait for some time later and re-use the last returned ID
+# Wait for some time later and reuse the last returned ID
id, packets = get_packets(id)
```
diff --git a/docs.openc3.com/docs/guides/scripting-api.md b/docs.openc3.com/docs/guides/scripting-api.md
index aea55db14e..e7e3ab9fb3 100644
--- a/docs.openc3.com/docs/guides/scripting-api.md
+++ b/docs.openc3.com/docs/guides/scripting-api.md
@@ -166,7 +166,7 @@ password = ask("Enter your password", False, True)
### ask_string
-Prompts the user for input with a question. User input is always returned as a string. For exampe if the user enters "1", the string "1" will be returned.
+Prompts the user for input with a question. User input is always returned as a string. For example if the user enters "1", the string "1" will be returned.
Ruby / Python Syntax:
@@ -560,7 +560,7 @@ cmd_no_hazardous_check("INST", "CLEAR")
### cmd_no_checks
-Sends a specified command without performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentially have invalid parameters.
+Sends a specified command without performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentionally have invalid parameters.
Ruby Syntax:
@@ -717,7 +717,7 @@ cmd_raw_no_hazardous_check("INST", "CLEAR")
### cmd_raw_no_checks
-Sends a specified command without running conversions or performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentially have invalid parameters.
+Sends a specified command without running conversions or performing the parameter range checks or notification if it is a hazardous command. This should only be used when it is necessary to fully automate testing involving hazardous commands that intentionally have invalid parameters.
Ruby Syntax:
@@ -1114,7 +1114,7 @@ These methods allow the user to interact with telemetry items.
### check, check_raw, check_formatted, check_with_units
-Performs a verification of a telemetry item using its specified telemetry type. If the verification fails then the script will be paused with an error. If no comparision is given to check then the telemetry item is simply printed to the script output. Note: In most cases using wait_check is a better choice than using check.
+Performs a verification of a telemetry item using its specified telemetry type. If the verification fails then the script will be paused with an error. If no comparison is given to check then the telemetry item is simply printed to the script output. Note: In most cases using wait_check is a better choice than using check.
Ruby / Python Syntax:
@@ -1631,7 +1631,7 @@ normalize_tlm("INST HEALTH_STATUS TEMP1", type='RAW') # clear only the RAW overr
### 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.
+Returns an array of the the currently overridden values set by override_tlm. NOTE: This returns all the value types that are overridden which by default is all 4 values types when using override_tlm.
Ruby / Python Syntax:
@@ -2281,7 +2281,7 @@ set_limits(, , , , , <
| Red High | Red High setting for this limits set. Any value above this value will be make the item red. |
| Green Low | Optional. If given, any value greater than Green Low and less than Green_High will make the item blue indicating a good operational value. |
| Green High | Optional. If given, any value greater than Green Low and less than Green_High will make the item blue indicating a good operational value. |
-| Limits Set | Optional. Set the limits for a specific limits set. If not given then it defaults to setting limts for the CUSTOM limits set. |
+| Limits Set | Optional. Set the limits for a specific limits set. If not given then it defaults to setting limits for the CUSTOM limits set. |
| Persistence | Optional. Set the number of samples this item must be out of limits before changing limits state. Defaults to no change. Note: This affects all limits settings across limits sets. |
| Enabled | Optional. Whether or not limits are enabled for this item. Defaults to true. Note: This affects all limits settings across limits sets. |
@@ -3323,7 +3323,7 @@ print(get_max_output()) #=> 50000
### disable_instrumentation
Disables instrumentation for a block of code (line highlighting and exception catching). This is especially useful for speeding up loops that are very slow if lines are instrumented.
-Consider breaking code like this into a seperate file and using either require/load to read the file for the same effect while still allowing errors to be caught by your script.
+Consider breaking code like this into a separate file and using either require/load to read the file for the same effect while still allowing errors to be caught by your script.
:::warning Use with Caution
Disabling instrumentation will cause any error that occurs while disabled to cause your script to completely stop.
@@ -3531,11 +3531,11 @@ Ruby / Python Syntax:
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. |
+| 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 metadata in the calendar. Default is #003784. |
Ruby Example:
@@ -3561,11 +3561,11 @@ Ruby / Python Syntax:
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. |
+| 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 metadata in the calendar. Default is #003784. |
Ruby Example:
@@ -3697,7 +3697,7 @@ print(get_settings('pypi_url')) #=> 'https://mypypiserver'
## Configuration
-Many COSMOS tools have the ability to load and save a configuration. These APIs allow you to programatically load and save the configuration.
+Many COSMOS tools have the ability to load and save a configuration. These APIs allow you to programmatically load and save the configuration.
### config_tool_names
diff --git a/docs.openc3.com/docs/tools/autonomic.md b/docs.openc3.com/docs/tools/autonomic.md
index ee0d1c7667..62f73aff83 100644
--- a/docs.openc3.com/docs/tools/autonomic.md
+++ b/docs.openc3.com/docs/tools/autonomic.md
@@ -14,7 +14,7 @@ Autonomic operates with some basic building blocks: Trigger Groups, Triggers, an
### TriggerGroups
-Triggers are organized into groups, these groups are both for organization and to ensure that we can scale. It also allows triggers to be evaluated independently and simulataneously and can be useful for overlapping or high priority triggers. However, each trigger group spawns system resources so they should only be created as needed.
+Triggers are organized into groups, these groups are both for organization and to ensure that we can scale. It also allows triggers to be evaluated independently and simultaneously and can be useful for overlapping or high priority triggers. However, each trigger group spawns system resources so they should only be created as needed.

diff --git a/docs.openc3.com/docs/tools/calendar.md b/docs.openc3.com/docs/tools/calendar.md
index 8e408fcb5c..627e047ba7 100644
--- a/docs.openc3.com/docs/tools/calendar.md
+++ b/docs.openc3.com/docs/tools/calendar.md
@@ -10,7 +10,7 @@ Calendar visualizes metadata, notes, and timeline information in one easy to und
### Adding Timelines
-Adding a Timeline to COSMOS is as simple as clicking Create -> Timeline and giving it a unique name. Timelines can be created for organizational purposes or for overlapping activities as no activies can overlap on a given timeline. However, each additional timeline consists of several threads so only create timelines as necessary.
+Adding a Timeline to COSMOS is as simple as clicking Create -> Timeline and giving it a unique name. Timelines can be created for organizational purposes or for overlapping activities as no activities can overlap on a given timeline. However, each additional timeline consists of several threads so only create timelines as necessary.
## Types of Events
@@ -46,7 +46,7 @@ Activities can run single commands, run a script, or simply "Reserve" space on t

-When calendar activities are scheduled they appear with a green circle containing a plus (+). Once they complete successfully the icon changes to a green circle containing a checkbox (✓). Reserve activites simply have a blank green circle.
+When calendar activities are scheduled they appear with a green circle containing a plus (+). Once they complete successfully the icon changes to a green circle containing a checkbox (✓). Reserve activities simply have a blank green circle.

@@ -56,9 +56,9 @@ Calendar events can also be viewed in a list format via File->Show Table Display
## Timeline Implementation Details
-When a user creates a timeline, a new timeline microservice starts. The timeline microservice is the main thread of execution for the timeline. This starts a scheduler manager thread. The scheduler manger thread contains a thread pool that hosts more than one thread to run the activity. The scheduler manger will evaluate the schedule and based on the start time of the activity it will add the activity to the queue.
+When a user creates a timeline, a new timeline microservice starts. The timeline microservice is the main thread of execution for the timeline. This starts a scheduler manager thread. The scheduler manager thread contains a thread pool that hosts more than one thread to run the activity. The scheduler manager will evaluate the schedule and based on the start time of the activity it will add the activity to the queue.
-The main thread will block on the web socket to listen to request changes to the timeline, these could be adding, removing, or updating activities. The main thread will make the changes to the in memory schedule if these changes are within the hour of the current time. When the web socket gets an update it has an action lookup table. These actions are "created", "updated", "deleted", ect... Some actions require updating the schedule from the database to ensure the schedule and the database are always in sync.
+The main thread will block on the web socket to listen to request changes to the timeline, these could be adding, removing, or updating activities. The main thread will make the changes to the in memory schedule if these changes are within the hour of the current time. When the web socket gets an update it has an action lookup table. These actions are "created", "updated", "deleted", etc... Some actions require updating the schedule from the database to ensure the schedule and the database are always in sync.
The schedule thread checks every second to make sure if a task can be run. If the start time is equal or less then the last 15 seconds it will then check the previously queued jobs list in the schedule. If the activity has not been queued and is not fulfilled the activity will be queued, this adds an event to the activity but is not saved to the database.
diff --git a/docs.openc3.com/docs/tools/cmd-tlm-server.md b/docs.openc3.com/docs/tools/cmd-tlm-server.md
index dee5f2f1d1..766353c925 100644
--- a/docs.openc3.com/docs/tools/cmd-tlm-server.md
+++ b/docs.openc3.com/docs/tools/cmd-tlm-server.md
@@ -4,7 +4,7 @@ title: Command and Telemetry Server
## Introduction
-The Command and Telemetry Server application provides status about the [interfaces](../configuration/interfaces.md) and targets instantiated in your COSMOS installation. Intefaces can be connected or disconnected and raw byte counts are returned. The application also provides quick shortcuts to view
+The Command and Telemetry Server application provides status about the [interfaces](../configuration/interfaces.md) and targets instantiated in your COSMOS installation. Interfaces can be connected or disconnected and raw byte counts are returned. The application also provides quick shortcuts to view
both raw and formatted command and telemetry packets as they go through the COSMOS system. At the bottom of the Command and Telemetry Server is the Log Messages showing server messages.

diff --git a/docs.openc3.com/docs/tools/limits-monitor.md b/docs.openc3.com/docs/tools/limits-monitor.md
index 4f6c0c02fb..9fac0b0629 100644
--- a/docs.openc3.com/docs/tools/limits-monitor.md
+++ b/docs.openc3.com/docs/tools/limits-monitor.md
@@ -4,7 +4,7 @@ title: Limits Monitor
## Introduction
-The Limits Monitor application provides situational awareness for all telemetry items with limits. All limits items which violate their yellow or red limits are shown and continue to be shown until explicity dismissed. Individual items and entire packets can be manually ignored to filter out known issues. In addition, all limits events are logged in a table which can be searched.
+The Limits Monitor application provides situational awareness for all telemetry items with limits. All limits items which violate their yellow or red limits are shown and continue to be shown until explicitly dismissed. Individual items and entire packets can be manually ignored to filter out known issues. In addition, all limits events are logged in a table which can be searched.

diff --git a/docs.openc3.com/docs/tools/script-runner.md b/docs.openc3.com/docs/tools/script-runner.md
index c8046d14f1..cd90b65c24 100644
--- a/docs.openc3.com/docs/tools/script-runner.md
+++ b/docs.openc3.com/docs/tools/script-runner.md
@@ -50,14 +50,14 @@ style={{"float": 'left', "margin-right": 50 + 'px', "height": 330 + 'px'}} />
- Display started and finished scripts
- Show environment variables
- Show defined metadata
-- Show overriden telemetry values
+- Show overridden telemetry values
- Perform a syntax check
- Perform a script mnemonic check
- View the instrumented script
- Shows the script call stack
- Display the [debug](script-runner.md#debugging-scripts) prompt
- Disconnect from real interfaces
-- Delete all sccript breakpoints
+- Delete all script breakpoints
The Execution Status popup lists the currently running scripts. This allows other users to connect to running scripts and follow along with the currently executing script. It also lists previously executed scripts so you can download the script log.
diff --git a/docs.openc3.com/docs/tools/tlm-viewer.md b/docs.openc3.com/docs/tools/tlm-viewer.md
index d04ac8d864..c97d1753eb 100644
--- a/docs.openc3.com/docs/tools/tlm-viewer.md
+++ b/docs.openc3.com/docs/tools/tlm-viewer.md
@@ -4,7 +4,7 @@ title: Telemetry Viewer
## Introduction
-Telemetry Viewer is a live telemetry viewer which displays custom built screens. Screens are configured through simple text files which utilize numerous build-in widgets.
+Telemetry Viewer is a live telemetry viewer which displays custom built screens. Screens are configured through simple text files which utilize numerous built-in widgets.

diff --git a/docs/404.html b/docs/404.html
index 99726efcdc..92528cc280 100644
--- a/docs/404.html
+++ b/docs/404.html
@@ -4,8 +4,8 @@
Page Not Found | OpenC3 Docs
-
-
+
+
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
diff --git a/docs/assets/js/0f5d161c.cff756ef.js b/docs/assets/js/0f5d161c.3c391ca4.js
similarity index 96%
rename from docs/assets/js/0f5d161c.cff756ef.js
rename to docs/assets/js/0f5d161c.3c391ca4.js
index 7ed688e429..ef4224f219 100644
--- a/docs/assets/js/0f5d161c.cff756ef.js
+++ b/docs/assets/js/0f5d161c.3c391ca4.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[2327],{5221:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=n(4848),r=n(8453);const s={title:"Script Runner"},o=void 0,a={id:"tools/script-runner",title:"Script Runner",description:"Introduction",source:"@site/docs/tools/script-runner.md",sourceDirName:"tools",slug:"/tools/script-runner",permalink:"/docs/tools/script-runner",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/script-runner.md",tags:[],version:"current",frontMatter:{title:"Script Runner"},sidebar:"defaultSidebar",previous:{title:"Packet Viewer",permalink:"/docs/tools/packet-viewer"},next:{title:"Table Manager",permalink:"/docs/tools/table-manager"}},l={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Script Runner Menus",id:"script-runner-menus",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"File Open",id:"file-open",level:4},{value:"File Save As",id:"file-save-as",level:4},{value:"Script Menu Items",id:"script-menu-items",level:3},{value:"Running Scripts",id:"running-scripts",level:2},{value:"Running Script Suites",id:"running-script-suites",level:2},{value:"Group",id:"group",level:3},{value:"Suite",id:"suite",level:3},{value:"Script Suite Options",id:"script-suite-options",level:3},{value:"Pause on Error",id:"pause-on-error",level:4},{value:"Continue after Error",id:"continue-after-error",level:4},{value:"Abort after Error",id:"abort-after-error",level:4},{value:"Manual",id:"manual",level:4},{value:"Loop",id:"loop",level:4},{value:"Break Loop on Error",id:"break-loop-on-error",level:4},{value:"Debugging Scripts",id:"debugging-scripts",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"Script Runner is both an editor of COSMOS scripts as well as executes scripts. Script files are stored within a COSMOS target and Script Runner provides the ability to open, save, download and delete these files. When a suite of scripts is opened, Script Runner provides additional options to run individual scripts, groups of scripts, or entire suites."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Script Runner",src:n(9056).A+"",width:"1273",height:"929"})}),"\n",(0,i.jsx)(t.h2,{id:"script-runner-menus",children:"Script Runner Menus"}),"\n",(0,i.jsx)(t.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,i.jsx)("img",{src:n(2549).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"250px"}}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Clears the editor and filename"}),"\n",(0,i.jsx)(t.li,{children:"Creates a new test suite in Ruby or Python"}),"\n",(0,i.jsx)(t.li,{children:"Opens a dialog to select a file to open"}),"\n",(0,i.jsx)(t.li,{children:"Opens a recently used file"}),"\n",(0,i.jsx)(t.li,{children:"Saves the currently opened file to disk"}),"\n",(0,i.jsx)(t.li,{children:"Rename the current file"}),"\n",(0,i.jsx)(t.li,{children:"Downloads the current file to the browser"}),"\n",(0,i.jsxs)(t.li,{children:["Deletes the current file (Permanently!)","\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"file-open",children:"File Open"}),"\n",(0,i.jsx)(t.p,{children:"The File Open Dialog displays a tree view of the installed targets. You can manually open the folders and browse for the file you want. You can also use the search box at the top and start typing part of the filename to filter the results."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"File Open",src:n(1011).A+"",width:"597",height:"599"})}),"\n",(0,i.jsx)(t.h4,{id:"file-save-as",children:"File Save As"}),"\n",(0,i.jsx)(t.p,{children:"When saving a file for the first time, or using File Save As, the File Save As Dialog appears. It works similar to the File Open Dialog displaying the tree view of the installed targets. You must select a folder by clicking the folder name and then filling out the Filename field with a filename before clicking Ok. You will be prompted before over-writing an existing file."}),"\n",(0,i.jsx)(t.h3,{id:"script-menu-items",children:"Script Menu Items"}),"\n",(0,i.jsx)("img",{src:n(2232).A,alt:"Script Menu",style:{float:"left","margin-right":"50px",height:"330px"}}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Display started and finished scripts"}),"\n",(0,i.jsx)(t.li,{children:"Show environment variables"}),"\n",(0,i.jsx)(t.li,{children:"Show defined metadata"}),"\n",(0,i.jsx)(t.li,{children:"Show overriden telemetry values"}),"\n",(0,i.jsx)(t.li,{children:"Perform a syntax check"}),"\n",(0,i.jsx)(t.li,{children:"Perform a script mnemonic check"}),"\n",(0,i.jsx)(t.li,{children:"View the instrumented script"}),"\n",(0,i.jsx)(t.li,{children:"Shows the script call stack"}),"\n",(0,i.jsxs)(t.li,{children:["Display the ",(0,i.jsx)(t.a,{href:"/docs/tools/script-runner#debugging-scripts",children:"debug"})," prompt"]}),"\n",(0,i.jsx)(t.li,{children:"Disconnect from real interfaces"}),"\n",(0,i.jsx)(t.li,{children:"Delete all sccript breakpoints"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The Execution Status popup lists the currently running scripts. This allows other users to connect to running scripts and follow along with the currently executing script. It also lists previously executed scripts so you can download the script log."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Running Scripts",src:n(1010).A+"",width:"1508",height:"505"})}),"\n",(0,i.jsx)(t.h2,{id:"running-scripts",children:"Running Scripts"}),"\n",(0,i.jsx)(t.p,{children:"Running a regular script is simply a matter of opening it and clicking the Start button. By default when you open a script the Filename is updated and the editor loads the script."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"checks.rb",src:n(9828).A+"",width:"1273",height:"533"})}),"\n",(0,i.jsx)(t.p,{children:"Once you click Start the script is spawned in the Server and the Script State becomes Connecting."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"connecting",src:n(1882).A+"",width:"1273",height:"68"})}),"\n",(0,i.jsx)(t.p,{children:"At that point the currently executing line is marked with green. If an error is encountered the line turns red and and the Pause button changes to Retry to allow the line to be re-tried."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"error",src:n(5842).A+"",width:"1273",height:"527"})}),"\n",(0,i.jsx)(t.p,{children:"This allows checks that depend on telemetry changing to potentially be retried as telemetry is being updated live in the background. You can also click Go to continue pass the error or Stop to end the script execution."}),"\n",(0,i.jsx)(t.h2,{id:"running-script-suites",children:"Running Script Suites"}),"\n",(0,i.jsx)(t.p,{children:"If a script is structured as a Suite it automatically causes Script Runner to parse the file to populate the Suite, Group, and Script drop down menus."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Suite Script",src:n(7580).A+"",width:"1273",height:"624"})}),"\n",(0,i.jsx)(t.p,{children:"To generate a new Suite use the File -> New Test Suite and then choose either Ruby or Python to create a Suite in that language."}),"\n",(0,i.jsx)(t.h3,{id:"group",children:"Group"}),"\n",(0,i.jsx)(t.p,{children:"The Group class contains the methods used to run the test or operations. Any methods starting with 'script', 'op', or 'test' which are implemented inside a Group class are automatically included as scripts to run. For example, in the above image, you'll notice the 'script_power_on' is in the Script drop down menu. Here's another simple Ruby example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'require \'openc3/script/suite.rb\'\nclass ExampleGroup < OpenC3::Group\n def setup\n puts "setup"\n end\n def script_1\n puts "script 1"\n end\n def teardown\n puts "teardown"\n end\nend\n'})}),"\n",(0,i.jsx)(t.p,{children:"Equivalent Python example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from openc3.script.suite import Suite, Group\nclass ExampleGroup(Group):\n def setup(self):\n print("setup")\n def script_1(self):\n print("script 1")\n def teardown(self)\n print("teardown")\n'})}),"\n",(0,i.jsx)(t.p,{children:"The setup and teardown methods are special methods which enable the Setup and Teardown buttons next to the Group drop down menu. Clicking these buttons runs the associated method."}),"\n",(0,i.jsx)(t.h3,{id:"suite",children:"Suite"}),"\n",(0,i.jsx)(t.p,{children:"Groups are added to Suites by creating a class inheriting from Suite and then calling the add_group method. For example in Ruby:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'class MySuite < OpenC3::Suite\n def initialize\n add_group(\'ExampleGroup\')\n end\n def setup\n puts "Suite setup"\n end\n def teardown\n puts "Suite teardown"\n end\nend\n'})}),"\n",(0,i.jsx)(t.p,{children:"In Python:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from openc3.script.suite import Suite, Group\nclass MySuite(Suite):\n def __init__(self):\n self.add_group(\'ExampleGroup\')\n def setup(self):\n print("Suite setup")\n def teardown(self):\n print("Suite teardown")\n'})}),"\n",(0,i.jsx)(t.p,{children:"Again there are setup and teardown methods which enable the Setup and Teardown buttons next to the Suite drop down menu."}),"\n",(0,i.jsx)(t.p,{children:"Multiple Suites and Groups can be created in the same file and will be parsed and added to the drop down menus. Clicking Start at the Suite level will run ALL Groups and ALL Scripts within each Group. Similarly, clicking Start at the Group level will run all Scripts in the Group. Clicking Start next to the Script will run just the single Script."}),"\n",(0,i.jsx)(t.h3,{id:"script-suite-options",children:"Script Suite Options"}),"\n",(0,i.jsx)(t.p,{children:"Opening a Script Suite creates six checkboxes which provide options to the running script."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Suite Checkboxes",src:n(4376).A+"",width:"464",height:"145"})}),"\n",(0,i.jsx)(t.h4,{id:"pause-on-error",children:"Pause on Error"}),"\n",(0,i.jsx)(t.p,{children:"Pauses the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box allows the script to continue past errors without user intervention. Similar to the User clicking Go upon encountering an error."}),"\n",(0,i.jsx)(t.h4,{id:"continue-after-error",children:"Continue after Error"}),"\n",(0,i.jsx)(t.p,{children:"Continue the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box means that the script will end after the first encountered error and execution will continue with any other scripts in the Suite/Group."}),"\n",(0,i.jsx)(t.h4,{id:"abort-after-error",children:"Abort after Error"}),"\n",(0,i.jsx)(t.p,{children:"Abort the entire execution upon encountering an error. If the first Script in a Suite's Group encounters an error the entire Suite will stop execution. Note, if Continue after Error is set, the current script is allowed to continue and complete."}),"\n",(0,i.jsx)(t.h4,{id:"manual",children:"Manual"}),"\n",(0,i.jsxs)(t.p,{children:["In Ruby, sets the global variable called ",(0,i.jsx)(t.code,{children:"$manual"})," to true. In Python, sets ",(0,i.jsx)(t.code,{children:"RunningScript.manual"})," to True. Setting this box only allows the script author to determine if the operator wants to execute manual steps or not. It is up the script author to use the variable in their scripts."]}),"\n",(0,i.jsx)(t.h4,{id:"loop",children:"Loop"}),"\n",(0,i.jsx)(t.p,{children:"Loop whatever the user started continuously. If the user clicks Start next to the Group then the entire Group will be looped. This is useful to catch and debug those tricky timing errors that only sometimes happen."}),"\n",(0,i.jsx)(t.h4,{id:"break-loop-on-error",children:"Break Loop on Error"}),"\n",(0,i.jsx)(t.p,{children:"Break the loop if an Error occurs. Only available if the Loop option is set."}),"\n",(0,i.jsx)(t.h2,{id:"debugging-scripts",children:"Debugging Scripts"}),"\n",(0,i.jsxs)(t.p,{children:["When you enable the Debug prompt an additional line appears between the script and the Log Messages. You can type local variables to cause them to be output in the Log Messages. You can also set local variables by typing ",(0,i.jsx)(t.code,{children:"var = 10"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Debug",src:n(5015).A+"",width:"1273",height:"748"})}),"\n",(0,i.jsx)(t.p,{children:"The Step button allows you to step line by line through the script. Clicking Go continues regular execution."})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2549:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/file_menu-470589e527d9e82ce40e0c7d4a865e33d19b42350c2429dba97186d168137b6d.png"},2232:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_menu-5a10df89d9806a59b41ef990fc1181c46c7ffa00496021efceb22c0f31dcc9cc.png"},9828:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/checks_rb-89f400098ff47774008ea420860c665c15ebf06819c3ee7050bed301ea0a9f46.png"},1882:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/connecting-0f804651a891ef6112a51ba8b2e4d8dcb46e3462dcbc94e7b3c75bff20fc04e7.png"},5015:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/debug-3103972d64395b50fff5808661fb846ae2de7d5934548ca5b88032f1ae12c541.png"},1011:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/file_open-a5bc9e5ef73c12913ea4882498ceb52f93c73afaf5bb0c1083c4c1ee402f571d.png"},1010:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/running_scripts-694a1b310d42791acf64cf76ea370bb273084954107d5e6e2caf15f4fb50e634.png"},5842:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_error-2061222e00f5e5190a4407be1f8999200badca9b3137659de007e27cf1708dc0.png"},9056:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_runner-31f6bfcb631b788ff0bf792ac21da30aaa503ca926b10a22d4337114effc28f0.png"},7580:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_suite-16647c3b3de01a8749f1b5c4ab2f8b452630df8c0470e5be38652acacfc98b5d.png"},4376:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/suite_checkboxes-af8452153dbc2143718fefcfc7d441e05f42c241b3c10d4f41200ae576f68063.png"},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var i=n(6540);const r={},s=i.createContext(r);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[2327],{5221:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=n(4848),r=n(8453);const s={title:"Script Runner"},o=void 0,a={id:"tools/script-runner",title:"Script Runner",description:"Introduction",source:"@site/docs/tools/script-runner.md",sourceDirName:"tools",slug:"/tools/script-runner",permalink:"/docs/tools/script-runner",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/script-runner.md",tags:[],version:"current",frontMatter:{title:"Script Runner"},sidebar:"defaultSidebar",previous:{title:"Packet Viewer",permalink:"/docs/tools/packet-viewer"},next:{title:"Table Manager",permalink:"/docs/tools/table-manager"}},l={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Script Runner Menus",id:"script-runner-menus",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"File Open",id:"file-open",level:4},{value:"File Save As",id:"file-save-as",level:4},{value:"Script Menu Items",id:"script-menu-items",level:3},{value:"Running Scripts",id:"running-scripts",level:2},{value:"Running Script Suites",id:"running-script-suites",level:2},{value:"Group",id:"group",level:3},{value:"Suite",id:"suite",level:3},{value:"Script Suite Options",id:"script-suite-options",level:3},{value:"Pause on Error",id:"pause-on-error",level:4},{value:"Continue after Error",id:"continue-after-error",level:4},{value:"Abort after Error",id:"abort-after-error",level:4},{value:"Manual",id:"manual",level:4},{value:"Loop",id:"loop",level:4},{value:"Break Loop on Error",id:"break-loop-on-error",level:4},{value:"Debugging Scripts",id:"debugging-scripts",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"Script Runner is both an editor of COSMOS scripts as well as executes scripts. Script files are stored within a COSMOS target and Script Runner provides the ability to open, save, download and delete these files. When a suite of scripts is opened, Script Runner provides additional options to run individual scripts, groups of scripts, or entire suites."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Script Runner",src:n(9056).A+"",width:"1273",height:"929"})}),"\n",(0,i.jsx)(t.h2,{id:"script-runner-menus",children:"Script Runner Menus"}),"\n",(0,i.jsx)(t.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,i.jsx)("img",{src:n(2549).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"250px"}}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Clears the editor and filename"}),"\n",(0,i.jsx)(t.li,{children:"Creates a new test suite in Ruby or Python"}),"\n",(0,i.jsx)(t.li,{children:"Opens a dialog to select a file to open"}),"\n",(0,i.jsx)(t.li,{children:"Opens a recently used file"}),"\n",(0,i.jsx)(t.li,{children:"Saves the currently opened file to disk"}),"\n",(0,i.jsx)(t.li,{children:"Rename the current file"}),"\n",(0,i.jsx)(t.li,{children:"Downloads the current file to the browser"}),"\n",(0,i.jsxs)(t.li,{children:["Deletes the current file (Permanently!)","\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"file-open",children:"File Open"}),"\n",(0,i.jsx)(t.p,{children:"The File Open Dialog displays a tree view of the installed targets. You can manually open the folders and browse for the file you want. You can also use the search box at the top and start typing part of the filename to filter the results."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"File Open",src:n(1011).A+"",width:"597",height:"599"})}),"\n",(0,i.jsx)(t.h4,{id:"file-save-as",children:"File Save As"}),"\n",(0,i.jsx)(t.p,{children:"When saving a file for the first time, or using File Save As, the File Save As Dialog appears. It works similar to the File Open Dialog displaying the tree view of the installed targets. You must select a folder by clicking the folder name and then filling out the Filename field with a filename before clicking Ok. You will be prompted before over-writing an existing file."}),"\n",(0,i.jsx)(t.h3,{id:"script-menu-items",children:"Script Menu Items"}),"\n",(0,i.jsx)("img",{src:n(2232).A,alt:"Script Menu",style:{float:"left","margin-right":"50px",height:"330px"}}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Display started and finished scripts"}),"\n",(0,i.jsx)(t.li,{children:"Show environment variables"}),"\n",(0,i.jsx)(t.li,{children:"Show defined metadata"}),"\n",(0,i.jsx)(t.li,{children:"Show overridden telemetry values"}),"\n",(0,i.jsx)(t.li,{children:"Perform a syntax check"}),"\n",(0,i.jsx)(t.li,{children:"Perform a script mnemonic check"}),"\n",(0,i.jsx)(t.li,{children:"View the instrumented script"}),"\n",(0,i.jsx)(t.li,{children:"Shows the script call stack"}),"\n",(0,i.jsxs)(t.li,{children:["Display the ",(0,i.jsx)(t.a,{href:"/docs/tools/script-runner#debugging-scripts",children:"debug"})," prompt"]}),"\n",(0,i.jsx)(t.li,{children:"Disconnect from real interfaces"}),"\n",(0,i.jsx)(t.li,{children:"Delete all script breakpoints"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The Execution Status popup lists the currently running scripts. This allows other users to connect to running scripts and follow along with the currently executing script. It also lists previously executed scripts so you can download the script log."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Running Scripts",src:n(1010).A+"",width:"1508",height:"505"})}),"\n",(0,i.jsx)(t.h2,{id:"running-scripts",children:"Running Scripts"}),"\n",(0,i.jsx)(t.p,{children:"Running a regular script is simply a matter of opening it and clicking the Start button. By default when you open a script the Filename is updated and the editor loads the script."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"checks.rb",src:n(9828).A+"",width:"1273",height:"533"})}),"\n",(0,i.jsx)(t.p,{children:"Once you click Start the script is spawned in the Server and the Script State becomes Connecting."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"connecting",src:n(1882).A+"",width:"1273",height:"68"})}),"\n",(0,i.jsx)(t.p,{children:"At that point the currently executing line is marked with green. If an error is encountered the line turns red and and the Pause button changes to Retry to allow the line to be re-tried."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"error",src:n(5842).A+"",width:"1273",height:"527"})}),"\n",(0,i.jsx)(t.p,{children:"This allows checks that depend on telemetry changing to potentially be retried as telemetry is being updated live in the background. You can also click Go to continue pass the error or Stop to end the script execution."}),"\n",(0,i.jsx)(t.h2,{id:"running-script-suites",children:"Running Script Suites"}),"\n",(0,i.jsx)(t.p,{children:"If a script is structured as a Suite it automatically causes Script Runner to parse the file to populate the Suite, Group, and Script drop down menus."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Suite Script",src:n(7580).A+"",width:"1273",height:"624"})}),"\n",(0,i.jsx)(t.p,{children:"To generate a new Suite use the File -> New Test Suite and then choose either Ruby or Python to create a Suite in that language."}),"\n",(0,i.jsx)(t.h3,{id:"group",children:"Group"}),"\n",(0,i.jsx)(t.p,{children:"The Group class contains the methods used to run the test or operations. Any methods starting with 'script', 'op', or 'test' which are implemented inside a Group class are automatically included as scripts to run. For example, in the above image, you'll notice the 'script_power_on' is in the Script drop down menu. Here's another simple Ruby example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'require \'openc3/script/suite.rb\'\nclass ExampleGroup < OpenC3::Group\n def setup\n puts "setup"\n end\n def script_1\n puts "script 1"\n end\n def teardown\n puts "teardown"\n end\nend\n'})}),"\n",(0,i.jsx)(t.p,{children:"Equivalent Python example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from openc3.script.suite import Suite, Group\nclass ExampleGroup(Group):\n def setup(self):\n print("setup")\n def script_1(self):\n print("script 1")\n def teardown(self)\n print("teardown")\n'})}),"\n",(0,i.jsx)(t.p,{children:"The setup and teardown methods are special methods which enable the Setup and Teardown buttons next to the Group drop down menu. Clicking these buttons runs the associated method."}),"\n",(0,i.jsx)(t.h3,{id:"suite",children:"Suite"}),"\n",(0,i.jsx)(t.p,{children:"Groups are added to Suites by creating a class inheriting from Suite and then calling the add_group method. For example in Ruby:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'class MySuite < OpenC3::Suite\n def initialize\n add_group(\'ExampleGroup\')\n end\n def setup\n puts "Suite setup"\n end\n def teardown\n puts "Suite teardown"\n end\nend\n'})}),"\n",(0,i.jsx)(t.p,{children:"In Python:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from openc3.script.suite import Suite, Group\nclass MySuite(Suite):\n def __init__(self):\n self.add_group(\'ExampleGroup\')\n def setup(self):\n print("Suite setup")\n def teardown(self):\n print("Suite teardown")\n'})}),"\n",(0,i.jsx)(t.p,{children:"Again there are setup and teardown methods which enable the Setup and Teardown buttons next to the Suite drop down menu."}),"\n",(0,i.jsx)(t.p,{children:"Multiple Suites and Groups can be created in the same file and will be parsed and added to the drop down menus. Clicking Start at the Suite level will run ALL Groups and ALL Scripts within each Group. Similarly, clicking Start at the Group level will run all Scripts in the Group. Clicking Start next to the Script will run just the single Script."}),"\n",(0,i.jsx)(t.h3,{id:"script-suite-options",children:"Script Suite Options"}),"\n",(0,i.jsx)(t.p,{children:"Opening a Script Suite creates six checkboxes which provide options to the running script."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Suite Checkboxes",src:n(4376).A+"",width:"464",height:"145"})}),"\n",(0,i.jsx)(t.h4,{id:"pause-on-error",children:"Pause on Error"}),"\n",(0,i.jsx)(t.p,{children:"Pauses the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box allows the script to continue past errors without user intervention. Similar to the User clicking Go upon encountering an error."}),"\n",(0,i.jsx)(t.h4,{id:"continue-after-error",children:"Continue after Error"}),"\n",(0,i.jsx)(t.p,{children:"Continue the script if an error is encountered. This is the default and identical to how normal scripts are executed. Unchecking this box means that the script will end after the first encountered error and execution will continue with any other scripts in the Suite/Group."}),"\n",(0,i.jsx)(t.h4,{id:"abort-after-error",children:"Abort after Error"}),"\n",(0,i.jsx)(t.p,{children:"Abort the entire execution upon encountering an error. If the first Script in a Suite's Group encounters an error the entire Suite will stop execution. Note, if Continue after Error is set, the current script is allowed to continue and complete."}),"\n",(0,i.jsx)(t.h4,{id:"manual",children:"Manual"}),"\n",(0,i.jsxs)(t.p,{children:["In Ruby, sets the global variable called ",(0,i.jsx)(t.code,{children:"$manual"})," to true. In Python, sets ",(0,i.jsx)(t.code,{children:"RunningScript.manual"})," to True. Setting this box only allows the script author to determine if the operator wants to execute manual steps or not. It is up the script author to use the variable in their scripts."]}),"\n",(0,i.jsx)(t.h4,{id:"loop",children:"Loop"}),"\n",(0,i.jsx)(t.p,{children:"Loop whatever the user started continuously. If the user clicks Start next to the Group then the entire Group will be looped. This is useful to catch and debug those tricky timing errors that only sometimes happen."}),"\n",(0,i.jsx)(t.h4,{id:"break-loop-on-error",children:"Break Loop on Error"}),"\n",(0,i.jsx)(t.p,{children:"Break the loop if an Error occurs. Only available if the Loop option is set."}),"\n",(0,i.jsx)(t.h2,{id:"debugging-scripts",children:"Debugging Scripts"}),"\n",(0,i.jsxs)(t.p,{children:["When you enable the Debug prompt an additional line appears between the script and the Log Messages. You can type local variables to cause them to be output in the Log Messages. You can also set local variables by typing ",(0,i.jsx)(t.code,{children:"var = 10"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Debug",src:n(5015).A+"",width:"1273",height:"748"})}),"\n",(0,i.jsx)(t.p,{children:"The Step button allows you to step line by line through the script. Clicking Go continues regular execution."})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2549:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/file_menu-470589e527d9e82ce40e0c7d4a865e33d19b42350c2429dba97186d168137b6d.png"},2232:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_menu-5a10df89d9806a59b41ef990fc1181c46c7ffa00496021efceb22c0f31dcc9cc.png"},9828:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/checks_rb-89f400098ff47774008ea420860c665c15ebf06819c3ee7050bed301ea0a9f46.png"},1882:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/connecting-0f804651a891ef6112a51ba8b2e4d8dcb46e3462dcbc94e7b3c75bff20fc04e7.png"},5015:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/debug-3103972d64395b50fff5808661fb846ae2de7d5934548ca5b88032f1ae12c541.png"},1011:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/file_open-a5bc9e5ef73c12913ea4882498ceb52f93c73afaf5bb0c1083c4c1ee402f571d.png"},1010:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/running_scripts-694a1b310d42791acf64cf76ea370bb273084954107d5e6e2caf15f4fb50e634.png"},5842:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_error-2061222e00f5e5190a4407be1f8999200badca9b3137659de007e27cf1708dc0.png"},9056:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_runner-31f6bfcb631b788ff0bf792ac21da30aaa503ca926b10a22d4337114effc28f0.png"},7580:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/script_suite-16647c3b3de01a8749f1b5c4ab2f8b452630df8c0470e5be38652acacfc98b5d.png"},4376:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/suite_checkboxes-af8452153dbc2143718fefcfc7d441e05f42c241b3c10d4f41200ae576f68063.png"},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var i=n(6540);const r={},s=i.createContext(r);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/103cc3be.3b5edd08.js b/docs/assets/js/103cc3be.3b5edd08.js
deleted file mode 100644
index eeffec5ef6..0000000000
--- a/docs/assets/js/103cc3be.3b5edd08.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[3467],{1318:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var n=i(4848),r=i(8453);const a={title:"Autonomic (Enterprise)"},s=void 0,o={id:"tools/autonomic",title:"Autonomic (Enterprise)",description:"Introduction",source:"@site/docs/tools/autonomic.md",sourceDirName:"tools",slug:"/tools/autonomic",permalink:"/docs/tools/autonomic",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/autonomic.md",tags:[],version:"current",frontMatter:{title:"Autonomic (Enterprise)"},sidebar:"defaultSidebar",previous:{title:"Tools",permalink:"/docs/tools"},next:{title:"Bucket Explorer",permalink:"/docs/tools/bucket-explorer"}},c={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Overview",id:"overview",level:3},{value:"TriggerGroups",id:"triggergroups",level:3},{value:"Triggers",id:"triggers",level:3},{value:"Reactions",id:"reactions",level:3}];function g(e){const t={admonition:"admonition",h2:"h2",h3:"h3",img:"img",p:"p",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(t.p,{children:"Autonomic allows for the automated execution of commands and scripts based on user-defined rules."}),"\n",(0,n.jsx)(t.h3,{id:"overview",children:"Overview"}),"\n",(0,n.jsx)(t.p,{children:"Autonomic operates with some basic building blocks: Trigger Groups, Triggers, and Reactions. Triggers are simply logical blocks which evaluate true or false. Reactions can be linked to one or many Triggers and specify an action to perform. Together they allow for an action to be taken based on anything going on in your system."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Autonomic",src:i(4984).A+"",width:"1266",height:"599"})}),"\n",(0,n.jsx)(t.h3,{id:"triggergroups",children:"TriggerGroups"}),"\n",(0,n.jsx)(t.p,{children:"Triggers are organized into groups, these groups are both for organization and to ensure that we can scale. It also allows triggers to be evaluated independently and simulataneously and can be useful for overlapping or high priority triggers. However, each trigger group spawns system resources so they should only be created as needed."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"TriggerGroups",src:i(90).A+"",width:"349",height:"99"})}),"\n",(0,n.jsx)(t.h3,{id:"triggers",children:"Triggers"}),"\n",(0,n.jsx)(t.p,{children:'Triggers are logical components that are evaluated to true or false. Creating a trigger is like specifying an equation to evaluate. The trigger creation dialog specifies the Trigger Group which owns the trigger and the "left operand". This can be a telemetry item or an existing trigger.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger1",src:i(5723).A+"",width:"648",height:"779"})}),"\n",(0,n.jsx)(t.p,{children:'Once you\'ve chosen the "left operand" you need to choose the operator.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger2",src:i(688).A+"",width:"648",height:"653"})}),"\n",(0,n.jsx)(t.p,{children:'Finally you choose the "right operand" which in this case is a simple value.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(1865).A+"",width:"648",height:"715"})}),"\n",(0,n.jsx)(t.p,{children:"After the trigger is created it is displayed in Autonomic and waits to be activated by the given logic. Active triggers are highlighted in the list."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(7163).A+"",width:"1268",height:"607"})}),"\n",(0,n.jsx)(t.p,{children:"Triggers can also be manually disabled and enabled by clicking the plug icon."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(9996).A+"",width:"1268",height:"715"})}),"\n",(0,n.jsx)(t.p,{children:"Note in the above screenshot the Events which track everything about the trigger."}),"\n",(0,n.jsx)(t.h3,{id:"reactions",children:"Reactions"}),"\n",(0,n.jsx)(t.p,{children:"Reactions wait for triggers to be evaluated to true and perform actions such as sending a command or running a script. Reactions can not exist without a corresponding trigger. The reaction creation dialog specifies whether to treat the trigger as an Edge or Level. It then allows you to select which trigger(s) the reaction will react to. Selecting multiple triggers allows any of the triggers to trigger the reaction (Note: Creating a reaction which responds to Trigger A AND Trigger B is done by creating additional triggers)."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction1",src:i(9550).A+"",width:"602",height:"574"})}),"\n",(0,n.jsx)(t.p,{children:"After the triggers are specified, the dialog prompts for the actions to take. You can either send a command, run a script, or simply push a notification. Commands and scripts can also optionally push a notification. In this example a script is specified with a notification at the WARN level."}),"\n",(0,n.jsx)(t.admonition,{title:"Spawning Scripts",type:"warning",children:(0,n.jsx)(t.p,{children:"Be aware of how and when you spawn scripts and whether they are running to completion. Spawning a faulty script can lead to many unfinished scripts consuming resources."})}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction2",src:i(5301).A+"",width:"602",height:"634"})}),"\n",(0,n.jsx)(t.p,{children:"Finally the snooze setting is specified. Snooze is the number of seconds after the reaction runs before the reaction will be allowed to run again. This is especially important in Level triggers where if the trigger remains active the reaction can run continuously."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction3",src:i(8764).A+"",width:"602",height:"391"})}),"\n",(0,n.jsx)(t.p,{children:"Once the reaction is created it is listed in the interface."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"InitialReaction",src:i(4207).A+"",width:"1271",height:"617"})}),"\n",(0,n.jsx)(t.p,{children:'When the reaction runs the "State" changes to the snooze icon and the "Snooze Until" is updated to indicate the reaction is waiting before being allowed to run again.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"SnoozedReaction",src:i(6717).A+"",width:"1271",height:"742"})})]})}function l(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(g,{...e})}):g(e)}},4984:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/autonomic-a2118149a079f587f8f373d61f65d4d6d5e4b3df41ec5446362a449a3b51a1b3.png"},9550:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction1-a07e04677c269cb3eb5edd13bc7504ed6ba4c94f6a60d2b14a33680470d376fe.png"},5301:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction2-63e4e9ddf06a2e8bc9911395162b5a05772f0756e8b0998bcecae64cf86c398e.png"},8764:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction3-bae25e33640193d3dbbfbbfce6691479ccde16f73dbb3f0dc3023b7006259baa.png"},5723:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger1-5e2f7ecf9ec2b7590aaa65503f48cd73549fea64f52e6c103370a408528538f6.png"},688:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger2-edf2c2e6aa78a2e317e07e1cdec560dfcbbd147934630459507695c71d539f3b.png"},1865:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger3-e63629173ae73bbfd78b53062061336db8ea92ba4542b9a93412d8ac6ed19e7a.png"},9996:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/disable_trigger-f5bb46fbc488bd4afcb27b21888de16816485d3e4fdbd4106b874ff06042f85b.png"},7163:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/enabled_trigger-86ce16c7294d4b954ec8b68ff344694093ed5f451fc5974f855f438557148518.png"},4207:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/initial_reaction-ce5d498a90cdd5a11e24471d277ed7fcb4eecc5dcaaf05220102a3178db0805e.png"},6717:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/snoozed_reaction-75ef2acab11a71f5827fbc0a1be95cf0fd6bd5b24b76f9ae6ebaf43fb293ba81.png"},90:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/trigger_groups-6d9ccc6962029baa456f2d12de0fd3d03e1dbafdbf069cea65886296d2b2bde0.png"},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>o});var n=i(6540);const r={},a=n.createContext(r);function s(e){const t=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(a.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/103cc3be.44a5d5c6.js b/docs/assets/js/103cc3be.44a5d5c6.js
new file mode 100644
index 0000000000..6a89a9228d
--- /dev/null
+++ b/docs/assets/js/103cc3be.44a5d5c6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[3467],{1318:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var n=i(4848),r=i(8453);const a={title:"Autonomic (Enterprise)"},s=void 0,o={id:"tools/autonomic",title:"Autonomic (Enterprise)",description:"Introduction",source:"@site/docs/tools/autonomic.md",sourceDirName:"tools",slug:"/tools/autonomic",permalink:"/docs/tools/autonomic",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/autonomic.md",tags:[],version:"current",frontMatter:{title:"Autonomic (Enterprise)"},sidebar:"defaultSidebar",previous:{title:"Tools",permalink:"/docs/tools"},next:{title:"Bucket Explorer",permalink:"/docs/tools/bucket-explorer"}},c={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Overview",id:"overview",level:3},{value:"TriggerGroups",id:"triggergroups",level:3},{value:"Triggers",id:"triggers",level:3},{value:"Reactions",id:"reactions",level:3}];function g(e){const t={admonition:"admonition",h2:"h2",h3:"h3",img:"img",p:"p",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(t.p,{children:"Autonomic allows for the automated execution of commands and scripts based on user-defined rules."}),"\n",(0,n.jsx)(t.h3,{id:"overview",children:"Overview"}),"\n",(0,n.jsx)(t.p,{children:"Autonomic operates with some basic building blocks: Trigger Groups, Triggers, and Reactions. Triggers are simply logical blocks which evaluate true or false. Reactions can be linked to one or many Triggers and specify an action to perform. Together they allow for an action to be taken based on anything going on in your system."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Autonomic",src:i(4984).A+"",width:"1266",height:"599"})}),"\n",(0,n.jsx)(t.h3,{id:"triggergroups",children:"TriggerGroups"}),"\n",(0,n.jsx)(t.p,{children:"Triggers are organized into groups, these groups are both for organization and to ensure that we can scale. It also allows triggers to be evaluated independently and simultaneously and can be useful for overlapping or high priority triggers. However, each trigger group spawns system resources so they should only be created as needed."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"TriggerGroups",src:i(90).A+"",width:"349",height:"99"})}),"\n",(0,n.jsx)(t.h3,{id:"triggers",children:"Triggers"}),"\n",(0,n.jsx)(t.p,{children:'Triggers are logical components that are evaluated to true or false. Creating a trigger is like specifying an equation to evaluate. The trigger creation dialog specifies the Trigger Group which owns the trigger and the "left operand". This can be a telemetry item or an existing trigger.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger1",src:i(5723).A+"",width:"648",height:"779"})}),"\n",(0,n.jsx)(t.p,{children:'Once you\'ve chosen the "left operand" you need to choose the operator.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger2",src:i(688).A+"",width:"648",height:"653"})}),"\n",(0,n.jsx)(t.p,{children:'Finally you choose the "right operand" which in this case is a simple value.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(1865).A+"",width:"648",height:"715"})}),"\n",(0,n.jsx)(t.p,{children:"After the trigger is created it is displayed in Autonomic and waits to be activated by the given logic. Active triggers are highlighted in the list."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(7163).A+"",width:"1268",height:"607"})}),"\n",(0,n.jsx)(t.p,{children:"Triggers can also be manually disabled and enabled by clicking the plug icon."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateTrigger3",src:i(9996).A+"",width:"1268",height:"715"})}),"\n",(0,n.jsx)(t.p,{children:"Note in the above screenshot the Events which track everything about the trigger."}),"\n",(0,n.jsx)(t.h3,{id:"reactions",children:"Reactions"}),"\n",(0,n.jsx)(t.p,{children:"Reactions wait for triggers to be evaluated to true and perform actions such as sending a command or running a script. Reactions can not exist without a corresponding trigger. The reaction creation dialog specifies whether to treat the trigger as an Edge or Level. It then allows you to select which trigger(s) the reaction will react to. Selecting multiple triggers allows any of the triggers to trigger the reaction (Note: Creating a reaction which responds to Trigger A AND Trigger B is done by creating additional triggers)."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction1",src:i(9550).A+"",width:"602",height:"574"})}),"\n",(0,n.jsx)(t.p,{children:"After the triggers are specified, the dialog prompts for the actions to take. You can either send a command, run a script, or simply push a notification. Commands and scripts can also optionally push a notification. In this example a script is specified with a notification at the WARN level."}),"\n",(0,n.jsx)(t.admonition,{title:"Spawning Scripts",type:"warning",children:(0,n.jsx)(t.p,{children:"Be aware of how and when you spawn scripts and whether they are running to completion. Spawning a faulty script can lead to many unfinished scripts consuming resources."})}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction2",src:i(5301).A+"",width:"602",height:"634"})}),"\n",(0,n.jsx)(t.p,{children:"Finally the snooze setting is specified. Snooze is the number of seconds after the reaction runs before the reaction will be allowed to run again. This is especially important in Level triggers where if the trigger remains active the reaction can run continuously."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CreateReaction3",src:i(8764).A+"",width:"602",height:"391"})}),"\n",(0,n.jsx)(t.p,{children:"Once the reaction is created it is listed in the interface."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"InitialReaction",src:i(4207).A+"",width:"1271",height:"617"})}),"\n",(0,n.jsx)(t.p,{children:'When the reaction runs the "State" changes to the snooze icon and the "Snooze Until" is updated to indicate the reaction is waiting before being allowed to run again.'}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"SnoozedReaction",src:i(6717).A+"",width:"1271",height:"742"})})]})}function l(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(g,{...e})}):g(e)}},4984:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/autonomic-a2118149a079f587f8f373d61f65d4d6d5e4b3df41ec5446362a449a3b51a1b3.png"},9550:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction1-a07e04677c269cb3eb5edd13bc7504ed6ba4c94f6a60d2b14a33680470d376fe.png"},5301:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction2-63e4e9ddf06a2e8bc9911395162b5a05772f0756e8b0998bcecae64cf86c398e.png"},8764:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_reaction3-bae25e33640193d3dbbfbbfce6691479ccde16f73dbb3f0dc3023b7006259baa.png"},5723:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger1-5e2f7ecf9ec2b7590aaa65503f48cd73549fea64f52e6c103370a408528538f6.png"},688:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger2-edf2c2e6aa78a2e317e07e1cdec560dfcbbd147934630459507695c71d539f3b.png"},1865:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/create_trigger3-e63629173ae73bbfd78b53062061336db8ea92ba4542b9a93412d8ac6ed19e7a.png"},9996:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/disable_trigger-f5bb46fbc488bd4afcb27b21888de16816485d3e4fdbd4106b874ff06042f85b.png"},7163:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/enabled_trigger-86ce16c7294d4b954ec8b68ff344694093ed5f451fc5974f855f438557148518.png"},4207:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/initial_reaction-ce5d498a90cdd5a11e24471d277ed7fcb4eecc5dcaaf05220102a3178db0805e.png"},6717:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/snoozed_reaction-75ef2acab11a71f5827fbc0a1be95cf0fd6bd5b24b76f9ae6ebaf43fb293ba81.png"},90:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/trigger_groups-6d9ccc6962029baa456f2d12de0fd3d03e1dbafdbf069cea65886296d2b2bde0.png"},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>o});var n=i(6540);const r={},a=n.createContext(r);function s(e){const t=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(a.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/13196248.63bb9020.js b/docs/assets/js/13196248.63bb9020.js
new file mode 100644
index 0000000000..b0052f2c9a
--- /dev/null
+++ b/docs/assets/js/13196248.63bb9020.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[6677],{9107:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>o});var i=a(4848),n=a(8453);const s={title:"Calendar (Enterprise)"},c=void 0,r={id:"tools/calendar",title:"Calendar (Enterprise)",description:"Introduction",source:"@site/docs/tools/calendar.md",sourceDirName:"tools",slug:"/tools/calendar",permalink:"/docs/tools/calendar",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/calendar.md",tags:[],version:"current",frontMatter:{title:"Calendar (Enterprise)"},sidebar:"defaultSidebar",previous:{title:"Bucket Explorer",permalink:"/docs/tools/bucket-explorer"},next:{title:"Command Sender",permalink:"/docs/tools/cmd-sender"}},d={},o=[{value:"Introduction",id:"introduction",level:2},{value:"Adding Timelines",id:"adding-timelines",level:3},{value:"Types of Events",id:"types-of-events",level:2},{value:"Metadata",id:"metadata",level:3},{value:"Note",id:"note",level:3},{value:"Activity",id:"activity",level:3},{value:"Timeline Implementation Details",id:"timeline-implementation-details",level:2}];function l(e){const t={h2:"h2",h3:"h3",img:"img",p:"p",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"Calendar visualizes metadata, notes, and timeline information in one easy to understand place. Timelines allow for the simple execution of commands and scripts based on future dates and times."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Calendar",src:a(4987).A+"",width:"1271",height:"707"})}),"\n",(0,i.jsx)(t.h3,{id:"adding-timelines",children:"Adding Timelines"}),"\n",(0,i.jsx)(t.p,{children:"Adding a Timeline to COSMOS is as simple as clicking Create -> Timeline and giving it a unique name. Timelines can be created for organizational purposes or for overlapping activities as no activities can overlap on a given timeline. However, each additional timeline consists of several threads so only create timelines as necessary."}),"\n",(0,i.jsx)(t.h2,{id:"types-of-events",children:"Types of Events"}),"\n",(0,i.jsx)(t.h3,{id:"metadata",children:"Metadata"}),"\n",(0,i.jsx)(t.p,{children:"Metadata allows you to record arbitrary data into the COSMOS system. For example, you could ask the user for inputs which fall outside the available target telemetry including operators, environmental factors, procedural steps, etc. This allows for searching metadata based on these fields and correlating the related telemetry data."}),"\n",(0,i.jsx)(t.p,{children:"You can create a new metadata item from either the Create menu or by right-clicking on the calendar in the given time slot you want the metadata item to appear. Note that metadata entries only have a start time, they do not have an end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateMetadata1",src:a(4317).A+"",width:"594",height:"440"})}),"\n",(0,i.jsx)(t.p,{children:"You then add key / value pairs for all the metadata items you want to create."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateMetadata2",src:a(313).A+"",width:"594",height:"443"})}),"\n",(0,i.jsx)(t.h3,{id:"note",children:"Note"}),"\n",(0,i.jsx)(t.p,{children:"Notes require both a start and end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateNote1",src:a(2372).A+"",width:"594",height:"431"})}),"\n",(0,i.jsx)(t.p,{children:"You then record the note to create the note event on the calendar."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateNote2",src:a(9231).A+"",width:"594",height:"405"})}),"\n",(0,i.jsx)(t.h3,{id:"activity",children:"Activity"}),"\n",(0,i.jsx)(t.p,{children:"Scheduled on a timeline, activities take both a start and end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateActivity1",src:a(8741).A+"",width:"596",height:"476"})}),"\n",(0,i.jsx)(t.p,{children:'Activities can run single commands, run a script, or simply "Reserve" space on the calendar for reference or other bookkeeping.'}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateActivity2",src:a(9966).A+"",width:"596",height:"340"})}),"\n",(0,i.jsx)(t.p,{children:"When calendar activities are scheduled they appear with a green circle containing a plus (+). Once they complete successfully the icon changes to a green circle containing a checkbox (\u2713). Reserve activities simply have a blank green circle."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Calendar",src:a(2498).A+"",width:"1274",height:"755"})}),"\n",(0,i.jsx)(t.p,{children:"Calendar events can also be viewed in a list format via File->Show Table Display which supports pagination for listing both past and future events."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"List View",src:a(134).A+"",width:"1231",height:"684"})}),"\n",(0,i.jsx)(t.h2,{id:"timeline-implementation-details",children:"Timeline Implementation Details"}),"\n",(0,i.jsx)(t.p,{children:"When a user creates a timeline, a new timeline microservice starts. The timeline microservice is the main thread of execution for the timeline. This starts a scheduler manager thread. The scheduler manager thread contains a thread pool that hosts more than one thread to run the activity. The scheduler manager will evaluate the schedule and based on the start time of the activity it will add the activity to the queue."}),"\n",(0,i.jsx)(t.p,{children:'The main thread will block on the web socket to listen to request changes to the timeline, these could be adding, removing, or updating activities. The main thread will make the changes to the in memory schedule if these changes are within the hour of the current time. When the web socket gets an update it has an action lookup table. These actions are "created", "updated", "deleted", etc... Some actions require updating the schedule from the database to ensure the schedule and the database are always in sync.'}),"\n",(0,i.jsx)(t.p,{children:"The schedule thread checks every second to make sure if a task can be run. If the start time is equal or less then the last 15 seconds it will then check the previously queued jobs list in the schedule. If the activity has not been queued and is not fulfilled the activity will be queued, this adds an event to the activity but is not saved to the database."}),"\n",(0,i.jsx)(t.p,{children:"The workers block on the queue until an activity is placed on the queue. Once a job is pulled from the queue they check the type and run the activity. The thread will mark the activity fulfillment true and update the database record with the complete. If the worker gets an error while trying to run the task the activity will NOT be fulfilled and record the error in the database."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Timeline Lifecycle",src:a(1976).A+"",width:"1065",height:"514"})})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},4987:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/blank_calendar-70e605942120937b862bd7039348229bab9af1f9c93d356ddbf401a3e8543c74.png"},2498:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/calendar-dacbcbb05175c76f3406b4aaade0465444c20b72e93366c79fed1f6eec018c42.png"},8741:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_activity1-c05ffc03af2df852aeb3ad246f53f259af504e0e6c64cdac21f9126947c49f95.png"},9966:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_activity2-58c7da6f79dd510701148c0c54fae02c830b9ca4af662a7b132987ed3410a8f7.png"},4317:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_metadata1-a331ba8f0bd19bf5f8d7f2e083c3c7164e9b7b9936f5a7f83c4141c62a6c46f6.png"},313:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_metadata2-c57b5420d5469b48289030ed7c64758539c2319dc742159caa0d4c8fe35050a8.png"},2372:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_note1-472b93e8e0e3e66a2e6198e0d4573cdc38cc356df87be66163f990f18137f6c0.png"},9231:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_note2-770501a149ef4aabae24d0b636f46ed61fbdcfda9537c61637c07c60257e9228.png"},134:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/list_view-2f36ce06962e67d5a4f1f060956e5089b3f13c8ab57f33103c3781687611e7a9.png"},1976:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/timeline_lifecycle-0bd916dee06bf67936b043abfdbc4d5fdec7cc5a32a889ee6c05e9faf74f4c6a.png"},8453:(e,t,a)=>{a.d(t,{R:()=>c,x:()=>r});var i=a(6540);const n={},s=i.createContext(n);function c(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/13196248.c858ae53.js b/docs/assets/js/13196248.c858ae53.js
deleted file mode 100644
index 97ea3dbf49..0000000000
--- a/docs/assets/js/13196248.c858ae53.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[6677],{9107:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>o});var i=a(4848),n=a(8453);const s={title:"Calendar (Enterprise)"},c=void 0,r={id:"tools/calendar",title:"Calendar (Enterprise)",description:"Introduction",source:"@site/docs/tools/calendar.md",sourceDirName:"tools",slug:"/tools/calendar",permalink:"/docs/tools/calendar",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/calendar.md",tags:[],version:"current",frontMatter:{title:"Calendar (Enterprise)"},sidebar:"defaultSidebar",previous:{title:"Bucket Explorer",permalink:"/docs/tools/bucket-explorer"},next:{title:"Command Sender",permalink:"/docs/tools/cmd-sender"}},d={},o=[{value:"Introduction",id:"introduction",level:2},{value:"Adding Timelines",id:"adding-timelines",level:3},{value:"Types of Events",id:"types-of-events",level:2},{value:"Metadata",id:"metadata",level:3},{value:"Note",id:"note",level:3},{value:"Activity",id:"activity",level:3},{value:"Timeline Implementation Details",id:"timeline-implementation-details",level:2}];function l(e){const t={h2:"h2",h3:"h3",img:"img",p:"p",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"Calendar visualizes metadata, notes, and timeline information in one easy to understand place. Timelines allow for the simple execution of commands and scripts based on future dates and times."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Calendar",src:a(4987).A+"",width:"1271",height:"707"})}),"\n",(0,i.jsx)(t.h3,{id:"adding-timelines",children:"Adding Timelines"}),"\n",(0,i.jsx)(t.p,{children:"Adding a Timeline to COSMOS is as simple as clicking Create -> Timeline and giving it a unique name. Timelines can be created for organizational purposes or for overlapping activities as no activies can overlap on a given timeline. However, each additional timeline consists of several threads so only create timelines as necessary."}),"\n",(0,i.jsx)(t.h2,{id:"types-of-events",children:"Types of Events"}),"\n",(0,i.jsx)(t.h3,{id:"metadata",children:"Metadata"}),"\n",(0,i.jsx)(t.p,{children:"Metadata allows you to record arbitrary data into the COSMOS system. For example, you could ask the user for inputs which fall outside the available target telemetry including operators, environmental factors, procedural steps, etc. This allows for searching metadata based on these fields and correlating the related telemetry data."}),"\n",(0,i.jsx)(t.p,{children:"You can create a new metadata item from either the Create menu or by right-clicking on the calendar in the given time slot you want the metadata item to appear. Note that metadata entries only have a start time, they do not have an end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateMetadata1",src:a(4317).A+"",width:"594",height:"440"})}),"\n",(0,i.jsx)(t.p,{children:"You then add key / value pairs for all the metadata items you want to create."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateMetadata2",src:a(313).A+"",width:"594",height:"443"})}),"\n",(0,i.jsx)(t.h3,{id:"note",children:"Note"}),"\n",(0,i.jsx)(t.p,{children:"Notes require both a start and end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateNote1",src:a(2372).A+"",width:"594",height:"431"})}),"\n",(0,i.jsx)(t.p,{children:"You then record the note to create the note event on the calendar."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateNote2",src:a(9231).A+"",width:"594",height:"405"})}),"\n",(0,i.jsx)(t.h3,{id:"activity",children:"Activity"}),"\n",(0,i.jsx)(t.p,{children:"Scheduled on a timeline, activities take both a start and end time."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateActivity1",src:a(8741).A+"",width:"596",height:"476"})}),"\n",(0,i.jsx)(t.p,{children:'Activities can run single commands, run a script, or simply "Reserve" space on the calendar for reference or other bookkeeping.'}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CreateActivity2",src:a(9966).A+"",width:"596",height:"340"})}),"\n",(0,i.jsx)(t.p,{children:"When calendar activities are scheduled they appear with a green circle containing a plus (+). Once they complete successfully the icon changes to a green circle containing a checkbox (\u2713). Reserve activites simply have a blank green circle."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Calendar",src:a(2498).A+"",width:"1274",height:"755"})}),"\n",(0,i.jsx)(t.p,{children:"Calendar events can also be viewed in a list format via File->Show Table Display which supports pagination for listing both past and future events."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"List View",src:a(134).A+"",width:"1231",height:"684"})}),"\n",(0,i.jsx)(t.h2,{id:"timeline-implementation-details",children:"Timeline Implementation Details"}),"\n",(0,i.jsx)(t.p,{children:"When a user creates a timeline, a new timeline microservice starts. The timeline microservice is the main thread of execution for the timeline. This starts a scheduler manager thread. The scheduler manger thread contains a thread pool that hosts more than one thread to run the activity. The scheduler manger will evaluate the schedule and based on the start time of the activity it will add the activity to the queue."}),"\n",(0,i.jsx)(t.p,{children:'The main thread will block on the web socket to listen to request changes to the timeline, these could be adding, removing, or updating activities. The main thread will make the changes to the in memory schedule if these changes are within the hour of the current time. When the web socket gets an update it has an action lookup table. These actions are "created", "updated", "deleted", ect... Some actions require updating the schedule from the database to ensure the schedule and the database are always in sync.'}),"\n",(0,i.jsx)(t.p,{children:"The schedule thread checks every second to make sure if a task can be run. If the start time is equal or less then the last 15 seconds it will then check the previously queued jobs list in the schedule. If the activity has not been queued and is not fulfilled the activity will be queued, this adds an event to the activity but is not saved to the database."}),"\n",(0,i.jsx)(t.p,{children:"The workers block on the queue until an activity is placed on the queue. Once a job is pulled from the queue they check the type and run the activity. The thread will mark the activity fulfillment true and update the database record with the complete. If the worker gets an error while trying to run the task the activity will NOT be fulfilled and record the error in the database."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Timeline Lifecycle",src:a(1976).A+"",width:"1065",height:"514"})})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},4987:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/blank_calendar-70e605942120937b862bd7039348229bab9af1f9c93d356ddbf401a3e8543c74.png"},2498:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/calendar-dacbcbb05175c76f3406b4aaade0465444c20b72e93366c79fed1f6eec018c42.png"},8741:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_activity1-c05ffc03af2df852aeb3ad246f53f259af504e0e6c64cdac21f9126947c49f95.png"},9966:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_activity2-58c7da6f79dd510701148c0c54fae02c830b9ca4af662a7b132987ed3410a8f7.png"},4317:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_metadata1-a331ba8f0bd19bf5f8d7f2e083c3c7164e9b7b9936f5a7f83c4141c62a6c46f6.png"},313:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_metadata2-c57b5420d5469b48289030ed7c64758539c2319dc742159caa0d4c8fe35050a8.png"},2372:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_note1-472b93e8e0e3e66a2e6198e0d4573cdc38cc356df87be66163f990f18137f6c0.png"},9231:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/create_note2-770501a149ef4aabae24d0b636f46ed61fbdcfda9537c61637c07c60257e9228.png"},134:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/list_view-2f36ce06962e67d5a4f1f060956e5089b3f13c8ab57f33103c3781687611e7a9.png"},1976:(e,t,a)=>{a.d(t,{A:()=>i});const i=a.p+"assets/images/timeline_lifecycle-0bd916dee06bf67936b043abfdbc4d5fdec7cc5a32a889ee6c05e9faf74f4c6a.png"},8453:(e,t,a)=>{a.d(t,{R:()=>c,x:()=>r});var i=a(6540);const n={},s=i.createContext(n);function c(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/2bb7bf90.b8a86f30.js b/docs/assets/js/2bb7bf90.89ab95f4.js
similarity index 84%
rename from docs/assets/js/2bb7bf90.b8a86f30.js
rename to docs/assets/js/2bb7bf90.89ab95f4.js
index 7e3c726cd1..0058a929ca 100644
--- a/docs/assets/js/2bb7bf90.b8a86f30.js
+++ b/docs/assets/js/2bb7bf90.89ab95f4.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[7757],{1170:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=t(4848),r=t(8453);const i={sidebar_position:3,title:"Code Generators"},o=void 0,a={id:"getting-started/generators",title:"Code Generators",description:"The COSMOS Code Generators are built into the scripts openc3.sh and openc3.bat that are included in the COSMOS project (more about projects).",source:"@site/docs/getting-started/generators.md",sourceDirName:"getting-started",slug:"/getting-started/generators",permalink:"/docs/getting-started/generators",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/getting-started/generators.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Code Generators"},sidebar:"defaultSidebar",previous:{title:"Getting Started",permalink:"/docs/getting-started/gettingstarted"},next:{title:"Upgrading",permalink:"/docs/getting-started/upgrading"}},l={},c=[{value:"Plugin Generator",id:"plugin-generator",level:2},{value:"Target Generator",id:"target-generator",level:2},{value:"Microservice Generator",id:"microservice-generator",level:2},{value:"Conversion Generator",id:"conversion-generator",level:2},{value:"Limits Response Generator",id:"limits-response-generator",level:2},{value:"Widget Generator",id:"widget-generator",level:2},{value:"Tool Generator",id:"tool-generator",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["The COSMOS Code Generators are built into the scripts ",(0,s.jsx)(n.code,{children:"openc3.sh"})," and ",(0,s.jsx)(n.code,{children:"openc3.bat"})," that are included in the COSMOS ",(0,s.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos-project",children:"project"})," (more about ",(0,s.jsx)(n.a,{href:"key_concepts#projects",children:"projects"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["If you followed the ",(0,s.jsx)(n.a,{href:"/docs/getting-started/installation",children:"Installation Guide"})," you should already be inside a cloned ",(0,s.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos-project",children:"openc3-project"})," which is in your PATH (necessary for openc3.bat / openc3.sh to be resolved). To see all the available code generators type the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"% openc3.sh cli generate\nUnknown generator ''. Valid generators: plugin, target, microservice, widget, conversion,\nlimits_response, tool, tool_vue, tool_angular, tool_react, tool_svelte\n"})}),"\n",(0,s.jsx)(n.admonition,{title:"Training Available",type:"note",children:(0,s.jsxs)(n.p,{children:["If any of this gets confusing, contact us at ",(0,s.jsx)("a",{href:"mailto:support@openc3.com",children:(0,s.jsx)(n.a,{href:"mailto:support@openc3.com",children:"support@openc3.com"})}),". We have training classes available!"]})}),"\n",(0,s.jsx)(n.h2,{id:"plugin-generator",children:"Plugin Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The plugin generator creates the scaffolding for a new COSMOS Plugin. It requires a plugin name and will create a new directory called ",(0,s.jsx)(n.code,{children:"openc3-cosmos-"}),". For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"% openc3.sh cli generate plugin\nUsage: cli generate plugin \n\n% openc3.sh cli generate plugin GSE\nPlugin openc3-cosmos-gse successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:".gitignore"}),(0,s.jsx)(n.td,{children:"Tells git to ignore any node_modules directory (for tool development)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"LICENSE.txt"}),(0,s.jsx)(n.td,{children:"License for the plugin. COSMOS Plugins should be licensed in a manner compatible with the AGPLv3, unless they are designed only for use with COSMOS Enterprise Edition."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"openc3-cosmos-gse.gemspec"}),(0,s.jsxs)(n.td,{children:["Gemspec file which should be edited to add user specific information like description, authors, emails, homepage, etc. The name of this file is used in compiling the plugin contents into the final corresponding gem file: e.g. openc3-cosmos-gse-1.0.0.gem. COSMOS plugins should always begin with the openc3-cosmos prefix to make them easily identifiable in the Rubygems repository. The file is formatted as documented at: ",(0,s.jsx)(n.a,{href:"https://guides.rubygems.org/specification-reference/",children:"https://guides.rubygems.org/specification-reference/"})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"plugin.txt"}),(0,s.jsxs)(n.td,{children:["COSMOS specific file for Plugin creation. Learn more ",(0,s.jsx)(n.a,{href:"../configuration/plugins",children:"here"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Rakefile"}),(0,s.jsx)(n.td,{children:'Ruby Rakefile configured to support building the plugin by running "openc3.sh cli rake build VERSION=X.X.X" where X.X.X is the plugin version number'})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"README.md"}),(0,s.jsx)(n.td,{children:"Markdown file used to document the plugin"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"While this structure is required, it is not very useful by itself. The plugin generator just creates the framework for other generators to use."}),"\n",(0,s.jsx)(n.h2,{id:"target-generator",children:"Target Generator"}),"\n",(0,s.jsx)(n.p,{children:"The target generator creates the scaffolding for a new COSMOS Target. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate target\nUsage: cli generate target (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate target GSE\nTarget GSE successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE"}),(0,s.jsx)(n.td,{children:"Contains the configuration for the GSE target. The target name is always defined in all caps. This is typically the default name of the target, but well-designed targets will allow themselves to be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm"}),(0,s.jsx)(n.td,{children:"Contains the command and telemetry definition files for the GSE target. These files capture the format of the commands that can be sent to the target, and the telemetry packets that are expected to be received by COSMOS from the target. Note that the files in this folder are processed in alphabetical order by default. That can matter if you reference a packet in another file (it must already have been defined)."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm/cmd.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"../configuration/command",children:"command"})," configuration. Will need to be edited for the target specific commands."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm/tlm.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"../configuration/telemetry",children:"telemetry"})," configuration. Will need to be edited for the target specific telemetry."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib"}),(0,s.jsxs)(n.td,{children:["Contains any custom code required by the target. Good examples of custom code are library files, custom ",(0,s.jsx)(n.a,{href:"../configuration/interfaces",children:"interface"})," classes and ",(0,s.jsx)(n.a,{href:"../configuration/protocols",children:"protocols"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/gse.rb"}),(0,s.jsx)(n.td,{children:"Example library file which can be expanded as the target is developed. COSMOS recommends building up library methods to avoid code duplication and ease reuse."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/procedures"}),(0,s.jsxs)(n.td,{children:["This folder contains target specific procedures and helper methods which exercise functionality of the target. These procedures should be kept simple and only use the command and telemetry definitions associated with this target. See the ",(0,s.jsx)(n.a,{href:"../guides/script-writing#script-organization",children:"Scripting Guide"})," for more information."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/procedures/procedure.rb"}),(0,s.jsx)(n.td,{children:"Procedure with an example of sending a command and checking telemetry"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/public"}),(0,s.jsxs)(n.td,{children:["Put image files here for use in Telemetry Viewer Canvas Image widgets such as ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens#canvasimage",children:"CANVASIMAGE"})," and ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens#canvasimagevalue",children:"CANVASIMAGEVALUE"})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/screens"}),(0,s.jsxs)(n.td,{children:["Contains telemetry ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"screens"})," for the target"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/screens/status.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"screen"})," to display telemetry values"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/target.txt"}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)(n.a,{href:"../configuration/target",children:"Target"})," configuration such as ignoring command and telemetry items and how to process the cmd/tlm files"]})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new target:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"VARIABLE gse_target_name GSE\n\nTARGET GSE <%= gse_target_name %>\nINTERFACE <%= gse_target_name %>_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET <%= gse_target_name %>\n"})}),"\n",(0,s.jsx)(n.h2,{id:"microservice-generator",children:"Microservice Generator"}),"\n",(0,s.jsx)(n.p,{children:"The microservice generator creates the scaffolding for a new COSMOS Microservice. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate microservice\nUsage: cli generate microservice (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate microservice background\nMicroservice BACKGROUND successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"microservices/BACKGROUND"}),(0,s.jsx)(n.td,{children:"Contains the code and any necessary configuration for the BACKGROUND microservice. The name is always defined in all caps. This is typically the default name of the microservice, but well-designed microservices will allow themselves to be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"microservices/BACKGROUND/background.rb"}),(0,s.jsx)(n.td,{children:"Fully functional microservice which will run every minute and log a message. Edit to implement any custom logic that you want to run in the background. Potential uses are safety microservices which can check and autonomously respond to complex events and take action (NOTE: Simple actions might just require a Limits Response)."})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new microservice:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"MICROSERVICE BACKGROUND background-microservice\n CMD ruby background.rb\n"})}),"\n",(0,s.jsx)(n.h2,{id:"conversion-generator",children:"Conversion Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The conversion generator creates the scaffolding for a new COSMOS ",(0,s.jsx)(n.a,{href:"../configuration/telemetry#read_conversion",children:"Conversion"}),". It must operate inside an existing COSMOS plugin and requires both a target name and conversion name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate conversion\nUsage: cli generate conversion (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE double\nConversion targets/GSE/lib/double_conversion.rb successfully generated!\nTo use the conversion add the following to a telemetry item:\n READ_CONVERSION double_conversion.rb\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/double_conversion.rb"}),(0,s.jsx)(n.td,{children:"Fully functional Conversion which has an example implementation of the call() method to convert any existing COSMOS values."})]})})]}),"\n",(0,s.jsx)(n.p,{children:"As the generator states, to use this conversion code you must add it to a telemetry item. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n READ_CONVERSION double_conversion.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"limits-response-generator",children:"Limits Response Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The limits_response generator creates the scaffolding for a new COSMOS ",(0,s.jsx)(n.a,{href:"../configuration/telemetry#limits_response",children:"Limits Response"}),". It must operate inside an existing COSMOS plugin and requires both a target name and limits response name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate limits_response\nUsage: cli generate limits_response (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE safe\nLimits response targets/GSE/lib/safe_limits_response.rb successfully generated!\nTo use the limits response add the following to a telemetry item:\n LIMITS_RESPONSE safe_limits_response.rb\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/safe_limits_response.rb"}),(0,s.jsx)(n.td,{children:"Fully functional Limits Response which has an example implementation of the call() method and taking action based on the current limits state of the particular item"})]})})]}),"\n",(0,s.jsx)(n.p,{children:"As the generator states, to use this limits code you must add it to a telemetry item which has limits defined. In the generated GSE target, none of the items have limits defined so you first need to add limits and then add the response."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0\n LIMITS_RESPONSE safe_limits_response.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"widget-generator",children:"Widget Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The conversion generator creates the scaffolding for a new COSMOS Widget for use in ",(0,s.jsx)(n.a,{href:"../configuration/telemetry-screens",children:"Telemetry Viewer Screens"}),". For more information see the ",(0,s.jsx)(n.a,{href:"../guides/custom-widgets",children:"Custom Widget"})," guide. It must operate inside an existing COSMOS plugin and requires a widget name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate widget\nUsage: cli generate widget \n\nopenc3-cosmos-gse % openc3.sh cli generate widget HelloworldWidget\nWidget HelloworldWidget successfully generated!\nPlease be sure HelloworldWidget does not overlap an existing widget: https://docs.openc3.com/docs/configuration/telemetry-screens\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/HelloworldWidget.vue"}),(0,s.jsx)(n.td,{children:"Fully functional widget which displays a simple value. This can be expanded using existing COSMOS Vue.js code to create any data visualization imaginable."})]})})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new widget:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"WIDGET Helloworld\n"})}),"\n",(0,s.jsx)(n.h2,{id:"tool-generator",children:"Tool Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelt. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see ",(0,s.jsx)(n.a,{href:"../development/developing#running-a-frontend-application",children:"Running a Frontend Application"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate tool\nUsage: cli generate tool 'Tool Name'\n\nopenc3-cosmos-gse % openc3.sh cli generate widget DataVis\nTool datavis successfully generated!\nPlease be sure datavis does not conflict with any other tools\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/App.vue"}),(0,s.jsx)(n.td,{children:"Basic Vue template to render the application."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/main.js"}),(0,s.jsx)(n.td,{children:"Entry point for the new tool which loads Vue, Vuetify, and other libraries."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/router.js"}),(0,s.jsx)(n.td,{children:"Vue component router."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/tools/datavis"}),(0,s.jsx)(n.td,{children:"Contains all the files necessary to serve a web-based tool named datavis. The name is always defined in all lowercase. Due to technical limitations, the toolname must be unique and cannot be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/tools/datavis/datavis.vue"}),(0,s.jsx)(n.td,{children:"Fully functional tool which displays a simple button. This can be expanded using existing COSMOS Vue.js code to create any tool imaginable."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"package.json"}),(0,s.jsx)(n.td,{children:"Build and dependency definition file. Used by npm or yarn to build the tool."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"vue.config.js"}),(0,s.jsx)(n.td,{children:"Vue configuration file used to serve the application in development and build the application."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:""}),(0,s.jsx)(n.td,{children:"Various dotfiles which help configure formatters and tools for Javascript frontend developemnt"})]})]})]}),"\n",(0,s.jsxs)(n.p,{children:["It also updates the plugin.txt file to add the new tool. The icon can be changed to any of the material design icons found ",(0,s.jsx)(n.a,{href:"https://pictogrammers.com/library/mdi/",children:"here"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TOOL datavis "DataVis"\n INLINE_URL js/app.js\n ICON mdi-file-cad-box\n'})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var s=t(6540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[7757],{1170:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=t(4848),r=t(8453);const i={sidebar_position:3,title:"Code Generators"},o=void 0,a={id:"getting-started/generators",title:"Code Generators",description:"The COSMOS Code Generators are built into the scripts openc3.sh and openc3.bat that are included in the COSMOS project (more about projects).",source:"@site/docs/getting-started/generators.md",sourceDirName:"getting-started",slug:"/getting-started/generators",permalink:"/docs/getting-started/generators",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/getting-started/generators.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Code Generators"},sidebar:"defaultSidebar",previous:{title:"Getting Started",permalink:"/docs/getting-started/gettingstarted"},next:{title:"Upgrading",permalink:"/docs/getting-started/upgrading"}},l={},c=[{value:"Plugin Generator",id:"plugin-generator",level:2},{value:"Target Generator",id:"target-generator",level:2},{value:"Microservice Generator",id:"microservice-generator",level:2},{value:"Conversion Generator",id:"conversion-generator",level:2},{value:"Limits Response Generator",id:"limits-response-generator",level:2},{value:"Widget Generator",id:"widget-generator",level:2},{value:"Tool Generator",id:"tool-generator",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["The COSMOS Code Generators are built into the scripts ",(0,s.jsx)(n.code,{children:"openc3.sh"})," and ",(0,s.jsx)(n.code,{children:"openc3.bat"})," that are included in the COSMOS ",(0,s.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos-project",children:"project"})," (more about ",(0,s.jsx)(n.a,{href:"key_concepts#projects",children:"projects"}),")."]}),"\n",(0,s.jsxs)(n.p,{children:["If you followed the ",(0,s.jsx)(n.a,{href:"/docs/getting-started/installation",children:"Installation Guide"})," you should already be inside a cloned ",(0,s.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos-project",children:"openc3-project"})," which is in your PATH (necessary for openc3.bat / openc3.sh to be resolved). To see all the available code generators type the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"% openc3.sh cli generate\nUnknown generator ''. Valid generators: plugin, target, microservice, widget, conversion,\nlimits_response, tool, tool_vue, tool_angular, tool_react, tool_svelte\n"})}),"\n",(0,s.jsx)(n.admonition,{title:"Training Available",type:"note",children:(0,s.jsxs)(n.p,{children:["If any of this gets confusing, contact us at ",(0,s.jsx)("a",{href:"mailto:support@openc3.com",children:(0,s.jsx)(n.a,{href:"mailto:support@openc3.com",children:"support@openc3.com"})}),". We have training classes available!"]})}),"\n",(0,s.jsx)(n.h2,{id:"plugin-generator",children:"Plugin Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The plugin generator creates the scaffolding for a new COSMOS Plugin. It requires a plugin name and will create a new directory called ",(0,s.jsx)(n.code,{children:"openc3-cosmos-"}),". For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"% openc3.sh cli generate plugin\nUsage: cli generate plugin \n\n% openc3.sh cli generate plugin GSE\nPlugin openc3-cosmos-gse successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:".gitignore"}),(0,s.jsx)(n.td,{children:"Tells git to ignore any node_modules directory (for tool development)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"LICENSE.txt"}),(0,s.jsx)(n.td,{children:"License for the plugin. COSMOS Plugins should be licensed in a manner compatible with the AGPLv3, unless they are designed only for use with COSMOS Enterprise Edition."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"openc3-cosmos-gse.gemspec"}),(0,s.jsxs)(n.td,{children:["Gemspec file which should be edited to add user specific information like description, authors, emails, homepage, etc. The name of this file is used in compiling the plugin contents into the final corresponding gem file: e.g. openc3-cosmos-gse-1.0.0.gem. COSMOS plugins should always begin with the openc3-cosmos prefix to make them easily identifiable in the Rubygems repository. The file is formatted as documented at: ",(0,s.jsx)(n.a,{href:"https://guides.rubygems.org/specification-reference/",children:"https://guides.rubygems.org/specification-reference/"})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"plugin.txt"}),(0,s.jsxs)(n.td,{children:["COSMOS specific file for Plugin creation. Learn more ",(0,s.jsx)(n.a,{href:"../configuration/plugins",children:"here"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Rakefile"}),(0,s.jsx)(n.td,{children:'Ruby Rakefile configured to support building the plugin by running "openc3.sh cli rake build VERSION=X.X.X" where X.X.X is the plugin version number'})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"README.md"}),(0,s.jsx)(n.td,{children:"Markdown file used to document the plugin"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"While this structure is required, it is not very useful by itself. The plugin generator just creates the framework for other generators to use."}),"\n",(0,s.jsx)(n.h2,{id:"target-generator",children:"Target Generator"}),"\n",(0,s.jsx)(n.p,{children:"The target generator creates the scaffolding for a new COSMOS Target. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate target\nUsage: cli generate target (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate target GSE\nTarget GSE successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE"}),(0,s.jsx)(n.td,{children:"Contains the configuration for the GSE target. The target name is always defined in all caps. This is typically the default name of the target, but well-designed targets will allow themselves to be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm"}),(0,s.jsx)(n.td,{children:"Contains the command and telemetry definition files for the GSE target. These files capture the format of the commands that can be sent to the target, and the telemetry packets that are expected to be received by COSMOS from the target. Note that the files in this folder are processed in alphabetical order by default. That can matter if you reference a packet in another file (it must already have been defined)."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm/cmd.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"../configuration/command",children:"command"})," configuration. Will need to be edited for the target specific commands."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/cmd_tlm/tlm.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"../configuration/telemetry",children:"telemetry"})," configuration. Will need to be edited for the target specific telemetry."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib"}),(0,s.jsxs)(n.td,{children:["Contains any custom code required by the target. Good examples of custom code are library files, custom ",(0,s.jsx)(n.a,{href:"../configuration/interfaces",children:"interface"})," classes and ",(0,s.jsx)(n.a,{href:"../configuration/protocols",children:"protocols"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/gse.rb"}),(0,s.jsx)(n.td,{children:"Example library file which can be expanded as the target is developed. COSMOS recommends building up library methods to avoid code duplication and ease reuse."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/procedures"}),(0,s.jsxs)(n.td,{children:["This folder contains target specific procedures and helper methods which exercise functionality of the target. These procedures should be kept simple and only use the command and telemetry definitions associated with this target. See the ",(0,s.jsx)(n.a,{href:"../guides/script-writing#script-organization",children:"Scripting Guide"})," for more information."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/procedures/procedure.rb"}),(0,s.jsx)(n.td,{children:"Procedure with an example of sending a command and checking telemetry"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/public"}),(0,s.jsxs)(n.td,{children:["Put image files here for use in Telemetry Viewer Canvas Image widgets such as ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens#canvasimage",children:"CANVASIMAGE"})," and ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens#canvasimagevalue",children:"CANVASIMAGEVALUE"})]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/screens"}),(0,s.jsxs)(n.td,{children:["Contains telemetry ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"screens"})," for the target"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/screens/status.txt"}),(0,s.jsxs)(n.td,{children:["Example ",(0,s.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"screen"})," to display telemetry values"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/target.txt"}),(0,s.jsxs)(n.td,{children:[(0,s.jsx)(n.a,{href:"../configuration/target",children:"Target"})," configuration such as ignoring command and telemetry items and how to process the cmd/tlm files"]})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new target:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"VARIABLE gse_target_name GSE\n\nTARGET GSE <%= gse_target_name %>\nINTERFACE <%= gse_target_name %>_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET <%= gse_target_name %>\n"})}),"\n",(0,s.jsx)(n.h2,{id:"microservice-generator",children:"Microservice Generator"}),"\n",(0,s.jsx)(n.p,{children:"The microservice generator creates the scaffolding for a new COSMOS Microservice. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate microservice\nUsage: cli generate microservice (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate microservice background\nMicroservice BACKGROUND successfully generated!\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"microservices/BACKGROUND"}),(0,s.jsx)(n.td,{children:"Contains the code and any necessary configuration for the BACKGROUND microservice. The name is always defined in all caps. This is typically the default name of the microservice, but well-designed microservices will allow themselves to be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"microservices/BACKGROUND/background.rb"}),(0,s.jsx)(n.td,{children:"Fully functional microservice which will run every minute and log a message. Edit to implement any custom logic that you want to run in the background. Potential uses are safety microservices which can check and autonomously respond to complex events and take action (NOTE: Simple actions might just require a Limits Response)."})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new microservice:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"MICROSERVICE BACKGROUND background-microservice\n CMD ruby background.rb\n"})}),"\n",(0,s.jsx)(n.h2,{id:"conversion-generator",children:"Conversion Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The conversion generator creates the scaffolding for a new COSMOS ",(0,s.jsx)(n.a,{href:"../configuration/telemetry#read_conversion",children:"Conversion"}),". It must operate inside an existing COSMOS plugin and requires both a target name and conversion name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate conversion\nUsage: cli generate conversion (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE double\nConversion targets/GSE/lib/double_conversion.rb successfully generated!\nTo use the conversion add the following to a telemetry item:\n READ_CONVERSION double_conversion.rb\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/double_conversion.rb"}),(0,s.jsx)(n.td,{children:"Fully functional Conversion which has an example implementation of the call() method to convert any existing COSMOS values."})]})})]}),"\n",(0,s.jsx)(n.p,{children:"As the generator states, to use this conversion code you must add it to a telemetry item. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n READ_CONVERSION double_conversion.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"limits-response-generator",children:"Limits Response Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The limits_response generator creates the scaffolding for a new COSMOS ",(0,s.jsx)(n.a,{href:"../configuration/telemetry#limits_response",children:"Limits Response"}),". It must operate inside an existing COSMOS plugin and requires both a target name and limits response name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate limits_response\nUsage: cli generate limits_response (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE safe\nLimits response targets/GSE/lib/safe_limits_response.rb successfully generated!\nTo use the limits response add the following to a telemetry item:\n LIMITS_RESPONSE safe_limits_response.rb\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"targets/GSE/lib/safe_limits_response.rb"}),(0,s.jsx)(n.td,{children:"Fully functional Limits Response which has an example implementation of the call() method and taking action based on the current limits state of the particular item"})]})})]}),"\n",(0,s.jsx)(n.p,{children:"As the generator states, to use this limits code you must add it to a telemetry item which has limits defined. In the generated GSE target, none of the items have limits defined so you first need to add limits and then add the response."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0\n LIMITS_RESPONSE safe_limits_response.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"widget-generator",children:"Widget Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The conversion generator creates the scaffolding for a new COSMOS Widget for use in ",(0,s.jsx)(n.a,{href:"../configuration/telemetry-screens",children:"Telemetry Viewer Screens"}),". For more information see the ",(0,s.jsx)(n.a,{href:"../guides/custom-widgets",children:"Custom Widget"})," guide. It must operate inside an existing COSMOS plugin and requires a widget name. For example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate widget\nUsage: cli generate widget \n\nopenc3-cosmos-gse % openc3.sh cli generate widget HelloworldWidget\nWidget HelloworldWidget successfully generated!\nPlease be sure HelloworldWidget does not overlap an existing widget: https://docs.openc3.com/docs/configuration/telemetry-screens\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsx)(n.tbody,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/HelloworldWidget.vue"}),(0,s.jsx)(n.td,{children:"Fully functional widget which displays a simple value. This can be expanded using existing COSMOS Vue.js code to create any data visualization imaginable."})]})})]}),"\n",(0,s.jsx)(n.p,{children:"It also updates the plugin.txt file to add the new widget:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"WIDGET Helloworld\n"})}),"\n",(0,s.jsx)(n.h2,{id:"tool-generator",children:"Tool Generator"}),"\n",(0,s.jsxs)(n.p,{children:["The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelte. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see ",(0,s.jsx)(n.a,{href:"../development/developing#running-a-frontend-application",children:"Running a Frontend Application"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate tool\nUsage: cli generate tool 'Tool Name'\n\nopenc3-cosmos-gse % openc3.sh cli generate widget DataVis\nTool datavis successfully generated!\nPlease be sure datavis does not conflict with any other tools\n"})}),"\n",(0,s.jsx)(n.p,{children:"This creates the following files and directories:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/App.vue"}),(0,s.jsx)(n.td,{children:"Basic Vue template to render the application."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/main.js"}),(0,s.jsx)(n.td,{children:"Entry point for the new tool which loads Vue, Vuetify, and other libraries."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/router.js"}),(0,s.jsx)(n.td,{children:"Vue component router."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/tools/datavis"}),(0,s.jsx)(n.td,{children:"Contains all the files necessary to serve a web-based tool named datavis. The name is always defined in all lowercase. Due to technical limitations, the toolname must be unique and cannot be renamed at installation."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"src/tools/datavis/datavis.vue"}),(0,s.jsx)(n.td,{children:"Fully functional tool which displays a simple button. This can be expanded using existing COSMOS Vue.js code to create any tool imaginable."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"package.json"}),(0,s.jsx)(n.td,{children:"Build and dependency definition file. Used by npm or yarn to build the tool."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"vue.config.js"}),(0,s.jsx)(n.td,{children:"Vue configuration file used to serve the application in development and build the application."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:""}),(0,s.jsx)(n.td,{children:"Various dotfiles which help configure formatters and tools for Javascript frontend development"})]})]})]}),"\n",(0,s.jsxs)(n.p,{children:["It also updates the plugin.txt file to add the new tool. The icon can be changed to any of the material design icons found ",(0,s.jsx)(n.a,{href:"https://pictogrammers.com/library/mdi/",children:"here"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TOOL datavis "DataVis"\n INLINE_URL js/app.js\n ICON mdi-file-cad-box\n'})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var s=t(6540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/42170351.59f60e99.js b/docs/assets/js/42170351.59f60e99.js
deleted file mode 100644
index 97e55a9bec..0000000000
--- a/docs/assets/js/42170351.59f60e99.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[3440],{7305:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=t(4848),s=t(8453);const r={title:"Script Writing Guide"},a=void 0,o={id:"guides/script-writing",title:"Script Writing Guide",description:"Introduction",source:"@site/docs/guides/script-writing.md",sourceDirName:"guides",slug:"/guides/script-writing",permalink:"/docs/guides/script-writing",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/guides/script-writing.md",tags:[],version:"current",frontMatter:{title:"Script Writing Guide"},sidebar:"defaultSidebar",previous:{title:"Raspberry Pi",permalink:"/docs/guides/raspberrypi"},next:{title:"Scripting API Guide",permalink:"/docs/guides/scripting-api"}},l={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Concepts",id:"concepts",level:2},{value:"Ruby vs Python in COSMOS",id:"ruby-vs-python-in-cosmos",level:3},{value:"Scripting Philosophy",id:"scripting-philosophy",level:2},{value:"A Super Basic Script Example",id:"a-super-basic-script-example",level:3},{value:"KISS (Keep It Simple Stupid)",id:"kiss-keep-it-simple-stupid",level:3},{value:"Keep things DRY (Don't Repeat Yourself)",id:"keep-things-dry-dont-repeat-yourself",level:3},{value:"Use Comments Appropriately",id:"use-comments-appropriately",level:3},{value:"Script Runner",id:"script-runner",level:3},{value:"Looping vs Unrolled Loops",id:"looping-vs-unrolled-loops",level:3},{value:"Script Organization",id:"script-organization",level:2},{value:"Organizing Your Scripts into a Plugin",id:"organizing-your-scripts-into-a-plugin",level:3},{value:"Organize Scripts into Methods",id:"organize-scripts-into-methods",level:3},{value:"Using Classes vs Unscoped Methods",id:"using-classes-vs-unscoped-methods",level:3},{value:"Instrumented vs Uninstrumented Lines (require vs load)",id:"instrumented-vs-uninstrumented-lines-require-vs-load",level:3},{value:"Debugging and Auditing",id:"debugging-and-auditing",level:2},{value:"Built-In Debugging Capabilities",id:"built-in-debugging-capabilities",level:3},{value:"Breakpoints",id:"breakpoints",level:3},{value:"Using Disconnect Mode",id:"using-disconnect-mode",level:3},{value:"Auditing your Scripts",id:"auditing-your-scripts",level:3},{value:"Ruby Syntax Check",id:"ruby-syntax-check",level:4},{value:"Common Scenarios",id:"common-scenarios",level:2},{value:"User Input Best Practices",id:"user-input-best-practices",level:3},{value:"Conditionally Require Manual User Input Steps",id:"conditionally-require-manual-user-input-steps",level:3},{value:"Outputing Extra Information to a Report",id:"outputing-extra-information-to-a-report",level:3},{value:"Getting the Most Recent Value of a Telemetry Point from Multiple Packets",id:"getting-the-most-recent-value-of-a-telemetry-point-from-multiple-packets",level:3},{value:"Checking Every Single Sample of a Telemetry Point",id:"checking-every-single-sample-of-a-telemetry-point",level:3},{value:"Using Variables in Mnemonics",id:"using-variables-in-mnemonics",level:3},{value:"Using Custom wait_check_expression",id:"using-custom-wait_check_expression",level:3},{value:"COSMOS Scripting Differences from Regular Ruby Scripting",id:"cosmos-scripting-differences-from-regular-ruby-scripting",level:3},{value:"Do not use single line if statements",id:"do-not-use-single-line-if-statements",level:4},{value:"When Things Go Wrong",id:"when-things-go-wrong",level:2},{value:"Common Reasons Checks Fail",id:"common-reasons-checks-fail",level:3},{value:"How to Recover from Anomalies",id:"how-to-recover-from-anomalies",level:3},{value:"Advanced Topics",id:"advanced-topics",level:2},{value:"Advanced Script Configuration with CSV or Excel",id:"advanced-script-configuration-with-csv-or-excel",level:3},{value:"When to use Ruby Modules",id:"when-to-use-ruby-modules",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"This guide aims to provide the best practices for using the scripting capabilities provided by COSMOS. Scripts are used to automate a series of activities for operations or testing. The goal of this document is to ensure scripts are written that are simple, easy to understand, maintainable, and correct. Guidance on some of the key details of using the COSMOS Script Runner is also provided."}),"\n",(0,i.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS supports both Ruby and Python for writing scripts. Ruby and Python are very similar scripting languages and most of this guide applies directly to both. Where examples are used, both a Ruby and Python example are given."}),"\n",(0,i.jsx)(n.h3,{id:"ruby-vs-python-in-cosmos",children:"Ruby vs Python in COSMOS"}),"\n",(0,i.jsx)(n.p,{children:"There are many similarities and a few key differences between Ruby and Python when it comes to writing COSMOS scripts."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"There is no 80 character limit on line length. Lines can be as long as you like, but be careful to not make them too long as it makes printed reviews of scripts more difficult."}),"\n",(0,i.jsxs)(n.li,{children:["Indentation white space:","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Ruby: Not significant. Ruby uses the ",(0,i.jsx)(n.code,{children:"end"})," keyword to determine indented code blocks with a standard of 2 spaces."]}),"\n",(0,i.jsx)(n.li,{children:"Python: Significant. Python uses indentation to determine code blocks with a standard of 4 spaces."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Variables do not have to be declared ahead of time and can be reassigned later, i.e. Ruby and Python are dynamically typed."}),"\n",(0,i.jsxs)(n.li,{children:["Variable interpolation:","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Ruby: Variable values can be placed into strings using the ",(0,i.jsx)(n.code,{children:'"#{variable}"'})," syntax."]}),"\n",(0,i.jsxs)(n.li,{children:["Python: Variable values can be placed into f-strings using the ",(0,i.jsx)(n.code,{children:'f"{variable}"'})," syntax."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"A variable declared inside of a block or loop will not exist outside of that block unless it was already declared."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Both languages provides a script writer a lot of power. But with great power comes great responsibility. Remember when writing your scripts that you or someone else will come along later and need to understand them. Therefore use the following style guidelines:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Use consistent spacing for indentation and do NOT use tabs"}),"\n",(0,i.jsxs)(n.li,{children:["Constants should be all caps with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"SPEED_OF_LIGHT = 299792458 # meters per s"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Variable names and method names should be in lowercase with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:'last_name = "Smith"'})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"perform_setup_operation()"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Class names (when used) should be camel case and the files which contain them should match but be lowercase with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"class DataUploader # in 'data_uploader.rb'"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"class CcsdsUtility: # in 'ccsds_utility.py'"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Don't add useless comments but instead describe intent"}),"\n"]}),"\n",(0,i.jsx)("div",{style:{clear:"both"}}),"\n",(0,i.jsx)(n.p,{children:"The following is an example of good Ruby style:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"load 'TARGET/lib/upload_utility.rb' # library we do NOT want to show executing\nload_utility 'TARGET/lib/helper_utility.rb' # library we do want to show executing\n\n# Declare constants\nOUR_TARGETS = ['INST','INST2']\n\n# Clear the collect counter of the passed in target name\ndef clear_collects(target)\n cmd(\"#{target} CLEAR\")\n wait_check(\"#{target} HEALTH_STATUS COLLECTS == 0\", 5)\nend\n\n######################################\n# START\n######################################\nhelper = HelperUtility.new\nhelper.setup\n\n# Perform collects on all the targets\nOUR_TARGETS.each do |target|\n collects = tlm(\"#{target} HEALTH_STATUS COLLECTS\")\n cmd(\"#{target} COLLECT with TYPE SPECIAL\")\n wait_check(\"#{target} HEALTH_STATUS COLLECTS == #{collects + 1}\", 5)\nend\n\nclear_collects('INST')\nclear_collects('INST2')\n"})}),"\n",(0,i.jsx)(n.p,{children:"The following is an example of good Python style:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"from openc3.script import *\n\nimport TARGET.lib.upload_utility # library we do NOT want to show executing\nload_utility('TARGET/lib/helper_utility.rb') # library we do want to show executing\n\n# Declare constants\nOUR_TARGETS = ['INST','INST2']\n\n# Clear the collect counter of the passed in target name\ndef clear_collects(target):\n cmd(f\"{target} CLEAR\")\n wait_check(f\"{target} HEALTH_STATUS COLLECTS == 0\", 5)\n\n######################################\n# START\n######################################\nhelper = HelperUtility()\nhelper.setup()\n\n# Perform collects on all the targets\nfor target in OUR_TARGETS:\n collects = tlm(f\"{target} HEALTH_STATUS COLLECTS\")\n cmd(f\"{target} COLLECT with TYPE SPECIAL\")\n wait_check(f\"{target} HEALTH_STATUS COLLECTS == {collects + 1}\", 5)\n\nclear_collects('INST')\nclear_collects('INST2')\n"})}),"\n",(0,i.jsx)(n.p,{children:"Both examples shows several features of COSMOS scripting in action. Notice the difference between 'load' or 'import' and 'load_utility'. The first is to load additional scripts which will NOT be shown in Script Runner when executing. This is a good place to put code which takes a long time to run such as image analysis or other looping code where you just want the output. 'load_utility' will visually execute the code line by line to show the user what is happening."}),"\n",(0,i.jsx)(n.p,{children:"Next we declare our constants and create an array of strings which we store in OUR_TARGETS. Notice the constant is all uppercase with underscores."}),"\n",(0,i.jsx)(n.p,{children:"Then we declare our local methods of which we have one called clear_collects. Please provide a comment at the beginning of each method describing what it does and the parameters that it takes."}),"\n",(0,i.jsx)(n.p,{children:"The 'helper_utility' is then created. Note the similarity in the class name and the file name we loaded."}),"\n",(0,i.jsxs)(n.p,{children:["The collect example shows how you can iterate over the array of strings we previously created and use variables when commanding and checking telemetry. The Ruby pound bracket #",' notation and python f-string f"'," notation puts whatever the variable holds into the string. You can even execute additional code inside the brackets like we do when checking for the collect count to increment."]}),"\n",(0,i.jsx)(n.p,{children:"Finally we call our 'clear_collects' method on each target by passing the target name."}),"\n",(0,i.jsx)(n.h2,{id:"scripting-philosophy",children:"Scripting Philosophy"}),"\n",(0,i.jsx)(n.h3,{id:"a-super-basic-script-example",children:"A Super Basic Script Example"}),"\n",(0,i.jsx)(n.p,{children:"Most COSMOS scripts can be broken down into the simple pattern of sending a command to a system/subsystem and then verifying that the command worked as expected. This pattern is most commonly implemented with cmd() followed by wait_check(), like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'cmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check("INST HEALTH_STATUS TYPE == \'NORMAL\'", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"or similarly with a counter that is sampled before the command."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'count = tlm("INST HEALTH_STATUS COLLECTS")\ncmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check("INST HEALTH_STATUS COLLECTS >= #{count + 1}", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'count = tlm("INST HEALTH_STATUS COLLECTS")\ncmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check(f"INST HEALTH_STATUS COLLECTS >= {count + 1}", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"90% of the COSMOS scripts you write should be the simple patterns shown above except that you may need to check more than one item after each command to make sure the command worked as expected."}),"\n",(0,i.jsx)(n.h3,{id:"kiss-keep-it-simple-stupid",children:"KISS (Keep It Simple Stupid)"}),"\n",(0,i.jsx)(n.p,{children:"Ruby and Python are very powerful languages with many ways to accomplish the same thing. Given that, always choose the method that is easiest to understand for yourself and others. While it is possible to create complex one liners or obtuse regular expressions, you'll thank yourself later by expanding complex one liners and breaking up and documenting regular expressions."}),"\n",(0,i.jsx)(n.h3,{id:"keep-things-dry-dont-repeat-yourself",children:"Keep things DRY (Don't Repeat Yourself)"}),"\n",(0,i.jsx)(n.p,{children:"A widespread problem in scripts written for any command and control system is large blocks of code that are repeated multiple times. In extreme cases, this has led to 100,000+ line scripts that are impossible to maintain and review."}),"\n",(0,i.jsx)(n.p,{children:"There are two common ways repetition presents itself: exact blocks of code to perform a common action such as powering on a subsystem, and blocks of code that only differ in the name of the mnemonic being checked or the values checked against. Both are solved by removing the repetition using methods (or functions)."}),"\n",(0,i.jsx)(n.p,{children:"For example, a script that powers on a subsystem and ensures correct telemetry would become:"}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"def power_on_subsystem\n # 100 lines of cmd(), wait_check(), etc\nend\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"def power_on_subsystem():\n # 100 lines of cmd(), wait_check(), etc\n"})}),"\n",(0,i.jsx)(n.p,{children:"Ideally, the above methods would be stored in another file where it could be used by other scripts. If it is truly only useful in the one script, then it could be at the top of the file. The updated script would then look like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"power_on_subsystem()\n# 150 lines operating the subsystem (e.g.)\n# cmd(...)\n# wait_check(...)\n#...\npower_off_subystem()\n# Unrelated activities\npower_on_subsystem()\n# etc.\n"})}),"\n",(0,i.jsx)(n.p,{children:"Blocks of code where only the only variation is the mnemonics or values checked can be replaced by methods with arguments."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp)\n cmd("TARGET #{enable_cmd_name} with ENABLE TRUE")\n wait_check("TARGET #{enable_tlm} == \'TRUE\'", 5)\n wait_check("TARGET #{temp_tlm} >= #{expected_temp}", 50)\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp):\n cmd(f"TARGET {enable_cmd_name} with ENABLE TRUE")\n wait_check(f"TARGET {enable_tlm} == \'TRUE\'", 5)\n wait_check(f"TARGET {temp_tlm} >= {expected_temp}", 50)\n'})}),"\n",(0,i.jsx)(n.h3,{id:"use-comments-appropriately",children:"Use Comments Appropriately"}),"\n",(0,i.jsx)(n.p,{children:"Use comments when what you are doing is unclear or there is a higher-level purpose to a set of lines. Try to avoid putting numbers or other details in a comment as they can become out of sync with the underlying code. Ruby and Python comments start with a # pound symbol and can be anywhere on a line."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# This line sends an abort command - BAD COMMENT, UNNECCESSARY\ncmd("INST ABORT")\n# Rotate the gimbal to look at the calibration target - GOOD COMMENT\ncmd("INST ROTATE with ANGLE 180.0") # Rotate 180 degrees - BAD COMMENT\n'})}),"\n",(0,i.jsx)(n.h3,{id:"script-runner",children:"Script Runner"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS provides two unique ways to run scripts (also known as procedures). Script Runner provides both a script execution environment and a script editor. The script editor includes code completion for both COSMOS methods and command/telemetry item names. It is also a great environment to develop and test scripts. Script Runner provides a framework for users that are familiar with a traditional scripting model with longer style procedures, and for users that want to be able to edit their scripts in place."}),"\n",(0,i.jsx)(n.p,{children:"When opening a suite file (named with 'suite') Script Runner provides a more formal, but also more powerful, environment for running scripts. Suite files breaks scripts down into suites, groups, and scripts (individual methods). Suites are the highest-level concept and would typically cover a large procedure such as a thermal vacuum test, or a large operations scenario such as performing on orbit checkout. Groups capture a related set of scripts such as all the scripts regarding a specific mechanism. A Group might be a collection of scripts all related to a subsystem, or a specific series of tests such as an RF checkout. Scripts capture individual activities that can either pass or fail. Script Runner allows for running an entire suite, one or more groups, or one or more scripts easily. It also automatically produces reports containing timing, pass / fail counts, etc."}),"\n",(0,i.jsx)(n.p,{children:"The correct environment for the job is up to individual users, and many programs will use both script formats to complete their goals."}),"\n",(0,i.jsx)(n.h3,{id:"looping-vs-unrolled-loops",children:"Looping vs Unrolled Loops"}),"\n",(0,i.jsx)(n.p,{children:"Loops are powerful constructs that allow you to perform the same operations multiple times without having to rewrite the same code over and over (See the DRY Concept). However, they can make restarting a COSMOS script at the point of a failure difficult or impossible. If there is a low probability of something failing, then loops are an excellent choice. If a script is running a loop over a list of telemetry points, it may be a better choice to \u201cunroll\u201d the loop by making the loop body into a method, and then calling that method directly for each iteration of a loop that would have occurred."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"10.times do |temperature_number|\n check_temperature(temperature_number + 1)\nend\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"for temperature_number in range(1, 11):\n check_temperature(temperature_number)\n"})}),"\n",(0,i.jsx)(n.p,{children:"If the above script was stopped after temperature number 3, there would be no way to restart the loop at temperature number 4. A better solution for small loop counts is to unroll the loop."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"check_temperature(1)\ncheck_temperature(2)\ncheck_temperature(3)\ncheck_temperature(4)\ncheck_temperature(5)\ncheck_temperature(6)\ncheck_temperature(7)\ncheck_temperature(8)\ncheck_temperature(9)\ncheck_temperature(10)\n"})}),"\n",(0,i.jsx)(n.p,{children:"In the unrolled version above, the COSMOS \u201cStart script at selected line\u201d feature can be used to resume the script at any point."}),"\n",(0,i.jsx)(n.h2,{id:"script-organization",children:"Script Organization"}),"\n",(0,i.jsxs)(n.p,{children:["All scripts must be part of a ",(0,i.jsx)(n.a,{href:"/docs/configuration/plugins",children:"Plugin"}),". You can create a simple plugin called SCRIPTS or PROCEDURES that only contains lib and procedures directories to store scripts. If COSMOS detects a plugin without defined cmd/tlm it will not spawn microservices for telemetry processing."]}),"\n",(0,i.jsx)(n.h3,{id:"organizing-your-scripts-into-a-plugin",children:"Organizing Your Scripts into a Plugin"}),"\n",(0,i.jsx)(n.p,{children:"As your scripts become large with many methods, it makes sense to break them up into multiple files within a plugin. Here is a recommended organization for your plugin's scripts/procedures."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Folder"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"targets/TARGET_NAME/lib"}),(0,i.jsx)(n.td,{children:"Place script files containing reusable target specific methods here"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"targets/TARGET_NAME/procedures"}),(0,i.jsx)(n.td,{children:"Place simple procedures that are centered around one specific target here"})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"In your main procedure you will usually bring in the other files with instrumentation using load_utility."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"# Ruby:\nload_utility('TARGET/lib/my_other_script.rb')\n# Python:\nload_utility('TARGET/procedures/my_other_script.py')\n"})}),"\n",(0,i.jsx)(n.h3,{id:"organize-scripts-into-methods",children:"Organize Scripts into Methods"}),"\n",(0,i.jsx)(n.p,{children:"Put each activity into a distinct method. Putting your scripts into methods makes organization easy and gives a great high-level overview of what the overall script does (assuming you name the methods well). There are no bonus points for vague, short method names. Make your method names long and clear."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def test_1_heater_zone_control\n puts "Verifies requirements 304, 306, and 310"\n # Test code here\nend\n\ndef script_1_heater_zone_control\n puts "Verifies requirements 304, 306, and 310"\n # Test code here\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def test_1_heater_zone_control():\n print("Verifies requirements 304, 306, and 310")\n # Test code here\n\ndef script_1_heater_zone_control():\n print("Verifies requirements 304, 306, and 310")\n # Test code here\n'})}),"\n",(0,i.jsx)(n.h3,{id:"using-classes-vs-unscoped-methods",children:"Using Classes vs Unscoped Methods"}),"\n",(0,i.jsx)(n.p,{children:"Classes in object-oriented programing allow you to organize a set of related methods and some associated state. The most important aspect is that the methods work on some shared state. For example, if you have code that moves a gimbal around, and need to keep track of the number of moves, or steps, performed across methods, then that is a wonderful place to use a class. If you just need a helper method to do something that happens multiple times in a script without copy and pasting, it probably does not need to be in a class."}),"\n",(0,i.jsx)(n.p,{children:"NOTE: The convention in COSMOS is to have a TARGET/lib/target.[rb/py] file which is named after the TARGET name and contains a class called Target. This discussion refers to scripts in the TARGET/procedures directory."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'class Gimbal\n attr_accessor :gimbal_steps\n def initialize()\n @gimbal_steps = 0\n end\n def move(steps_to_move)\n # Move the gimbal\n @gimbal_steps += steps_to_move\n end\n def home_gimbal\n # Home the gimbal\n @gimbal_steps = 0\n end\nend\n\ndef perform_common_math(x, y)\n x + y\nend\n\ngimbal = Gimbal.new\ngimbal.home_gimbal\ngimbal.move(100)\ngimbal.move(200)\nputs "Moved gimbal #{gimbal.gimbal_steps}"\nresult = perform_common_math(gimbal.gimbal_steps, 10)\nputs "Math:#{result}"\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'class Gimbal:\n def __init__(self):\n self.gimbal_steps = 0\n\n def move(self, steps_to_move):\n # Move the gimbal\n self.gimbal_steps += steps_to_move\n\n def home_gimbal(self):\n # Home the gimbal\n self.gimbal_steps = 0\n\ndef perform_common_math(x, y):\n return x + y\n\ngimbal = Gimbal()\ngimbal.home_gimbal()\ngimbal.move(100)\ngimbal.move(200)\nprint(f"Moved gimbal {gimbal.gimbal_steps}")\nresult = perform_common_math(gimbal.gimbal_steps, 10)\nprint(f"Math:{result}")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"instrumented-vs-uninstrumented-lines-require-vs-load",children:"Instrumented vs Uninstrumented Lines (require vs load)"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS scripts are normally \u201cinstrumented\u201d. This means that each line has some extra code added behind the scenes that primarily highlights the current executing line and catches exceptions if things fail such as a wait_check. If your script needs to use code in other files, there are a few ways to bring in that code. Some techniques bring in instrumented code and others bring in uninstrumented code. There are reasons to use both."}),"\n",(0,i.jsx)(n.p,{children:"load_utility (and the deprecated require_utility), bring in instrumented code from other files. When COSMOS runs the code in the other file, Script Runner will dive into the other file and show each line highlighted as it executes. This should be the default way to bring in other files, as it allows continuing if something fails, and provides better visibility to operators."}),"\n",(0,i.jsx)(n.p,{children:"However, sometimes you don't want to display code executing from other files. Externally developed libraries generally do not like to be instrumented, and code that contains large loops or that just takes a long time to execute when highlighting lines, will be much faster if included in a method that does not instrument lines. Ruby provides two ways to bring in uninstrumented code. The first is the \u201cload\u201d keyword. Load will bring in the code from another file and will bring in any changes to the file if it is updated on the next call to load. \u201crequire\u201d is like load but is optimized to only bring in the code from another file once. Therefore, if you use require and then change the file it requires, you must restart Script Runner to re-require the file and bring in the changes. In general, load is recommended over require for COSMOS scripting. One gotcha with load is that it requires the full filename including extension, while the require keyword does not."}),"\n",(0,i.jsx)(n.p,{children:"In Python, libraries are included using the import syntax. Any code imported using import is not instrumented. Only the code imported using load_utility is instrumented."}),"\n",(0,i.jsx)(n.p,{children:"Finally, COSMOS scripting has a special syntax for disabling instrumentation in the middle of an instrumented script, with the disable_instrumentation method. This allows you to disable instrumentation for large loops and other activities that are too slow when running instrumented."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"temp = 0\ndisable_instrumentation do\n # Make sure nothing in here will raise exceptions!\n 5000000.times do\n temp += 1\n end\nend\nputs temp\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"temp = 0\nwith disable_instrumentation():\n # Make sure nothing in here will raise exceptions!\n for x in range(0,5000000):\n temp += 1\nprint(temp)\n"})}),"\n",(0,i.jsx)(n.admonition,{title:"When Running Uninstrumented Code",type:"warning",children:(0,i.jsx)(n.p,{children:"Make sure that the code will not raise any exceptions or have any check failures. If an exception is raised from uninstrumented code, then your entire script will stop."})}),"\n",(0,i.jsx)(n.h2,{id:"debugging-and-auditing",children:"Debugging and Auditing"}),"\n",(0,i.jsx)(n.h3,{id:"built-in-debugging-capabilities",children:"Built-In Debugging Capabilities"}),"\n",(0,i.jsx)(n.p,{children:"Script Runner has built in debugging capabilities that can be useful in determining why your script is behaving in a certain way. Of primary importance is the ability to inspect and set script variables."}),"\n",(0,i.jsx)(n.p,{children:"To use the debugging functionality, first select the \u201cToggle Debug\u201d option from the Script Menu. This will add a small Debug: prompt to the bottom of the tool. Any code entered in this prompt will be executed when Enter is pressed. To inspect variables in a running script, pause the script and then type the variable name to print out the value of the variable in the debug prompt."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"variable_name\n"})}),"\n",(0,i.jsx)(n.p,{children:"Variables can also be set simply by using equals."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"variable_name = 5\n"})}),"\n",(0,i.jsx)(n.p,{children:"If necessary, you can also inject commands from the debug prompt using the normal commanding methods. These commands will be logged to the Script Runner message log, which may be advantageous over using a different COSMOS tool like CmdSender (where the command would only be logged in the CmdTlmServer message log)."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'cmd("INST COLLECT with TYPE NORMAL")\n'})}),"\n",(0,i.jsx)(n.p,{children:"Note that the debug prompt keeps the command history and you can scroll through the history by using the up and down arrows."}),"\n",(0,i.jsx)(n.h3,{id:"breakpoints",children:"Breakpoints"}),"\n",(0,i.jsx)(n.p,{children:"You can click the line number (left side gutter) in Script Runner to add a breakpoint. The script will automatically pause when it hits the breakpoint. Once stopped at the breakpoint, you can evaluate variables using the Debug line."}),"\n",(0,i.jsx)(n.h3,{id:"using-disconnect-mode",children:"Using Disconnect Mode"}),"\n",(0,i.jsx)(n.p,{children:"Disconnect mode is a feature of Script Runner that allows testing scripts in an environment without real hardware in the loop. Disconnect mode is started by selecting Script -> Toggle Disconnect. Once selected, the user is prompted to select which targets to disconnect. By default, all targets are disconnected, which allows for testing scripts without any real hardware. Optionally, only a subset of targets can be selected which can be useful for trying out scripts in partially integrated environments."}),"\n",(0,i.jsx)(n.p,{children:"While in disconnect mode, commands to the disconnected targets always succeed. Additionally, all checks of disconnected targets' telemetry are immediately successful. This allows for a quick run-through of procedures for logic errors and other script specific errors without having to worry about the behavior and proper functioning of hardware."}),"\n",(0,i.jsx)(n.h3,{id:"auditing-your-scripts",children:"Auditing your Scripts"}),"\n",(0,i.jsx)(n.p,{children:"Script Runner includes several tools to help audit your scripts both before and after execution."}),"\n",(0,i.jsx)(n.h4,{id:"ruby-syntax-check",children:"Ruby Syntax Check"}),"\n",(0,i.jsx)(n.p,{children:"The Ruby Syntax Check tool is found under the Script Menu. This tool uses the ruby executable with the -c flag to run a syntax check on your script. If any syntax errors are found the exact message presented by the Ruby interpreter is shown to the user. These can be cryptic, but the most common faults are not closing a quoted string, forgetting an \u201cend\u201d keyword, or using a block but forgetting the proceeding \u201cdo\u201d keyword."}),"\n",(0,i.jsx)(n.h2,{id:"common-scenarios",children:"Common Scenarios"}),"\n",(0,i.jsx)(n.h3,{id:"user-input-best-practices",children:"User Input Best Practices"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS provides several different methods to gather manual user input in scripts. When using user input methods that allow for arbitrary values (like ask() and ask_string()), it is very important to validate the value given in your script before moving on. When asking for text input, it is extra important to handle different casing possibilities and to ensure that invalid input will either re-prompt the user or take a safe path."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'answer = ask_string("Do you want to continue (y/n)?")\nif answer != \'y\' and answer != \'Y\'\n raise "User entered: #{answer}"\nend\n\ntemp = 0.0\nwhile temp < 10.0 or temp > 50.0\n temp = ask("Enter the desired temperature between 10.0 and 50.0")\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'answer = ask_string("Do you want to continue (y/n)?")\nif answer != \'y\' and answer != \'Y\':\n raise RuntimeError(f"User entered: {answer}")\n\ntemp = 0.0\nwhile temp < 10.0 or temp > 50.0:\n temp = ask("Enter the desired temperature between 10.0 and 50.0")\n'})}),"\n",(0,i.jsx)(n.p,{children:"When possible, always use one of the other user input methods that has a constrained list of choices for your users (message_box, vertical_message_box, combo_box)."}),"\n",(0,i.jsx)(n.p,{children:"Note that all these user input methods provide the user the option to \u201cCancel\u201d. When cancel is clicked, the script is paused but remains at the user input line. When hitting \u201cGo\u201d to the continue, the user will be re-prompted to enter the value."}),"\n",(0,i.jsx)(n.h3,{id:"conditionally-require-manual-user-input-steps",children:"Conditionally Require Manual User Input Steps"}),"\n",(0,i.jsx)(n.p,{children:"When possible, a useful design pattern is to write your scripts such that they can run without prompting for any user input. This allows the scripts to be more easily tested and provides a documented default value for any user input choices or values. To implement this pattern, all manual steps such as ask(), prompt(), and infinite wait() statements need to be wrapped with an if statement that checks the value of $manual in Ruby or RunningScript.manual in Python. If the variable is set, then the manual steps should be executed. If not, then a default value should be used."}),"\n",(0,i.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'if $manual\n temp = ask("Please enter the temperature")\nelse\n temp = 20.0\nend\nif !$manual\n puts "Skipping infinite wait in auto mode"\nelse\n wait\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'if RunningScript.manual:\n temp = ask("Please enter the temperature")\nelse:\n temp = 20.0\nif not RunningScript.manual:\n print("Skipping infinite wait in auto mode")\nelse:\n wait()\n'})}),"\n",(0,i.jsx)(n.p,{children:"When running suites, there is a checkbox at the top of the tool called \u201cManual\u201d that affects this $manual variable directly."}),"\n",(0,i.jsx)(n.h3,{id:"outputing-extra-information-to-a-report",children:"Outputing Extra Information to a Report"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS Script Runner operating on a script suite automatically generates a report that shows the PASS/FAILED/SKIPPED state for each script. You can also inject arbitrary text into this report using the example as follows. Alternatively, you can simply use print text into the Script Runner message log."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'class MyGroup < OpenC3::Group\n def script_1\n # The following text will be placed in the report\n OpenC3::Group.puts "Verifies requirements 304, 306, 310"\n # This puts line will show up in the sr_messages log file\n puts "script_1 complete"\n end\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'from openc3.script.suite import Group\nclass MyGroup(Group):\n def script_1():\n # The following text will be placed in the report\n Group.print("Verifies requirements 304, 306, 310")\n # This puts line will show up in the sr_messages log file\n print("script_1 complete")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"getting-the-most-recent-value-of-a-telemetry-point-from-multiple-packets",children:"Getting the Most Recent Value of a Telemetry Point from Multiple Packets"}),"\n",(0,i.jsx)(n.p,{children:"Some systems include high rate data points with the same name in every packet. COSMOS supports getting the most recent value of a telemetry point that is in multiple packets using a special packet name of LATEST. Assume the target INST has two packets, PACKET1 and PACKET2. Both packets have a telemetry point called TEMP."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# Get the value of TEMP from the most recently received PACKET1\nvalue = tlm("INST PACKET1 TEMP")\n# Get the value of TEMP from the most recently received PACKET2\nvalue = tlm("INST PACKET2 TEMP")\n# Get the value of TEMP from the most recently received PACKET1 or PACKET2\nvalue = tlm("INST LATEST TEMP")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"checking-every-single-sample-of-a-telemetry-point",children:"Checking Every Single Sample of a Telemetry Point"}),"\n",(0,i.jsx)(n.p,{children:"When writing COSMOS scripts, checking the most recent value of a telemetry point normally gets the job done. The tlm(), tlm_raw(), etc methods all retrieve the most recent value of a telemetry point. Sometimes you need to perform analysis on every single sample of a telemetry point. This can be done using the COSMOS packet subscription system. The packet subscription system lets you choose one or more packets and receive them all from a queue. You can then pick out the specific telemetry points you care about from each packet."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']])\nwait 1.5\nid, packets = get_packets(id)\npackets.each do |packet|\n puts \"#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}\"\nend\n# Wait for some time later and re-use the last returned ID\nid, packets = get_packets(id)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']])\nwait(1.5)\nid, packets = get_packets(id)\nfor packet in packets:\n print(f\"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}\")\n# Wait for some time later and re-use the last returned ID\nid, packets = get_packets(id)\n"})}),"\n",(0,i.jsx)(n.h3,{id:"using-variables-in-mnemonics",children:"Using Variables in Mnemonics"}),"\n",(0,i.jsx)(n.p,{children:"Because command and telemetry mnemonics are just strings in COSMOS scripts, you can make use of variables in some contexts to make reusable code. For example, a method can take a target name as an input to support multiple instances of a target. You could also pass in the value for a set of numbered telemetry points."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def example(target_name, temp_number)\n cmd("#{target_name} COLLECT with TYPE NORMAL")\n wait_check("#{target_name} TEMP#{temp_number} > 50.0")\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def example(target_name, temp_number):\n cmd(f"{target_name} COLLECT with TYPE NORMAL")\n wait_check(f"{target_name} TEMP{temp_number} > 50.0")\n'})}),"\n",(0,i.jsxs)(n.p,{children:["This can also be useful when looping through a numbered set of telemetry points but be considerate of the downsides of looping as discussed in the ",(0,i.jsx)(n.a,{href:"#looping-vs-unrolled-loops",children:"Looping vs Unrolled Loops"})," section."]}),"\n",(0,i.jsx)(n.h3,{id:"using-custom-wait_check_expression",children:"Using Custom wait_check_expression"}),"\n",(0,i.jsx)(n.p,{children:"The COSMOS wait_check_expression (and check_expression) allow you to perform more complicated checks and still stop the script with a CHECK error message if something goes wrong. For example, you can check variables against each other or check a telemetry point against a range. The exact string of text passed to wait_check_expression is repeatedly evaluated until it passes, or a timeout occurs. It is important to not use string interpolation within the actual expression or the values inside of the string interpolation syntax will only be evaluated once when it is converted into a string."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'one = 1\ntwo = 2\n\nwait_check_expression("one == two", 1)\n# ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds\n\n# Checking an integer range\nwait_check_expression("one > 0 and one < 10 # init value one = #{one}", 1)\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'one = 1\ntwo = 2\n\nwait_check_expression("one == two", 1, 0.25, locals())\n# ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds\n\n# Checking an integer range\nwait_check_expression("one > 0 and one < 10", 1, 0.25, locals())\n'})}),"\n",(0,i.jsx)(n.h3,{id:"cosmos-scripting-differences-from-regular-ruby-scripting",children:"COSMOS Scripting Differences from Regular Ruby Scripting"}),"\n",(0,i.jsx)(n.h4,{id:"do-not-use-single-line-if-statements",children:"Do not use single line if statements"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS scripting instruments each line to catch exceptions if things go wrong. With single line if statements the exception handling doesn't know which part of the statement failed and cannot properly continue. If an exception is raised in a single line if statement, then the entire script will stop and not be able to continue. Do not use single line if statements in COSMOS scripts. (However, they are fine to use in interfaces and other Ruby code, just not COSMOS scripts)."}),"\n",(0,i.jsx)(n.p,{children:"Don't do this:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'run_method() if tlm("INST HEALTH_STATUS TEMP1") > 10.0\n'})}),"\n",(0,i.jsx)(n.p,{children:"Do this instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# It is best not to execute any code that could fail in an if statement, ie\n# tlm() could fail if the CmdTlmServer was not running or a mnemonic\n# was misspelled\ntemp1 = tlm("INST HEALTH_STATUS TEMP1")\nif temp1 > 10.0\n run_method()\nend\n'})}),"\n",(0,i.jsx)(n.h2,{id:"when-things-go-wrong",children:"When Things Go Wrong"}),"\n",(0,i.jsx)(n.h3,{id:"common-reasons-checks-fail",children:"Common Reasons Checks Fail"}),"\n",(0,i.jsx)(n.p,{children:"There are three common reasons that checks fail in COSMOS scripts:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The delay given was too short"}),"\n",(0,i.jsx)(n.p,{children:"The wait_check() method takes a timeout that indicates how long to wait for the referenced telemetry point to pass the check. The timeout needs to be large enough for the system under test to finish its action and for updated telemetry to be received. Note that the script will continue as soon as the check completes successfully. Thus, the only penalty for a longer timeout is the additional wait time in a failure condition."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The range or value checked against was incorrect or too stringent"}),"\n",(0,i.jsx)(n.p,{children:"Often the actual telemetry value is ok, but the expected value checked against was too tight. Loosen the ranges on checks when it makes sense. Ensure your script is using the wait_check_tolerance() routine when checking floating point numbers and verify you're using an appropriate tolerance value."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The check really failed"}),"\n",(0,i.jsx)(n.p,{children:"Of course, sometimes there are real failures. See the next section for how to handle them and recover."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"how-to-recover-from-anomalies",children:"How to Recover from Anomalies"}),"\n",(0,i.jsx)(n.p,{children:"Once something has failed, and your script has stopped with a pink highlighted line, how can you recover? Fortunately, COSMOS provides several mechanisms that can be used to recover after something in your script fails."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Retry"}),"\n",(0,i.jsx)(n.p,{children:"After a failure, the Script Runner \u201cPause\u201d button changes to \u201cRetry\u201d. Clicking on the Retry button will re-execute the line the failed. For failures due to timing issues, this will often resolve the issue and allow the script to continue. Make note of the failure and be sure to update your script prior to the next run."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Use the Debug Prompt"}),"\n",(0,i.jsx)(n.p,{children:"By selecting Script -> Toggle Debug, you can perform arbitrary actions that may be needed to correct the situation without stopping the running script. You can also inspect variables to help determine why something failed."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Execute Selection"}),"\n",(0,i.jsx)(n.p,{children:'If only a small section of a script needs to be run, then \u201cExecute Selection" can be used to execute only a small portion of the script. This can also be used when a script is paused or stopped in error.'}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Run from here"}),"\n",(0,i.jsx)(n.p,{children:'By clicking into a script, and right clicking to select "Run from here", users can restart a script at an arbitrary point. This works well if no required variable definitions exist earlier in the script.'}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"advanced-topics",children:"Advanced Topics"}),"\n",(0,i.jsx)(n.h3,{id:"advanced-script-configuration-with-csv-or-excel",children:"Advanced Script Configuration with CSV or Excel"}),"\n",(0,i.jsx)(n.p,{children:"Using a spreadsheet to store the values for use by a script can be a great option if you have a CM-controlled script but need to be able to tweak some values for a test or if you need to use different values for different serial numbers."}),"\n",(0,i.jsx)(n.p,{children:"The Ruby CSV class be used to easily read data from CSV files (recommended for cross platform projects)."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"require 'csv'\nvalues = CSV.read('test.csv')\nputs values[0][0]\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you are only using Windows, COSMOS also contains a library for reading Excel files."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"require 'openc3/win32/excel'\nss = ExcelSpreadsheet.new('C:/git/cosmos/test.xlsx')\nputs ss[0][0][0]\n"})}),"\n",(0,i.jsx)(n.h3,{id:"when-to-use-ruby-modules",children:"When to use Ruby Modules"}),"\n",(0,i.jsx)(n.p,{children:"Modules in Ruby have two purposes: namespacing and mixins. Namespacing allows having classes and methods with the same name, but with different meanings. For example, if they are namespaced, COSMOS can have a Packet class and another Ruby library can have a Packet class. This isn't typically useful for COSMOS scripting though."}),"\n",(0,i.jsx)(n.p,{children:"Mixins allow adding common methods to classes without using inheritance. Mixins can be useful to add common functionality to some classes but not others, or to break up classes into multiple files."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"module MyModule\n def module_method\n end\nend\nclass MyTest < OpenC3::Group\n include MyModule\n def test_1\n module_method()\n end\nend\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>o});var i=t(6540);const s={},r=i.createContext(s);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/42170351.6fe86f8a.js b/docs/assets/js/42170351.6fe86f8a.js
new file mode 100644
index 0000000000..ce074e08a4
--- /dev/null
+++ b/docs/assets/js/42170351.6fe86f8a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[3440],{7305:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=t(4848),s=t(8453);const r={title:"Script Writing Guide"},a=void 0,o={id:"guides/script-writing",title:"Script Writing Guide",description:"Introduction",source:"@site/docs/guides/script-writing.md",sourceDirName:"guides",slug:"/guides/script-writing",permalink:"/docs/guides/script-writing",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/guides/script-writing.md",tags:[],version:"current",frontMatter:{title:"Script Writing Guide"},sidebar:"defaultSidebar",previous:{title:"Raspberry Pi",permalink:"/docs/guides/raspberrypi"},next:{title:"Scripting API Guide",permalink:"/docs/guides/scripting-api"}},l={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Concepts",id:"concepts",level:2},{value:"Ruby vs Python in COSMOS",id:"ruby-vs-python-in-cosmos",level:3},{value:"Scripting Philosophy",id:"scripting-philosophy",level:2},{value:"A Super Basic Script Example",id:"a-super-basic-script-example",level:3},{value:"KISS (Keep It Simple Stupid)",id:"kiss-keep-it-simple-stupid",level:3},{value:"Keep things DRY (Don't Repeat Yourself)",id:"keep-things-dry-dont-repeat-yourself",level:3},{value:"Use Comments Appropriately",id:"use-comments-appropriately",level:3},{value:"Script Runner",id:"script-runner",level:3},{value:"Looping vs Unrolled Loops",id:"looping-vs-unrolled-loops",level:3},{value:"Script Organization",id:"script-organization",level:2},{value:"Organizing Your Scripts into a Plugin",id:"organizing-your-scripts-into-a-plugin",level:3},{value:"Organize Scripts into Methods",id:"organize-scripts-into-methods",level:3},{value:"Using Classes vs Unscoped Methods",id:"using-classes-vs-unscoped-methods",level:3},{value:"Instrumented vs Uninstrumented Lines (require vs load)",id:"instrumented-vs-uninstrumented-lines-require-vs-load",level:3},{value:"Debugging and Auditing",id:"debugging-and-auditing",level:2},{value:"Built-In Debugging Capabilities",id:"built-in-debugging-capabilities",level:3},{value:"Breakpoints",id:"breakpoints",level:3},{value:"Using Disconnect Mode",id:"using-disconnect-mode",level:3},{value:"Auditing your Scripts",id:"auditing-your-scripts",level:3},{value:"Ruby Syntax Check",id:"ruby-syntax-check",level:4},{value:"Common Scenarios",id:"common-scenarios",level:2},{value:"User Input Best Practices",id:"user-input-best-practices",level:3},{value:"Conditionally Require Manual User Input Steps",id:"conditionally-require-manual-user-input-steps",level:3},{value:"Outputting Extra Information to a Report",id:"outputting-extra-information-to-a-report",level:3},{value:"Getting the Most Recent Value of a Telemetry Point from Multiple Packets",id:"getting-the-most-recent-value-of-a-telemetry-point-from-multiple-packets",level:3},{value:"Checking Every Single Sample of a Telemetry Point",id:"checking-every-single-sample-of-a-telemetry-point",level:3},{value:"Using Variables in Mnemonics",id:"using-variables-in-mnemonics",level:3},{value:"Using Custom wait_check_expression",id:"using-custom-wait_check_expression",level:3},{value:"COSMOS Scripting Differences from Regular Ruby Scripting",id:"cosmos-scripting-differences-from-regular-ruby-scripting",level:3},{value:"Do not use single line if statements",id:"do-not-use-single-line-if-statements",level:4},{value:"When Things Go Wrong",id:"when-things-go-wrong",level:2},{value:"Common Reasons Checks Fail",id:"common-reasons-checks-fail",level:3},{value:"How to Recover from Anomalies",id:"how-to-recover-from-anomalies",level:3},{value:"Advanced Topics",id:"advanced-topics",level:2},{value:"Advanced Script Configuration with CSV or Excel",id:"advanced-script-configuration-with-csv-or-excel",level:3},{value:"When to use Ruby Modules",id:"when-to-use-ruby-modules",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"This guide aims to provide the best practices for using the scripting capabilities provided by COSMOS. Scripts are used to automate a series of activities for operations or testing. The goal of this document is to ensure scripts are written that are simple, easy to understand, maintainable, and correct. Guidance on some of the key details of using the COSMOS Script Runner is also provided."}),"\n",(0,i.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS supports both Ruby and Python for writing scripts. Ruby and Python are very similar scripting languages and most of this guide applies directly to both. Where examples are used, both a Ruby and Python example are given."}),"\n",(0,i.jsx)(n.h3,{id:"ruby-vs-python-in-cosmos",children:"Ruby vs Python in COSMOS"}),"\n",(0,i.jsx)(n.p,{children:"There are many similarities and a few key differences between Ruby and Python when it comes to writing COSMOS scripts."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"There is no 80 character limit on line length. Lines can be as long as you like, but be careful to not make them too long as it makes printed reviews of scripts more difficult."}),"\n",(0,i.jsxs)(n.li,{children:["Indentation white space:","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Ruby: Not significant. Ruby uses the ",(0,i.jsx)(n.code,{children:"end"})," keyword to determine indented code blocks with a standard of 2 spaces."]}),"\n",(0,i.jsx)(n.li,{children:"Python: Significant. Python uses indentation to determine code blocks with a standard of 4 spaces."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Variables do not have to be declared ahead of time and can be reassigned later, i.e. Ruby and Python are dynamically typed."}),"\n",(0,i.jsxs)(n.li,{children:["Variable interpolation:","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Ruby: Variable values can be placed into strings using the ",(0,i.jsx)(n.code,{children:'"#{variable}"'})," syntax."]}),"\n",(0,i.jsxs)(n.li,{children:["Python: Variable values can be placed into f-strings using the ",(0,i.jsx)(n.code,{children:'f"{variable}"'})," syntax."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"A variable declared inside of a block or loop will not exist outside of that block unless it was already declared."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Both languages provides a script writer a lot of power. But with great power comes great responsibility. Remember when writing your scripts that you or someone else will come along later and need to understand them. Therefore use the following style guidelines:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Use consistent spacing for indentation and do NOT use tabs"}),"\n",(0,i.jsxs)(n.li,{children:["Constants should be all caps with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"SPEED_OF_LIGHT = 299792458 # meters per s"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Variable names and method names should be in lowercase with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:'last_name = "Smith"'})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"perform_setup_operation()"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Class names (when used) should be camel case and the files which contain them should match but be lowercase with underscores","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"class DataUploader # in 'data_uploader.rb'"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"class CcsdsUtility: # in 'ccsds_utility.py'"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Don't add useless comments but instead describe intent"}),"\n"]}),"\n",(0,i.jsx)("div",{style:{clear:"both"}}),"\n",(0,i.jsx)(n.p,{children:"The following is an example of good Ruby style:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"load 'TARGET/lib/upload_utility.rb' # library we do NOT want to show executing\nload_utility 'TARGET/lib/helper_utility.rb' # library we do want to show executing\n\n# Declare constants\nOUR_TARGETS = ['INST','INST2']\n\n# Clear the collect counter of the passed in target name\ndef clear_collects(target)\n cmd(\"#{target} CLEAR\")\n wait_check(\"#{target} HEALTH_STATUS COLLECTS == 0\", 5)\nend\n\n######################################\n# START\n######################################\nhelper = HelperUtility.new\nhelper.setup\n\n# Perform collects on all the targets\nOUR_TARGETS.each do |target|\n collects = tlm(\"#{target} HEALTH_STATUS COLLECTS\")\n cmd(\"#{target} COLLECT with TYPE SPECIAL\")\n wait_check(\"#{target} HEALTH_STATUS COLLECTS == #{collects + 1}\", 5)\nend\n\nclear_collects('INST')\nclear_collects('INST2')\n"})}),"\n",(0,i.jsx)(n.p,{children:"The following is an example of good Python style:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"from openc3.script import *\n\nimport TARGET.lib.upload_utility # library we do NOT want to show executing\nload_utility('TARGET/lib/helper_utility.rb') # library we do want to show executing\n\n# Declare constants\nOUR_TARGETS = ['INST','INST2']\n\n# Clear the collect counter of the passed in target name\ndef clear_collects(target):\n cmd(f\"{target} CLEAR\")\n wait_check(f\"{target} HEALTH_STATUS COLLECTS == 0\", 5)\n\n######################################\n# START\n######################################\nhelper = HelperUtility()\nhelper.setup()\n\n# Perform collects on all the targets\nfor target in OUR_TARGETS:\n collects = tlm(f\"{target} HEALTH_STATUS COLLECTS\")\n cmd(f\"{target} COLLECT with TYPE SPECIAL\")\n wait_check(f\"{target} HEALTH_STATUS COLLECTS == {collects + 1}\", 5)\n\nclear_collects('INST')\nclear_collects('INST2')\n"})}),"\n",(0,i.jsx)(n.p,{children:"Both examples shows several features of COSMOS scripting in action. Notice the difference between 'load' or 'import' and 'load_utility'. The first is to load additional scripts which will NOT be shown in Script Runner when executing. This is a good place to put code which takes a long time to run such as image analysis or other looping code where you just want the output. 'load_utility' will visually execute the code line by line to show the user what is happening."}),"\n",(0,i.jsx)(n.p,{children:"Next we declare our constants and create an array of strings which we store in OUR_TARGETS. Notice the constant is all uppercase with underscores."}),"\n",(0,i.jsx)(n.p,{children:"Then we declare our local methods of which we have one called clear_collects. Please provide a comment at the beginning of each method describing what it does and the parameters that it takes."}),"\n",(0,i.jsx)(n.p,{children:"The 'helper_utility' is then created. Note the similarity in the class name and the file name we loaded."}),"\n",(0,i.jsxs)(n.p,{children:["The collect example shows how you can iterate over the array of strings we previously created and use variables when commanding and checking telemetry. The Ruby pound bracket #",' notation and python f-string f"'," notation puts whatever the variable holds into the string. You can even execute additional code inside the brackets like we do when checking for the collect count to increment."]}),"\n",(0,i.jsx)(n.p,{children:"Finally we call our 'clear_collects' method on each target by passing the target name."}),"\n",(0,i.jsx)(n.h2,{id:"scripting-philosophy",children:"Scripting Philosophy"}),"\n",(0,i.jsx)(n.h3,{id:"a-super-basic-script-example",children:"A Super Basic Script Example"}),"\n",(0,i.jsx)(n.p,{children:"Most COSMOS scripts can be broken down into the simple pattern of sending a command to a system/subsystem and then verifying that the command worked as expected. This pattern is most commonly implemented with cmd() followed by wait_check(), like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'cmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check("INST HEALTH_STATUS TYPE == \'NORMAL\'", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"or similarly with a counter that is sampled before the command."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'count = tlm("INST HEALTH_STATUS COLLECTS")\ncmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check("INST HEALTH_STATUS COLLECTS >= #{count + 1}", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'count = tlm("INST HEALTH_STATUS COLLECTS")\ncmd("INST COLLECT with TYPE NORMAL, TEMP 10.0")\nwait_check(f"INST HEALTH_STATUS COLLECTS >= {count + 1}", 5)\n'})}),"\n",(0,i.jsx)(n.p,{children:"90% of the COSMOS scripts you write should be the simple patterns shown above except that you may need to check more than one item after each command to make sure the command worked as expected."}),"\n",(0,i.jsx)(n.h3,{id:"kiss-keep-it-simple-stupid",children:"KISS (Keep It Simple Stupid)"}),"\n",(0,i.jsx)(n.p,{children:"Ruby and Python are very powerful languages with many ways to accomplish the same thing. Given that, always choose the method that is easiest to understand for yourself and others. While it is possible to create complex one liners or obtuse regular expressions, you'll thank yourself later by expanding complex one liners and breaking up and documenting regular expressions."}),"\n",(0,i.jsx)(n.h3,{id:"keep-things-dry-dont-repeat-yourself",children:"Keep things DRY (Don't Repeat Yourself)"}),"\n",(0,i.jsx)(n.p,{children:"A widespread problem in scripts written for any command and control system is large blocks of code that are repeated multiple times. In extreme cases, this has led to 100,000+ line scripts that are impossible to maintain and review."}),"\n",(0,i.jsx)(n.p,{children:"There are two common ways repetition presents itself: exact blocks of code to perform a common action such as powering on a subsystem, and blocks of code that only differ in the name of the mnemonic being checked or the values checked against. Both are solved by removing the repetition using methods (or functions)."}),"\n",(0,i.jsx)(n.p,{children:"For example, a script that powers on a subsystem and ensures correct telemetry would become:"}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"def power_on_subsystem\n # 100 lines of cmd(), wait_check(), etc\nend\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"def power_on_subsystem():\n # 100 lines of cmd(), wait_check(), etc\n"})}),"\n",(0,i.jsx)(n.p,{children:"Ideally, the above methods would be stored in another file where it could be used by other scripts. If it is truly only useful in the one script, then it could be at the top of the file. The updated script would then look like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"power_on_subsystem()\n# 150 lines operating the subsystem (e.g.)\n# cmd(...)\n# wait_check(...)\n#...\npower_off_subystem()\n# Unrelated activities\npower_on_subsystem()\n# etc.\n"})}),"\n",(0,i.jsx)(n.p,{children:"Blocks of code where only the only variation is the mnemonics or values checked can be replaced by methods with arguments."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp)\n cmd("TARGET #{enable_cmd_name} with ENABLE TRUE")\n wait_check("TARGET #{enable_tlm} == \'TRUE\'", 5)\n wait_check("TARGET #{temp_tlm} >= #{expected_temp}", 50)\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def test_minimum_temp(enable_cmd_name, enable_tlm, temp_tlm, expected_temp):\n cmd(f"TARGET {enable_cmd_name} with ENABLE TRUE")\n wait_check(f"TARGET {enable_tlm} == \'TRUE\'", 5)\n wait_check(f"TARGET {temp_tlm} >= {expected_temp}", 50)\n'})}),"\n",(0,i.jsx)(n.h3,{id:"use-comments-appropriately",children:"Use Comments Appropriately"}),"\n",(0,i.jsx)(n.p,{children:"Use comments when what you are doing is unclear or there is a higher-level purpose to a set of lines. Try to avoid putting numbers or other details in a comment as they can become out of sync with the underlying code. Ruby and Python comments start with a # pound symbol and can be anywhere on a line."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# This line sends an abort command - BAD COMMENT, UNNECESSARY\ncmd("INST ABORT")\n# Rotate the gimbal to look at the calibration target - GOOD COMMENT\ncmd("INST ROTATE with ANGLE 180.0") # Rotate 180 degrees - BAD COMMENT\n'})}),"\n",(0,i.jsx)(n.h3,{id:"script-runner",children:"Script Runner"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS provides two unique ways to run scripts (also known as procedures). Script Runner provides both a script execution environment and a script editor. The script editor includes code completion for both COSMOS methods and command/telemetry item names. It is also a great environment to develop and test scripts. Script Runner provides a framework for users that are familiar with a traditional scripting model with longer style procedures, and for users that want to be able to edit their scripts in place."}),"\n",(0,i.jsx)(n.p,{children:"When opening a suite file (named with 'suite') Script Runner provides a more formal, but also more powerful, environment for running scripts. Suite files breaks scripts down into suites, groups, and scripts (individual methods). Suites are the highest-level concept and would typically cover a large procedure such as a thermal vacuum test, or a large operations scenario such as performing on orbit checkout. Groups capture a related set of scripts such as all the scripts regarding a specific mechanism. A Group might be a collection of scripts all related to a subsystem, or a specific series of tests such as an RF checkout. Scripts capture individual activities that can either pass or fail. Script Runner allows for running an entire suite, one or more groups, or one or more scripts easily. It also automatically produces reports containing timing, pass / fail counts, etc."}),"\n",(0,i.jsx)(n.p,{children:"The correct environment for the job is up to individual users, and many programs will use both script formats to complete their goals."}),"\n",(0,i.jsx)(n.h3,{id:"looping-vs-unrolled-loops",children:"Looping vs Unrolled Loops"}),"\n",(0,i.jsx)(n.p,{children:"Loops are powerful constructs that allow you to perform the same operations multiple times without having to rewrite the same code over and over (See the DRY Concept). However, they can make restarting a COSMOS script at the point of a failure difficult or impossible. If there is a low probability of something failing, then loops are an excellent choice. If a script is running a loop over a list of telemetry points, it may be a better choice to \u201cunroll\u201d the loop by making the loop body into a method, and then calling that method directly for each iteration of a loop that would have occurred."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"10.times do |temperature_number|\n check_temperature(temperature_number + 1)\nend\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"for temperature_number in range(1, 11):\n check_temperature(temperature_number)\n"})}),"\n",(0,i.jsx)(n.p,{children:"If the above script was stopped after temperature number 3, there would be no way to restart the loop at temperature number 4. A better solution for small loop counts is to unroll the loop."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"check_temperature(1)\ncheck_temperature(2)\ncheck_temperature(3)\ncheck_temperature(4)\ncheck_temperature(5)\ncheck_temperature(6)\ncheck_temperature(7)\ncheck_temperature(8)\ncheck_temperature(9)\ncheck_temperature(10)\n"})}),"\n",(0,i.jsx)(n.p,{children:"In the unrolled version above, the COSMOS \u201cStart script at selected line\u201d feature can be used to resume the script at any point."}),"\n",(0,i.jsx)(n.h2,{id:"script-organization",children:"Script Organization"}),"\n",(0,i.jsxs)(n.p,{children:["All scripts must be part of a ",(0,i.jsx)(n.a,{href:"/docs/configuration/plugins",children:"Plugin"}),". You can create a simple plugin called SCRIPTS or PROCEDURES that only contains lib and procedures directories to store scripts. If COSMOS detects a plugin without defined cmd/tlm it will not spawn microservices for telemetry processing."]}),"\n",(0,i.jsx)(n.h3,{id:"organizing-your-scripts-into-a-plugin",children:"Organizing Your Scripts into a Plugin"}),"\n",(0,i.jsx)(n.p,{children:"As your scripts become large with many methods, it makes sense to break them up into multiple files within a plugin. Here is a recommended organization for your plugin's scripts/procedures."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Folder"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"targets/TARGET_NAME/lib"}),(0,i.jsx)(n.td,{children:"Place script files containing reusable target specific methods here"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"targets/TARGET_NAME/procedures"}),(0,i.jsx)(n.td,{children:"Place simple procedures that are centered around one specific target here"})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"In your main procedure you will usually bring in the other files with instrumentation using load_utility."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"# Ruby:\nload_utility('TARGET/lib/my_other_script.rb')\n# Python:\nload_utility('TARGET/procedures/my_other_script.py')\n"})}),"\n",(0,i.jsx)(n.h3,{id:"organize-scripts-into-methods",children:"Organize Scripts into Methods"}),"\n",(0,i.jsx)(n.p,{children:"Put each activity into a distinct method. Putting your scripts into methods makes organization easy and gives a great high-level overview of what the overall script does (assuming you name the methods well). There are no bonus points for vague, short method names. Make your method names long and clear."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def test_1_heater_zone_control\n puts "Verifies requirements 304, 306, and 310"\n # Test code here\nend\n\ndef script_1_heater_zone_control\n puts "Verifies requirements 304, 306, and 310"\n # Test code here\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def test_1_heater_zone_control():\n print("Verifies requirements 304, 306, and 310")\n # Test code here\n\ndef script_1_heater_zone_control():\n print("Verifies requirements 304, 306, and 310")\n # Test code here\n'})}),"\n",(0,i.jsx)(n.h3,{id:"using-classes-vs-unscoped-methods",children:"Using Classes vs Unscoped Methods"}),"\n",(0,i.jsx)(n.p,{children:"Classes in object-oriented programming allow you to organize a set of related methods and some associated state. The most important aspect is that the methods work on some shared state. For example, if you have code that moves a gimbal around, and need to keep track of the number of moves, or steps, performed across methods, then that is a wonderful place to use a class. If you just need a helper method to do something that happens multiple times in a script without copy and pasting, it probably does not need to be in a class."}),"\n",(0,i.jsx)(n.p,{children:"NOTE: The convention in COSMOS is to have a TARGET/lib/target.[rb/py] file which is named after the TARGET name and contains a class called Target. This discussion refers to scripts in the TARGET/procedures directory."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'class Gimbal\n attr_accessor :gimbal_steps\n def initialize()\n @gimbal_steps = 0\n end\n def move(steps_to_move)\n # Move the gimbal\n @gimbal_steps += steps_to_move\n end\n def home_gimbal\n # Home the gimbal\n @gimbal_steps = 0\n end\nend\n\ndef perform_common_math(x, y)\n x + y\nend\n\ngimbal = Gimbal.new\ngimbal.home_gimbal\ngimbal.move(100)\ngimbal.move(200)\nputs "Moved gimbal #{gimbal.gimbal_steps}"\nresult = perform_common_math(gimbal.gimbal_steps, 10)\nputs "Math:#{result}"\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'class Gimbal:\n def __init__(self):\n self.gimbal_steps = 0\n\n def move(self, steps_to_move):\n # Move the gimbal\n self.gimbal_steps += steps_to_move\n\n def home_gimbal(self):\n # Home the gimbal\n self.gimbal_steps = 0\n\ndef perform_common_math(x, y):\n return x + y\n\ngimbal = Gimbal()\ngimbal.home_gimbal()\ngimbal.move(100)\ngimbal.move(200)\nprint(f"Moved gimbal {gimbal.gimbal_steps}")\nresult = perform_common_math(gimbal.gimbal_steps, 10)\nprint(f"Math:{result}")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"instrumented-vs-uninstrumented-lines-require-vs-load",children:"Instrumented vs Uninstrumented Lines (require vs load)"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS scripts are normally \u201cinstrumented\u201d. This means that each line has some extra code added behind the scenes that primarily highlights the current executing line and catches exceptions if things fail such as a wait_check. If your script needs to use code in other files, there are a few ways to bring in that code. Some techniques bring in instrumented code and others bring in uninstrumented code. There are reasons to use both."}),"\n",(0,i.jsx)(n.p,{children:"load_utility (and the deprecated require_utility), bring in instrumented code from other files. When COSMOS runs the code in the other file, Script Runner will dive into the other file and show each line highlighted as it executes. This should be the default way to bring in other files, as it allows continuing if something fails, and provides better visibility to operators."}),"\n",(0,i.jsx)(n.p,{children:"However, sometimes you don't want to display code executing from other files. Externally developed libraries generally do not like to be instrumented, and code that contains large loops or that just takes a long time to execute when highlighting lines, will be much faster if included in a method that does not instrument lines. Ruby provides two ways to bring in uninstrumented code. The first is the \u201cload\u201d keyword. Load will bring in the code from another file and will bring in any changes to the file if it is updated on the next call to load. \u201crequire\u201d is like load but is optimized to only bring in the code from another file once. Therefore, if you use require and then change the file it requires, you must restart Script Runner to re-require the file and bring in the changes. In general, load is recommended over require for COSMOS scripting. One gotcha with load is that it requires the full filename including extension, while the require keyword does not."}),"\n",(0,i.jsx)(n.p,{children:"In Python, libraries are included using the import syntax. Any code imported using import is not instrumented. Only the code imported using load_utility is instrumented."}),"\n",(0,i.jsx)(n.p,{children:"Finally, COSMOS scripting has a special syntax for disabling instrumentation in the middle of an instrumented script, with the disable_instrumentation method. This allows you to disable instrumentation for large loops and other activities that are too slow when running instrumented."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"temp = 0\ndisable_instrumentation do\n # Make sure nothing in here will raise exceptions!\n 5000000.times do\n temp += 1\n end\nend\nputs temp\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"temp = 0\nwith disable_instrumentation():\n # Make sure nothing in here will raise exceptions!\n for x in range(0,5000000):\n temp += 1\nprint(temp)\n"})}),"\n",(0,i.jsx)(n.admonition,{title:"When Running Uninstrumented Code",type:"warning",children:(0,i.jsx)(n.p,{children:"Make sure that the code will not raise any exceptions or have any check failures. If an exception is raised from uninstrumented code, then your entire script will stop."})}),"\n",(0,i.jsx)(n.h2,{id:"debugging-and-auditing",children:"Debugging and Auditing"}),"\n",(0,i.jsx)(n.h3,{id:"built-in-debugging-capabilities",children:"Built-In Debugging Capabilities"}),"\n",(0,i.jsx)(n.p,{children:"Script Runner has built in debugging capabilities that can be useful in determining why your script is behaving in a certain way. Of primary importance is the ability to inspect and set script variables."}),"\n",(0,i.jsx)(n.p,{children:"To use the debugging functionality, first select the \u201cToggle Debug\u201d option from the Script Menu. This will add a small Debug: prompt to the bottom of the tool. Any code entered in this prompt will be executed when Enter is pressed. To inspect variables in a running script, pause the script and then type the variable name to print out the value of the variable in the debug prompt."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"variable_name\n"})}),"\n",(0,i.jsx)(n.p,{children:"Variables can also be set simply by using equals."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"variable_name = 5\n"})}),"\n",(0,i.jsx)(n.p,{children:"If necessary, you can also inject commands from the debug prompt using the normal commanding methods. These commands will be logged to the Script Runner message log, which may be advantageous over using a different COSMOS tool like CmdSender (where the command would only be logged in the CmdTlmServer message log)."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'cmd("INST COLLECT with TYPE NORMAL")\n'})}),"\n",(0,i.jsx)(n.p,{children:"Note that the debug prompt keeps the command history and you can scroll through the history by using the up and down arrows."}),"\n",(0,i.jsx)(n.h3,{id:"breakpoints",children:"Breakpoints"}),"\n",(0,i.jsx)(n.p,{children:"You can click the line number (left side gutter) in Script Runner to add a breakpoint. The script will automatically pause when it hits the breakpoint. Once stopped at the breakpoint, you can evaluate variables using the Debug line."}),"\n",(0,i.jsx)(n.h3,{id:"using-disconnect-mode",children:"Using Disconnect Mode"}),"\n",(0,i.jsx)(n.p,{children:"Disconnect mode is a feature of Script Runner that allows testing scripts in an environment without real hardware in the loop. Disconnect mode is started by selecting Script -> Toggle Disconnect. Once selected, the user is prompted to select which targets to disconnect. By default, all targets are disconnected, which allows for testing scripts without any real hardware. Optionally, only a subset of targets can be selected which can be useful for trying out scripts in partially integrated environments."}),"\n",(0,i.jsx)(n.p,{children:"While in disconnect mode, commands to the disconnected targets always succeed. Additionally, all checks of disconnected targets' telemetry are immediately successful. This allows for a quick run-through of procedures for logic errors and other script specific errors without having to worry about the behavior and proper functioning of hardware."}),"\n",(0,i.jsx)(n.h3,{id:"auditing-your-scripts",children:"Auditing your Scripts"}),"\n",(0,i.jsx)(n.p,{children:"Script Runner includes several tools to help audit your scripts both before and after execution."}),"\n",(0,i.jsx)(n.h4,{id:"ruby-syntax-check",children:"Ruby Syntax Check"}),"\n",(0,i.jsx)(n.p,{children:"The Ruby Syntax Check tool is found under the Script Menu. This tool uses the ruby executable with the -c flag to run a syntax check on your script. If any syntax errors are found the exact message presented by the Ruby interpreter is shown to the user. These can be cryptic, but the most common faults are not closing a quoted string, forgetting an \u201cend\u201d keyword, or using a block but forgetting the proceeding \u201cdo\u201d keyword."}),"\n",(0,i.jsx)(n.h2,{id:"common-scenarios",children:"Common Scenarios"}),"\n",(0,i.jsx)(n.h3,{id:"user-input-best-practices",children:"User Input Best Practices"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS provides several different methods to gather manual user input in scripts. When using user input methods that allow for arbitrary values (like ask() and ask_string()), it is very important to validate the value given in your script before moving on. When asking for text input, it is extra important to handle different casing possibilities and to ensure that invalid input will either re-prompt the user or take a safe path."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'answer = ask_string("Do you want to continue (y/n)?")\nif answer != \'y\' and answer != \'Y\'\n raise "User entered: #{answer}"\nend\n\ntemp = 0.0\nwhile temp < 10.0 or temp > 50.0\n temp = ask("Enter the desired temperature between 10.0 and 50.0")\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'answer = ask_string("Do you want to continue (y/n)?")\nif answer != \'y\' and answer != \'Y\':\n raise RuntimeError(f"User entered: {answer}")\n\ntemp = 0.0\nwhile temp < 10.0 or temp > 50.0:\n temp = ask("Enter the desired temperature between 10.0 and 50.0")\n'})}),"\n",(0,i.jsx)(n.p,{children:"When possible, always use one of the other user input methods that has a constrained list of choices for your users (message_box, vertical_message_box, combo_box)."}),"\n",(0,i.jsx)(n.p,{children:"Note that all these user input methods provide the user the option to \u201cCancel\u201d. When cancel is clicked, the script is paused but remains at the user input line. When hitting \u201cGo\u201d to the continue, the user will be re-prompted to enter the value."}),"\n",(0,i.jsx)(n.h3,{id:"conditionally-require-manual-user-input-steps",children:"Conditionally Require Manual User Input Steps"}),"\n",(0,i.jsx)(n.p,{children:"When possible, a useful design pattern is to write your scripts such that they can run without prompting for any user input. This allows the scripts to be more easily tested and provides a documented default value for any user input choices or values. To implement this pattern, all manual steps such as ask(), prompt(), and infinite wait() statements need to be wrapped with an if statement that checks the value of $manual in Ruby or RunningScript.manual in Python. If the variable is set, then the manual steps should be executed. If not, then a default value should be used."}),"\n",(0,i.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'if $manual\n temp = ask("Please enter the temperature")\nelse\n temp = 20.0\nend\nif !$manual\n puts "Skipping infinite wait in auto mode"\nelse\n wait\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'if RunningScript.manual:\n temp = ask("Please enter the temperature")\nelse:\n temp = 20.0\nif not RunningScript.manual:\n print("Skipping infinite wait in auto mode")\nelse:\n wait()\n'})}),"\n",(0,i.jsx)(n.p,{children:"When running suites, there is a checkbox at the top of the tool called \u201cManual\u201d that affects this $manual variable directly."}),"\n",(0,i.jsx)(n.h3,{id:"outputting-extra-information-to-a-report",children:"Outputting Extra Information to a Report"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS Script Runner operating on a script suite automatically generates a report that shows the PASS/FAILED/SKIPPED state for each script. You can also inject arbitrary text into this report using the example as follows. Alternatively, you can simply use print text into the Script Runner message log."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'class MyGroup < OpenC3::Group\n def script_1\n # The following text will be placed in the report\n OpenC3::Group.puts "Verifies requirements 304, 306, 310"\n # This puts line will show up in the sr_messages log file\n puts "script_1 complete"\n end\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'from openc3.script.suite import Group\nclass MyGroup(Group):\n def script_1():\n # The following text will be placed in the report\n Group.print("Verifies requirements 304, 306, 310")\n # This puts line will show up in the sr_messages log file\n print("script_1 complete")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"getting-the-most-recent-value-of-a-telemetry-point-from-multiple-packets",children:"Getting the Most Recent Value of a Telemetry Point from Multiple Packets"}),"\n",(0,i.jsx)(n.p,{children:"Some systems include high rate data points with the same name in every packet. COSMOS supports getting the most recent value of a telemetry point that is in multiple packets using a special packet name of LATEST. Assume the target INST has two packets, PACKET1 and PACKET2. Both packets have a telemetry point called TEMP."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# Get the value of TEMP from the most recently received PACKET1\nvalue = tlm("INST PACKET1 TEMP")\n# Get the value of TEMP from the most recently received PACKET2\nvalue = tlm("INST PACKET2 TEMP")\n# Get the value of TEMP from the most recently received PACKET1 or PACKET2\nvalue = tlm("INST LATEST TEMP")\n'})}),"\n",(0,i.jsx)(n.h3,{id:"checking-every-single-sample-of-a-telemetry-point",children:"Checking Every Single Sample of a Telemetry Point"}),"\n",(0,i.jsx)(n.p,{children:"When writing COSMOS scripts, checking the most recent value of a telemetry point normally gets the job done. The tlm(), tlm_raw(), etc methods all retrieve the most recent value of a telemetry point. Sometimes you need to perform analysis on every single sample of a telemetry point. This can be done using the COSMOS packet subscription system. The packet subscription system lets you choose one or more packets and receive them all from a queue. You can then pick out the specific telemetry points you care about from each packet."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']])\nwait 1.5\nid, packets = get_packets(id)\npackets.each do |packet|\n puts \"#{packet['PACKET_TIMESECONDS']}: #{packet['target_name']} #{packet['packet_name']}\"\nend\n# Wait for some time later and reuse the last returned ID\nid, packets = get_packets(id)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"id = subscribe_packets([['INST', 'HEALTH_STATUS'], ['INST', 'ADCS']])\nwait(1.5)\nid, packets = get_packets(id)\nfor packet in packets:\n print(f\"{packet['PACKET_TIMESECONDS']}: {packet['target_name']} {packet['packet_name']}\")\n# Wait for some time later and reuse the last returned ID\nid, packets = get_packets(id)\n"})}),"\n",(0,i.jsx)(n.h3,{id:"using-variables-in-mnemonics",children:"Using Variables in Mnemonics"}),"\n",(0,i.jsx)(n.p,{children:"Because command and telemetry mnemonics are just strings in COSMOS scripts, you can make use of variables in some contexts to make reusable code. For example, a method can take a target name as an input to support multiple instances of a target. You could also pass in the value for a set of numbered telemetry points."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'def example(target_name, temp_number)\n cmd("#{target_name} COLLECT with TYPE NORMAL")\n wait_check("#{target_name} TEMP#{temp_number} > 50.0")\nend\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'def example(target_name, temp_number):\n cmd(f"{target_name} COLLECT with TYPE NORMAL")\n wait_check(f"{target_name} TEMP{temp_number} > 50.0")\n'})}),"\n",(0,i.jsxs)(n.p,{children:["This can also be useful when looping through a numbered set of telemetry points but be considerate of the downsides of looping as discussed in the ",(0,i.jsx)(n.a,{href:"#looping-vs-unrolled-loops",children:"Looping vs Unrolled Loops"})," section."]}),"\n",(0,i.jsx)(n.h3,{id:"using-custom-wait_check_expression",children:"Using Custom wait_check_expression"}),"\n",(0,i.jsx)(n.p,{children:"The COSMOS wait_check_expression (and check_expression) allow you to perform more complicated checks and still stop the script with a CHECK error message if something goes wrong. For example, you can check variables against each other or check a telemetry point against a range. The exact string of text passed to wait_check_expression is repeatedly evaluated until it passes, or a timeout occurs. It is important to not use string interpolation within the actual expression or the values inside of the string interpolation syntax will only be evaluated once when it is converted into a string."}),"\n",(0,i.jsx)(n.p,{children:"Ruby:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'one = 1\ntwo = 2\n\nwait_check_expression("one == two", 1)\n# ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds\n\n# Checking an integer range\nwait_check_expression("one > 0 and one < 10 # init value one = #{one}", 1)\n'})}),"\n",(0,i.jsx)(n.p,{children:"Python:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'one = 1\ntwo = 2\n\nwait_check_expression("one == two", 1, 0.25, locals())\n# ERROR: CHECK: one == two is FALSE after waiting 1.017035 seconds\n\n# Checking an integer range\nwait_check_expression("one > 0 and one < 10", 1, 0.25, locals())\n'})}),"\n",(0,i.jsx)(n.h3,{id:"cosmos-scripting-differences-from-regular-ruby-scripting",children:"COSMOS Scripting Differences from Regular Ruby Scripting"}),"\n",(0,i.jsx)(n.h4,{id:"do-not-use-single-line-if-statements",children:"Do not use single line if statements"}),"\n",(0,i.jsx)(n.p,{children:"COSMOS scripting instruments each line to catch exceptions if things go wrong. With single line if statements the exception handling doesn't know which part of the statement failed and cannot properly continue. If an exception is raised in a single line if statement, then the entire script will stop and not be able to continue. Do not use single line if statements in COSMOS scripts. (However, they are fine to use in interfaces and other Ruby code, just not COSMOS scripts)."}),"\n",(0,i.jsx)(n.p,{children:"Don't do this:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'run_method() if tlm("INST HEALTH_STATUS TEMP1") > 10.0\n'})}),"\n",(0,i.jsx)(n.p,{children:"Do this instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:'# It is best not to execute any code that could fail in an if statement, ie\n# tlm() could fail if the CmdTlmServer was not running or a mnemonic\n# was misspelled\ntemp1 = tlm("INST HEALTH_STATUS TEMP1")\nif temp1 > 10.0\n run_method()\nend\n'})}),"\n",(0,i.jsx)(n.h2,{id:"when-things-go-wrong",children:"When Things Go Wrong"}),"\n",(0,i.jsx)(n.h3,{id:"common-reasons-checks-fail",children:"Common Reasons Checks Fail"}),"\n",(0,i.jsx)(n.p,{children:"There are three common reasons that checks fail in COSMOS scripts:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The delay given was too short"}),"\n",(0,i.jsx)(n.p,{children:"The wait_check() method takes a timeout that indicates how long to wait for the referenced telemetry point to pass the check. The timeout needs to be large enough for the system under test to finish its action and for updated telemetry to be received. Note that the script will continue as soon as the check completes successfully. Thus, the only penalty for a longer timeout is the additional wait time in a failure condition."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The range or value checked against was incorrect or too stringent"}),"\n",(0,i.jsx)(n.p,{children:"Often the actual telemetry value is ok, but the expected value checked against was too tight. Loosen the ranges on checks when it makes sense. Ensure your script is using the wait_check_tolerance() routine when checking floating point numbers and verify you're using an appropriate tolerance value."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The check really failed"}),"\n",(0,i.jsx)(n.p,{children:"Of course, sometimes there are real failures. See the next section for how to handle them and recover."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"how-to-recover-from-anomalies",children:"How to Recover from Anomalies"}),"\n",(0,i.jsx)(n.p,{children:"Once something has failed, and your script has stopped with a pink highlighted line, how can you recover? Fortunately, COSMOS provides several mechanisms that can be used to recover after something in your script fails."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Retry"}),"\n",(0,i.jsx)(n.p,{children:"After a failure, the Script Runner \u201cPause\u201d button changes to \u201cRetry\u201d. Clicking on the Retry button will re-execute the line the failed. For failures due to timing issues, this will often resolve the issue and allow the script to continue. Make note of the failure and be sure to update your script prior to the next run."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Use the Debug Prompt"}),"\n",(0,i.jsx)(n.p,{children:"By selecting Script -> Toggle Debug, you can perform arbitrary actions that may be needed to correct the situation without stopping the running script. You can also inspect variables to help determine why something failed."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Execute Selection"}),"\n",(0,i.jsx)(n.p,{children:'If only a small section of a script needs to be run, then \u201cExecute Selection" can be used to execute only a small portion of the script. This can also be used when a script is paused or stopped in error.'}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Run from here"}),"\n",(0,i.jsx)(n.p,{children:'By clicking into a script, and right clicking to select "Run from here", users can restart a script at an arbitrary point. This works well if no required variable definitions exist earlier in the script.'}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"advanced-topics",children:"Advanced Topics"}),"\n",(0,i.jsx)(n.h3,{id:"advanced-script-configuration-with-csv-or-excel",children:"Advanced Script Configuration with CSV or Excel"}),"\n",(0,i.jsx)(n.p,{children:"Using a spreadsheet to store the values for use by a script can be a great option if you have a CM-controlled script but need to be able to tweak some values for a test or if you need to use different values for different serial numbers."}),"\n",(0,i.jsx)(n.p,{children:"The Ruby CSV class be used to easily read data from CSV files (recommended for cross platform projects)."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"require 'csv'\nvalues = CSV.read('test.csv')\nputs values[0][0]\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you are only using Windows, COSMOS also contains a library for reading Excel files."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"require 'openc3/win32/excel'\nss = ExcelSpreadsheet.new('C:/git/cosmos/test.xlsx')\nputs ss[0][0][0]\n"})}),"\n",(0,i.jsx)(n.h3,{id:"when-to-use-ruby-modules",children:"When to use Ruby Modules"}),"\n",(0,i.jsx)(n.p,{children:"Modules in Ruby have two purposes: namespacing and mixins. Namespacing allows having classes and methods with the same name, but with different meanings. For example, if they are namespaced, COSMOS can have a Packet class and another Ruby library can have a Packet class. This isn't typically useful for COSMOS scripting though."}),"\n",(0,i.jsx)(n.p,{children:"Mixins allow adding common methods to classes without using inheritance. Mixins can be useful to add common functionality to some classes but not others, or to break up classes into multiple files."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ruby",children:"module MyModule\n def module_method\n end\nend\nclass MyTest < OpenC3::Group\n include MyModule\n def test_1\n module_method()\n end\nend\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>o});var i=t(6540);const s={},r=i.createContext(s);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/54d0d530.2a16170c.js b/docs/assets/js/54d0d530.2a16170c.js
deleted file mode 100644
index d71fac65e4..0000000000
--- a/docs/assets/js/54d0d530.2a16170c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[6464],{1510:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var n=t(4848),s=t(8453);const o={title:"Limits Monitor"},a=void 0,l={id:"tools/limits-monitor",title:"Limits Monitor",description:"Introduction",source:"@site/docs/tools/limits-monitor.md",sourceDirName:"tools",slug:"/tools/limits-monitor",permalink:"/docs/tools/limits-monitor",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/limits-monitor.md",tags:[],version:"current",frontMatter:{title:"Limits Monitor"},sidebar:"defaultSidebar",previous:{title:"Handbooks",permalink:"/docs/tools/handbooks"},next:{title:"Packet Viewer",permalink:"/docs/tools/packet-viewer"}},r={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Limits Monitor Menus",id:"limits-monitor-menus",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"Show Ignored",id:"show-ignored",level:4},{value:"Change Limits Set",id:"change-limits-set",level:4},{value:"Open Configuration",id:"open-configuration",level:4},{value:"Save Configuration",id:"save-configuration",level:4},{value:"Limits Items",id:"limits-items",level:2},{value:"Limits Log",id:"limits-log",level:2}];function c(e){const i={a:"a",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(i.p,{children:"The Limits Monitor application provides situational awareness for all telemetry items with limits. All limits items which violate their yellow or red limits are shown and continue to be shown until explicity dismissed. Individual items and entire packets can be manually ignored to filter out known issues. In addition, all limits events are logged in a table which can be searched."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Cmd Tlm Server",src:t(3204).A+"",width:"1270",height:"803"})}),"\n",(0,n.jsx)(i.h2,{id:"limits-monitor-menus",children:"Limits Monitor Menus"}),"\n",(0,n.jsx)(i.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,n.jsx)("img",{src:t(3722).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"150px"}}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"Show the list of ignored items"}),"\n",(0,n.jsx)(i.li,{children:"Change the overall COSMOS limits set"}),"\n",(0,n.jsx)(i.li,{children:"Opens a saved configuration"}),"\n",(0,n.jsx)(i.li,{children:"Save the current configuration (ignored items)"}),"\n",(0,n.jsx)(i.li,{children:"Reset the configuration (defaults settings)"}),"\n"]}),"\n",(0,n.jsx)(i.h4,{id:"show-ignored",children:"Show Ignored"}),"\n",(0,n.jsx)(i.p,{children:"This dialog displays all the items which the user has manually ignored by clicking the ignore icons next to out of limits items. Note that entire Packets which have been ignored are listed as TARGET PACKET without an item (as shown by INST MECH). Ignored items are removed by clicking the Trash icon. This means that the next time this item goes out of limits it will be displayed."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Ignored",src:t(4289).A+"",width:"594",height:"306"})}),"\n",(0,n.jsx)(i.h4,{id:"change-limits-set",children:"Change Limits Set"}),"\n",(0,n.jsxs)(i.p,{children:["Limits sets are defined with the ",(0,n.jsx)(i.a,{href:"../configuration/telemetry#limits",children:"LIMITS"})," keyword on telemetry items. Each item must have at least a DEFAULT limits set but can also have other named limit sets. COSMOS only has a single limits set active at one time. This dialog allows the user to change the active limits set and apply new limit values across all of COSMOS."]}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Change Limits Set",src:t(1813).A+"",width:"647",height:"217"})}),"\n",(0,n.jsx)(i.h4,{id:"open-configuration",children:"Open Configuration"}),"\n",(0,n.jsx)(i.p,{children:"The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,n.jsx)(i.h4,{id:"save-configuration",children:"Save Configuration"}),"\n",(0,n.jsx)(i.p,{children:"The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,n.jsx)(i.h2,{id:"limits-items",children:"Limits Items"}),"\n",(0,n.jsx)(i.p,{children:"The main interface of Limits Monitor is the top where items are displayed when they violate a yellow or red limit."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Limits",src:t(3204).A+"",width:"1270",height:"803"})}),"\n",(0,n.jsxs)(i.p,{children:["Items with limits values are displayed using a red yellow green limits bar displaying where the current value lies within the defined limits (as shown by the various TEMP items). Items with yellow or red ",(0,n.jsx)(i.a,{href:"/docs/configuration/telemetry#state",children:"states"})," are simply displayed with their state color (as shown by GROUND1STATUS). The COSMOS Demo contains both INST HEALTH_STATUS TEMP2 and INST2 HEALTH_STATUS TEMP2 which are identically named items within different target packets. Limits Monitor only displays the item name to save space, however if you mouse over the value box the full target and packet name is displayed."]}),"\n",(0,n.jsx)(i.p,{children:"Clicking the first nested 'X' icon ignores the entire packet where the item resides. Any additional items in that packet which go out of limits are also ignored by Limits Monitor. Clicking the second (middle) 'X' ignores ONLY that specific item. If any packets or items are ignored the Overall Limits State is updated to indicate \"(Some items ignored)\" to indicate the Limits State is potentially being affected by ignored items."}),"\n",(0,n.jsx)(i.p,{children:"Clicking the last icon (eye with strike-through) temporarily hides the specified item. This is different from ignoring an item because if this item goes out of limits it will be again be displayed. Hiding an item is useful if the item has gone back to green and you want to continue to track it but want to clean up the current list of items. For example, we might hide the GROUND1STATUS items in the above example as they have transitioned back to green."}),"\n",(0,n.jsx)(i.h2,{id:"limits-log",children:"Limits Log"}),"\n",(0,n.jsx)(i.p,{children:"The Log section lists all limits events. Events can be filtered by using the Search box as shown."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Log",src:t(2113).A+"",width:"1261",height:"522"})})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},3722:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/file_menu-953e2fc0c1a5b30c90d6f748add6ee28f8b42f30fc33d0b3c8709d6c85f06585.png"},1813:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/change_limits_set-b72da282ea28d783bd7e1d0cd48db72486dacb4e76e1cd46d52c7999028d9c0d.png"},4289:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/ignored-0917bd9f41f4e93704daa45cc0a7b70809bdbba03615d6de254336141b598992.png"},3204:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/limits_monitor-34ca441e5a7198b4dc57a27b2e6fcb973dddad5eaaa5e9bf0d60738f4143c73a.png"},2113:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/log-6cf3276d9e6b7dc30573b2b6a5989c6c5defc658e2c0ae4c2150a5fd11fd49d3.png"},8453:(e,i,t)=>{t.d(i,{R:()=>a,x:()=>l});var n=t(6540);const s={},o=n.createContext(s);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/54d0d530.d11ea055.js b/docs/assets/js/54d0d530.d11ea055.js
new file mode 100644
index 0000000000..d6db948ac5
--- /dev/null
+++ b/docs/assets/js/54d0d530.d11ea055.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[6464],{1510:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var n=t(4848),s=t(8453);const o={title:"Limits Monitor"},a=void 0,l={id:"tools/limits-monitor",title:"Limits Monitor",description:"Introduction",source:"@site/docs/tools/limits-monitor.md",sourceDirName:"tools",slug:"/tools/limits-monitor",permalink:"/docs/tools/limits-monitor",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/limits-monitor.md",tags:[],version:"current",frontMatter:{title:"Limits Monitor"},sidebar:"defaultSidebar",previous:{title:"Handbooks",permalink:"/docs/tools/handbooks"},next:{title:"Packet Viewer",permalink:"/docs/tools/packet-viewer"}},r={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Limits Monitor Menus",id:"limits-monitor-menus",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"Show Ignored",id:"show-ignored",level:4},{value:"Change Limits Set",id:"change-limits-set",level:4},{value:"Open Configuration",id:"open-configuration",level:4},{value:"Save Configuration",id:"save-configuration",level:4},{value:"Limits Items",id:"limits-items",level:2},{value:"Limits Log",id:"limits-log",level:2}];function c(e){const i={a:"a",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(i.p,{children:"The Limits Monitor application provides situational awareness for all telemetry items with limits. All limits items which violate their yellow or red limits are shown and continue to be shown until explicitly dismissed. Individual items and entire packets can be manually ignored to filter out known issues. In addition, all limits events are logged in a table which can be searched."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Cmd Tlm Server",src:t(3204).A+"",width:"1270",height:"803"})}),"\n",(0,n.jsx)(i.h2,{id:"limits-monitor-menus",children:"Limits Monitor Menus"}),"\n",(0,n.jsx)(i.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,n.jsx)("img",{src:t(3722).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"150px"}}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"Show the list of ignored items"}),"\n",(0,n.jsx)(i.li,{children:"Change the overall COSMOS limits set"}),"\n",(0,n.jsx)(i.li,{children:"Opens a saved configuration"}),"\n",(0,n.jsx)(i.li,{children:"Save the current configuration (ignored items)"}),"\n",(0,n.jsx)(i.li,{children:"Reset the configuration (defaults settings)"}),"\n"]}),"\n",(0,n.jsx)(i.h4,{id:"show-ignored",children:"Show Ignored"}),"\n",(0,n.jsx)(i.p,{children:"This dialog displays all the items which the user has manually ignored by clicking the ignore icons next to out of limits items. Note that entire Packets which have been ignored are listed as TARGET PACKET without an item (as shown by INST MECH). Ignored items are removed by clicking the Trash icon. This means that the next time this item goes out of limits it will be displayed."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Ignored",src:t(4289).A+"",width:"594",height:"306"})}),"\n",(0,n.jsx)(i.h4,{id:"change-limits-set",children:"Change Limits Set"}),"\n",(0,n.jsxs)(i.p,{children:["Limits sets are defined with the ",(0,n.jsx)(i.a,{href:"../configuration/telemetry#limits",children:"LIMITS"})," keyword on telemetry items. Each item must have at least a DEFAULT limits set but can also have other named limit sets. COSMOS only has a single limits set active at one time. This dialog allows the user to change the active limits set and apply new limit values across all of COSMOS."]}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Change Limits Set",src:t(1813).A+"",width:"647",height:"217"})}),"\n",(0,n.jsx)(i.h4,{id:"open-configuration",children:"Open Configuration"}),"\n",(0,n.jsx)(i.p,{children:"The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,n.jsx)(i.h4,{id:"save-configuration",children:"Save Configuration"}),"\n",(0,n.jsx)(i.p,{children:"The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,n.jsx)(i.h2,{id:"limits-items",children:"Limits Items"}),"\n",(0,n.jsx)(i.p,{children:"The main interface of Limits Monitor is the top where items are displayed when they violate a yellow or red limit."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Limits",src:t(3204).A+"",width:"1270",height:"803"})}),"\n",(0,n.jsxs)(i.p,{children:["Items with limits values are displayed using a red yellow green limits bar displaying where the current value lies within the defined limits (as shown by the various TEMP items). Items with yellow or red ",(0,n.jsx)(i.a,{href:"/docs/configuration/telemetry#state",children:"states"})," are simply displayed with their state color (as shown by GROUND1STATUS). The COSMOS Demo contains both INST HEALTH_STATUS TEMP2 and INST2 HEALTH_STATUS TEMP2 which are identically named items within different target packets. Limits Monitor only displays the item name to save space, however if you mouse over the value box the full target and packet name is displayed."]}),"\n",(0,n.jsx)(i.p,{children:"Clicking the first nested 'X' icon ignores the entire packet where the item resides. Any additional items in that packet which go out of limits are also ignored by Limits Monitor. Clicking the second (middle) 'X' ignores ONLY that specific item. If any packets or items are ignored the Overall Limits State is updated to indicate \"(Some items ignored)\" to indicate the Limits State is potentially being affected by ignored items."}),"\n",(0,n.jsx)(i.p,{children:"Clicking the last icon (eye with strike-through) temporarily hides the specified item. This is different from ignoring an item because if this item goes out of limits it will be again be displayed. Hiding an item is useful if the item has gone back to green and you want to continue to track it but want to clean up the current list of items. For example, we might hide the GROUND1STATUS items in the above example as they have transitioned back to green."}),"\n",(0,n.jsx)(i.h2,{id:"limits-log",children:"Limits Log"}),"\n",(0,n.jsx)(i.p,{children:"The Log section lists all limits events. Events can be filtered by using the Search box as shown."}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.img,{alt:"Log",src:t(2113).A+"",width:"1261",height:"522"})})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},3722:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/file_menu-953e2fc0c1a5b30c90d6f748add6ee28f8b42f30fc33d0b3c8709d6c85f06585.png"},1813:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/change_limits_set-b72da282ea28d783bd7e1d0cd48db72486dacb4e76e1cd46d52c7999028d9c0d.png"},4289:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/ignored-0917bd9f41f4e93704daa45cc0a7b70809bdbba03615d6de254336141b598992.png"},3204:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/limits_monitor-34ca441e5a7198b4dc57a27b2e6fcb973dddad5eaaa5e9bf0d60738f4143c73a.png"},2113:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/log-6cf3276d9e6b7dc30573b2b6a5989c6c5defc658e2c0ae4c2150a5fd11fd49d3.png"},8453:(e,i,t)=>{t.d(i,{R:()=>a,x:()=>l});var n=t(6540);const s={},o=n.createContext(s);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/5fe211ef.7cabc4a4.js b/docs/assets/js/5fe211ef.7cabc4a4.js
new file mode 100644
index 0000000000..569e376f18
--- /dev/null
+++ b/docs/assets/js/5fe211ef.7cabc4a4.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[864],{472:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>o,frontMatter:()=>s,metadata:()=>d,toc:()=>h});var r=i(4848),t=i(8453);const s={sidebar_position:8,title:"Tables"},l=void 0,d={id:"configuration/table",title:"Tables",description:"Table Definition Files",source:"@site/docs/configuration/table.md",sourceDirName:"configuration",slug:"/configuration/table",permalink:"/docs/configuration/table",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/table.md",tags:[],version:"current",sidebarPosition:8,frontMatter:{sidebar_position:8,title:"Tables"},sidebar:"defaultSidebar",previous:{title:"Protocols",permalink:"/docs/configuration/protocols"},next:{title:"Screens",permalink:"/docs/configuration/telemetry-screens"}},a={},h=[{value:"Table Definition Files",id:"table-definition-files",level:2},{value:"TABLEFILE",id:"tablefile",level:2},{value:"TABLE",id:"table",level:2},{value:"TABLE Modifiers",id:"table-modifiers",level:2},{value:"PARAMETER",id:"parameter",level:3},{value:"PARAMETER Modifiers",id:"parameter-modifiers",level:3},{value:"FORMAT_STRING",id:"format_string",level:4},{value:"UNITS",id:"units",level:4},{value:"DESCRIPTION",id:"description",level:4},{value:"META",id:"meta",level:4},{value:"OVERLAP",id:"overlap",level:4},{value:"KEY",id:"key",level:4},{value:"VARIABLE_BIT_SIZE",id:"variable_bit_size",level:4},{value:"REQUIRED",id:"required",level:4},{value:"MINIMUM_VALUE",id:"minimum_value",level:4},{value:"MAXIMUM_VALUE",id:"maximum_value",level:4},{value:"DEFAULT_VALUE",id:"default_value",level:4},{value:"STATE",id:"state",level:4},{value:"WRITE_CONVERSION",id:"write_conversion",level:4},{value:"POLY_WRITE_CONVERSION",id:"poly_write_conversion",level:4},{value:"SEG_POLY_WRITE_CONVERSION",id:"seg_poly_write_conversion",level:4},{value:"GENERIC_WRITE_CONVERSION_START",id:"generic_write_conversion_start",level:4},{value:"GENERIC_WRITE_CONVERSION_END",id:"generic_write_conversion_end",level:4},{value:"OVERFLOW",id:"overflow",level:4},{value:"HIDDEN",id:"hidden",level:4},{value:"UNEDITABLE",id:"uneditable",level:4},{value:"APPEND_PARAMETER",id:"append_parameter",level:3},{value:"SELECT_TABLE",id:"select_table",level:2},{value:"DEFAULT",id:"default",level:2},{value:"Example File",id:"example-file",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"table-definition-files",children:"Table Definition Files"}),"\n",(0,r.jsxs)(n.p,{children:["Table definition files define the binary tables that can be displayed in COSMOS ",(0,r.jsx)(n.a,{href:"/docs/tools/table-manager",children:"Table Manager"}),"\n. Table definitions are defined in the target's tables/config directory and are typically named after the table such as ",(0,r.jsx)(n.code,{children:"PPSSelectionTable_def.txt"}),". The ",(0,r.jsx)(n.code,{children:"_def.txt"})," extension helps to identify the file as a table definition. Table definitions can be combined using the ",(0,r.jsx)(n.code,{children:"TABLEFILE"})," keyword. This allows you to build individual table components into a larger binary."]}),"\n",(0,r.jsxs)(n.p,{children:["The Table definition files share a lot of similarity with the ",(0,r.jsx)(n.a,{href:"/docs/configuration/command",children:"Command Configuration"}),". You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data."]}),"\n",(0,r.jsx)("div",{style:{clear:"both"}}),"\n",(0,r.jsx)(n.h1,{id:"table-keywords",children:"Table Keywords"}),"\n",(0,r.jsx)(n.h2,{id:"tablefile",children:"TABLEFILE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Specify another file to open and process for table definitions"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"File Name"}),(0,r.jsx)(n.td,{children:"Name of the file. The file will be looked for in the directory of the current definition file."}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"table",children:"TABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Start a new table definition"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the table in quotes. The name will appear on the GUI tab."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this table is in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Display"}),(0,r.jsxs)(n.td,{children:["Indicates the table contains KEY_VALUE rows (e.g. each row is unique), or a ROW_COLUMN table with identical rows containing different values.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"KEY_VALUE, ROW_COLUMN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Display is KEY_VALUE the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description of the table in quotes. The description is used in mouseover popups and status line information."}),(0,r.jsx)(n.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"When Display is ROW_COLUMN the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Rows"}),(0,r.jsx)(n.td,{children:"The number of rows in the table"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description of the table in quotes. The description is used in mouseover popups and status line information."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"table-modifiers",children:"TABLE Modifiers"}),"\n",(0,r.jsx)(n.p,{children:"The following keywords must follow a TABLE keyword."}),"\n",(0,r.jsx)(n.h3,{id:"parameter",children:"PARAMETER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a parameter in the current table"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the parameter. Must be unique within the table."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Offset"}),(0,r.jsx)(n.td,{children:"Bit offset into the table of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the table. Always use a bit offset of 0 for derived parameters."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Size"}),(0,r.jsx)(n.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Data Type"}),(0,r.jsxs)(n.td,{children:["Data Type of this parameter",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Minimum Value"}),(0,r.jsx)(n.td,{children:"Minimum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Maximum Value"}),(0,r.jsx)(n.td,{children:"Maximum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,r.jsx)(n.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"parameter-modifiers",children:"PARAMETER Modifiers"}),"\n",(0,r.jsx)(n.p,{children:"The following keywords must follow a PARAMETER keyword."}),"\n",(0,r.jsx)(n.h4,{id:"format_string",children:"FORMAT_STRING"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds printf style formatting"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Format"}),(0,r.jsx)(n.td,{children:"How to format using printf syntax. For example, '0x%0X' will display the value in hex."}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'FORMAT_STRING "0x%0X"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"units",children:"UNITS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Add displayed units"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Full Name"}),(0,r.jsx)(n.td,{children:"Full name of the units type, e.g. Celsius"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Abbreviated"}),(0,r.jsx)(n.td,{children:"Abbreviation for the units, e.g. C"}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"UNITS Celsius C\nUNITS Kilometers KM\n"})}),"\n",(0,r.jsx)(n.h4,{id:"description",children:"DESCRIPTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined description"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new description"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"meta",children:"META"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Stores custom user metadata"})}),"\n",(0,r.jsx)(n.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Meta Name"}),(0,r.jsx)(n.td,{children:"Name of the metadata to store"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Meta Values"}),(0,r.jsx)(n.td,{children:"One or more values to be stored for this Meta Name"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'META TEST "This parameter is for test purposes only"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"overlap",children:"OVERLAP"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,r.jsx)(n.strong,{children:"This item is allowed to overlap other items in the packet"})]}),"\n",(0,r.jsx)(n.p,{children:"If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message."}),"\n",(0,r.jsx)(n.h4,{id:"key",children:"KEY"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,r.jsx)(n.strong,{children:"Defines the key used to access this raw value in the packet."})]}),"\n",(0,r.jsx)(n.p,{children:"Keys are often JsonPath or XPath strings"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Key string"}),(0,r.jsx)(n.td,{children:"The key to access this item"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"KEY $.book.title\n"})}),"\n",(0,r.jsx)(n.h4,{id:"variable_bit_size",children:"VARIABLE_BIT_SIZE"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,r.jsx)(n.strong,{children:"Marks an item as having its bit size defined by another length item"})]}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Item Name"}),(0,r.jsx)(n.td,{children:"The name of the associated length item"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Bits Per Count"}),(0,r.jsx)(n.td,{children:"Bits per count of the length item. Defaults to 8"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Value Bit Offset"}),(0,r.jsx)(n.td,{children:"Offset in Bits to Apply to Length Field Value. Defaults to 0"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h4,{id:"required",children:"REQUIRED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Parameter is required to be populated in scripts"})}),"\n",(0,r.jsx)(n.p,{children:"When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition."}),"\n",(0,r.jsx)(n.h4,{id:"minimum_value",children:"MINIMUM_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined minimum value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new minimum value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"maximum_value",children:"MAXIMUM_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined maximum value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new maximum value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"default_value",children:"DEFAULT_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined default value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new default value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"state",children:"STATE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a key/value pair for the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Key"}),(0,r.jsx)(n.td,{children:"The string state name"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The numerical state value"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Hazardous / Disable Messages"}),(0,r.jsxs)(n.td,{children:["Indicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"HAZARDOUS"})]}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Hazardous Description"}),(0,r.jsx)(n.td,{children:"String describing why this state is hazardous"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting"\n STATE FALSE 0\n STATE TRUE 1\nAPPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter"\n STATE "NOOP" "NOOP" DISABLE_MESSAGES\n STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard"\n STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"write_conversion",children:"WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Applies a conversion when writing the current command parameter"})}),"\n",(0,r.jsxs)(n.p,{children:["Conversions are implemented in a custom Ruby or Python file which should be\nlocated in the target's lib folder. The class must inherit from Conversion.\nIt must implement the ",(0,r.jsx)(n.code,{children:"initialize"})," (Ruby) or ",(0,r.jsx)(n.code,{children:"__init__"})," (Python) method if it\ntakes extra parameters and must always implement the ",(0,r.jsx)(n.code,{children:"call"})," method. The conversion\nfactor is applied to the value entered by the user before it is written into\nthe binary command packet and sent."]}),"\n",(0,r.jsx)(n.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,r.jsx)(n.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Class Filename"}),(0,r.jsx)(n.td,{children:"The filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Parameter"}),(0,r.jsx)(n.td,{children:"Additional parameter values for the conversion which are passed to the class constructor."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"WRITE_CONVERSION the_great_conversion.rb 1000\n\nDefined in the_great_conversion.rb:\n\nrequire 'openc3/conversions/conversion'\nmodule OpenC3\n class TheGreatConversion < Conversion\n def initialize(multiplier)\n super()\n @multiplier = multiplier.to_f\n end\n def call(value, packet, buffer)\n return value * multiplier\n end\n end\nend\n"})}),"\n",(0,r.jsx)(n.p,{children:"Python Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"WRITE_CONVERSION the_great_conversion.py 1000\n\nDefined in the_great_conversion.py:\n\nfrom openc3.conversions.conversion import Conversion\nclass TheGreatConversion(Conversion):\n def __init__(self, multiplier):\n super().__init__()\n self.multiplier = float(multiplier)\n def call(self, value, packet, buffer):\n return value * multiplier\n"})}),"\n",(0,r.jsx)(n.h4,{id:"poly_write_conversion",children:"POLY_WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds a polynomial conversion factor to the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"C0"}),(0,r.jsx)(n.td,{children:"Coefficient"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Cx"}),(0,r.jsx)(n.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"POLY_WRITE_CONVERSION 10 0.5 0.25\n"})}),"\n",(0,r.jsx)(n.h4,{id:"seg_poly_write_conversion",children:"SEG_POLY_WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds a segmented polynomial conversion factor to the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Lower Bound"}),(0,r.jsx)(n.td,{children:"Defines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"C0"}),(0,r.jsx)(n.td,{children:"Coefficient"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Cx"}),(0,r.jsx)(n.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50\nSEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100\nSEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100\n"})}),"\n",(0,r.jsx)(n.h4,{id:"generic_write_conversion_start",children:"GENERIC_WRITE_CONVERSION_START"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Start a generic write conversion"})}),"\n",(0,r.jsx)(n.p,{children:"Adds a generic conversion function to the current command parameter.\nThis conversion factor is applied to the value entered by the user before it\nis written into the binary command packet and sent. The conversion is specified\nas Ruby or Python code that receives two implied parameters. 'value' which is the raw\nvalue being written and 'packet' which is a reference to the command packet\nclass (Note, referencing the packet as 'myself' is still supported for backwards\ncompatibility). The last line of code should return the converted\nvalue. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of\ncode for the conversion have been given."}),"\n",(0,r.jsx)(n.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,r.jsx)(n.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,r.jsx)(n.admonition,{type:"warning",children:(0,r.jsx)(n.p,{children:"Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance."})}),"\n",(0,r.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return (value * 1.5).to_i # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,r.jsx)(n.p,{children:"Python Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return int(value * 1.5) # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,r.jsx)(n.h4,{id:"generic_write_conversion_end",children:"GENERIC_WRITE_CONVERSION_END"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Complete a generic write conversion"})}),"\n",(0,r.jsx)(n.h4,{id:"overflow",children:"OVERFLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Set the behavior when writing a value overflows the type"})}),"\n",(0,r.jsx)(n.p,{children:"By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Behavior"}),(0,r.jsxs)(n.td,{children:["How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE"})]}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"OVERFLOW TRUNCATE\n"})}),"\n",(0,r.jsx)(n.h4,{id:"hidden",children:"HIDDEN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Indicates that the parameter should not be shown to the user in the Table Manager GUI"})}),"\n",(0,r.jsx)(n.p,{children:"Hidden parameters still exist and will be saved to the resulting binary. This is useful for padding and other essential but non-user editable fields."}),"\n",(0,r.jsx)(n.h4,{id:"uneditable",children:"UNEDITABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Indicates that the parameter should be shown to the user but not editable."})}),"\n",(0,r.jsx)(n.p,{children:"Uneditable parameters are useful for control fields which the user may be interested in but should not be able to edit."}),"\n",(0,r.jsx)(n.h3,{id:"append_parameter",children:"APPEND_PARAMETER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a parameter in the current table"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the parameter. Must be unique within the table."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Size"}),(0,r.jsx)(n.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Data Type"}),(0,r.jsxs)(n.td,{children:["Data Type of this parameter",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Minimum Value"}),(0,r.jsx)(n.td,{children:"Minimum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Maximum Value"}),(0,r.jsx)(n.td,{children:"Maximum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,r.jsx)(n.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"select_table",children:"SELECT_TABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Select an existing table for editing, typically done to override an existing definition"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Table"}),(0,r.jsx)(n.td,{children:"The name of the existing table"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"default",children:"DEFAULT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Specify default values for a SINGLE row in a multi-column table"})}),"\n",(0,r.jsx)(n.p,{children:"If you have multiple rows you need a DEFAULT line for each row. If all your rows are identical consider using ERB as shown in the OpenC3 demo."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default values"}),(0,r.jsx)(n.td,{children:"A STATE value or data value corresponding to the data type"}),(0,r.jsx)(n.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"example-file",children:"Example File"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Example File: TARGET/tables/config/MCConfigurationTable_def.txt"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'TABLE "MC_Configuration" BIG_ENDIAN KEY_VALUE "Memory Control Configuration Table"\n APPEND_PARAMETER "Scrub_Region_1_Start_Addr" 32 UINT 0 0x03FFFFFB 0\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_1_End_Addr" 32 UINT 0 0x03FFFFFF 0x03FFFFFF\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_2_Start_Addr" 32 UINT 0 0x03FFFFB 0\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_2_End_Addr" 32 UINT 0 0x03FFFFF 0x03FFFFF\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Dump_Packet_Throttle_(sec)" 32 UINT 0 0x0FFFFFFFF 2 "Number of seconds to wait between dumping large packets"\n APPEND_PARAMETER "Memory_Scrubbing" 8 UINT 0 1 1\n STATE DISABLE 0\n STATE ENABLE 1\n APPEND_PARAMETER "SIOC_Memory_Config" 8 UINT 1 3 3\n APPEND_PARAMETER "Uneditable_Text" 32 UINT MIN MAX 0xDEADBEEF "Uneditable field"\n FORMAT_STRING "0x%0X"\n UNEDITABLE\n APPEND_PARAMETER "Uneditable_State" 16 UINT MIN MAX 0 "Uneditable field"\n STATE DISABLE 0\n STATE ENABLE 1\n UNEDITABLE\n APPEND_PARAMETER "Uneditable_Check" 16 UINT MIN MAX 1 "Uneditable field"\n STATE UNCHECKED 0\n STATE CHECKED 1\n UNEDITABLE\n APPEND_PARAMETER "Binary" 32 STRING 0xDEADBEEF "Binary string"\n APPEND_PARAMETER "Pad" 16 UINT 0 0 0\n HIDDEN\n'})})]})}function o(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>d});var r=i(6540);const t={},s=r.createContext(t);function l(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/5fe211ef.c27ff303.js b/docs/assets/js/5fe211ef.c27ff303.js
deleted file mode 100644
index ab2b2f15b2..0000000000
--- a/docs/assets/js/5fe211ef.c27ff303.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[864],{472:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>o,frontMatter:()=>s,metadata:()=>d,toc:()=>h});var r=i(4848),t=i(8453);const s={sidebar_position:8,title:"Tables"},l=void 0,d={id:"configuration/table",title:"Tables",description:"Table Definition Files",source:"@site/docs/configuration/table.md",sourceDirName:"configuration",slug:"/configuration/table",permalink:"/docs/configuration/table",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/table.md",tags:[],version:"current",sidebarPosition:8,frontMatter:{sidebar_position:8,title:"Tables"},sidebar:"defaultSidebar",previous:{title:"Protocols",permalink:"/docs/configuration/protocols"},next:{title:"Screens",permalink:"/docs/configuration/telemetry-screens"}},a={},h=[{value:"Table Definition Files",id:"table-definition-files",level:2},{value:"TABLEFILE",id:"tablefile",level:2},{value:"TABLE",id:"table",level:2},{value:"TABLE Modifiers",id:"table-modifiers",level:2},{value:"PARAMETER",id:"parameter",level:3},{value:"PARAMETER Modifiers",id:"parameter-modifiers",level:3},{value:"FORMAT_STRING",id:"format_string",level:4},{value:"UNITS",id:"units",level:4},{value:"DESCRIPTION",id:"description",level:4},{value:"META",id:"meta",level:4},{value:"OVERLAP",id:"overlap",level:4},{value:"KEY",id:"key",level:4},{value:"VARIABLE_BIT_SIZE",id:"variable_bit_size",level:4},{value:"REQUIRED",id:"required",level:4},{value:"MINIMUM_VALUE",id:"minimum_value",level:4},{value:"MAXIMUM_VALUE",id:"maximum_value",level:4},{value:"DEFAULT_VALUE",id:"default_value",level:4},{value:"STATE",id:"state",level:4},{value:"WRITE_CONVERSION",id:"write_conversion",level:4},{value:"POLY_WRITE_CONVERSION",id:"poly_write_conversion",level:4},{value:"SEG_POLY_WRITE_CONVERSION",id:"seg_poly_write_conversion",level:4},{value:"GENERIC_WRITE_CONVERSION_START",id:"generic_write_conversion_start",level:4},{value:"GENERIC_WRITE_CONVERSION_END",id:"generic_write_conversion_end",level:4},{value:"OVERFLOW",id:"overflow",level:4},{value:"HIDDEN",id:"hidden",level:4},{value:"UNEDITABLE",id:"uneditable",level:4},{value:"APPEND_PARAMETER",id:"append_parameter",level:3},{value:"SELECT_TABLE",id:"select_table",level:2},{value:"DEFAULT",id:"default",level:2},{value:"Example File",id:"example-file",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"table-definition-files",children:"Table Definition Files"}),"\n",(0,r.jsxs)(n.p,{children:["Table definition files define the binary tables that can be displayed in COSMOS ",(0,r.jsx)(n.a,{href:"/docs/tools/table-manager",children:"Table Manager"}),"\n. Table definitions are defined in the target's tables/config directory and are typically named after the table such as ",(0,r.jsx)(n.code,{children:"PPSSelectionTable_def.txt"}),". The ",(0,r.jsx)(n.code,{children:"_def.txt"})," extention helps to identify the file as a table definition. Table definitions can be combined using the ",(0,r.jsx)(n.code,{children:"TABLEFILE"})," keyword. This allows you to build individual table components into a larger binary."]}),"\n",(0,r.jsxs)(n.p,{children:["The Table definition files share a lot of similarity with the ",(0,r.jsx)(n.a,{href:"/docs/configuration/command",children:"Command Configuration"}),". You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data."]}),"\n",(0,r.jsx)("div",{style:{clear:"both"}}),"\n",(0,r.jsx)(n.h1,{id:"table-keywords",children:"Table Keywords"}),"\n",(0,r.jsx)(n.h2,{id:"tablefile",children:"TABLEFILE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Specify another file to open and process for table definitions"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"File Name"}),(0,r.jsx)(n.td,{children:"Name of the file. The file will be looked for in the directory of the current definition file."}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"table",children:"TABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Start a new table definition"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the table in quotes. The name will appear on the GUI tab."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this table is in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Display"}),(0,r.jsxs)(n.td,{children:["Indicates the table contains KEY_VALUE rows (e.g. each row is unique), or a ROW_COLUMN table with identical rows containing different values.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"KEY_VALUE, ROW_COLUMN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Display is KEY_VALUE the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description of the table in quotes. The description is used in mouseover popups and status line information."}),(0,r.jsx)(n.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"When Display is ROW_COLUMN the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Rows"}),(0,r.jsx)(n.td,{children:"The number of rows in the table"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description of the table in quotes. The description is used in mouseover popups and status line information."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"table-modifiers",children:"TABLE Modifiers"}),"\n",(0,r.jsx)(n.p,{children:"The following keywords must follow a TABLE keyword."}),"\n",(0,r.jsx)(n.h3,{id:"parameter",children:"PARAMETER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a parameter in the current table"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the parameter. Must be unique within the table."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Offset"}),(0,r.jsx)(n.td,{children:"Bit offset into the table of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the table. Always use a bit offset of 0 for derived parameters."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Size"}),(0,r.jsx)(n.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Data Type"}),(0,r.jsxs)(n.td,{children:["Data Type of this parameter",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Minimum Value"}),(0,r.jsx)(n.td,{children:"Minimum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Maximum Value"}),(0,r.jsx)(n.td,{children:"Maximum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,r.jsx)(n.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"parameter-modifiers",children:"PARAMETER Modifiers"}),"\n",(0,r.jsx)(n.p,{children:"The following keywords must follow a PARAMETER keyword."}),"\n",(0,r.jsx)(n.h4,{id:"format_string",children:"FORMAT_STRING"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds printf style formatting"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Format"}),(0,r.jsx)(n.td,{children:"How to format using printf syntax. For example, '0x%0X' will display the value in hex."}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'FORMAT_STRING "0x%0X"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"units",children:"UNITS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Add displayed units"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Full Name"}),(0,r.jsx)(n.td,{children:"Full name of the units type, e.g. Celsius"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Abbreviated"}),(0,r.jsx)(n.td,{children:"Abbreviation for the units, e.g. C"}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"UNITS Celsius C\nUNITS Kilometers KM\n"})}),"\n",(0,r.jsx)(n.h4,{id:"description",children:"DESCRIPTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined description"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new description"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"meta",children:"META"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Stores custom user metadata"})}),"\n",(0,r.jsx)(n.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Meta Name"}),(0,r.jsx)(n.td,{children:"Name of the metadata to store"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Meta Values"}),(0,r.jsx)(n.td,{children:"One or more values to be stored for this Meta Name"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'META TEST "This parameter is for test purposes only"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"overlap",children:"OVERLAP"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,r.jsx)(n.strong,{children:"This item is allowed to overlap other items in the packet"})]}),"\n",(0,r.jsx)(n.p,{children:"If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message."}),"\n",(0,r.jsx)(n.h4,{id:"key",children:"KEY"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,r.jsx)(n.strong,{children:"Defines the key used to access this raw value in the packet."})]}),"\n",(0,r.jsx)(n.p,{children:"Keys are often JsonPath or XPath strings"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Key string"}),(0,r.jsx)(n.td,{children:"The key to access this item"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"KEY $.book.title\n"})}),"\n",(0,r.jsx)(n.h4,{id:"variable_bit_size",children:"VARIABLE_BIT_SIZE"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,r.jsx)(n.strong,{children:"Marks an item as having its bit size defined by another length item"})]}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Item Name"}),(0,r.jsx)(n.td,{children:"The name of the associated length item"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Bits Per Count"}),(0,r.jsx)(n.td,{children:"Bits per count of the length item. Defaults to 8"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Length Value Bit Offset"}),(0,r.jsx)(n.td,{children:"Offset in Bits to Apply to Length Field Value. Defaults to 0"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h4,{id:"required",children:"REQUIRED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Parameter is required to be populated in scripts"})}),"\n",(0,r.jsx)(n.p,{children:"When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition."}),"\n",(0,r.jsx)(n.h4,{id:"minimum_value",children:"MINIMUM_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined minimum value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new minimum value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"maximum_value",children:"MAXIMUM_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined maximum value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new maximum value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"default_value",children:"DEFAULT_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Override the defined default value"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The new default value for the parameter"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h4,{id:"state",children:"STATE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a key/value pair for the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Key"}),(0,r.jsx)(n.td,{children:"The string state name"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Value"}),(0,r.jsx)(n.td,{children:"The numerical state value"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Hazardous / Disable Messages"}),(0,r.jsxs)(n.td,{children:["Indicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"HAZARDOUS"})]}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Hazardous Description"}),(0,r.jsx)(n.td,{children:"String describing why this state is hazardous"}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting"\n STATE FALSE 0\n STATE TRUE 1\nAPPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter"\n STATE "NOOP" "NOOP" DISABLE_MESSAGES\n STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard"\n STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!"\n'})}),"\n",(0,r.jsx)(n.h4,{id:"write_conversion",children:"WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Applies a conversion when writing the current command parameter"})}),"\n",(0,r.jsxs)(n.p,{children:["Conversions are implemented in a custom Ruby or Python file which should be\nlocated in the target's lib folder. The class must inherit from Conversion.\nIt must implement the ",(0,r.jsx)(n.code,{children:"initialize"})," (Ruby) or ",(0,r.jsx)(n.code,{children:"__init__"})," (Python) method if it\ntakes extra parameters and must always implement the ",(0,r.jsx)(n.code,{children:"call"})," method. The conversion\nfactor is applied to the value entered by the user before it is written into\nthe binary command packet and sent."]}),"\n",(0,r.jsx)(n.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,r.jsx)(n.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Class Filename"}),(0,r.jsx)(n.td,{children:"The filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Parameter"}),(0,r.jsx)(n.td,{children:"Additional parameter values for the conversion which are passed to the class constructor."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"WRITE_CONVERSION the_great_conversion.rb 1000\n\nDefined in the_great_conversion.rb:\n\nrequire 'openc3/conversions/conversion'\nmodule OpenC3\n class TheGreatConversion < Conversion\n def initialize(multiplier)\n super()\n @multiplier = multiplier.to_f\n end\n def call(value, packet, buffer)\n return value * multiplier\n end\n end\nend\n"})}),"\n",(0,r.jsx)(n.p,{children:"Python Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"WRITE_CONVERSION the_great_conversion.py 1000\n\nDefined in the_great_conversion.py:\n\nfrom openc3.conversions.conversion import Conversion\nclass TheGreatConversion(Conversion):\n def __init__(self, multiplier):\n super().__init__()\n self.multiplier = float(multiplier)\n def call(self, value, packet, buffer):\n return value * multiplier\n"})}),"\n",(0,r.jsx)(n.h4,{id:"poly_write_conversion",children:"POLY_WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds a polynomial conversion factor to the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"C0"}),(0,r.jsx)(n.td,{children:"Coefficient"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Cx"}),(0,r.jsx)(n.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"POLY_WRITE_CONVERSION 10 0.5 0.25\n"})}),"\n",(0,r.jsx)(n.h4,{id:"seg_poly_write_conversion",children:"SEG_POLY_WRITE_CONVERSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Adds a segmented polynomial conversion factor to the current command parameter"})}),"\n",(0,r.jsx)(n.p,{children:"This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Lower Bound"}),(0,r.jsx)(n.td,{children:"Defines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"C0"}),(0,r.jsx)(n.td,{children:"Coefficient"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Cx"}),(0,r.jsx)(n.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50\nSEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100\nSEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100\n"})}),"\n",(0,r.jsx)(n.h4,{id:"generic_write_conversion_start",children:"GENERIC_WRITE_CONVERSION_START"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Start a generic write conversion"})}),"\n",(0,r.jsx)(n.p,{children:"Adds a generic conversion function to the current command parameter.\nThis conversion factor is applied to the value entered by the user before it\nis written into the binary command packet and sent. The conversion is specified\nas Ruby or Python code that receives two implied parameters. 'value' which is the raw\nvalue being written and 'packet' which is a reference to the command packet\nclass (Note, referencing the packet as 'myself' is still supported for backwards\ncompatibility). The last line of code should return the converted\nvalue. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of\ncode for the conversion have been given."}),"\n",(0,r.jsx)(n.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,r.jsx)(n.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,r.jsx)(n.admonition,{type:"warning",children:(0,r.jsx)(n.p,{children:"Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance."})}),"\n",(0,r.jsx)(n.p,{children:"Ruby Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return (value * 1.5).to_i # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,r.jsx)(n.p,{children:"Python Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return int(value * 1.5) # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,r.jsx)(n.h4,{id:"generic_write_conversion_end",children:"GENERIC_WRITE_CONVERSION_END"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Complete a generic write conversion"})}),"\n",(0,r.jsx)(n.h4,{id:"overflow",children:"OVERFLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Set the behavior when writing a value overflows the type"})}),"\n",(0,r.jsx)(n.p,{children:"By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Behavior"}),(0,r.jsxs)(n.td,{children:["How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE"})]}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:"OVERFLOW TRUNCATE\n"})}),"\n",(0,r.jsx)(n.h4,{id:"hidden",children:"HIDDEN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Indicates that the parameter should not be shown to the user in the Table Manager GUI"})}),"\n",(0,r.jsx)(n.p,{children:"Hidden parameters still exist and will be saved to the resulting binary. This is useful for padding and other essential but non-user editable fields."}),"\n",(0,r.jsx)(n.h4,{id:"uneditable",children:"UNEDITABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Indicates that the parameter should be shown to the user but not editable."})}),"\n",(0,r.jsx)(n.p,{children:"Uneditable parameters are useful for control fields which the user may be interested in but should not be able to edit."}),"\n",(0,r.jsx)(n.h3,{id:"append_parameter",children:"APPEND_PARAMETER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Defines a parameter in the current table"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Name"}),(0,r.jsx)(n.td,{children:"Name of the parameter. Must be unique within the table."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Bit Size"}),(0,r.jsx)(n.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Data Type"}),(0,r.jsxs)(n.td,{children:["Data Type of this parameter",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,r.jsx)(n.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Minimum Value"}),(0,r.jsx)(n.td,{children:"Minimum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Maximum Value"}),(0,r.jsx)(n.td,{children:"Maximum allowed value for this parameter"}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,r.jsx)(n.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default Value"}),(0,r.jsx)(n.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,r.jsx)(n.td,{children:"True"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Description"}),(0,r.jsx)(n.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,r.jsx)(n.td,{children:"False"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Endianness"}),(0,r.jsxs)(n.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,r.jsx)(n.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"select_table",children:"SELECT_TABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Select an existing table for editing, typically done to override an existing definition"})}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Table"}),(0,r.jsx)(n.td,{children:"The name of the existin table"}),(0,r.jsx)(n.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"default",children:"DEFAULT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Specify default values for a SINGLE row in a multi-column table"})}),"\n",(0,r.jsx)(n.p,{children:"If you have multiple rows you need a DEFAULT line for each row. If all your rows are identical consider using ERB as shown in the OpenC3 demo."}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Parameter"}),(0,r.jsx)(n.th,{children:"Description"}),(0,r.jsx)(n.th,{children:"Required"})]})}),(0,r.jsx)(n.tbody,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Default values"}),(0,r.jsx)(n.td,{children:"A STATE value or data value corresponding to the data type"}),(0,r.jsx)(n.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(n.h2,{id:"example-file",children:"Example File"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Example File: TARGET/tables/config/MCConfigurationTable_def.txt"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ruby",children:'TABLE "MC_Configuration" BIG_ENDIAN KEY_VALUE "Memory Control Configuration Table"\n APPEND_PARAMETER "Scrub_Region_1_Start_Addr" 32 UINT 0 0x03FFFFFB 0\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_1_End_Addr" 32 UINT 0 0x03FFFFFF 0x03FFFFFF\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_2_Start_Addr" 32 UINT 0 0x03FFFFB 0\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Scrub_Region_2_End_Addr" 32 UINT 0 0x03FFFFF 0x03FFFFF\n FORMAT_STRING "0x%0X"\n APPEND_PARAMETER "Dump_Packet_Throttle_(sec)" 32 UINT 0 0x0FFFFFFFF 2 "Number of seconds to wait between dumping large packets"\n APPEND_PARAMETER "Memory_Scrubbing" 8 UINT 0 1 1\n STATE DISABLE 0\n STATE ENABLE 1\n APPEND_PARAMETER "SIOC_Memory_Config" 8 UINT 1 3 3\n APPEND_PARAMETER "Uneditable_Text" 32 UINT MIN MAX 0xDEADBEEF "Uneditable field"\n FORMAT_STRING "0x%0X"\n UNEDITABLE\n APPEND_PARAMETER "Uneditable_State" 16 UINT MIN MAX 0 "Uneditable field"\n STATE DISABLE 0\n STATE ENABLE 1\n UNEDITABLE\n APPEND_PARAMETER "Uneditable_Check" 16 UINT MIN MAX 1 "Uneditable field"\n STATE UNCHECKED 0\n STATE CHECKED 1\n UNEDITABLE\n APPEND_PARAMETER "Binary" 32 STRING 0xDEADBEEF "Binary string"\n APPEND_PARAMETER "Pad" 16 UINT 0 0 0\n HIDDEN\n'})})]})}function o(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>d});var r=i(6540);const t={},s=r.createContext(t);function l(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/6831b732.fcd3d5cf.js b/docs/assets/js/6831b732.f6016e52.js
similarity index 96%
rename from docs/assets/js/6831b732.fcd3d5cf.js
rename to docs/assets/js/6831b732.f6016e52.js
index df1d7f015f..d0618954e1 100644
--- a/docs/assets/js/6831b732.fcd3d5cf.js
+++ b/docs/assets/js/6831b732.f6016e52.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[9527],{2124:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>o,frontMatter:()=>t,metadata:()=>d,toc:()=>h});var i=n(4848),s=n(8453);const t={sidebar_position:2,title:"Plugins"},l=void 0,d={id:"configuration/plugins",title:"Plugins",description:"Introduction",source:"@site/docs/configuration/plugins.md",sourceDirName:"configuration",slug:"/configuration/plugins",permalink:"/docs/configuration/plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/plugins.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Plugins"},sidebar:"defaultSidebar",previous:{title:"File Format",permalink:"/docs/configuration/format"},next:{title:"Targets",permalink:"/docs/configuration/target"}},c={},h=[{value:"Introduction",id:"introduction",level:2},{value:"Concepts",id:"concepts",level:2},{value:"Target",id:"target",level:3},{value:"Interface",id:"interface",level:3},{value:"Router",id:"router",level:3},{value:"Tool",id:"tool",level:3},{value:"Microservice",id:"microservice",level:3},{value:"Plugin Directory Structure",id:"plugin-directory-structure",level:2},{value:"plugin.txt Configuration File",id:"plugintxt-configuration-file",level:2},{value:"VARIABLE",id:"variable",level:2},{value:"NEEDS_DEPENDENCIES",id:"needs_dependencies",level:2},{value:"INTERFACE",id:"interface-1",level:2},{value:"INTERFACE Modifiers",id:"interface-modifiers",level:2},{value:"MAP_TARGET",id:"map_target",level:3},{value:"MAP_CMD_TARGET",id:"map_cmd_target",level:3},{value:"MAP_TLM_TARGET",id:"map_tlm_target",level:3},{value:"DONT_CONNECT",id:"dont_connect",level:3},{value:"DONT_RECONNECT",id:"dont_reconnect",level:3},{value:"RECONNECT_DELAY",id:"reconnect_delay",level:3},{value:"DISABLE_DISCONNECT",id:"disable_disconnect",level:3},{value:"LOG_RAW",id:"log_raw",level:3},{value:"LOG_STREAM",id:"log_stream",level:3},{value:"PROTOCOL",id:"protocol",level:3},{value:"OPTION",id:"option",level:3},{value:"SECRET",id:"secret",level:3},{value:"ENV",id:"env",level:3},{value:"WORK_DIR",id:"work_dir",level:3},{value:"PORT",id:"port",level:3},{value:"CMD",id:"cmd",level:3},{value:"CONTAINER",id:"container",level:3},{value:"ROUTE_PREFIX",id:"route_prefix",level:3},{value:"ROUTER",id:"router-1",level:2},{value:"TARGET",id:"target-1",level:2},{value:"TARGET Modifiers",id:"target-modifiers",level:2},{value:"CMD_BUFFER_DEPTH",id:"cmd_buffer_depth",level:3},{value:"CMD_LOG_CYCLE_TIME",id:"cmd_log_cycle_time",level:3},{value:"CMD_LOG_CYCLE_SIZE",id:"cmd_log_cycle_size",level:3},{value:"CMD_LOG_RETAIN_TIME",id:"cmd_log_retain_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_TIME",id:"cmd_decom_log_cycle_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_SIZE",id:"cmd_decom_log_cycle_size",level:3},{value:"CMD_DECOM_LOG_RETAIN_TIME",id:"cmd_decom_log_retain_time",level:3},{value:"TLM_BUFFER_DEPTH",id:"tlm_buffer_depth",level:3},{value:"TLM_LOG_CYCLE_TIME",id:"tlm_log_cycle_time",level:3},{value:"TLM_LOG_CYCLE_SIZE",id:"tlm_log_cycle_size",level:3},{value:"TLM_LOG_RETAIN_TIME",id:"tlm_log_retain_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_TIME",id:"tlm_decom_log_cycle_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_SIZE",id:"tlm_decom_log_cycle_size",level:3},{value:"TLM_DECOM_LOG_RETAIN_TIME",id:"tlm_decom_log_retain_time",level:3},{value:"REDUCED_MINUTE_LOG_RETAIN_TIME",id:"reduced_minute_log_retain_time",level:3},{value:"REDUCED_HOUR_LOG_RETAIN_TIME",id:"reduced_hour_log_retain_time",level:3},{value:"REDUCED_DAY_LOG_RETAIN_TIME",id:"reduced_day_log_retain_time",level:3},{value:"LOG_RETAIN_TIME",id:"log_retain_time",level:3},{value:"REDUCED_LOG_RETAIN_TIME",id:"reduced_log_retain_time",level:3},{value:"CLEANUP_POLL_TIME",id:"cleanup_poll_time",level:3},{value:"REDUCER_DISABLE",id:"reducer_disable",level:3},{value:"REDUCER_MAX_CPU_UTILIZATION",id:"reducer_max_cpu_utilization",level:3},{value:"TARGET_MICROSERVICE",id:"target_microservice",level:3},{value:"PACKET",id:"packet",level:3},{value:"DISABLE_ERB",id:"disable_erb",level:3},{value:"MICROSERVICE",id:"microservice-1",level:2},{value:"MICROSERVICE Modifiers",id:"microservice-modifiers",level:2},{value:"ENV",id:"env-1",level:3},{value:"WORK_DIR",id:"work_dir-1",level:3},{value:"PORT",id:"port-1",level:3},{value:"TOPIC",id:"topic",level:3},{value:"TARGET_NAME",id:"target_name",level:3},{value:"CMD",id:"cmd-1",level:3},{value:"OPTION",id:"option-1",level:3},{value:"CONTAINER",id:"container-1",level:3},{value:"SECRET",id:"secret-1",level:3},{value:"ROUTE_PREFIX",id:"route_prefix-1",level:3},{value:"DISABLE_ERB",id:"disable_erb-1",level:3},{value:"TOOL",id:"tool-1",level:2},{value:"TOOL Modifiers",id:"tool-modifiers",level:2},{value:"URL",id:"url",level:3},{value:"INLINE_URL",id:"inline_url",level:3},{value:"WINDOW",id:"window",level:3},{value:"ICON",id:"icon",level:3},{value:"CATEGORY",id:"category",level:3},{value:"SHOWN",id:"shown",level:3},{value:"POSITION",id:"position",level:3},{value:"DISABLE_ERB",id:"disable_erb-2",level:3},{value:"WIDGET",id:"widget",level:2},{value:"WIDGET Modifiers",id:"widget-modifiers",level:2},{value:"DISABLE_ERB",id:"disable_erb-3",level:3}];function a(e){const r={a:"a",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(r.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(r.p,{children:"This document provides the information necessary to configure a COSMOS plugin. Plugins are how you configure and extend COSMOS."}),"\n",(0,i.jsx)(r.p,{children:"Plugins are where you define targets (and their corresponding command and telemetry packet definitions), where you configure the interfaces needed to talk to targets, where you can define routers to stream raw data out of COSMOS, how you can add new tools to the COSMOS user interface, and how you can run additional microservices to provide new functionality."}),"\n",(0,i.jsx)(r.p,{children:"Each plugin is built as a Ruby gem and thus has a plugin.gemspec file which builds it. Plugins have a plugin.txt file which declares all the variables used by the plugin and how to interface to the target(s) it contains."}),"\n",(0,i.jsx)(r.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(r.h3,{id:"target",children:"Target"}),"\n",(0,i.jsx)(r.p,{children:"Targets are the external pieces of hardware and/or software that COSMOS communicates with. These are things like Front End Processors (FEPs), ground support equipment (GSE), custom software tools, and pieces of hardware like satellites themselves. A target is anything that COSMOS can send commands to and receive telemetry from."}),"\n",(0,i.jsx)(r.h3,{id:"interface",children:"Interface"}),"\n",(0,i.jsx)(r.p,{children:"Interfaces implement the physical connection to one or more targets. They are typically ethernet connections implemented using TCP or UDP but can be other connections like serial ports. Interfaces send commands to targets and receive telemetry from targets."}),"\n",(0,i.jsx)(r.h3,{id:"router",children:"Router"}),"\n",(0,i.jsx)(r.p,{children:"Routers flow streams of telemetry packets out of COSMOS and receive streams of commands into COSMOS. The commands are forwarded by COSMOS to associated interfaces. Telemetry comes from associated interfaces."}),"\n",(0,i.jsx)(r.h3,{id:"tool",children:"Tool"}),"\n",(0,i.jsx)(r.p,{children:"COSMOS Tools are web-based applications the communicate with the COSMOS APIs to perform takes like displaying telemetry, sending commands, and running scripts."}),"\n",(0,i.jsx)(r.h3,{id:"microservice",children:"Microservice"}),"\n",(0,i.jsx)(r.p,{children:"Microservices are persistent running backend code that runs within the COSMOS environment. They can process data and perform other useful tasks."}),"\n",(0,i.jsx)(r.h2,{id:"plugin-directory-structure",children:"Plugin Directory Structure"}),"\n",(0,i.jsxs)(r.p,{children:["COSMOS plugins have a well-defined directory structure described in detail in the ",(0,i.jsx)(r.a,{href:"../getting-started/generators",children:"Code Generator"})," documentation."]}),"\n",(0,i.jsx)(r.h2,{id:"plugintxt-configuration-file",children:"plugin.txt Configuration File"}),"\n",(0,i.jsx)(r.p,{children:"A plugin.txt configuration file is required for any COSMOS plugin. It declares the contents of the plugin and provides variables that allow the plugin to be configured at the time it is initially installed or upgraded.\nThis file follows the standard COSMOS configuration file format of keywords followed by zero or more space separated parameters. The following keywords are supported by the plugin.txt config file:"}),"\n",(0,i.jsx)(r.h2,{id:"variable",children:"VARIABLE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a configurable variable for the plugin"})}),"\n",(0,i.jsx)(r.p,{children:"The VARIABLE keyword defines a variable that will be requested for the user to enter during plugin installation. Variables can be used to handle details of targets that are user defined such as specific IP addresses and ports. Variables should also be used to allow users to rename targets to whatever name they want and support multiple installations of the same target with different names. Variables can be used later in plugin.txt or in any other configuration file included in a plugin using Ruby ERB syntax. The variables are assigned to accessible local variables in the file. At a high level, ERB allows you to run Ruby code in configuration files."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Variable Name"}),(0,i.jsx)(r.td,{children:"The name of the variable"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Default Value"}),(0,i.jsx)(r.td,{children:"Default value of the variable"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.h2,{id:"needs_dependencies",children:"NEEDS_DEPENDENCIES"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,i.jsx)(r.strong,{children:"Indicates the plugin needs dependencies and sets the GEM_HOME environment variable"})]}),"\n",(0,i.jsx)(r.p,{children:"If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kuberentes pod."}),"\n",(0,i.jsx)(r.h2,{id:"interface-1",children:"INTERFACE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a connection to a physical target"})}),"\n",(0,i.jsx)(r.p,{children:"Interfaces are what OpenC3 uses to talk to a particular piece of hardware. Interfaces require a Ruby or Python file which implements all the interface methods necessary to talk to the hardware. OpenC3 defines many built in interfaces or you can define your own as long as it implements the interface protocol."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Interface Name"}),(0,i.jsx)(r.td,{children:"Name of the interface. This name will appear in the Interfaces tab of the Server and is also referenced by other keywords. The OpenC3 convention is to name interfaces after their targets with '_INT' appended to the name, e.g. INST_INT for the INST target."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Filename"}),(0,i.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,i.jsx)(r.a,{href:"/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,i.jsx)(r.h2,{id:"interface-modifiers",children:"INTERFACE Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a INTERFACE keyword."}),"\n",(0,i.jsx)(r.h3,{id:"map_target",children:"MAP_TARGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Maps a target name to an interface"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,i.jsx)(r.h3,{id:"map_cmd_target",children:"MAP_CMD_TARGET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Maps a target name to an interface for commands only"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Command target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE CMD_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE CMD_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,i.jsx)(r.h3,{id:"map_tlm_target",children:"MAP_TLM_TARGET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Maps a target name to an interface for telemetry only"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Telemetry target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE TLM_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE TLM_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,i.jsx)(r.h3,{id:"dont_connect",children:"DONT_CONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Server will not automatically try to connect to the interface at startup"})}),"\n",(0,i.jsx)(r.h3,{id:"dont_reconnect",children:"DONT_RECONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Server will not try to reconnect to the interface if the connection is lost"})}),"\n",(0,i.jsx)(r.h3,{id:"reconnect_delay",children:"RECONNECT_DELAY"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Reconnect delay in seconds"})}),"\n",(0,i.jsx)(r.p,{children:"If DONT_RECONNECT is not present the Server will try to reconnect to an interface if the connection is lost. Reconnect delay sets the interval in seconds between reconnect tries."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Delay"}),(0,i.jsx)(r.td,{children:"Delay in seconds between reconnect attempts. The default is 15 seconds."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_disconnect",children:"DISABLE_DISCONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Disable the Disconnect button on the Interfaces tab in the Server"})}),"\n",(0,i.jsx)(r.p,{children:"Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertantly disconnect from a target."}),"\n",(0,i.jsx)(r.h3,{id:"log_raw",children:"LOG_RAW"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Deprecated, use LOG_STREAM"})}),"\n",(0,i.jsx)(r.h3,{id:"log_stream",children:"LOG_STREAM"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.2)"}),(0,i.jsx)(r.strong,{children:"Log all data on the interface exactly as it is sent and received"})]}),"\n",(0,i.jsx)(r.p,{children:"LOG_STREAM does not add any OpenC3 headers and thus can not be read by OpenC3 tools. It is primarily useful for low level debugging of an interface. You will have to manually parse these logs yourself using a hex editor or other application."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Time"}),(0,i.jsx)(r.td,{children:"Amount of time to wait before cycling the log file. Default is 10 min. If nil refer to Cycle Hour and Cycle Minute."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Size"}),(0,i.jsx)(r.td,{children:"Amount of data to write before cycling the log file. Default is 50MB."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Hour"}),(0,i.jsx)(r.td,{children:"The time at which to cycle the log. Combined with Cycle Minute to cycle the log daily at the specified time. If nil, the log will be cycled hourly at the specified Cycle Minute. Only applies if Cycle Time is nil."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Minute"}),(0,i.jsx)(r.td,{children:"See Cycle Hour."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE EXAMPLE example_interface.rb\n # Override the default log time of 600\n LOG_STREAM 60\n"})}),"\n",(0,i.jsx)(r.h3,{id:"protocol",children:"PROTOCOL"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 4.0.0)"}),(0,i.jsx)(r.strong,{children:"Protocols modify the interface by processing the data"})]}),"\n",(0,i.jsxs)(r.p,{children:["Protocols can be either READ, WRITE, or READ_WRITE. READ protocols act on the data received by the interface while write acts on the data before it is sent out. READ_WRITE applies the protocol to both reading and writing.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{})," For information on creating your own custom protocol please see ",(0,i.jsx)(r.a,{href:"/docs/configuration/protocols",children:"Protocols"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsxs)(r.td,{children:["Whether to apply the protocol on incoming data, outgoing data, or both",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"READ, WRITE, READ_WRITE"})]}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol Filename or Classname"}),(0,i.jsx)(r.td,{children:"Ruby or Python filename or class name which implements the protocol"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol specific parameters"}),(0,i.jsx)(r.td,{children:"Additional parameters used by the protocol"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil nil\n MAP_TARGET DATA\n # Rather than defining the LENGTH protocol on the INTERFACE line we define it here\n PROTOCOL READ LengthProtocol 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n PROTOCOL READ IgnorePacketProtocol INST IMAGE # Drop all INST IMAGE packets\n"})}),"\n",(0,i.jsx)(r.h3,{id:"option",children:"OPTION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set a parameter on an interface"})}),"\n",(0,i.jsx)(r.p,{children:"When an option is set the interface class calls the set_option method. Custom interfaces can override set_option to handle any additional options they want."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"The option to set. OpenC3 defines several options on the core provided interfaces. The SerialInterface defines FLOW_CONTROL which can be NONE (default) or RTSCTS and DATA_BITS which changes the data bits of the serial interface. The TcpipServerInterface and HttpServerInterface define LISTEN_ADDRESS which is the IP address to accept connections on (default 0.0.0.0)."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Parameters"}),(0,i.jsx)(r.td,{children:"Parameters to pass to the option"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil\n OPTION FLOW_CONTROL RTSCTS\n OPTION DATA_BITS 8\nROUTER SERIAL_ROUTER tcpip_server_interface.rb 2950 2950 10.0 nil BURST\n ROUTE SERIAL_INT\n OPTION LISTEN_ADDRESS 127.0.0.1\n"})}),"\n",(0,i.jsx)(r.h3,{id:"secret",children:"SECRET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,i.jsx)(r.strong,{children:"Define a secret needed by this interface"})]}),"\n",(0,i.jsx)(r.p,{children:"Defines a secret for this interface and optionally assigns its value to an option"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Name"}),(0,i.jsx)(r.td,{children:"The name of the secret to retrieve"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,i.jsx)(r.td,{children:"Environment variable name or file path to store secret"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Name"}),(0,i.jsx)(r.td,{children:"Interface option to pass the secret value"}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Store Name"}),(0,i.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME USERNAME\nSECRET FILE KEY "/tmp/DATA/cert" KEY\n'})}),"\n",(0,i.jsx)(r.h3,{id:"env",children:"ENV"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Key"}),(0,i.jsx)(r.td,{children:"Environment variable name"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Value"}),(0,i.jsx)(r.td,{children:"Environment variable value"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"ENV COMPANY OpenC3\n"})}),"\n",(0,i.jsx)(r.h3,{id:"work_dir",children:"WORK_DIR"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Set the working directory"})]}),"\n",(0,i.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Directory"}),(0,i.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"WORK_DIR '/openc3/lib/openc3/microservices'\n"})}),"\n",(0,i.jsx)(r.h3,{id:"port",children:"PORT"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Number"}),(0,i.jsx)(r.td,{children:"Port number"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol"}),(0,i.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"PORT 7272\n"})}),"\n",(0,i.jsx)(r.h3,{id:"cmd",children:"CMD"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Command line to execute to run the microservice."})]}),"\n",(0,i.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"CMD ruby interface_microservice.rb DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"CMD python interface_microservice.py DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,i.jsx)(r.h3,{id:"container",children:"CONTAINER"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Docker Container"})]}),"\n",(0,i.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"Name of the container"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"route_prefix",children:"ROUTE_PREFIX"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,i.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Route Prefix"}),(0,i.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"ROUTE_PREFIX /interface\n"})}),"\n",(0,i.jsx)(r.h2,{id:"router-1",children:"ROUTER"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Create router to receive commands and output telemetry packets from one or more interfaces"})}),"\n",(0,i.jsx)(r.p,{children:"Creates an router which receives command packets from their remote clients and sends them to associated interfaces. They receive telemetry packets from their interfaces and send them to their remote clients. This allows routers to be intermediaries between an external client and an actual device."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"Name of the router"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Filename"}),(0,i.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,i.jsx)(r.a,{href:"/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,i.jsx)(r.h2,{id:"target-1",children:"TARGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a new target"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Folder Name"}),(0,i.jsx)(r.td,{children:"The target folder"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"The target name. While this is almost always the same as Folder Name it can be different to create multiple targets based on the same target folder."}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"TARGET INST INST\n"})}),"\n",(0,i.jsx)(r.h2,{id:"target-modifiers",children:"TARGET Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a TARGET keyword."}),"\n",(0,i.jsx)(r.h3,{id:"cmd_buffer_depth",children:"CMD_BUFFER_DEPTH"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Number of commands to buffer to ensure logged in order"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Buffer Depth"}),(0,i.jsx)(r.td,{children:"Buffer depth in packets (Default = 5)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_cycle_time",children:"CMD_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command binary logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_cycle_size",children:"CMD_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_retain_time",children:"CMD_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep raw command logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep raw command logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_cycle_time",children:"CMD_DECOM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command decommutation logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_cycle_size",children:"CMD_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_retain_time",children:"CMD_DECOM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep decom command logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep decom command logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_buffer_depth",children:"TLM_BUFFER_DEPTH"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Number of telemetry packets to buffer to ensure logged in order"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Buffer Depth"}),(0,i.jsx)(r.td,{children:"Buffer depth in packets (Default = 60)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_cycle_time",children:"TLM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry binary logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_cycle_size",children:"TLM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_retain_time",children:"TLM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep raw telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep raw telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_cycle_time",children:"TLM_DECOM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_cycle_size",children:"TLM_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_retain_time",children:"TLM_DECOM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep decom telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep decom telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_minute_log_retain_time",children:"REDUCED_MINUTE_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced minute telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced minute telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_hour_log_retain_time",children:"REDUCED_HOUR_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced hour telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced hour telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_day_log_retain_time",children:"REDUCED_DAY_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced day telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced day telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"log_retain_time",children:"LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep all regular telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep all regular telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_log_retain_time",children:"REDUCED_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep all reduced telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep all reduced telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cleanup_poll_time",children:"CLEANUP_POLL_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Period at which to run the cleanup process."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds between runs of the cleanup process (default = 900 = 15 minutes)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reducer_disable",children:"REDUCER_DISABLE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Disables the data reduction microservice for the target"})}),"\n",(0,i.jsx)(r.h3,{id:"reducer_max_cpu_utilization",children:"REDUCER_MAX_CPU_UTILIZATION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Maximum amount of CPU utilization to apply to data reduction"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Percentage"}),(0,i.jsx)(r.td,{children:"0 to 100 percent (default = 30)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"target_microservice",children:"TARGET_MICROSERVICE"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Breaks a target microservice out into its own process."})]}),"\n",(0,i.jsx)(r.p,{children:"Can be used to give more resources to processing that is falling behind. If defined multiple times for the same type, will create multiple processes. Each process can be given specific packets to process with the PACKET keyword."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"The target microservice type. Must be one of DECOM, COMMANDLOG, DECOMCMDLOG, PACKETLOG, DECOMLOG, REDUCER, or CLEANUP"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"packet",children:"PACKET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Packet Name to allocate to the current TARGET_MICROSERVICE."})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Packet Name"}),(0,i.jsx)(r.td,{children:"The packet name. Does not apply to REDUCER or CLEANUP target microservice types."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire target or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"microservice-1",children:"MICROSERVICE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a new microservice"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a microservice that the plugin adds to the OpenC3 system. Microservices are background software processes that perform persistent processing."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Microservice Folder Name"}),(0,i.jsx)(r.td,{children:"The exact name of the microservice folder in the plugin. ie. microservices/MicroserviceFolderName"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Microservice Name"}),(0,i.jsx)(r.td,{children:"The specific name of this instance of the microservice in the OpenC3 system"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n"})}),"\n",(0,i.jsx)(r.h2,{id:"microservice-modifiers",children:"MICROSERVICE Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a MICROSERVICE keyword."}),"\n",(0,i.jsx)(r.h3,{id:"env-1",children:"ENV"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Key"}),(0,i.jsx)(r.td,{children:"Environment variable name"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Value"}),(0,i.jsx)(r.td,{children:"Environment variable value"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n ENV COMPANY OpenC3\n"})}),"\n",(0,i.jsx)(r.h3,{id:"work_dir-1",children:"WORK_DIR"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set the working directory"})}),"\n",(0,i.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Directory"}),(0,i.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n WORK_DIR .\n"})}),"\n",(0,i.jsx)(r.h3,{id:"port-1",children:"PORT"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,i.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Number"}),(0,i.jsx)(r.td,{children:"Port number"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol"}),(0,i.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n PORT 7272\n"})}),"\n",(0,i.jsx)(r.h3,{id:"topic",children:"TOPIC"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Associate a Redis topic"})}),"\n",(0,i.jsx)(r.p,{children:"Redis topic to associate with this microservice. Standard OpenC3 microservices such as decom_microservice use this information to know what packet streams to subscribe to. The TOPIC keyword can be used as many times as necessary to associate all needed topics."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Topic Name"}),(0,i.jsx)(r.td,{children:"Redis Topic to associate with the microservice"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n # Manually assigning topics is an advanced topic and requires\n # intimate knowledge of the internal COSMOS data structures.\n TOPIC DEFAULT__openc3_log_messages\n TOPIC DEFAULT__TELEMETRY__EXAMPLE__STATUS\n"})}),"\n",(0,i.jsx)(r.h3,{id:"target_name",children:"TARGET_NAME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Associate a OpenC3 target"})}),"\n",(0,i.jsx)(r.p,{children:"OpenC3 target to associate with the microservice. For standard OpenC3 microservices such as decom_microservice this causes the target configuration to get loaded into the container for the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"OpenC3 target to associate with the microservice"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n TARGET_NAME EXAMPLE\n"})}),"\n",(0,i.jsx)(r.h3,{id:"cmd-1",children:"CMD"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command line to execute to run the microservice."})}),"\n",(0,i.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n CMD ruby example_target.rb\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"MICROSERVICE EXAMPLE openc3-example\n CMD python example_target.py\n"})}),"\n",(0,i.jsx)(r.h3,{id:"option-1",children:"OPTION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Pass an option to the microservice"})}),"\n",(0,i.jsx)(r.p,{children:"Generic key/value(s) options to pass to the microservice. These take the form of KEYWORD/PARAMS like a line in a OpenC3 configuration file. Multiple OPTION keywords can be used to pass multiple options to the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Name"}),(0,i.jsx)(r.td,{children:"Name of the option"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Value(s)"}),(0,i.jsx)(r.td,{children:"One or more values to associate with the option"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.h3,{id:"container-1",children:"CONTAINER"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Docker Container"})}),"\n",(0,i.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"Name of the container"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"secret-1",children:"SECRET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,i.jsx)(r.strong,{children:"Define a secret needed by this microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Defines a secret for this microservice"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Name"}),(0,i.jsx)(r.td,{children:"The name of the secret to retrieve"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,i.jsx)(r.td,{children:"Environment variable name or file path to store secret"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Store Name"}),(0,i.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME\nSECRET FILE KEY "/tmp/DATA/cert"\n'})}),"\n",(0,i.jsx)(r.h3,{id:"route_prefix-1",children:"ROUTE_PREFIX"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,i.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,i.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Route Prefix"}),(0,i.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE CFDP CFDP\n ROUTE_PREFIX /cfdp\n"})}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-1",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire microservice or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"tool-1",children:"TOOL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a tool"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a tool that the plugin adds to the OpenC3 system. Tools are web based applications that make use of the Single-SPA javascript library that allows them to by dynamically added to the running system as independent frontend microservices."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Tool Folder Name"}),(0,i.jsx)(r.td,{children:"The exact name of the tool folder in the plugin. ie. tools/ToolFolderName"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Tool Name"}),(0,i.jsx)(r.td,{children:"Name of the tool that is displayed in the OpenC3 Navigation menu"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"TOOL DEMO Demo\n"})}),"\n",(0,i.jsx)(r.h2,{id:"tool-modifiers",children:"TOOL Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a TOOL keyword."}),"\n",(0,i.jsx)(r.h3,{id:"url",children:"URL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Url used to access the tool"})}),"\n",(0,i.jsx)(r.p,{children:'The relative url used to access the tool. Defaults to "/tools/ToolFolderName".'}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Url"}),(0,i.jsx)(r.td,{children:"The url. If not given defaults to tools/ToolFolderName. Generally should not be given unless linking to external tools."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"inline_url",children:"INLINE_URL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Internal url to load a tool"})}),"\n",(0,i.jsx)(r.p,{children:'The url of the javascript file used to load the tool into single-SPA. Defaults to "js/app.js".'}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Url"}),(0,i.jsx)(r.td,{children:"The inline url. If not given defaults to js/app.js. Generally should not be given unless using a non-standard filename."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"window",children:"WINDOW"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How to display the tool when navigated to"})}),"\n",(0,i.jsx)(r.p,{children:"The window mode used to display the tool. INLINE opens the tool internally without refreshing the page using the Single-SPA framework. IFRAME opens external tools in an Iframe within OpenC3. NEW opens the tool in a new TAB."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Window Mode"}),(0,i.jsxs)(r.td,{children:["Tool display mode",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"INLINE, IFRAME, NEW"})]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"icon",children:"ICON"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set tool icon"})}),"\n",(0,i.jsx)(r.p,{children:"Icon shown next to the tool name in the OpenC3 navigation menu."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Icon Name"}),(0,i.jsxs)(r.td,{children:["Icon to display next to the tool name. Icons come from Font Awesome, Material Design (",(0,i.jsx)(r.a,{href:"https://materialdesignicons.com/",children:"https://materialdesignicons.com/"}),"), and Astro."]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"category",children:"CATEGORY"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Category for the tool"})}),"\n",(0,i.jsx)(r.p,{children:"Associates the tool with a category which becomes a submenu in the Navigation menu."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Category Name"}),(0,i.jsx)(r.td,{children:"Category to associate the tool with"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"shown",children:"SHOWN"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Show the tool or not"})}),"\n",(0,i.jsx)(r.p,{children:"Whether or not the tool is shown in the Navigation menu. Should generally be true, except for the openc3 base tool."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Shown"}),(0,i.jsxs)(r.td,{children:["Whether or not the tool is shown. TRUE or FALSE",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"true, false"})]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"position",children:"POSITION"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.0.8)"}),(0,i.jsx)(r.strong,{children:"Position of the tool in the nav bar"})]}),"\n",(0,i.jsx)(r.p,{children:"Position of the tool as an integer starting at 1. Tools without a position are appended to the end as they are installed."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Position"}),(0,i.jsx)(r.td,{children:"Numerical position"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-2",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire tool or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"widget",children:"WIDGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a custom widget"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a custom widget that can be used in Telemetry Viewer screens."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Widget Name"}),(0,i.jsxs)(r.td,{children:["The name of the widget wil be used to build a path to the widget implementation. For example, ",(0,i.jsx)(r.code,{children:"WIDGET HELLOWORLD"})," will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the ",(0,i.jsx)(r.a,{href:"/docs/guides/custom-widgets",children:"Custom Widgets"})," guide for more details."]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"WIDGET HELLOWORLD\n"})}),"\n",(0,i.jsx)(r.h2,{id:"widget-modifiers",children:"WIDGET Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a WIDGET keyword."}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-3",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire widget or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]})]})}function o(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,i.jsx)(r,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>l,x:()=>d});var i=n(6540);const s={},t=i.createContext(s);function l(e){const r=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(t.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[9527],{2124:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>a,frontMatter:()=>t,metadata:()=>d,toc:()=>h});var i=n(4848),s=n(8453);const t={sidebar_position:2,title:"Plugins"},l=void 0,d={id:"configuration/plugins",title:"Plugins",description:"Introduction",source:"@site/docs/configuration/plugins.md",sourceDirName:"configuration",slug:"/configuration/plugins",permalink:"/docs/configuration/plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/plugins.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Plugins"},sidebar:"defaultSidebar",previous:{title:"File Format",permalink:"/docs/configuration/format"},next:{title:"Targets",permalink:"/docs/configuration/target"}},c={},h=[{value:"Introduction",id:"introduction",level:2},{value:"Concepts",id:"concepts",level:2},{value:"Target",id:"target",level:3},{value:"Interface",id:"interface",level:3},{value:"Router",id:"router",level:3},{value:"Tool",id:"tool",level:3},{value:"Microservice",id:"microservice",level:3},{value:"Plugin Directory Structure",id:"plugin-directory-structure",level:2},{value:"plugin.txt Configuration File",id:"plugintxt-configuration-file",level:2},{value:"VARIABLE",id:"variable",level:2},{value:"NEEDS_DEPENDENCIES",id:"needs_dependencies",level:2},{value:"INTERFACE",id:"interface-1",level:2},{value:"INTERFACE Modifiers",id:"interface-modifiers",level:2},{value:"MAP_TARGET",id:"map_target",level:3},{value:"MAP_CMD_TARGET",id:"map_cmd_target",level:3},{value:"MAP_TLM_TARGET",id:"map_tlm_target",level:3},{value:"DONT_CONNECT",id:"dont_connect",level:3},{value:"DONT_RECONNECT",id:"dont_reconnect",level:3},{value:"RECONNECT_DELAY",id:"reconnect_delay",level:3},{value:"DISABLE_DISCONNECT",id:"disable_disconnect",level:3},{value:"LOG_RAW",id:"log_raw",level:3},{value:"LOG_STREAM",id:"log_stream",level:3},{value:"PROTOCOL",id:"protocol",level:3},{value:"OPTION",id:"option",level:3},{value:"SECRET",id:"secret",level:3},{value:"ENV",id:"env",level:3},{value:"WORK_DIR",id:"work_dir",level:3},{value:"PORT",id:"port",level:3},{value:"CMD",id:"cmd",level:3},{value:"CONTAINER",id:"container",level:3},{value:"ROUTE_PREFIX",id:"route_prefix",level:3},{value:"ROUTER",id:"router-1",level:2},{value:"TARGET",id:"target-1",level:2},{value:"TARGET Modifiers",id:"target-modifiers",level:2},{value:"CMD_BUFFER_DEPTH",id:"cmd_buffer_depth",level:3},{value:"CMD_LOG_CYCLE_TIME",id:"cmd_log_cycle_time",level:3},{value:"CMD_LOG_CYCLE_SIZE",id:"cmd_log_cycle_size",level:3},{value:"CMD_LOG_RETAIN_TIME",id:"cmd_log_retain_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_TIME",id:"cmd_decom_log_cycle_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_SIZE",id:"cmd_decom_log_cycle_size",level:3},{value:"CMD_DECOM_LOG_RETAIN_TIME",id:"cmd_decom_log_retain_time",level:3},{value:"TLM_BUFFER_DEPTH",id:"tlm_buffer_depth",level:3},{value:"TLM_LOG_CYCLE_TIME",id:"tlm_log_cycle_time",level:3},{value:"TLM_LOG_CYCLE_SIZE",id:"tlm_log_cycle_size",level:3},{value:"TLM_LOG_RETAIN_TIME",id:"tlm_log_retain_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_TIME",id:"tlm_decom_log_cycle_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_SIZE",id:"tlm_decom_log_cycle_size",level:3},{value:"TLM_DECOM_LOG_RETAIN_TIME",id:"tlm_decom_log_retain_time",level:3},{value:"REDUCED_MINUTE_LOG_RETAIN_TIME",id:"reduced_minute_log_retain_time",level:3},{value:"REDUCED_HOUR_LOG_RETAIN_TIME",id:"reduced_hour_log_retain_time",level:3},{value:"REDUCED_DAY_LOG_RETAIN_TIME",id:"reduced_day_log_retain_time",level:3},{value:"LOG_RETAIN_TIME",id:"log_retain_time",level:3},{value:"REDUCED_LOG_RETAIN_TIME",id:"reduced_log_retain_time",level:3},{value:"CLEANUP_POLL_TIME",id:"cleanup_poll_time",level:3},{value:"REDUCER_DISABLE",id:"reducer_disable",level:3},{value:"REDUCER_MAX_CPU_UTILIZATION",id:"reducer_max_cpu_utilization",level:3},{value:"TARGET_MICROSERVICE",id:"target_microservice",level:3},{value:"PACKET",id:"packet",level:3},{value:"DISABLE_ERB",id:"disable_erb",level:3},{value:"MICROSERVICE",id:"microservice-1",level:2},{value:"MICROSERVICE Modifiers",id:"microservice-modifiers",level:2},{value:"ENV",id:"env-1",level:3},{value:"WORK_DIR",id:"work_dir-1",level:3},{value:"PORT",id:"port-1",level:3},{value:"TOPIC",id:"topic",level:3},{value:"TARGET_NAME",id:"target_name",level:3},{value:"CMD",id:"cmd-1",level:3},{value:"OPTION",id:"option-1",level:3},{value:"CONTAINER",id:"container-1",level:3},{value:"SECRET",id:"secret-1",level:3},{value:"ROUTE_PREFIX",id:"route_prefix-1",level:3},{value:"DISABLE_ERB",id:"disable_erb-1",level:3},{value:"TOOL",id:"tool-1",level:2},{value:"TOOL Modifiers",id:"tool-modifiers",level:2},{value:"URL",id:"url",level:3},{value:"INLINE_URL",id:"inline_url",level:3},{value:"WINDOW",id:"window",level:3},{value:"ICON",id:"icon",level:3},{value:"CATEGORY",id:"category",level:3},{value:"SHOWN",id:"shown",level:3},{value:"POSITION",id:"position",level:3},{value:"DISABLE_ERB",id:"disable_erb-2",level:3},{value:"WIDGET",id:"widget",level:2},{value:"WIDGET Modifiers",id:"widget-modifiers",level:2},{value:"DISABLE_ERB",id:"disable_erb-3",level:3}];function o(e){const r={a:"a",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(r.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(r.p,{children:"This document provides the information necessary to configure a COSMOS plugin. Plugins are how you configure and extend COSMOS."}),"\n",(0,i.jsx)(r.p,{children:"Plugins are where you define targets (and their corresponding command and telemetry packet definitions), where you configure the interfaces needed to talk to targets, where you can define routers to stream raw data out of COSMOS, how you can add new tools to the COSMOS user interface, and how you can run additional microservices to provide new functionality."}),"\n",(0,i.jsx)(r.p,{children:"Each plugin is built as a Ruby gem and thus has a plugin.gemspec file which builds it. Plugins have a plugin.txt file which declares all the variables used by the plugin and how to interface to the target(s) it contains."}),"\n",(0,i.jsx)(r.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(r.h3,{id:"target",children:"Target"}),"\n",(0,i.jsx)(r.p,{children:"Targets are the external pieces of hardware and/or software that COSMOS communicates with. These are things like Front End Processors (FEPs), ground support equipment (GSE), custom software tools, and pieces of hardware like satellites themselves. A target is anything that COSMOS can send commands to and receive telemetry from."}),"\n",(0,i.jsx)(r.h3,{id:"interface",children:"Interface"}),"\n",(0,i.jsx)(r.p,{children:"Interfaces implement the physical connection to one or more targets. They are typically ethernet connections implemented using TCP or UDP but can be other connections like serial ports. Interfaces send commands to targets and receive telemetry from targets."}),"\n",(0,i.jsx)(r.h3,{id:"router",children:"Router"}),"\n",(0,i.jsx)(r.p,{children:"Routers flow streams of telemetry packets out of COSMOS and receive streams of commands into COSMOS. The commands are forwarded by COSMOS to associated interfaces. Telemetry comes from associated interfaces."}),"\n",(0,i.jsx)(r.h3,{id:"tool",children:"Tool"}),"\n",(0,i.jsx)(r.p,{children:"COSMOS Tools are web-based applications the communicate with the COSMOS APIs to perform takes like displaying telemetry, sending commands, and running scripts."}),"\n",(0,i.jsx)(r.h3,{id:"microservice",children:"Microservice"}),"\n",(0,i.jsx)(r.p,{children:"Microservices are persistent running backend code that runs within the COSMOS environment. They can process data and perform other useful tasks."}),"\n",(0,i.jsx)(r.h2,{id:"plugin-directory-structure",children:"Plugin Directory Structure"}),"\n",(0,i.jsxs)(r.p,{children:["COSMOS plugins have a well-defined directory structure described in detail in the ",(0,i.jsx)(r.a,{href:"../getting-started/generators",children:"Code Generator"})," documentation."]}),"\n",(0,i.jsx)(r.h2,{id:"plugintxt-configuration-file",children:"plugin.txt Configuration File"}),"\n",(0,i.jsx)(r.p,{children:"A plugin.txt configuration file is required for any COSMOS plugin. It declares the contents of the plugin and provides variables that allow the plugin to be configured at the time it is initially installed or upgraded.\nThis file follows the standard COSMOS configuration file format of keywords followed by zero or more space separated parameters. The following keywords are supported by the plugin.txt config file:"}),"\n",(0,i.jsx)(r.h2,{id:"variable",children:"VARIABLE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a configurable variable for the plugin"})}),"\n",(0,i.jsx)(r.p,{children:"The VARIABLE keyword defines a variable that will be requested for the user to enter during plugin installation. Variables can be used to handle details of targets that are user defined such as specific IP addresses and ports. Variables should also be used to allow users to rename targets to whatever name they want and support multiple installations of the same target with different names. Variables can be used later in plugin.txt or in any other configuration file included in a plugin using Ruby ERB syntax. The variables are assigned to accessible local variables in the file. At a high level, ERB allows you to run Ruby code in configuration files."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Variable Name"}),(0,i.jsx)(r.td,{children:"The name of the variable"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Default Value"}),(0,i.jsx)(r.td,{children:"Default value of the variable"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.h2,{id:"needs_dependencies",children:"NEEDS_DEPENDENCIES"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,i.jsx)(r.strong,{children:"Indicates the plugin needs dependencies and sets the GEM_HOME environment variable"})]}),"\n",(0,i.jsx)(r.p,{children:"If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kubernetes pod."}),"\n",(0,i.jsx)(r.h2,{id:"interface-1",children:"INTERFACE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a connection to a physical target"})}),"\n",(0,i.jsx)(r.p,{children:"Interfaces are what OpenC3 uses to talk to a particular piece of hardware. Interfaces require a Ruby or Python file which implements all the interface methods necessary to talk to the hardware. OpenC3 defines many built in interfaces or you can define your own as long as it implements the interface protocol."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Interface Name"}),(0,i.jsx)(r.td,{children:"Name of the interface. This name will appear in the Interfaces tab of the Server and is also referenced by other keywords. The OpenC3 convention is to name interfaces after their targets with '_INT' appended to the name, e.g. INST_INT for the INST target."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Filename"}),(0,i.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,i.jsx)(r.a,{href:"/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,i.jsx)(r.h2,{id:"interface-modifiers",children:"INTERFACE Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a INTERFACE keyword."}),"\n",(0,i.jsx)(r.h3,{id:"map_target",children:"MAP_TARGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Maps a target name to an interface"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,i.jsx)(r.h3,{id:"map_cmd_target",children:"MAP_CMD_TARGET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Maps a target name to an interface for commands only"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Command target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE CMD_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE CMD_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,i.jsx)(r.h3,{id:"map_tlm_target",children:"MAP_TLM_TARGET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Maps a target name to an interface for telemetry only"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"Telemetry target name to map to this interface"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE TLM_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE TLM_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,i.jsx)(r.h3,{id:"dont_connect",children:"DONT_CONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Server will not automatically try to connect to the interface at startup"})}),"\n",(0,i.jsx)(r.h3,{id:"dont_reconnect",children:"DONT_RECONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Server will not try to reconnect to the interface if the connection is lost"})}),"\n",(0,i.jsx)(r.h3,{id:"reconnect_delay",children:"RECONNECT_DELAY"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Reconnect delay in seconds"})}),"\n",(0,i.jsx)(r.p,{children:"If DONT_RECONNECT is not present the Server will try to reconnect to an interface if the connection is lost. Reconnect delay sets the interval in seconds between reconnect tries."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Delay"}),(0,i.jsx)(r.td,{children:"Delay in seconds between reconnect attempts. The default is 15 seconds."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_disconnect",children:"DISABLE_DISCONNECT"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Disable the Disconnect button on the Interfaces tab in the Server"})}),"\n",(0,i.jsx)(r.p,{children:"Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertently disconnect from a target."}),"\n",(0,i.jsx)(r.h3,{id:"log_raw",children:"LOG_RAW"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Deprecated, use LOG_STREAM"})}),"\n",(0,i.jsx)(r.h3,{id:"log_stream",children:"LOG_STREAM"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.2)"}),(0,i.jsx)(r.strong,{children:"Log all data on the interface exactly as it is sent and received"})]}),"\n",(0,i.jsx)(r.p,{children:"LOG_STREAM does not add any OpenC3 headers and thus can not be read by OpenC3 tools. It is primarily useful for low level debugging of an interface. You will have to manually parse these logs yourself using a hex editor or other application."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Time"}),(0,i.jsx)(r.td,{children:"Amount of time to wait before cycling the log file. Default is 10 min. If nil refer to Cycle Hour and Cycle Minute."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Size"}),(0,i.jsx)(r.td,{children:"Amount of data to write before cycling the log file. Default is 50MB."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Hour"}),(0,i.jsx)(r.td,{children:"The time at which to cycle the log. Combined with Cycle Minute to cycle the log daily at the specified time. If nil, the log will be cycled hourly at the specified Cycle Minute. Only applies if Cycle Time is nil."}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Cycle Minute"}),(0,i.jsx)(r.td,{children:"See Cycle Hour."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE EXAMPLE example_interface.rb\n # Override the default log time of 600\n LOG_STREAM 60\n"})}),"\n",(0,i.jsx)(r.h3,{id:"protocol",children:"PROTOCOL"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 4.0.0)"}),(0,i.jsx)(r.strong,{children:"Protocols modify the interface by processing the data"})]}),"\n",(0,i.jsxs)(r.p,{children:["Protocols can be either READ, WRITE, or READ_WRITE. READ protocols act on the data received by the interface while write acts on the data before it is sent out. READ_WRITE applies the protocol to both reading and writing.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{})," For information on creating your own custom protocol please see ",(0,i.jsx)(r.a,{href:"/docs/configuration/protocols",children:"Protocols"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsxs)(r.td,{children:["Whether to apply the protocol on incoming data, outgoing data, or both",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"READ, WRITE, READ_WRITE"})]}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol Filename or Classname"}),(0,i.jsx)(r.td,{children:"Ruby or Python filename or class name which implements the protocol"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol specific parameters"}),(0,i.jsx)(r.td,{children:"Additional parameters used by the protocol"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil nil\n MAP_TARGET DATA\n # Rather than defining the LENGTH protocol on the INTERFACE line we define it here\n PROTOCOL READ LengthProtocol 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n PROTOCOL READ IgnorePacketProtocol INST IMAGE # Drop all INST IMAGE packets\n"})}),"\n",(0,i.jsx)(r.h3,{id:"option",children:"OPTION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set a parameter on an interface"})}),"\n",(0,i.jsx)(r.p,{children:"When an option is set the interface class calls the set_option method. Custom interfaces can override set_option to handle any additional options they want."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"The option to set. OpenC3 defines several options on the core provided interfaces. The SerialInterface defines FLOW_CONTROL which can be NONE (default) or RTSCTS and DATA_BITS which changes the data bits of the serial interface. The TcpipServerInterface and HttpServerInterface define LISTEN_ADDRESS which is the IP address to accept connections on (default 0.0.0.0)."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Parameters"}),(0,i.jsx)(r.td,{children:"Parameters to pass to the option"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil\n OPTION FLOW_CONTROL RTSCTS\n OPTION DATA_BITS 8\nROUTER SERIAL_ROUTER tcpip_server_interface.rb 2950 2950 10.0 nil BURST\n ROUTE SERIAL_INT\n OPTION LISTEN_ADDRESS 127.0.0.1\n"})}),"\n",(0,i.jsx)(r.h3,{id:"secret",children:"SECRET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,i.jsx)(r.strong,{children:"Define a secret needed by this interface"})]}),"\n",(0,i.jsx)(r.p,{children:"Defines a secret for this interface and optionally assigns its value to an option"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Name"}),(0,i.jsx)(r.td,{children:"The name of the secret to retrieve"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,i.jsx)(r.td,{children:"Environment variable name or file path to store secret"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Name"}),(0,i.jsx)(r.td,{children:"Interface option to pass the secret value"}),(0,i.jsx)(r.td,{children:"False"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Store Name"}),(0,i.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME USERNAME\nSECRET FILE KEY "/tmp/DATA/cert" KEY\n'})}),"\n",(0,i.jsx)(r.h3,{id:"env",children:"ENV"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Key"}),(0,i.jsx)(r.td,{children:"Environment variable name"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Value"}),(0,i.jsx)(r.td,{children:"Environment variable value"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"ENV COMPANY OpenC3\n"})}),"\n",(0,i.jsx)(r.h3,{id:"work_dir",children:"WORK_DIR"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Set the working directory"})]}),"\n",(0,i.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Directory"}),(0,i.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"WORK_DIR '/openc3/lib/openc3/microservices'\n"})}),"\n",(0,i.jsx)(r.h3,{id:"port",children:"PORT"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Number"}),(0,i.jsx)(r.td,{children:"Port number"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol"}),(0,i.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"PORT 7272\n"})}),"\n",(0,i.jsx)(r.h3,{id:"cmd",children:"CMD"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Command line to execute to run the microservice."})]}),"\n",(0,i.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"CMD ruby interface_microservice.rb DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"CMD python interface_microservice.py DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,i.jsx)(r.h3,{id:"container",children:"CONTAINER"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Docker Container"})]}),"\n",(0,i.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"Name of the container"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"route_prefix",children:"ROUTE_PREFIX"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,i.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,i.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Route Prefix"}),(0,i.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"ROUTE_PREFIX /interface\n"})}),"\n",(0,i.jsx)(r.h2,{id:"router-1",children:"ROUTER"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Create router to receive commands and output telemetry packets from one or more interfaces"})}),"\n",(0,i.jsx)(r.p,{children:"Creates an router which receives command packets from their remote clients and sends them to associated interfaces. They receive telemetry packets from their interfaces and send them to their remote clients. This allows routers to be intermediaries between an external client and an actual device."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"Name of the router"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Filename"}),(0,i.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,i.jsx)(r.a,{href:"/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,i.jsx)(r.h2,{id:"target-1",children:"TARGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a new target"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Folder Name"}),(0,i.jsx)(r.td,{children:"The target folder"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Name"}),(0,i.jsx)(r.td,{children:"The target name. While this is almost always the same as Folder Name it can be different to create multiple targets based on the same target folder."}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"TARGET INST INST\n"})}),"\n",(0,i.jsx)(r.h2,{id:"target-modifiers",children:"TARGET Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a TARGET keyword."}),"\n",(0,i.jsx)(r.h3,{id:"cmd_buffer_depth",children:"CMD_BUFFER_DEPTH"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Number of commands to buffer to ensure logged in order"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Buffer Depth"}),(0,i.jsx)(r.td,{children:"Buffer depth in packets (Default = 5)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_cycle_time",children:"CMD_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command binary logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_cycle_size",children:"CMD_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_log_retain_time",children:"CMD_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep raw command logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep raw command logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_cycle_time",children:"CMD_DECOM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command decommutation logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_cycle_size",children:"CMD_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cmd_decom_log_retain_time",children:"CMD_DECOM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep decom command logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep decom command logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_buffer_depth",children:"TLM_BUFFER_DEPTH"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Number of telemetry packets to buffer to ensure logged in order"})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Buffer Depth"}),(0,i.jsx)(r.td,{children:"Buffer depth in packets (Default = 60)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_cycle_time",children:"TLM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry binary logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_cycle_size",children:"TLM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_log_retain_time",children:"TLM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep raw telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep raw telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_cycle_time",children:"TLM_DECOM_LOG_CYCLE_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled on a time interval."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_cycle_size",children:"TLM_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Size"}),(0,i.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"tlm_decom_log_retain_time",children:"TLM_DECOM_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep decom telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep decom telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_minute_log_retain_time",children:"REDUCED_MINUTE_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced minute telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced minute telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_hour_log_retain_time",children:"REDUCED_HOUR_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced hour telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced hour telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_day_log_retain_time",children:"REDUCED_DAY_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep reduced day telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep reduced day telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"log_retain_time",children:"LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep all regular telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep all regular telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reduced_log_retain_time",children:"REDUCED_LOG_RETAIN_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How long to keep all reduced telemetry logs in seconds."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds to keep all reduced telemetry logs (default = nil = Forever)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"cleanup_poll_time",children:"CLEANUP_POLL_TIME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Period at which to run the cleanup process."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Time"}),(0,i.jsx)(r.td,{children:"Number of seconds between runs of the cleanup process (default = 900 = 15 minutes)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"reducer_disable",children:"REDUCER_DISABLE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Disables the data reduction microservice for the target"})}),"\n",(0,i.jsx)(r.h3,{id:"reducer_max_cpu_utilization",children:"REDUCER_MAX_CPU_UTILIZATION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Maximum amount of CPU utilization to apply to data reduction"})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Percentage"}),(0,i.jsx)(r.td,{children:"0 to 100 percent (default = 30)"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"target_microservice",children:"TARGET_MICROSERVICE"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Breaks a target microservice out into its own process."})]}),"\n",(0,i.jsx)(r.p,{children:"Can be used to give more resources to processing that is falling behind. If defined multiple times for the same type, will create multiple processes. Each process can be given specific packets to process with the PACKET keyword."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"The target microservice type. Must be one of DECOM, COMMANDLOG, DECOMCMDLOG, PACKETLOG, DECOMLOG, REDUCER, or CLEANUP"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"packet",children:"PACKET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,i.jsx)(r.strong,{children:"Packet Name to allocate to the current TARGET_MICROSERVICE."})]}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Packet Name"}),(0,i.jsx)(r.td,{children:"The packet name. Does not apply to REDUCER or CLEANUP target microservice types."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire target or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"microservice-1",children:"MICROSERVICE"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Defines a new microservice"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a microservice that the plugin adds to the OpenC3 system. Microservices are background software processes that perform persistent processing."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Microservice Folder Name"}),(0,i.jsx)(r.td,{children:"The exact name of the microservice folder in the plugin. ie. microservices/MicroserviceFolderName"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Microservice Name"}),(0,i.jsx)(r.td,{children:"The specific name of this instance of the microservice in the OpenC3 system"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n"})}),"\n",(0,i.jsx)(r.h2,{id:"microservice-modifiers",children:"MICROSERVICE Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a MICROSERVICE keyword."}),"\n",(0,i.jsx)(r.h3,{id:"env-1",children:"ENV"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Key"}),(0,i.jsx)(r.td,{children:"Environment variable name"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Value"}),(0,i.jsx)(r.td,{children:"Environment variable value"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n ENV COMPANY OpenC3\n"})}),"\n",(0,i.jsx)(r.h3,{id:"work_dir-1",children:"WORK_DIR"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set the working directory"})}),"\n",(0,i.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Directory"}),(0,i.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n WORK_DIR .\n"})}),"\n",(0,i.jsx)(r.h3,{id:"port-1",children:"PORT"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,i.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Number"}),(0,i.jsx)(r.td,{children:"Port number"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Protocol"}),(0,i.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n PORT 7272\n"})}),"\n",(0,i.jsx)(r.h3,{id:"topic",children:"TOPIC"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Associate a Redis topic"})}),"\n",(0,i.jsx)(r.p,{children:"Redis topic to associate with this microservice. Standard OpenC3 microservices such as decom_microservice use this information to know what packet streams to subscribe to. The TOPIC keyword can be used as many times as necessary to associate all needed topics."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Topic Name"}),(0,i.jsx)(r.td,{children:"Redis Topic to associate with the microservice"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n # Manually assigning topics is an advanced topic and requires\n # intimate knowledge of the internal COSMOS data structures.\n TOPIC DEFAULT__openc3_log_messages\n TOPIC DEFAULT__TELEMETRY__EXAMPLE__STATUS\n"})}),"\n",(0,i.jsx)(r.h3,{id:"target_name",children:"TARGET_NAME"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Associate a OpenC3 target"})}),"\n",(0,i.jsx)(r.p,{children:"OpenC3 target to associate with the microservice. For standard OpenC3 microservices such as decom_microservice this causes the target configuration to get loaded into the container for the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Target Name"}),(0,i.jsx)(r.td,{children:"OpenC3 target to associate with the microservice"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n TARGET_NAME EXAMPLE\n"})}),"\n",(0,i.jsx)(r.h3,{id:"cmd-1",children:"CMD"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Command line to execute to run the microservice."})}),"\n",(0,i.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n CMD ruby example_target.rb\n"})}),"\n",(0,i.jsx)(r.p,{children:"Python Example:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-python",children:"MICROSERVICE EXAMPLE openc3-example\n CMD python example_target.py\n"})}),"\n",(0,i.jsx)(r.h3,{id:"option-1",children:"OPTION"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Pass an option to the microservice"})}),"\n",(0,i.jsx)(r.p,{children:"Generic key/value(s) options to pass to the microservice. These take the form of KEYWORD/PARAMS like a line in a OpenC3 configuration file. Multiple OPTION keywords can be used to pass multiple options to the microservice."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Name"}),(0,i.jsx)(r.td,{children:"Name of the option"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Option Value(s)"}),(0,i.jsx)(r.td,{children:"One or more values to associate with the option"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.h3,{id:"container-1",children:"CONTAINER"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Docker Container"})}),"\n",(0,i.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Args"}),(0,i.jsx)(r.td,{children:"Name of the container"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"secret-1",children:"SECRET"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,i.jsx)(r.strong,{children:"Define a secret needed by this microservice"})]}),"\n",(0,i.jsx)(r.p,{children:"Defines a secret for this microservice"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Type"}),(0,i.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Name"}),(0,i.jsx)(r.td,{children:"The name of the secret to retrieve"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,i.jsx)(r.td,{children:"Environment variable name or file path to store secret"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Secret Store Name"}),(0,i.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,i.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME\nSECRET FILE KEY "/tmp/DATA/cert"\n'})}),"\n",(0,i.jsx)(r.h3,{id:"route_prefix-1",children:"ROUTE_PREFIX"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,i.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,i.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Route Prefix"}),(0,i.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE CFDP CFDP\n ROUTE_PREFIX /cfdp\n"})}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-1",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire microservice or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"tool-1",children:"TOOL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a tool"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a tool that the plugin adds to the OpenC3 system. Tools are web based applications that make use of the Single-SPA javascript library that allows them to by dynamically added to the running system as independent frontend microservices."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsxs)(r.tbody,{children:[(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Tool Folder Name"}),(0,i.jsx)(r.td,{children:"The exact name of the tool folder in the plugin. ie. tools/ToolFolderName"}),(0,i.jsx)(r.td,{children:"True"})]}),(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Tool Name"}),(0,i.jsx)(r.td,{children:"Name of the tool that is displayed in the OpenC3 Navigation menu"}),(0,i.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"TOOL DEMO Demo\n"})}),"\n",(0,i.jsx)(r.h2,{id:"tool-modifiers",children:"TOOL Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a TOOL keyword."}),"\n",(0,i.jsx)(r.h3,{id:"url",children:"URL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Url used to access the tool"})}),"\n",(0,i.jsx)(r.p,{children:'The relative url used to access the tool. Defaults to "/tools/ToolFolderName".'}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Url"}),(0,i.jsx)(r.td,{children:"The url. If not given defaults to tools/ToolFolderName. Generally should not be given unless linking to external tools."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"inline_url",children:"INLINE_URL"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Internal url to load a tool"})}),"\n",(0,i.jsx)(r.p,{children:'The url of the javascript file used to load the tool into single-SPA. Defaults to "js/app.js".'}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Url"}),(0,i.jsx)(r.td,{children:"The inline url. If not given defaults to js/app.js. Generally should not be given unless using a non-standard filename."}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"window",children:"WINDOW"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"How to display the tool when navigated to"})}),"\n",(0,i.jsx)(r.p,{children:"The window mode used to display the tool. INLINE opens the tool internally without refreshing the page using the Single-SPA framework. IFRAME opens external tools in an Iframe within OpenC3. NEW opens the tool in a new TAB."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Window Mode"}),(0,i.jsxs)(r.td,{children:["Tool display mode",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"INLINE, IFRAME, NEW"})]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"icon",children:"ICON"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Set tool icon"})}),"\n",(0,i.jsx)(r.p,{children:"Icon shown next to the tool name in the OpenC3 navigation menu."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Icon Name"}),(0,i.jsxs)(r.td,{children:["Icon to display next to the tool name. Icons come from Font Awesome, Material Design (",(0,i.jsx)(r.a,{href:"https://materialdesignicons.com/",children:"https://materialdesignicons.com/"}),"), and Astro."]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"category",children:"CATEGORY"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Category for the tool"})}),"\n",(0,i.jsx)(r.p,{children:"Associates the tool with a category which becomes a submenu in the Navigation menu."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Category Name"}),(0,i.jsx)(r.td,{children:"Category to associate the tool with"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"shown",children:"SHOWN"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Show the tool or not"})}),"\n",(0,i.jsx)(r.p,{children:"Whether or not the tool is shown in the Navigation menu. Should generally be true, except for the openc3 base tool."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Shown"}),(0,i.jsxs)(r.td,{children:["Whether or not the tool is shown. TRUE or FALSE",(0,i.jsx)("br",{}),(0,i.jsx)("br",{}),"Valid Values: ",(0,i.jsx)("span",{class:"values",children:"true, false"})]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"position",children:"POSITION"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.0.8)"}),(0,i.jsx)(r.strong,{children:"Position of the tool in the nav bar"})]}),"\n",(0,i.jsx)(r.p,{children:"Position of the tool as an integer starting at 1. Tools without a position are appended to the end as they are installed."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Position"}),(0,i.jsx)(r.td,{children:"Numerical position"}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-2",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire tool or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,i.jsx)(r.h2,{id:"widget",children:"WIDGET"}),"\n",(0,i.jsx)(r.p,{children:(0,i.jsx)(r.strong,{children:"Define a custom widget"})}),"\n",(0,i.jsx)(r.p,{children:"Defines a custom widget that can be used in Telemetry Viewer screens."}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Widget Name"}),(0,i.jsxs)(r.td,{children:["The name of the widget will be used to build a path to the widget implementation. For example, ",(0,i.jsx)(r.code,{children:"WIDGET HELLOWORLD"})," will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the ",(0,i.jsx)(r.a,{href:"/docs/guides/custom-widgets",children:"Custom Widgets"})," guide for more details."]}),(0,i.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,i.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,i.jsx)(r.pre,{children:(0,i.jsx)(r.code,{className:"language-ruby",children:"WIDGET HELLOWORLD\n"})}),"\n",(0,i.jsx)(r.h2,{id:"widget-modifiers",children:"WIDGET Modifiers"}),"\n",(0,i.jsx)(r.p,{children:"The following keywords must follow a WIDGET keyword."}),"\n",(0,i.jsx)(r.h3,{id:"disable_erb-3",children:"DISABLE_ERB"}),"\n",(0,i.jsxs)(r.p,{children:[(0,i.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,i.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,i.jsx)(r.p,{children:"Disable ERB processing for the entire widget or a set of regular expressions over its filenames"}),"\n",(0,i.jsxs)(r.table,{children:[(0,i.jsx)(r.thead,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.th,{children:"Parameter"}),(0,i.jsx)(r.th,{children:"Description"}),(0,i.jsx)(r.th,{children:"Required"})]})}),(0,i.jsx)(r.tbody,{children:(0,i.jsxs)(r.tr,{children:[(0,i.jsx)(r.td,{children:"Regex"}),(0,i.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,i.jsx)(r.td,{children:"False"})]})})]})]})}function a(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,i.jsx)(r,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>l,x:()=>d});var i=n(6540);const s={},t=i.createContext(s);function l(e){const r=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(t.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/6b210247.91d244c1.js b/docs/assets/js/6b210247.95683d32.js
similarity index 96%
rename from docs/assets/js/6b210247.91d244c1.js
rename to docs/assets/js/6b210247.95683d32.js
index c62cf504e4..2ed78401a7 100644
--- a/docs/assets/js/6b210247.91d244c1.js
+++ b/docs/assets/js/6b210247.95683d32.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[8353],{1276:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>d,default:()=>o,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var s=r(4848),n=r(8453);const i={sidebar_position:6,title:"Requirements and Design"},d=void 0,l={id:"getting-started/requirements",title:"Requirements and Design",description:"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations.",source:"@site/docs/getting-started/requirements.md",sourceDirName:"getting-started",slug:"/getting-started/requirements",permalink:"/docs/getting-started/requirements",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/getting-started/requirements.md",tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6,title:"Requirements and Design"},sidebar:"defaultSidebar",previous:{title:"Key Concepts",permalink:"/docs/getting-started/key_concepts"},next:{title:"Podman",permalink:"/docs/getting-started/podman"}},a={},c=[{value:"Terminology",id:"terminology",level:2},{value:"Overall Architecture and Context Diagram",id:"overall-architecture-and-context-diagram",level:2},{value:"Overall Requirements",id:"overall-requirements",level:2},{value:"Api Requirements",id:"api-requirements",level:2},{value:"Command and Telemetry Server",id:"command-and-telemetry-server",level:2},{value:"Limits Monitor",id:"limits-monitor",level:2},{value:"Command Sender",id:"command-sender",level:2},{value:"Script Runner",id:"script-runner",level:2},{value:"Packet Viewer",id:"packet-viewer",level:2},{value:"Telemetry Viewer",id:"telemetry-viewer",level:2},{value:"Telemetry Grapher",id:"telemetry-grapher",level:2},{value:"Data Extractor",id:"data-extractor",level:2},{value:"Data Viewer",id:"data-viewer",level:2},{value:"Calendar",id:"calendar",level:2},{value:"Admin",id:"admin",level:2}];function h(e){const t={h2:"h2",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations."}),"\n",(0,s.jsx)(t.p,{children:"COSMOS is currently made up of the following applications:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Command and Telemetry Server"})," - Provides status of realtime commanding, telemetry reception, logging, limits monitoring, and packet routing."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Limits Monitor"})," - Monitors telemetry with defined limits and shows items that currently are or have violated limits."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Command Sender"})," - Provides a graphical interface for manually sending individual commands."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Script Runner"})," - Executes scripts and provides highlighting of the currently executing line. Now also includes TestRunner functionality."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Packet Viewer"})," - Provides realtime visualization of every telemetry packet that has been defined."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Telemetry Viewer"})," - Provides custom telemetry screen functionality with advanced layout and visualization widgets."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Telemetry Grapher"})," - Provides realtime and offline graphing of telemetry data."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Data Extractor"})," - Extracts telemetry and command packet log files into CSV data."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Data Viewer"})," - Provides text based telemetry visualization for items."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Bucket Explorer"})," - Browse the COSMOS bucket storage in any cloud environment."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Table Manager"})," - Binary file editor with Script Runner integration for upload / download."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Handbooks"})," - Generate html page of the command and telemetry definitions."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Calendar"})," - Provides scheduling of commands and scripts. Also provides a framework for reserving resources."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Admin"})," - Provides an administrative interface to COSMOS."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"More detailed descriptions, requirements, and design for each tool are found later in this document. Additionally, each of the above applications is built using COSMOS libraries that are available for use as a framework to develop custom program/project applications."}),"\n",(0,s.jsx)(t.h2,{id:"terminology",children:"Terminology"}),"\n",(0,s.jsx)(t.p,{children:"The COSMOS system uses several terms that are important to understand. The following table defines these terms."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Term"}),(0,s.jsx)(t.th,{children:"Definition"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Target"}),(0,s.jsx)(t.td,{children:"A COSMOS target is an embedded system that the COSMOS Command and Telemetry Server connects to using an interface in order to send commands to and/or receive telemetry from."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Command"}),(0,s.jsx)(t.td,{children:"A packet of information telling a target to perform an action of some sort."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Telemetry Packet"}),(0,s.jsx)(t.td,{children:"A packet of information providing status from a target."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Interface"}),(0,s.jsx)(t.td,{children:"A Ruby class that knows how to send commands to and/or receive telemetry from a target. COSMOS comes with interfaces that support TCP/IP, UDP, and serial connections. Custom interfaces are easy to add to the system."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Ruby"}),(0,s.jsx)(t.td,{children:"The powerful dynamic programming language used to write the COSMOS applications and libraries as well as COSMOS scripts and test procedures."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Configuration Files"}),(0,s.jsx)(t.td,{children:"COSMOS uses simple plain text configuration files to define commands and telemetry packets, and to configure each COSMOS application. These files are easily human readable/editable and machine readable/editable."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Packet Log Files"}),(0,s.jsx)(t.td,{children:"Binary files containing either logged commands or telemetry packets."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Message Log Files"}),(0,s.jsx)(t.td,{children:"Text files containing messages generated by the system."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool"}),(0,s.jsx)(t.td,{children:"Another name for a COSMOS application."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"overall-architecture-and-context-diagram",children:"Overall Architecture and Context Diagram"}),"\n",(0,s.jsx)(t.p,{children:"The following diagram shows the COSMOS 5 architecture."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"COSMOS Architecture",src:r(324).A+"",width:"1155",height:"538"})}),"\n",(0,s.jsx)(t.p,{children:"Key aspects of this architecture:"}),"\n",(0,s.jsx)(t.p,{children:"COSMOS 5 is a cloud native, containerized, microservice oriented command and control system. All the COSMOS microservices are docker containers which is why Docker is shown containing the entire COSMOS system. The green boxes on the left represent external embedded systems (Targets) which COSMOS connects to. The Redis data store contains the configuration for all the microservices, the current value table, as well as data streams containing decommutated data. The Minio data store contains plugins, targets, configuration data, text logs as well as binary logs of all the raw, decommutated, and reduced data. Users interact with COSMOS from a web browser which routes through the internal Traefik load balancer."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"COSMOS can connect to many different kinds of targets. The examples include things like Flight software (FSW), Ground Support Equipment (GSE), Labview, and COTS targets such as an Agilent power supply. Any embedded system that provides a communication interface can be connected to COSMOS."}),"\n",(0,s.jsx)(t.li,{children:"COSMOS ships with interfaces for connecting over TCP/IP, UDP, MQTT, and serial connections. This covers most systems, but custom interfaces can also be written to connect to anything."}),"\n",(0,s.jsx)(t.li,{children:"All realtime communication with targets flows through the COSMOS system. This ensures all commands and telemetry are logged."}),"\n",(0,s.jsx)(t.li,{children:"Every tool is configured with plain text configuration files."}),"\n",(0,s.jsx)(t.li,{children:"Program specific tools can be written using the COSMOS libraries that can interact with the realtime command and telemetry streams and can process logged data."}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"overall-requirements",children:"Overall Requirements"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-1"}),(0,s.jsx)(t.td,{children:"All COSMOS core functionality shall be containerized."}),(0,s.jsx)(t.td,{children:"Verify COSMOS is running in Docker"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-2"}),(0,s.jsx)(t.td,{children:"The COSMOS user interface shall be accessible from Chromium based web browsers"}),(0,s.jsx)(t.td,{children:"Open COSMOS in Chrome/Edge"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-3"}),(0,s.jsx)(t.td,{children:"The COSMOS user interface shall be accessible from the Firefox web browser"}),(0,s.jsx)(t.td,{children:"Open COSMOS in Firefox"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-4"}),(0,s.jsx)(t.td,{children:"COSMOS shall log all commands sent"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-5"}),(0,s.jsx)(t.td,{children:"COSMOS shall log all telemetry received"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-6"}),(0,s.jsx)(t.td,{children:"COSMOS shall decommutate all telemetry packets recieved"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-7"}),(0,s.jsx)(t.td,{children:"COSMOS shall support autonomously attempting to connect to targets."}),(0,s.jsx)(t.td,{children:"Verify targets are connected upon starting the CTS."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-8"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp telemetry packets upon receipt."}),(0,s.jsx)(t.td,{children:"Verify logged packets are timestamped."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-9"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp telemetry packets to a resolution of 1 millisecond or better. Note: This requirement only refers to resolution. COSMOS does not run on real-time operating systems and accuracy cannot be guaranteed."}),(0,s.jsx)(t.td,{children:"View time stamps in log."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-10"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp received telemetry with a UTC timestamp."}),(0,s.jsx)(t.td,{children:"Verify logged time stamps are as expected."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-11"}),(0,s.jsx)(t.td,{children:"COSMOS shall maintain a timestamped log of commands received, limits violations, and errors encountered."}),(0,s.jsx)(t.td,{children:"View COSMOS message log."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"api-requirements",children:"Api Requirements"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-1"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted connection and disconnection of interfaces."}),(0,s.jsx)(t.td,{children:"Disconnect and connect an interface from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-2"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted connection and disconnection of routers."}),(0,s.jsx)(t.td,{children:"Disconnect and connect a router from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-3"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted setting of the current limits set."}),(0,s.jsx)(t.td,{children:"Select a different limits set from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-4"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow commanding of targets"}),(0,s.jsx)(t.td,{children:"Send a command"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-5"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow reading the current value of any telemetry item"}),(0,s.jsx)(t.td,{children:"Read a telemetry point"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-6"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow streaming realtime and logged telemetry packets"}),(0,s.jsx)(t.td,{children:"Stream telemetry packets"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-7"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow streaming realtime and logged command packets"}),(0,s.jsx)(t.td,{children:"Stream command packets"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-8"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow starting COSMOS scripts"}),(0,s.jsx)(t.td,{children:"Start a script using the API"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"command-and-telemetry-server",children:"Command and Telemetry Server"}),"\n",(0,s.jsx)(t.p,{children:"The Command and Telemetry server provides status on the the overall COSMOS installation for a specific scope."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-1"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all interfaces."}),(0,s.jsx)(t.td,{children:"View the Interfaces tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-2"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manual connection and disconnection of interfaces."}),(0,s.jsx)(t.td,{children:"Press a GUI button to disconnect and connect an interface."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-3"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all targets."}),(0,s.jsx)(t.td,{children:"View the Targets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-4"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of known commands."}),(0,s.jsx)(t.td,{children:"View the Cmd Packets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-5"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display raw command data for the most recent command received."}),(0,s.jsx)(t.td,{children:"View the Cmd Packets tab and click the View Raw button for a command."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-6"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of known telemetry packets."}),(0,s.jsx)(t.td,{children:"View the Tlm Packets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-7"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display raw telemetry packet data for the most recent telemetry packet received."}),(0,s.jsx)(t.td,{children:"View the Tlm Packets tab and click the View Raw button for a telemetry packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-8"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all routers."}),(0,s.jsx)(t.td,{children:"View the Routers tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-9"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manual connection and disconnection of routers."}),(0,s.jsx)(t.td,{children:"Press a GUI button to disconnect and connect a router."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-10"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manually setting the current limits set."}),(0,s.jsx)(t.td,{children:"Select a different limits set from the combobox."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-11"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall support opening telemetry packets in Packet Viewer."}),(0,s.jsx)(t.td,{children:"On the Tlm Packets tab click View in Packet Viewer for a telemetry packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-12"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display time stamps in local time."}),(0,s.jsx)(t.td,{children:"View time stamps in log."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"limits-monitor",children:"Limits Monitor"}),"\n",(0,s.jsx)(t.p,{children:"Limits Monitor displays all telemetry points that are currently out of limits and also shows any telemetry points that have gone out of limits since Limits Monitor was started."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-1"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall display all telemetry points currently out of limits."}),(0,s.jsx)(t.td,{children:"View displayed telemetry points."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-2"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support ignoring telemetry points."}),(0,s.jsx)(t.td,{children:"Click ignore on a telemetry point."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-3"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall keep a displayed log of limits violations."}),(0,s.jsx)(t.td,{children:"View the log tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-4"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall continue displaying a telemetry point that temporarily went out of limits."}),(0,s.jsx)(t.td,{children:"Watch until a telemetry points returns to green."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-5"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support saving its configuration."}),(0,s.jsx)(t.td,{children:"Save the configuration."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-6"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support loading its configuration."}),(0,s.jsx)(t.td,{children:"Load the configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"command-sender",children:"Command Sender"}),"\n",(0,s.jsx)(t.p,{children:"Command Sender provides an easy method to send single commands to targets. The graphical user interface provides simple dropdowns to quickly select the desired command to send organized by target name and command name. After the user has selected the command, they then fill in the desired command parameters and click send to send the command to the target."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-1"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow selection of a command by target name and packet name."}),(0,s.jsx)(t.td,{children:"Select a specific command by target name and packet name in the drop down menus."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-2"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow sending the selected command."}),(0,s.jsx)(t.td,{children:"Send the selected command by pressing the Send button."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-3"}),(0,s.jsx)(t.td,{children:"Command Sender shall display non-ignored parameters for the selected command."}),(0,s.jsx)(t.td,{children:"Select a specific command and verify the expected parameters are shown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-4"}),(0,s.jsx)(t.td,{children:"Command Sender shall provide a mechanism to select state values for command parameters with states."}),(0,s.jsx)(t.td,{children:"Select a specific state value for a specific command with states."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-5"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow sending a manually entered value for a command parameter with states."}),(0,s.jsx)(t.td,{children:"Manually enter a value for a specific command with states."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-6"}),(0,s.jsx)(t.td,{children:"Command Sender shall refuse to send commands if required parameters are not provided."}),(0,s.jsx)(t.td,{children:"Attempt to send a command with a required parameter not filled out."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-7"}),(0,s.jsx)(t.td,{children:"Command Sender shall support sending commands while ignoring range checking."}),(0,s.jsx)(t.td,{children:"Enter Ignore Range Checking mode and then send a command with an out of range parameter."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-8"}),(0,s.jsx)(t.td,{children:"Command Sender shall optionally display state values in hex."}),(0,s.jsx)(t.td,{children:'Enter "Display State Values in Hex" mode and verify state values are displayed as hex.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-9"}),(0,s.jsx)(t.td,{children:"Command Sender shall optionally display ignored command parameters."}),(0,s.jsx)(t.td,{children:'Enter "Show Ignored Parameters" mode and verify ignored parameters are displayed.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-10"}),(0,s.jsx)(t.td,{children:"Command Sender shall respect hazardous commands and notify the user before proceeding."}),(0,s.jsx)(t.td,{children:"Send a hazardous command and verify a dialog box appears before the command is sent. Verify both accepting the dialog and declining to send."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-11"}),(0,s.jsx)(t.td,{children:"Command Sender shall keep a command history of each command sent."}),(0,s.jsx)(t.td,{children:"Send a command and verify that it shows up in the command history box."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-12"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow resending of any command in the command history."}),(0,s.jsx)(t.td,{children:"Resend one of the commands in the command history box."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"script-runner",children:"Script Runner"}),"\n",(0,s.jsx)(t.p,{children:"Script Runner provides a visual interface for editing and executing scripts/procedures. A full featured text editor provides syntax highlighting and code completion while developing scripts. During script execution, the currently executing line is highlighted and any logged messages are highlighted to the user. If any failure occurs, the script is paused and the user alerted. The user can then decide whether to stop the script, or ignore the failure and continue. The user can also retry the failed lines, or other nearby lines before proceeding."}),"\n",(0,s.jsx)(t.p,{children:"Script Runner now also provides a structured methodology for designing system level scripting that mirrors the very successful pattern used in software unit tests (previously implemented in the Test Runner tool). System level tests/procedures are built up of cases that are organized into groups. For example, you might have one group that verified all of the requirements associated with a particular mechanism. Ideally you would break this down into individual cases for different scenarios. One perhaps for opening a shutter, another for closing it, etc. Cases are ideally small and independent tasks. A number of these groups are then combined into an overall suite which would be run to execute a major test such as EMI, or software FQT."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-1"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide a text editor for developing test scripts."}),(0,s.jsx)(t.td,{children:"Open Script Runner and create a simple test script. Perform all standard file operations including New, Open, Reload, Close, Save, and Save As. Perform all standard editing operations such as Cut, Copy, Paste, Undo, Redo, Select All, and Comment/Uncomment lines."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-2"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide search and replace functionality."}),(0,s.jsx)(t.td,{children:"Perform all standard search and replace functionality, including search, replace, find next, and find previous."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-3"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide code completion for cmd(), tlm(), and wait_check() COSMOS API methods. Note: Other methods may also be supported."}),(0,s.jsx)(t.td,{children:"Create a script and exercise code completion on the mentioned keywords."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-4"}),(0,s.jsx)(t.td,{children:"Script Runner shall execute Ruby-based COSMOS scripts."}),(0,s.jsx)(t.td,{children:"Press start and execute a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-5"}),(0,s.jsx)(t.td,{children:"Script Runner shall highlight the currently executing line of the script."}),(0,s.jsx)(t.td,{children:"Verify that lines are highlighted as a test script executes."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-6"}),(0,s.jsx)(t.td,{children:"Script Runner shall allow pausing an executing script."}),(0,s.jsx)(t.td,{children:"Press pause button and verify script is paused. Press start to resume."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-7"}),(0,s.jsx)(t.td,{children:"Script Runner shall allow stopping an executing script."}),(0,s.jsx)(t.td,{children:"Press stop and verify script stops."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-8"}),(0,s.jsx)(t.td,{children:"Script Runner shall pause an executing script upon the occurance of an error."}),(0,s.jsx)(t.td,{children:"Create a script with a statement that is guaranteed to fail and verify that the script is paused."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-9"}),(0,s.jsx)(t.td,{children:"Script Runner shall log commands sent."}),(0,s.jsx)(t.td,{children:"Execute a script that sends a command and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-10"}),(0,s.jsx)(t.td,{children:"Script Runner shall log text written to STDOUT. Note: Typically through the puts method."}),(0,s.jsx)(t.td,{children:"Execute a script that uses puts to write a message and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-11"}),(0,s.jsx)(t.td,{children:"Script Runner shall log wait times."}),(0,s.jsx)(t.td,{children:"Execute a script that includes a wait method and verify wait time is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-12"}),(0,s.jsx)(t.td,{children:"Script Runner shall log errors that occur while the script is executing."}),(0,s.jsx)(t.td,{children:"Create a script with a check statement that is guaranteed to fail and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-13"}),(0,s.jsx)(t.td,{children:"Script Runner shall log check statement success and failure."}),(0,s.jsx)(t.td,{children:"Create a script with a check statement that is guaranteed to fail and one that is guaranteed to succeeed. Verify both the success and failure are logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-14"}),(0,s.jsx)(t.td,{children:"Script Runner shall support executing selected lines."}),(0,s.jsx)(t.td,{children:"Select a set of lines and execute them using Script->Execute Selected Lines."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-15"}),(0,s.jsx)(t.td,{children:"Script Runner shall support executing selected lines while paused."}),(0,s.jsx)(t.td,{children:"Select a set of lines and execute them from the right-click context menu."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-16"}),(0,s.jsx)(t.td,{children:"Script Runner shall support starting a script from any line."}),(0,s.jsx)(t.td,{children:"Place the mouse cursor at the desired first line and then select Script->Execute From Cursor."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-17"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a mnemonic checking function."}),(0,s.jsx)(t.td,{children:"Select Script->Mnemonic Check."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-18"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a syntax checking function."}),(0,s.jsx)(t.td,{children:"Select Script->Ruby Syntax Check."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-19"}),(0,s.jsx)(t.td,{children:"Script Runner shall support viewing the script instrumentation."}),(0,s.jsx)(t.td,{children:"Select Script->View Instrumented Script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-20"}),(0,s.jsx)(t.td,{children:"Script Runner shall support an disconnected mode to allow for executing scripts without a connection to the Command and Telemetry Server."}),(0,s.jsx)(t.td,{children:"Select Script->Toggle Disconnect. Execute a script with commands and check statements and verify that it runs to completion."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-21"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a Debug terminal to aid in debugging scripts."}),(0,s.jsx)(t.td,{children:"Select Script->Toggle Debug."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-22"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a step mode where the script will stop and wait for use interaction after each line."}),(0,s.jsx)(t.td,{children:"Press Step to progress through the script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-23"}),(0,s.jsx)(t.td,{children:"Script Runner shall support breakpoint functionality."}),(0,s.jsx)(t.td,{children:"Create a breakpoint then execute the script and verify it stops at the specified line."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-25"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test suites."}),(0,s.jsx)(t.td,{children:"Execute an individual test suite."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-26"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test groups."}),(0,s.jsx)(t.td,{children:"Execute an individual test group."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-27"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test cases."}),(0,s.jsx)(t.td,{children:"Execute an individual test case."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-28"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing test group setup and teardown methods individually."}),(0,s.jsx)(t.td,{children:"Execute a test group setup. Execute a test group teardown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-29"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing test suite setup and teardown methods individually."}),(0,s.jsx)(t.td,{children:"Execute a test suite setup. Execute a test suite teardown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-30"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall create a report after executing any suite test."}),(0,s.jsx)(t.td,{children:"Verify a report is generated after executing a suite."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-31"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support pausing when an error occurs."}),(0,s.jsx)(t.td,{children:"Execute a test script with the pause on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-32"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support allowing the user to proceed on an error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the Allow go/retry on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-33"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support aborting execution on an error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the abort on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-34"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support looping a test."}),(0,s.jsx)(t.td,{children:"Execute a test script with the loop testing box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-35"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support breaking the looping of a test on error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the break loop on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-36"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support a user readable flag indicating that loop testing is occurring."}),(0,s.jsx)(t.td,{children:"Execute a test script that checks the $loop_testing variable while looping and again while not looping."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-37"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support a user readable flag indicating manual operations are desired."}),(0,s.jsx)(t.td,{children:"Execute a test script with the manual box checked and without."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"packet-viewer",children:"Packet Viewer"}),"\n",(0,s.jsx)(t.p,{children:"Packet Viewer provides a simple tool to view the realtime contents of any telemetry packet defined in the system in a tabular, key-value format."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-1"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall allow selection of a telemetry packet by target name and packet name."}),(0,s.jsx)(t.td,{children:"Select a specific telemetry packet by target name and packet name in the drop down menus."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-2"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall display the contents of the selected telemetry packet."}),(0,s.jsx)(t.td,{children:"Ensure all items of the selected telemetry packet are displayed and updating."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-3"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall provide a mechanism to get detailed information on a telemetry item."}),(0,s.jsx)(t.td,{children:'Right click on a telemetry item and select "Details" from the context menu.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-4"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall provide a mechanism to view a graph of any telemetry item."}),(0,s.jsx)(t.td,{children:'Right click on a telemetry item and select "Graph" from the context menu.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-5"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall color telemetry values based upon limits state."}),(0,s.jsx)(t.td,{children:"View a packet with items containing limits and verify they are colored."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-6"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support a configurable polling rate."}),(0,s.jsx)(t.td,{children:"Select File->Options and change the polling rate."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-7"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support a color-blind mode to allow distinguishing limits states for those who are color blind."}),(0,s.jsx)(t.td,{children:"Select View->Color Blind Mode and verify that items with limits are also displayed with a textual indication of limits state color."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-8"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support displaying telemetry in each of the four COSMOS value types (raw, converted, formatted, and formatted with units)"}),(0,s.jsx)(t.td,{children:"In the View menu, select each of the four value types and verify values are displayed accordingly."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"telemetry-viewer",children:"Telemetry Viewer"}),"\n",(0,s.jsx)(t.p,{children:'Telemetry Viewer provides a way to organize telemetry points into custom "screens" that allow for the creation of unique and organized views of telemetry data. Screens are made up of widgets or small GUI components that display telemetry in unique ways.'}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-1"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall display user-defined telemetry screens."}),(0,s.jsx)(t.td,{children:"Open a telemetry"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-2"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall display realtime data."}),(0,s.jsx)(t.td,{children:"Verify telemetry screens show realtime data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-3"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall support saving open telemetry screens and their positions."}),(0,s.jsx)(t.td,{children:"Open three telemetry screens and then select File->Save Configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"telemetry-grapher",children:"Telemetry Grapher"}),"\n",(0,s.jsx)(t.p,{children:"Telemetry Grapher performs graphing of telemetry points in both realtime and log file playback."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-1"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall provide line graphs of telemetry points."}),(0,s.jsx)(t.td,{children:"Add several housekeeping data objects to a plot."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-2"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support realtime graphing of telemetry."}),(0,s.jsx)(t.td,{children:"Press Start to start realtime graphing."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-3"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing data from logged telemetry."}),(0,s.jsx)(t.td,{children:"Select the menu option to graph data from a logged data"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-4"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support multiple plots per browser tab."}),(0,s.jsx)(t.td,{children:"Add multiple plots."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-5"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support multiple telemetry points per plot."}),(0,s.jsx)(t.td,{children:"Add multiple data objects to one plot."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-6"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support saving a variable number of data points."}),(0,s.jsx)(t.td,{children:"Edit Points Saved."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-7"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing a variable duration of time."}),(0,s.jsx)(t.td,{children:"Edit Seconds Plotted."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-8"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing a variable number of data points."}),(0,s.jsx)(t.td,{children:"Edit Points Plotted."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-9"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support saving its configuration."}),(0,s.jsx)(t.td,{children:"Save the current configuration."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-10"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support loading its configuration."}),(0,s.jsx)(t.td,{children:"Load the previously saved configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"data-extractor",children:"Data Extractor"}),"\n",(0,s.jsx)(t.p,{children:"Data Extractor processes logged data and extracts data into a CSV format for analysis in Excel or other tools."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-1"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding individual telemetry points."}),(0,s.jsx)(t.td,{children:"Add an individual telemetry point."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-2"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding entire telemetry packets."}),(0,s.jsx)(t.td,{children:"Add an entire packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-3"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding entire telemetry targets."}),(0,s.jsx)(t.td,{children:"Add all packets for a target."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-4"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support selecting the value type to extract for each telemetry point (RAW, CONVERTED, FORMATTED, WITH_UNITS)"}),(0,s.jsx)(t.td,{children:"Click an item and change the value type."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-5"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support saving configurations."}),(0,s.jsx)(t.td,{children:"Select File->Save Config"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-6"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support loading configurations."}),(0,s.jsx)(t.td,{children:"Select File->Load Config"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-7"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support deleting items"}),(0,s.jsx)(t.td,{children:"Select an Item and press delete"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"data-viewer",children:"Data Viewer"}),"\n",(0,s.jsx)(t.p,{children:"Data Viewer provides for textual display of telemetry packets where other display methods are not a good fit. It is especially useful for memory dumps and for log message type data display."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-1"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support realtime processing of telemetry packets."}),(0,s.jsx)(t.td,{children:"Press Start to start realtime processing."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-2"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support logged playback of telemetry packets."}),(0,s.jsx)(t.td,{children:"Select a time range to playback."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-3"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support textual display of telemetry packets."}),(0,s.jsx)(t.td,{children:"View the display of data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-4"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support multiple tabs for data display."}),(0,s.jsx)(t.td,{children:"Switch between several tabs of data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-5"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support deleting tabs."}),(0,s.jsx)(t.td,{children:"Delete a tab."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"calendar",children:"Calendar"}),"\n",(0,s.jsx)(t.p,{children:"The Calendar tool provides a user interface and API for initiating scheduled actions in COSMOS"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-1"}),(0,s.jsx)(t.td,{children:"Calendar shall allow creating new timelines"}),(0,s.jsx)(t.td,{children:"Click the button and create a new timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-2"}),(0,s.jsx)(t.td,{children:"Calendar shall allow scheduling commands for future execection"}),(0,s.jsx)(t.td,{children:"Add a command to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-3"}),(0,s.jsx)(t.td,{children:"Calendar shall allow scheduling scripts for future execution"}),(0,s.jsx)(t.td,{children:"Add a script to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-4"}),(0,s.jsx)(t.td,{children:"Calendar shall allow for reserving a resource"}),(0,s.jsx)(t.td,{children:"Add a reservation to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-5"}),(0,s.jsx)(t.td,{children:"Calendar shall track success or failure of commands"}),(0,s.jsx)(t.td,{children:"Look at status from a completed command"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-6"}),(0,s.jsx)(t.td,{children:"Calendar shall track success or failure of scripts"}),(0,s.jsx)(t.td,{children:"Look at status from a completed script"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-7"}),(0,s.jsx)(t.td,{children:"Calendar shall allow deleting activities from timelines"}),(0,s.jsx)(t.td,{children:"Delete a preexisting item from a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-8"}),(0,s.jsx)(t.td,{children:"Calendar shall allow deleting timelines"}),(0,s.jsx)(t.td,{children:"Delete a timeline"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"admin",children:"Admin"}),"\n",(0,s.jsx)(t.p,{children:"The Admin tool provides administrative functionality including managing plugins for the COSMOS system"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-1"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall allow installing plugins"}),(0,s.jsx)(t.td,{children:"Upload and Install a Plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-2"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support upgrading plugins"}),(0,s.jsx)(t.td,{children:"Upgrade an installed plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-3"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support uninstalling plugins"}),(0,s.jsx)(t.td,{children:"Uninstall a plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-4"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall display information on installed plugins"}),(0,s.jsx)(t.td,{children:"View info on Interfaces, Microservices, etc"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-5"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support editing microservices"}),(0,s.jsx)(t.td,{children:"Edit the settings for a microservice"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-6"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support discovery of plugins"}),(0,s.jsx)(t.td,{children:"Discover and download a plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-7"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support adding links to external tools"}),(0,s.jsx)(t.td,{children:"Add a link to Google"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-8"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support reordering tools"}),(0,s.jsx)(t.td,{children:"Reorder tools on the tools tab"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-9"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support configuring a classification bar"}),(0,s.jsx)(t.td,{children:"Add a classification bar on the settings tab"})]})]})]})]})}function o(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},324:(e,t,r)=>{r.d(t,{A:()=>s});const s=r.p+"assets/images/architecture-b78f12eba076a0c07af7abdd9dd4187c59aa6b4f5c51b47ad03f73e9f98a6ed6.png"},8453:(e,t,r)=>{r.d(t,{R:()=>d,x:()=>l});var s=r(6540);const n={},i=s.createContext(n);function d(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:d(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[8353],{1276:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>d,default:()=>o,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var s=r(4848),n=r(8453);const i={sidebar_position:6,title:"Requirements and Design"},d=void 0,l={id:"getting-started/requirements",title:"Requirements and Design",description:"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations.",source:"@site/docs/getting-started/requirements.md",sourceDirName:"getting-started",slug:"/getting-started/requirements",permalink:"/docs/getting-started/requirements",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/getting-started/requirements.md",tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6,title:"Requirements and Design"},sidebar:"defaultSidebar",previous:{title:"Key Concepts",permalink:"/docs/getting-started/key_concepts"},next:{title:"Podman",permalink:"/docs/getting-started/podman"}},a={},c=[{value:"Terminology",id:"terminology",level:2},{value:"Overall Architecture and Context Diagram",id:"overall-architecture-and-context-diagram",level:2},{value:"Overall Requirements",id:"overall-requirements",level:2},{value:"Api Requirements",id:"api-requirements",level:2},{value:"Command and Telemetry Server",id:"command-and-telemetry-server",level:2},{value:"Limits Monitor",id:"limits-monitor",level:2},{value:"Command Sender",id:"command-sender",level:2},{value:"Script Runner",id:"script-runner",level:2},{value:"Packet Viewer",id:"packet-viewer",level:2},{value:"Telemetry Viewer",id:"telemetry-viewer",level:2},{value:"Telemetry Grapher",id:"telemetry-grapher",level:2},{value:"Data Extractor",id:"data-extractor",level:2},{value:"Data Viewer",id:"data-viewer",level:2},{value:"Calendar",id:"calendar",level:2},{value:"Admin",id:"admin",level:2}];function h(e){const t={h2:"h2",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations."}),"\n",(0,s.jsx)(t.p,{children:"COSMOS is currently made up of the following applications:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Command and Telemetry Server"})," - Provides status of realtime commanding, telemetry reception, logging, limits monitoring, and packet routing."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Limits Monitor"})," - Monitors telemetry with defined limits and shows items that currently are or have violated limits."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Command Sender"})," - Provides a graphical interface for manually sending individual commands."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Script Runner"})," - Executes scripts and provides highlighting of the currently executing line. Now also includes TestRunner functionality."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Packet Viewer"})," - Provides realtime visualization of every telemetry packet that has been defined."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Telemetry Viewer"})," - Provides custom telemetry screen functionality with advanced layout and visualization widgets."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Telemetry Grapher"})," - Provides realtime and offline graphing of telemetry data."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Data Extractor"})," - Extracts telemetry and command packet log files into CSV data."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Data Viewer"})," - Provides text based telemetry visualization for items."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Bucket Explorer"})," - Browse the COSMOS bucket storage in any cloud environment."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Table Manager"})," - Binary file editor with Script Runner integration for upload / download."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Handbooks"})," - Generate html page of the command and telemetry definitions."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Calendar"})," - Provides scheduling of commands and scripts. Also provides a framework for reserving resources."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Admin"})," - Provides an administrative interface to COSMOS."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"More detailed descriptions, requirements, and design for each tool are found later in this document. Additionally, each of the above applications is built using COSMOS libraries that are available for use as a framework to develop custom program/project applications."}),"\n",(0,s.jsx)(t.h2,{id:"terminology",children:"Terminology"}),"\n",(0,s.jsx)(t.p,{children:"The COSMOS system uses several terms that are important to understand. The following table defines these terms."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Term"}),(0,s.jsx)(t.th,{children:"Definition"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Target"}),(0,s.jsx)(t.td,{children:"A COSMOS target is an embedded system that the COSMOS Command and Telemetry Server connects to using an interface in order to send commands to and/or receive telemetry from."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Command"}),(0,s.jsx)(t.td,{children:"A packet of information telling a target to perform an action of some sort."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Telemetry Packet"}),(0,s.jsx)(t.td,{children:"A packet of information providing status from a target."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Interface"}),(0,s.jsx)(t.td,{children:"A Ruby class that knows how to send commands to and/or receive telemetry from a target. COSMOS comes with interfaces that support TCP/IP, UDP, and serial connections. Custom interfaces are easy to add to the system."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Ruby"}),(0,s.jsx)(t.td,{children:"The powerful dynamic programming language used to write the COSMOS applications and libraries as well as COSMOS scripts and test procedures."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Configuration Files"}),(0,s.jsx)(t.td,{children:"COSMOS uses simple plain text configuration files to define commands and telemetry packets, and to configure each COSMOS application. These files are easily human readable/editable and machine readable/editable."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Packet Log Files"}),(0,s.jsx)(t.td,{children:"Binary files containing either logged commands or telemetry packets."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Message Log Files"}),(0,s.jsx)(t.td,{children:"Text files containing messages generated by the system."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Tool"}),(0,s.jsx)(t.td,{children:"Another name for a COSMOS application."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"overall-architecture-and-context-diagram",children:"Overall Architecture and Context Diagram"}),"\n",(0,s.jsx)(t.p,{children:"The following diagram shows the COSMOS 5 architecture."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"COSMOS Architecture",src:r(324).A+"",width:"1155",height:"538"})}),"\n",(0,s.jsx)(t.p,{children:"Key aspects of this architecture:"}),"\n",(0,s.jsx)(t.p,{children:"COSMOS 5 is a cloud native, containerized, microservice oriented command and control system. All the COSMOS microservices are docker containers which is why Docker is shown containing the entire COSMOS system. The green boxes on the left represent external embedded systems (Targets) which COSMOS connects to. The Redis data store contains the configuration for all the microservices, the current value table, as well as data streams containing decommutated data. The Minio data store contains plugins, targets, configuration data, text logs as well as binary logs of all the raw, decommutated, and reduced data. Users interact with COSMOS from a web browser which routes through the internal Traefik load balancer."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"COSMOS can connect to many different kinds of targets. The examples include things like Flight software (FSW), Ground Support Equipment (GSE), Labview, and COTS targets such as an Agilent power supply. Any embedded system that provides a communication interface can be connected to COSMOS."}),"\n",(0,s.jsx)(t.li,{children:"COSMOS ships with interfaces for connecting over TCP/IP, UDP, MQTT, and serial connections. This covers most systems, but custom interfaces can also be written to connect to anything."}),"\n",(0,s.jsx)(t.li,{children:"All realtime communication with targets flows through the COSMOS system. This ensures all commands and telemetry are logged."}),"\n",(0,s.jsx)(t.li,{children:"Every tool is configured with plain text configuration files."}),"\n",(0,s.jsx)(t.li,{children:"Program specific tools can be written using the COSMOS libraries that can interact with the realtime command and telemetry streams and can process logged data."}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"overall-requirements",children:"Overall Requirements"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-1"}),(0,s.jsx)(t.td,{children:"All COSMOS core functionality shall be containerized."}),(0,s.jsx)(t.td,{children:"Verify COSMOS is running in Docker"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-2"}),(0,s.jsx)(t.td,{children:"The COSMOS user interface shall be accessible from Chromium based web browsers"}),(0,s.jsx)(t.td,{children:"Open COSMOS in Chrome/Edge"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-3"}),(0,s.jsx)(t.td,{children:"The COSMOS user interface shall be accessible from the Firefox web browser"}),(0,s.jsx)(t.td,{children:"Open COSMOS in Firefox"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-4"}),(0,s.jsx)(t.td,{children:"COSMOS shall log all commands sent"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-5"}),(0,s.jsx)(t.td,{children:"COSMOS shall log all telemetry received"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-6"}),(0,s.jsx)(t.td,{children:"COSMOS shall decommutate all telemetry packets received"}),(0,s.jsx)(t.td,{})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-7"}),(0,s.jsx)(t.td,{children:"COSMOS shall support autonomously attempting to connect to targets."}),(0,s.jsx)(t.td,{children:"Verify targets are connected upon starting the CTS."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-8"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp telemetry packets upon receipt."}),(0,s.jsx)(t.td,{children:"Verify logged packets are timestamped."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-9"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp telemetry packets to a resolution of 1 millisecond or better. Note: This requirement only refers to resolution. COSMOS does not run on real-time operating systems and accuracy cannot be guaranteed."}),(0,s.jsx)(t.td,{children:"View time stamps in log."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-10"}),(0,s.jsx)(t.td,{children:"COSMOS shall time stamp received telemetry with a UTC timestamp."}),(0,s.jsx)(t.td,{children:"Verify logged time stamps are as expected."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"COSMOS-11"}),(0,s.jsx)(t.td,{children:"COSMOS shall maintain a timestamped log of commands received, limits violations, and errors encountered."}),(0,s.jsx)(t.td,{children:"View COSMOS message log."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"api-requirements",children:"Api Requirements"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-1"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted connection and disconnection of interfaces."}),(0,s.jsx)(t.td,{children:"Disconnect and connect an interface from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-2"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted connection and disconnection of routers."}),(0,s.jsx)(t.td,{children:"Disconnect and connect a router from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-3"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow scripted setting of the current limits set."}),(0,s.jsx)(t.td,{children:"Select a different limits set from a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-4"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow commanding of targets"}),(0,s.jsx)(t.td,{children:"Send a command"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-5"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow reading the current value of any telemetry item"}),(0,s.jsx)(t.td,{children:"Read a telemetry point"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-6"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow streaming realtime and logged telemetry packets"}),(0,s.jsx)(t.td,{children:"Stream telemetry packets"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-7"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow streaming realtime and logged command packets"}),(0,s.jsx)(t.td,{children:"Stream command packets"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"API-8"}),(0,s.jsx)(t.td,{children:"The COSMOS API shall allow starting COSMOS scripts"}),(0,s.jsx)(t.td,{children:"Start a script using the API"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"command-and-telemetry-server",children:"Command and Telemetry Server"}),"\n",(0,s.jsx)(t.p,{children:"The Command and Telemetry server provides status on the the overall COSMOS installation for a specific scope."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-1"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all interfaces."}),(0,s.jsx)(t.td,{children:"View the Interfaces tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-2"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manual connection and disconnection of interfaces."}),(0,s.jsx)(t.td,{children:"Press a GUI button to disconnect and connect an interface."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-3"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all targets."}),(0,s.jsx)(t.td,{children:"View the Targets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-4"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of known commands."}),(0,s.jsx)(t.td,{children:"View the Cmd Packets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-5"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display raw command data for the most recent command received."}),(0,s.jsx)(t.td,{children:"View the Cmd Packets tab and click the View Raw button for a command."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-6"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of known telemetry packets."}),(0,s.jsx)(t.td,{children:"View the Tlm Packets tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-7"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display raw telemetry packet data for the most recent telemetry packet received."}),(0,s.jsx)(t.td,{children:"View the Tlm Packets tab and click the View Raw button for a telemetry packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-8"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display a list of all routers."}),(0,s.jsx)(t.td,{children:"View the Routers tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-9"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manual connection and disconnection of routers."}),(0,s.jsx)(t.td,{children:"Press a GUI button to disconnect and connect a router."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-10"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall allow manually setting the current limits set."}),(0,s.jsx)(t.td,{children:"Select a different limits set from the combobox."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-11"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall support opening telemetry packets in Packet Viewer."}),(0,s.jsx)(t.td,{children:"On the Tlm Packets tab click View in Packet Viewer for a telemetry packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CTS-12"}),(0,s.jsx)(t.td,{children:"The Command and Telemetry Server shall display time stamps in local time."}),(0,s.jsx)(t.td,{children:"View time stamps in log."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"limits-monitor",children:"Limits Monitor"}),"\n",(0,s.jsx)(t.p,{children:"Limits Monitor displays all telemetry points that are currently out of limits and also shows any telemetry points that have gone out of limits since Limits Monitor was started."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-1"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall display all telemetry points currently out of limits."}),(0,s.jsx)(t.td,{children:"View displayed telemetry points."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-2"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support ignoring telemetry points."}),(0,s.jsx)(t.td,{children:"Click ignore on a telemetry point."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-3"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall keep a displayed log of limits violations."}),(0,s.jsx)(t.td,{children:"View the log tab."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-4"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall continue displaying a telemetry point that temporarily went out of limits."}),(0,s.jsx)(t.td,{children:"Watch until a telemetry points returns to green."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-5"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support saving its configuration."}),(0,s.jsx)(t.td,{children:"Save the configuration."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"LM-6"}),(0,s.jsx)(t.td,{children:"Limits Monitor shall support loading its configuration."}),(0,s.jsx)(t.td,{children:"Load the configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"command-sender",children:"Command Sender"}),"\n",(0,s.jsx)(t.p,{children:"Command Sender provides an easy method to send single commands to targets. The graphical user interface provides simple dropdowns to quickly select the desired command to send organized by target name and command name. After the user has selected the command, they then fill in the desired command parameters and click send to send the command to the target."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-1"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow selection of a command by target name and packet name."}),(0,s.jsx)(t.td,{children:"Select a specific command by target name and packet name in the drop down menus."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-2"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow sending the selected command."}),(0,s.jsx)(t.td,{children:"Send the selected command by pressing the Send button."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-3"}),(0,s.jsx)(t.td,{children:"Command Sender shall display non-ignored parameters for the selected command."}),(0,s.jsx)(t.td,{children:"Select a specific command and verify the expected parameters are shown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-4"}),(0,s.jsx)(t.td,{children:"Command Sender shall provide a mechanism to select state values for command parameters with states."}),(0,s.jsx)(t.td,{children:"Select a specific state value for a specific command with states."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-5"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow sending a manually entered value for a command parameter with states."}),(0,s.jsx)(t.td,{children:"Manually enter a value for a specific command with states."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-6"}),(0,s.jsx)(t.td,{children:"Command Sender shall refuse to send commands if required parameters are not provided."}),(0,s.jsx)(t.td,{children:"Attempt to send a command with a required parameter not filled out."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-7"}),(0,s.jsx)(t.td,{children:"Command Sender shall support sending commands while ignoring range checking."}),(0,s.jsx)(t.td,{children:"Enter Ignore Range Checking mode and then send a command with an out of range parameter."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-8"}),(0,s.jsx)(t.td,{children:"Command Sender shall optionally display state values in hex."}),(0,s.jsx)(t.td,{children:'Enter "Display State Values in Hex" mode and verify state values are displayed as hex.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-9"}),(0,s.jsx)(t.td,{children:"Command Sender shall optionally display ignored command parameters."}),(0,s.jsx)(t.td,{children:'Enter "Show Ignored Parameters" mode and verify ignored parameters are displayed.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-10"}),(0,s.jsx)(t.td,{children:"Command Sender shall respect hazardous commands and notify the user before proceeding."}),(0,s.jsx)(t.td,{children:"Send a hazardous command and verify a dialog box appears before the command is sent. Verify both accepting the dialog and declining to send."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-11"}),(0,s.jsx)(t.td,{children:"Command Sender shall keep a command history of each command sent."}),(0,s.jsx)(t.td,{children:"Send a command and verify that it shows up in the command history box."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"CMD-12"}),(0,s.jsx)(t.td,{children:"Command Sender shall allow resending of any command in the command history."}),(0,s.jsx)(t.td,{children:"Resend one of the commands in the command history box."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"script-runner",children:"Script Runner"}),"\n",(0,s.jsx)(t.p,{children:"Script Runner provides a visual interface for editing and executing scripts/procedures. A full featured text editor provides syntax highlighting and code completion while developing scripts. During script execution, the currently executing line is highlighted and any logged messages are highlighted to the user. If any failure occurs, the script is paused and the user alerted. The user can then decide whether to stop the script, or ignore the failure and continue. The user can also retry the failed lines, or other nearby lines before proceeding."}),"\n",(0,s.jsx)(t.p,{children:"Script Runner now also provides a structured methodology for designing system level scripting that mirrors the very successful pattern used in software unit tests (previously implemented in the Test Runner tool). System level tests/procedures are built up of cases that are organized into groups. For example, you might have one group that verified all of the requirements associated with a particular mechanism. Ideally you would break this down into individual cases for different scenarios. One perhaps for opening a shutter, another for closing it, etc. Cases are ideally small and independent tasks. A number of these groups are then combined into an overall suite which would be run to execute a major test such as EMI, or software FQT."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-1"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide a text editor for developing test scripts."}),(0,s.jsx)(t.td,{children:"Open Script Runner and create a simple test script. Perform all standard file operations including New, Open, Reload, Close, Save, and Save As. Perform all standard editing operations such as Cut, Copy, Paste, Undo, Redo, Select All, and Comment/Uncomment lines."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-2"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide search and replace functionality."}),(0,s.jsx)(t.td,{children:"Perform all standard search and replace functionality, including search, replace, find next, and find previous."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-3"}),(0,s.jsx)(t.td,{children:"Script Runner shall provide code completion for cmd(), tlm(), and wait_check() COSMOS API methods. Note: Other methods may also be supported."}),(0,s.jsx)(t.td,{children:"Create a script and exercise code completion on the mentioned keywords."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-4"}),(0,s.jsx)(t.td,{children:"Script Runner shall execute Ruby-based COSMOS scripts."}),(0,s.jsx)(t.td,{children:"Press start and execute a script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-5"}),(0,s.jsx)(t.td,{children:"Script Runner shall highlight the currently executing line of the script."}),(0,s.jsx)(t.td,{children:"Verify that lines are highlighted as a test script executes."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-6"}),(0,s.jsx)(t.td,{children:"Script Runner shall allow pausing an executing script."}),(0,s.jsx)(t.td,{children:"Press pause button and verify script is paused. Press start to resume."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-7"}),(0,s.jsx)(t.td,{children:"Script Runner shall allow stopping an executing script."}),(0,s.jsx)(t.td,{children:"Press stop and verify script stops."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-8"}),(0,s.jsx)(t.td,{children:"Script Runner shall pause an executing script upon the occurrence of an error."}),(0,s.jsx)(t.td,{children:"Create a script with a statement that is guaranteed to fail and verify that the script is paused."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-9"}),(0,s.jsx)(t.td,{children:"Script Runner shall log commands sent."}),(0,s.jsx)(t.td,{children:"Execute a script that sends a command and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-10"}),(0,s.jsx)(t.td,{children:"Script Runner shall log text written to STDOUT. Note: Typically through the puts method."}),(0,s.jsx)(t.td,{children:"Execute a script that uses puts to write a message and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-11"}),(0,s.jsx)(t.td,{children:"Script Runner shall log wait times."}),(0,s.jsx)(t.td,{children:"Execute a script that includes a wait method and verify wait time is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-12"}),(0,s.jsx)(t.td,{children:"Script Runner shall log errors that occur while the script is executing."}),(0,s.jsx)(t.td,{children:"Create a script with a check statement that is guaranteed to fail and verify it is logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-13"}),(0,s.jsx)(t.td,{children:"Script Runner shall log check statement success and failure."}),(0,s.jsx)(t.td,{children:"Create a script with a check statement that is guaranteed to fail and one that is guaranteed to succeed. Verify both the success and failure are logged."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-14"}),(0,s.jsx)(t.td,{children:"Script Runner shall support executing selected lines."}),(0,s.jsx)(t.td,{children:"Select a set of lines and execute them using Script->Execute Selected Lines."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-15"}),(0,s.jsx)(t.td,{children:"Script Runner shall support executing selected lines while paused."}),(0,s.jsx)(t.td,{children:"Select a set of lines and execute them from the right-click context menu."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-16"}),(0,s.jsx)(t.td,{children:"Script Runner shall support starting a script from any line."}),(0,s.jsx)(t.td,{children:"Place the mouse cursor at the desired first line and then select Script->Execute From Cursor."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-17"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a mnemonic checking function."}),(0,s.jsx)(t.td,{children:"Select Script->Mnemonic Check."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-18"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a syntax checking function."}),(0,s.jsx)(t.td,{children:"Select Script->Ruby Syntax Check."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-19"}),(0,s.jsx)(t.td,{children:"Script Runner shall support viewing the script instrumentation."}),(0,s.jsx)(t.td,{children:"Select Script->View Instrumented Script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-20"}),(0,s.jsx)(t.td,{children:"Script Runner shall support an disconnected mode to allow for executing scripts without a connection to the Command and Telemetry Server."}),(0,s.jsx)(t.td,{children:"Select Script->Toggle Disconnect. Execute a script with commands and check statements and verify that it runs to completion."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-21"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a Debug terminal to aid in debugging scripts."}),(0,s.jsx)(t.td,{children:"Select Script->Toggle Debug."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-22"}),(0,s.jsx)(t.td,{children:"Script Runner shall support a step mode where the script will stop and wait for use interaction after each line."}),(0,s.jsx)(t.td,{children:"Press Step to progress through the script."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-23"}),(0,s.jsx)(t.td,{children:"Script Runner shall support breakpoint functionality."}),(0,s.jsx)(t.td,{children:"Create a breakpoint then execute the script and verify it stops at the specified line."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-25"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test suites."}),(0,s.jsx)(t.td,{children:"Execute an individual test suite."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-26"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test groups."}),(0,s.jsx)(t.td,{children:"Execute an individual test group."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-27"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing individual test cases."}),(0,s.jsx)(t.td,{children:"Execute an individual test case."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-28"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing test group setup and teardown methods individually."}),(0,s.jsx)(t.td,{children:"Execute a test group setup. Execute a test group teardown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-29"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support executing test suite setup and teardown methods individually."}),(0,s.jsx)(t.td,{children:"Execute a test suite setup. Execute a test suite teardown."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-30"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall create a report after executing any suite test."}),(0,s.jsx)(t.td,{children:"Verify a report is generated after executing a suite."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-31"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support pausing when an error occurs."}),(0,s.jsx)(t.td,{children:"Execute a test script with the pause on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-32"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support allowing the user to proceed on an error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the Allow go/retry on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-33"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support aborting execution on an error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the abort on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-34"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support looping a test."}),(0,s.jsx)(t.td,{children:"Execute a test script with the loop testing box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-35"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support breaking the looping of a test on error."}),(0,s.jsx)(t.td,{children:"Execute a test script with the break loop on error box checked and without."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-36"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support a user readable flag indicating that loop testing is occurring."}),(0,s.jsx)(t.td,{children:"Execute a test script that checks the $loop_testing variable while looping and again while not looping."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"SR-37"}),(0,s.jsx)(t.td,{children:"Script Runner Suite Mode shall support a user readable flag indicating manual operations are desired."}),(0,s.jsx)(t.td,{children:"Execute a test script with the manual box checked and without."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"packet-viewer",children:"Packet Viewer"}),"\n",(0,s.jsx)(t.p,{children:"Packet Viewer provides a simple tool to view the realtime contents of any telemetry packet defined in the system in a tabular, key-value format."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-1"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall allow selection of a telemetry packet by target name and packet name."}),(0,s.jsx)(t.td,{children:"Select a specific telemetry packet by target name and packet name in the drop down menus."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-2"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall display the contents of the selected telemetry packet."}),(0,s.jsx)(t.td,{children:"Ensure all items of the selected telemetry packet are displayed and updating."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-3"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall provide a mechanism to get detailed information on a telemetry item."}),(0,s.jsx)(t.td,{children:'Right click on a telemetry item and select "Details" from the context menu.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-4"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall provide a mechanism to view a graph of any telemetry item."}),(0,s.jsx)(t.td,{children:'Right click on a telemetry item and select "Graph" from the context menu.'})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-5"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall color telemetry values based upon limits state."}),(0,s.jsx)(t.td,{children:"View a packet with items containing limits and verify they are colored."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-6"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support a configurable polling rate."}),(0,s.jsx)(t.td,{children:"Select File->Options and change the polling rate."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-7"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support a color-blind mode to allow distinguishing limits states for those who are color blind."}),(0,s.jsx)(t.td,{children:"Select View->Color Blind Mode and verify that items with limits are also displayed with a textual indication of limits state color."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"PV-8"}),(0,s.jsx)(t.td,{children:"Packet Viewer shall support displaying telemetry in each of the four COSMOS value types (raw, converted, formatted, and formatted with units)"}),(0,s.jsx)(t.td,{children:"In the View menu, select each of the four value types and verify values are displayed accordingly."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"telemetry-viewer",children:"Telemetry Viewer"}),"\n",(0,s.jsx)(t.p,{children:'Telemetry Viewer provides a way to organize telemetry points into custom "screens" that allow for the creation of unique and organized views of telemetry data. Screens are made up of widgets or small GUI components that display telemetry in unique ways.'}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-1"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall display user-defined telemetry screens."}),(0,s.jsx)(t.td,{children:"Open a telemetry"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-2"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall display realtime data."}),(0,s.jsx)(t.td,{children:"Verify telemetry screens show realtime data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TV-3"}),(0,s.jsx)(t.td,{children:"Telemetry Viewer shall support saving open telemetry screens and their positions."}),(0,s.jsx)(t.td,{children:"Open three telemetry screens and then select File->Save Configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"telemetry-grapher",children:"Telemetry Grapher"}),"\n",(0,s.jsx)(t.p,{children:"Telemetry Grapher performs graphing of telemetry points in both realtime and log file playback."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-1"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall provide line graphs of telemetry points."}),(0,s.jsx)(t.td,{children:"Add several housekeeping data objects to a plot."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-2"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support realtime graphing of telemetry."}),(0,s.jsx)(t.td,{children:"Press Start to start realtime graphing."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-3"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing data from logged telemetry."}),(0,s.jsx)(t.td,{children:"Select the menu option to graph data from a logged data"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-4"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support multiple plots per browser tab."}),(0,s.jsx)(t.td,{children:"Add multiple plots."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-5"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support multiple telemetry points per plot."}),(0,s.jsx)(t.td,{children:"Add multiple data objects to one plot."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-6"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support saving a variable number of data points."}),(0,s.jsx)(t.td,{children:"Edit Points Saved."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-7"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing a variable duration of time."}),(0,s.jsx)(t.td,{children:"Edit Seconds Plotted."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-8"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support graphing a variable number of data points."}),(0,s.jsx)(t.td,{children:"Edit Points Plotted."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-9"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support saving its configuration."}),(0,s.jsx)(t.td,{children:"Save the current configuration."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TG-10"}),(0,s.jsx)(t.td,{children:"Telemetry Grapher shall support loading its configuration."}),(0,s.jsx)(t.td,{children:"Load the previously saved configuration."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"data-extractor",children:"Data Extractor"}),"\n",(0,s.jsx)(t.p,{children:"Data Extractor processes logged data and extracts data into a CSV format for analysis in Excel or other tools."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-1"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding individual telemetry points."}),(0,s.jsx)(t.td,{children:"Add an individual telemetry point."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-2"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding entire telemetry packets."}),(0,s.jsx)(t.td,{children:"Add an entire packet."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-3"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support adding entire telemetry targets."}),(0,s.jsx)(t.td,{children:"Add all packets for a target."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-4"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support selecting the value type to extract for each telemetry point (RAW, CONVERTED, FORMATTED, WITH_UNITS)"}),(0,s.jsx)(t.td,{children:"Click an item and change the value type."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-5"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support saving configurations."}),(0,s.jsx)(t.td,{children:"Select File->Save Config"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-6"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support loading configurations."}),(0,s.jsx)(t.td,{children:"Select File->Load Config"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DE-7"}),(0,s.jsx)(t.td,{children:"Data Extractor shall support deleting items"}),(0,s.jsx)(t.td,{children:"Select an Item and press delete"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"data-viewer",children:"Data Viewer"}),"\n",(0,s.jsx)(t.p,{children:"Data Viewer provides for textual display of telemetry packets where other display methods are not a good fit. It is especially useful for memory dumps and for log message type data display."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-1"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support realtime processing of telemetry packets."}),(0,s.jsx)(t.td,{children:"Press Start to start realtime processing."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-2"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support logged playback of telemetry packets."}),(0,s.jsx)(t.td,{children:"Select a time range to playback."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-3"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support textual display of telemetry packets."}),(0,s.jsx)(t.td,{children:"View the display of data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-4"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support multiple tabs for data display."}),(0,s.jsx)(t.td,{children:"Switch between several tabs of data."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"DV-5"}),(0,s.jsx)(t.td,{children:"Data Viewer shall support deleting tabs."}),(0,s.jsx)(t.td,{children:"Delete a tab."})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"calendar",children:"Calendar"}),"\n",(0,s.jsx)(t.p,{children:"The Calendar tool provides a user interface and API for initiating scheduled actions in COSMOS"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-1"}),(0,s.jsx)(t.td,{children:"Calendar shall allow creating new timelines"}),(0,s.jsx)(t.td,{children:"Click the button and create a new timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-2"}),(0,s.jsx)(t.td,{children:"Calendar shall allow scheduling commands for future execection"}),(0,s.jsx)(t.td,{children:"Add a command to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-3"}),(0,s.jsx)(t.td,{children:"Calendar shall allow scheduling scripts for future execution"}),(0,s.jsx)(t.td,{children:"Add a script to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-4"}),(0,s.jsx)(t.td,{children:"Calendar shall allow for reserving a resource"}),(0,s.jsx)(t.td,{children:"Add a reservation to a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-5"}),(0,s.jsx)(t.td,{children:"Calendar shall track success or failure of commands"}),(0,s.jsx)(t.td,{children:"Look at status from a completed command"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-6"}),(0,s.jsx)(t.td,{children:"Calendar shall track success or failure of scripts"}),(0,s.jsx)(t.td,{children:"Look at status from a completed script"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-7"}),(0,s.jsx)(t.td,{children:"Calendar shall allow deleting activities from timelines"}),(0,s.jsx)(t.td,{children:"Delete a preexisting item from a timeline"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"TL-8"}),(0,s.jsx)(t.td,{children:"Calendar shall allow deleting timelines"}),(0,s.jsx)(t.td,{children:"Delete a timeline"})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"admin",children:"Admin"}),"\n",(0,s.jsx)(t.p,{children:"The Admin tool provides administrative functionality including managing plugins for the COSMOS system"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Reqt. ID"}),(0,s.jsx)(t.th,{children:"Description"}),(0,s.jsx)(t.th,{children:"Test Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-1"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall allow installing plugins"}),(0,s.jsx)(t.td,{children:"Upload and Install a Plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-2"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support upgrading plugins"}),(0,s.jsx)(t.td,{children:"Upgrade an installed plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-3"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support uninstalling plugins"}),(0,s.jsx)(t.td,{children:"Uninstall a plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-4"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall display information on installed plugins"}),(0,s.jsx)(t.td,{children:"View info on Interfaces, Microservices, etc"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-5"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support editing microservices"}),(0,s.jsx)(t.td,{children:"Edit the settings for a microservice"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-6"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support discovery of plugins"}),(0,s.jsx)(t.td,{children:"Discover and download a plugin"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-7"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support adding links to external tools"}),(0,s.jsx)(t.td,{children:"Add a link to Google"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-8"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support reordering tools"}),(0,s.jsx)(t.td,{children:"Reorder tools on the tools tab"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"AD-9"}),(0,s.jsx)(t.td,{children:"The Admin Tool shall support configuring a classification bar"}),(0,s.jsx)(t.td,{children:"Add a classification bar on the settings tab"})]})]})]})]})}function o(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},324:(e,t,r)=>{r.d(t,{A:()=>s});const s=r.p+"assets/images/architecture-b78f12eba076a0c07af7abdd9dd4187c59aa6b4f5c51b47ad03f73e9f98a6ed6.png"},8453:(e,t,r)=>{r.d(t,{R:()=>d,x:()=>l});var s=r(6540);const n={},i=s.createContext(n);function d(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:d(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/6b65133b.9807e2a5.js b/docs/assets/js/6b65133b.09a9f077.js
similarity index 99%
rename from docs/assets/js/6b65133b.9807e2a5.js
rename to docs/assets/js/6b65133b.09a9f077.js
index 286e53d5ac..bd8be561bc 100644
--- a/docs/assets/js/6b65133b.9807e2a5.js
+++ b/docs/assets/js/6b65133b.09a9f077.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[7827],{3541:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var i=t(4848),s=t(8453);const r={title:"Telemetry Viewer"},o=void 0,c={id:"tools/tlm-viewer",title:"Telemetry Viewer",description:"Introduction",source:"@site/docs/tools/tlm-viewer.md",sourceDirName:"tools",slug:"/tools/tlm-viewer",permalink:"/docs/tools/tlm-viewer",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/tlm-viewer.md",tags:[],version:"current",frontMatter:{title:"Telemetry Viewer"},sidebar:"defaultSidebar",previous:{title:"Telemetry Grapher",permalink:"/docs/tools/tlm-grapher"},next:{title:"Guides",permalink:"/docs/guides"}},a={},l=[{value:"Introduction",id:"introduction",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"Open Configuration",id:"open-configuration",level:4},{value:"Save Configuration",id:"save-configuration",level:4},{value:"Selecting Screens",id:"selecting-screens",level:2},{value:"New Screen",id:"new-screen",level:2},{value:"Edit Screen",id:"edit-screen",level:2},{value:"Screen Window Management",id:"screen-window-management",level:2},{value:"Building Screens",id:"building-screens",level:2}];function d(e){const n={a:"a",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"Telemetry Viewer is a live telemetry viewer which displays custom built screens. Screens are configured through simple text files which utilize numerous build-in widgets."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(7470).A+"",width:"1274",height:"895"})}),"\n",(0,i.jsx)(n.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,i.jsx)("img",{src:t(7711).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"90px"}}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Open a saved configuration"}),"\n",(0,i.jsx)(n.li,{children:"Save the current configuration"}),"\n",(0,i.jsx)(n.li,{children:"Reset the configuration (default settings)"}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"open-configuration",children:"Open Configuration"}),"\n",(0,i.jsx)(n.p,{children:"The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,i.jsx)(n.h4,{id:"save-configuration",children:"Save Configuration"}),"\n",(0,i.jsx)(n.p,{children:"The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,i.jsx)(n.h2,{id:"selecting-screens",children:"Selecting Screens"}),"\n",(0,i.jsx)(n.p,{children:"Selecting a target from the Select Target drop down automatically updates the available screens for that target in the Select Screen drop down. Clicking Show Screen causes that screen to display."}),"\n",(0,i.jsx)(n.h2,{id:"new-screen",children:"New Screen"}),"\n",(0,i.jsx)(n.p,{children:"Clicking New Screen brings up the new screen dialog."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(3753).A+"",width:"595",height:"424"})}),"\n",(0,i.jsx)(n.p,{children:"Screens are owned by Targets so Select Target chooses where the screen will be created. Screens can be based on a Packet such that all the items in that particular packet will be generated in a simple vertical screen similar to Packet Viewer. This is a good starting point for customizing a screen. Note that screen names must be unique so the screen name is set to 'adcs2' since an 'ADCS' screen already exists."}),"\n",(0,i.jsx)(n.h2,{id:"edit-screen",children:"Edit Screen"}),"\n",(0,i.jsx)(n.p,{children:"Clicking the pencil icon in the title bar of the screen brings up the edit dialog."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(7985).A+"",width:"1149",height:"698"})}),"\n",(0,i.jsx)(n.p,{children:"The screen source is displayed in an editor with syntax highlighting and auto-completion. You can download the screen source using the download button in the upper right or delete the screen using the trash icon in the upper left. Click Save to save the screen edits at which point Telemetry Viewer will re-render the screen."}),"\n",(0,i.jsx)(n.h2,{id:"screen-window-management",children:"Screen Window Management"}),"\n",(0,i.jsx)(n.p,{children:"All screens can be moved around the browser window by clicking their title bar and moving them. Other screens will move around intelligently to fill the space. This allows you to order the screens no matter which order they were created in."}),"\n",(0,i.jsx)(n.p,{children:"You can also float the screens by clicking the grid icon in the upper left of the title bar. It will change to a balloon icon and allow you to click up and down to change the relative Z index of the window. The image screen is floated in the following screen shot."}),"\n",(0,i.jsx)(n.p,{children:"The dash button in the upper right of the title bar minimizes the screen to effectively hide it. This allows you to focus on a single screen without closing existing screens. In the screen shot below there are two minimized windows at the very bottom."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Float Minimized",src:t(2753).A+"",width:"1275",height:"928"})}),"\n",(0,i.jsx)(n.p,{children:"The X button closes the screen."}),"\n",(0,i.jsx)(n.h2,{id:"building-screens",children:"Building Screens"}),"\n",(0,i.jsxs)(n.p,{children:["For documentation on how to build Telemetry Screens and how to configure the\nscreen widgets please see the ",(0,i.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"Telemetry Screens"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},7711:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/file_menu-8a0c6243e35822617229a729a598ace78e401b6c29f66eb5e07035d77d9be1aa.png"},7985:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/edit_screen-c655c75fe90429c0425b61cccf23835b6882975abaa56de21d58c9a4b19a4773.png"},2753:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/float_minimize-a27fc649e517b279db5d2435fbd4f1de81418b9ef5f47fc83a9443bba0b1a7e0.png"},3753:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/new_screen-0d9bea0538e91fa2332346f1ff73b1dda2e418d295dcd7d6a13ba240cf32187e.png"},7470:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/telemetry_viewer-e4ac466930993a640f95aea4b01bb9a415eec77dfbfaa184f767cb59940ba943.png"},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>c});var i=t(6540);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[7827],{3541:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var i=t(4848),s=t(8453);const r={title:"Telemetry Viewer"},o=void 0,c={id:"tools/tlm-viewer",title:"Telemetry Viewer",description:"Introduction",source:"@site/docs/tools/tlm-viewer.md",sourceDirName:"tools",slug:"/tools/tlm-viewer",permalink:"/docs/tools/tlm-viewer",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/tlm-viewer.md",tags:[],version:"current",frontMatter:{title:"Telemetry Viewer"},sidebar:"defaultSidebar",previous:{title:"Telemetry Grapher",permalink:"/docs/tools/tlm-grapher"},next:{title:"Guides",permalink:"/docs/guides"}},a={},l=[{value:"Introduction",id:"introduction",level:2},{value:"File Menu Items",id:"file-menu-items",level:3},{value:"Open Configuration",id:"open-configuration",level:4},{value:"Save Configuration",id:"save-configuration",level:4},{value:"Selecting Screens",id:"selecting-screens",level:2},{value:"New Screen",id:"new-screen",level:2},{value:"Edit Screen",id:"edit-screen",level:2},{value:"Screen Window Management",id:"screen-window-management",level:2},{value:"Building Screens",id:"building-screens",level:2}];function d(e){const n={a:"a",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"Telemetry Viewer is a live telemetry viewer which displays custom built screens. Screens are configured through simple text files which utilize numerous built-in widgets."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(7470).A+"",width:"1274",height:"895"})}),"\n",(0,i.jsx)(n.h3,{id:"file-menu-items",children:"File Menu Items"}),"\n",(0,i.jsx)("img",{src:t(7711).A,alt:"File Menu",style:{float:"left","margin-right":"50px",height:"90px"}}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Open a saved configuration"}),"\n",(0,i.jsx)(n.li,{children:"Save the current configuration"}),"\n",(0,i.jsx)(n.li,{children:"Reset the configuration (default settings)"}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"open-configuration",children:"Open Configuration"}),"\n",(0,i.jsx)(n.p,{children:"The Open Configuration dialog displays a list of all saved configurations. You select a configuration and then click Ok to load it. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,i.jsx)(n.h4,{id:"save-configuration",children:"Save Configuration"}),"\n",(0,i.jsx)(n.p,{children:"The Save Configuration dialog also displays a list of all saved configurations. You click the Configuration Name text field, enter the name of your new configuration, and click Ok to save. You can delete existing configurations by clicking the Trash icon next to a configuration name."}),"\n",(0,i.jsx)(n.h2,{id:"selecting-screens",children:"Selecting Screens"}),"\n",(0,i.jsx)(n.p,{children:"Selecting a target from the Select Target drop down automatically updates the available screens for that target in the Select Screen drop down. Clicking Show Screen causes that screen to display."}),"\n",(0,i.jsx)(n.h2,{id:"new-screen",children:"New Screen"}),"\n",(0,i.jsx)(n.p,{children:"Clicking New Screen brings up the new screen dialog."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(3753).A+"",width:"595",height:"424"})}),"\n",(0,i.jsx)(n.p,{children:"Screens are owned by Targets so Select Target chooses where the screen will be created. Screens can be based on a Packet such that all the items in that particular packet will be generated in a simple vertical screen similar to Packet Viewer. This is a good starting point for customizing a screen. Note that screen names must be unique so the screen name is set to 'adcs2' since an 'ADCS' screen already exists."}),"\n",(0,i.jsx)(n.h2,{id:"edit-screen",children:"Edit Screen"}),"\n",(0,i.jsx)(n.p,{children:"Clicking the pencil icon in the title bar of the screen brings up the edit dialog."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Telemetry Viewer",src:t(7985).A+"",width:"1149",height:"698"})}),"\n",(0,i.jsx)(n.p,{children:"The screen source is displayed in an editor with syntax highlighting and auto-completion. You can download the screen source using the download button in the upper right or delete the screen using the trash icon in the upper left. Click Save to save the screen edits at which point Telemetry Viewer will re-render the screen."}),"\n",(0,i.jsx)(n.h2,{id:"screen-window-management",children:"Screen Window Management"}),"\n",(0,i.jsx)(n.p,{children:"All screens can be moved around the browser window by clicking their title bar and moving them. Other screens will move around intelligently to fill the space. This allows you to order the screens no matter which order they were created in."}),"\n",(0,i.jsx)(n.p,{children:"You can also float the screens by clicking the grid icon in the upper left of the title bar. It will change to a balloon icon and allow you to click up and down to change the relative Z index of the window. The image screen is floated in the following screen shot."}),"\n",(0,i.jsx)(n.p,{children:"The dash button in the upper right of the title bar minimizes the screen to effectively hide it. This allows you to focus on a single screen without closing existing screens. In the screen shot below there are two minimized windows at the very bottom."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Float Minimized",src:t(2753).A+"",width:"1275",height:"928"})}),"\n",(0,i.jsx)(n.p,{children:"The X button closes the screen."}),"\n",(0,i.jsx)(n.h2,{id:"building-screens",children:"Building Screens"}),"\n",(0,i.jsxs)(n.p,{children:["For documentation on how to build Telemetry Screens and how to configure the\nscreen widgets please see the ",(0,i.jsx)(n.a,{href:"/docs/configuration/telemetry-screens",children:"Telemetry Screens"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},7711:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/file_menu-8a0c6243e35822617229a729a598ace78e401b6c29f66eb5e07035d77d9be1aa.png"},7985:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/edit_screen-c655c75fe90429c0425b61cccf23835b6882975abaa56de21d58c9a4b19a4773.png"},2753:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/float_minimize-a27fc649e517b279db5d2435fbd4f1de81418b9ef5f47fc83a9443bba0b1a7e0.png"},3753:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/new_screen-0d9bea0538e91fa2332346f1ff73b1dda2e418d295dcd7d6a13ba240cf32187e.png"},7470:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/telemetry_viewer-e4ac466930993a640f95aea4b01bb9a415eec77dfbfaa184f767cb59940ba943.png"},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>c});var i=t(6540);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/72c6d8a8.e1eb0c3a.js b/docs/assets/js/72c6d8a8.e1eb0c3a.js
deleted file mode 100644
index 2766b52973..0000000000
--- a/docs/assets/js/72c6d8a8.e1eb0c3a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[1524],{4785:(e,r,s)=>{s.r(r),s.d(r,{assets:()=>l,contentTitle:()=>d,default:()=>o,frontMatter:()=>i,metadata:()=>a,toc:()=>h});var t=s(4848),n=s(8453);const i={sidebar_position:4,title:"Commands"},d=void 0,a={id:"configuration/command",title:"Commands",description:"Command Definition Files",source:"@site/docs/configuration/command.md",sourceDirName:"configuration",slug:"/configuration/command",permalink:"/docs/configuration/command",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/command.md",tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Commands"},sidebar:"defaultSidebar",previous:{title:"Targets",permalink:"/docs/configuration/target"},next:{title:"Telemetry",permalink:"/docs/configuration/telemetry"}},l={},h=[{value:"Command Definition Files",id:"command-definition-files",level:2},{value:"COMMAND",id:"command",level:2},{value:"COMMAND Modifiers",id:"command-modifiers",level:2},{value:"PARAMETER",id:"parameter",level:3},{value:"PARAMETER Modifiers",id:"parameter-modifiers",level:3},{value:"FORMAT_STRING",id:"format_string",level:4},{value:"UNITS",id:"units",level:4},{value:"DESCRIPTION",id:"description",level:4},{value:"META",id:"meta",level:4},{value:"OVERLAP",id:"overlap",level:4},{value:"KEY",id:"key",level:4},{value:"VARIABLE_BIT_SIZE",id:"variable_bit_size",level:4},{value:"REQUIRED",id:"required",level:4},{value:"MINIMUM_VALUE",id:"minimum_value",level:4},{value:"MAXIMUM_VALUE",id:"maximum_value",level:4},{value:"DEFAULT_VALUE",id:"default_value",level:4},{value:"STATE",id:"state",level:4},{value:"WRITE_CONVERSION",id:"write_conversion",level:4},{value:"POLY_WRITE_CONVERSION",id:"poly_write_conversion",level:4},{value:"SEG_POLY_WRITE_CONVERSION",id:"seg_poly_write_conversion",level:4},{value:"GENERIC_WRITE_CONVERSION_START",id:"generic_write_conversion_start",level:4},{value:"GENERIC_WRITE_CONVERSION_END",id:"generic_write_conversion_end",level:4},{value:"OVERFLOW",id:"overflow",level:4},{value:"APPEND_PARAMETER",id:"append_parameter",level:3},{value:"ID_PARAMETER",id:"id_parameter",level:3},{value:"APPEND_ID_PARAMETER",id:"append_id_parameter",level:3},{value:"ARRAY_PARAMETER",id:"array_parameter",level:3},{value:"APPEND_ARRAY_PARAMETER",id:"append_array_parameter",level:3},{value:"SELECT_PARAMETER",id:"select_parameter",level:3},{value:"DELETE_PARAMETER",id:"delete_parameter",level:3},{value:"HIDDEN",id:"hidden",level:3},{value:"DISABLED",id:"disabled",level:3},{value:"DISABLE_MESSAGES",id:"disable_messages",level:3},{value:"META",id:"meta-1",level:3},{value:"HAZARDOUS",id:"hazardous",level:3},{value:"ACCESSOR",id:"accessor",level:3},{value:"TEMPLATE",id:"template",level:3},{value:"TEMPLATE_FILE",id:"template_file",level:3},{value:"RESPONSE",id:"response",level:3},{value:"ERROR_RESPONSE",id:"error_response",level:3},{value:"RELATED_ITEM",id:"related_item",level:3},{value:"SCREEN",id:"screen",level:3},{value:"VIRTUAL",id:"virtual",level:3},{value:"SELECT_COMMAND",id:"select_command",level:2},{value:"Example File",id:"example-file",level:2}];function c(e){const r={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h2,{id:"command-definition-files",children:"Command Definition Files"}),"\n",(0,t.jsxs)(r.p,{children:["Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the ",(0,t.jsx)(r.a,{href:"http://www.asciitable.com/",children:"ASCII Table"})," is structured, files beginning with capital letters are processed before lower case letters."]}),"\n",(0,t.jsx)(r.p,{children:"When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters."}),"\n",(0,t.jsx)("div",{style:{clear:"both"}}),"\n",(0,t.jsx)(r.h1,{id:"command-keywords",children:"Command Keywords"}),"\n",(0,t.jsx)(r.h2,{id:"command",children:"COMMAND"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a new command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target"}),(0,t.jsx)(r.td,{children:"Name of the target this command is associated with"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Command"}),(0,t.jsx)(r.td,{children:"Name of this command. Also referred to as its mnemonic. Must be unique to commands to this target. Ideally will be as short and clear as possible."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description of this command which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'COMMAND INST COLLECT BIG_ENDIAN "Start collect"\n'})}),"\n",(0,t.jsx)(r.h2,{id:"command-modifiers",children:"COMMAND Modifiers"}),"\n",(0,t.jsx)(r.p,{children:"The following keywords must follow a COMMAND keyword."}),"\n",(0,t.jsx)(r.h3,{id:"parameter",children:"PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'PARAMETER SYNC 0 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern"\nPARAMETER DATA 32 32 INT MIN MAX 0 "Data value"\nPARAMETER VALUE 64 32 FLOAT 0 10.5 2.5\nPARAMETER LABEL 96 96 STRING "OPENC3" "The label to apply"\nPARAMETER BLOCK 192 0 BLOCK 0x0 "Block of binary data"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"parameter-modifiers",children:"PARAMETER Modifiers"}),"\n",(0,t.jsx)(r.p,{children:"The following keywords must follow a PARAMETER keyword."}),"\n",(0,t.jsx)(r.h4,{id:"format_string",children:"FORMAT_STRING"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds printf style formatting"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Format"}),(0,t.jsx)(r.td,{children:"How to format using printf syntax. For example, '0x%0X' will display the value in hex."}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'FORMAT_STRING "0x%0X"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"units",children:"UNITS"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Add displayed units"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Full Name"}),(0,t.jsx)(r.td,{children:"Full name of the units type, e.g. Celsius"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Abbreviated"}),(0,t.jsx)(r.td,{children:"Abbreviation for the units, e.g. C"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"UNITS Celsius C\nUNITS Kilometers KM\n"})}),"\n",(0,t.jsx)(r.h4,{id:"description",children:"DESCRIPTION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined description"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new description"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"meta",children:"META"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Stores custom user metadata"})}),"\n",(0,t.jsx)(r.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Name"}),(0,t.jsx)(r.td,{children:"Name of the metadata to store"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Values"}),(0,t.jsx)(r.td,{children:"One or more values to be stored for this Meta Name"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'META TEST "This parameter is for test purposes only"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"overlap",children:"OVERLAP"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,t.jsx)(r.strong,{children:"This item is allowed to overlap other items in the packet"})]}),"\n",(0,t.jsx)(r.p,{children:"If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message."}),"\n",(0,t.jsx)(r.h4,{id:"key",children:"KEY"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines the key used to access this raw value in the packet."})]}),"\n",(0,t.jsx)(r.p,{children:"Keys are often JsonPath or XPath strings"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Key string"}),(0,t.jsx)(r.td,{children:"The key to access this item"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"KEY $.book.title\n"})}),"\n",(0,t.jsx)(r.h4,{id:"variable_bit_size",children:"VARIABLE_BIT_SIZE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,t.jsx)(r.strong,{children:"Marks an item as having its bit size defined by another length item"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Item Name"}),(0,t.jsx)(r.td,{children:"The name of the associated length item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Bits Per Count"}),(0,t.jsx)(r.td,{children:"Bits per count of the length item. Defaults to 8"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Value Bit Offset"}),(0,t.jsx)(r.td,{children:"Offset in Bits to Apply to Length Field Value. Defaults to 0"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.h4,{id:"required",children:"REQUIRED"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Parameter is required to be populated in scripts"})}),"\n",(0,t.jsx)(r.p,{children:"When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition."}),"\n",(0,t.jsx)(r.h4,{id:"minimum_value",children:"MINIMUM_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined minimum value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new minimum value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"maximum_value",children:"MAXIMUM_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined maximum value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new maximum value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"default_value",children:"DEFAULT_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined default value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new default value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"state",children:"STATE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a key/value pair for the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Key"}),(0,t.jsx)(r.td,{children:"The string state name"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The numerical state value"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Hazardous / Disable Messages"}),(0,t.jsxs)(r.td,{children:["Indicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"HAZARDOUS"})]}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Hazardous Description"}),(0,t.jsx)(r.td,{children:"String describing why this state is hazardous"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting"\n STATE FALSE 0\n STATE TRUE 1\nAPPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter"\n STATE "NOOP" "NOOP" DISABLE_MESSAGES\n STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard"\n STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"write_conversion",children:"WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Applies a conversion when writing the current command parameter"})}),"\n",(0,t.jsxs)(r.p,{children:["Conversions are implemented in a custom Ruby or Python file which should be\nlocated in the target's lib folder. The class must inherit from Conversion.\nIt must implement the ",(0,t.jsx)(r.code,{children:"initialize"})," (Ruby) or ",(0,t.jsx)(r.code,{children:"__init__"})," (Python) method if it\ntakes extra parameters and must always implement the ",(0,t.jsx)(r.code,{children:"call"})," method. The conversion\nfactor is applied to the value entered by the user before it is written into\nthe binary command packet and sent."]}),"\n",(0,t.jsx)(r.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,t.jsx)(r.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Class Filename"}),(0,t.jsx)(r.td,{children:"The filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Additional parameter values for the conversion which are passed to the class constructor."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"WRITE_CONVERSION the_great_conversion.rb 1000\n\nDefined in the_great_conversion.rb:\n\nrequire 'openc3/conversions/conversion'\nmodule OpenC3\n class TheGreatConversion < Conversion\n def initialize(multiplier)\n super()\n @multiplier = multiplier.to_f\n end\n def call(value, packet, buffer)\n return value * multiplier\n end\n end\nend\n"})}),"\n",(0,t.jsx)(r.p,{children:"Python Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-python",children:"WRITE_CONVERSION the_great_conversion.py 1000\n\nDefined in the_great_conversion.py:\n\nfrom openc3.conversions.conversion import Conversion\nclass TheGreatConversion(Conversion):\n def __init__(self, multiplier):\n super().__init__()\n self.multiplier = float(multiplier)\n def call(self, value, packet, buffer):\n return value * multiplier\n"})}),"\n",(0,t.jsx)(r.h4,{id:"poly_write_conversion",children:"POLY_WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds a polynomial conversion factor to the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"C0"}),(0,t.jsx)(r.td,{children:"Coefficient"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Cx"}),(0,t.jsx)(r.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"POLY_WRITE_CONVERSION 10 0.5 0.25\n"})}),"\n",(0,t.jsx)(r.h4,{id:"seg_poly_write_conversion",children:"SEG_POLY_WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds a segmented polynomial conversion factor to the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Lower Bound"}),(0,t.jsx)(r.td,{children:"Defines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"C0"}),(0,t.jsx)(r.td,{children:"Coefficient"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Cx"}),(0,t.jsx)(r.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50\nSEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100\nSEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100\n"})}),"\n",(0,t.jsx)(r.h4,{id:"generic_write_conversion_start",children:"GENERIC_WRITE_CONVERSION_START"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Start a generic write conversion"})}),"\n",(0,t.jsx)(r.p,{children:"Adds a generic conversion function to the current command parameter.\nThis conversion factor is applied to the value entered by the user before it\nis written into the binary command packet and sent. The conversion is specified\nas Ruby or Python code that receives two implied parameters. 'value' which is the raw\nvalue being written and 'packet' which is a reference to the command packet\nclass (Note, referencing the packet as 'myself' is still supported for backwards\ncompatibility). The last line of code should return the converted\nvalue. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of\ncode for the conversion have been given."}),"\n",(0,t.jsx)(r.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,t.jsx)(r.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,t.jsx)(r.admonition,{type:"warning",children:(0,t.jsx)(r.p,{children:"Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance."})}),"\n",(0,t.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return (value * 1.5).to_i # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,t.jsx)(r.p,{children:"Python Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-python",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return int(value * 1.5) # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,t.jsx)(r.h4,{id:"generic_write_conversion_end",children:"GENERIC_WRITE_CONVERSION_END"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Complete a generic write conversion"})}),"\n",(0,t.jsx)(r.h4,{id:"overflow",children:"OVERFLOW"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Set the behavior when writing a value overflows the type"})}),"\n",(0,t.jsx)(r.p,{children:"By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Behavior"}),(0,t.jsxs)(r.td,{children:["How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE"})]}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"OVERFLOW TRUNCATE\n"})}),"\n",(0,t.jsx)(r.h3,{id:"append_parameter",children:"APPEND_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_PARAMETER SYNC 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern"\nAPPEND_PARAMETER VALUE 32 FLOAT 0 10.5 2.5\nAPPEND_PARAMETER LABEL 0 STRING "OPENC3" "The label to apply"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"id_parameter",children:"ID_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines an identification command parameter in the current command packet"})}),"\n",(0,t.jsx)(r.p,{children:"ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"ID Value"}),(0,t.jsx)(r.td,{children:"Identification value for this parameter. The binary data must match this value for the buffer to be identified as this packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'ID_PARAMETER OPCODE 32 32 UINT 2 2 2 "Opcode identifier"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"append_id_parameter",children:"APPEND_ID_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines an identification command parameter in the current command packet"})}),"\n",(0,t.jsx)(r.p,{children:"ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"ID Value"}),(0,t.jsx)(r.td,{children:"Identification value for this parameter. The binary data must match this value for the buffer to be identified as this packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_ID_PARAMETER OPCODE 32 UINT 2 2 2 "Opcode identifier"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"array_parameter",children:"ARRAY_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet that is an array"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of each array item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of each array item",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, STRING, BLOCK, DERIVED"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Array Bit Size"}),(0,t.jsx)(r.td,{children:"Total Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'ARRAY_PARAMETER ARRAY 64 64 FLOAT 640 "Array of 10 64bit floats"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"append_array_parameter",children:"APPEND_ARRAY_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet that is an array"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of each array item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of each array item",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, STRING, BLOCK, DERIVED"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Array Bit Size"}),(0,t.jsx)(r.td,{children:"Total Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_ARRAY_PARAMETER ARRAY 64 FLOAT 640 "Array of 10 64bit floats"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"select_parameter",children:"SELECT_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Selects an existing command parameter for editing"})}),"\n",(0,t.jsx)(r.p,{children:"Must be used in conjunction with SELECT_COMMAND to first select the packet. Typically used to override generated values or make specific changes to commands that only affect a particular instance of a target used multiple times."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Name of the parameter to select for modification"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n SELECT_PARAMETER DURATION\n # Add units\n UNITS Seconds S\n"})}),"\n",(0,t.jsx)(r.h3,{id:"delete_parameter",children:"DELETE_PARAMETER"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,t.jsx)(r.strong,{children:"Deletes an existing command parameter from the packet definition"})]}),"\n",(0,t.jsx)(r.p,{children:'Deleting a parameter from the command definition does not remove the defined space for that parameter. Thus unless you redefine a new parameter, there will be a "hole" in the packet where the data is not accessible. You can use SELECT_COMMAND and then PARAMETER to define a new parameter.'}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Name of the parameter to delete"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n DELETE_PARAMETER DURATION\n"})}),"\n",(0,t.jsx)(r.h3,{id:"hidden",children:"HIDDEN"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Hides this command from all OpenC3 tools such as Command Sender and Handbook Creator"})}),"\n",(0,t.jsx)(r.p,{children:"Hidden commands do not appear in the Script Runner popup helper when writing scripts. The command still exists in the system and can be sent by scripts."}),"\n",(0,t.jsx)(r.h3,{id:"disabled",children:"DISABLED"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Disables this command from being sent"})}),"\n",(0,t.jsx)(r.p,{children:"Hides the command and also disables it from being sent by scripts. Attempts to send DISABLED commands result in an error message."}),"\n",(0,t.jsx)(r.h3,{id:"disable_messages",children:"DISABLE_MESSAGES"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Disable the Server from printing cmd(...) messages. Commands are still logged."})}),"\n",(0,t.jsx)(r.h3,{id:"meta-1",children:"META"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Stores metadata for the current command"})}),"\n",(0,t.jsx)(r.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Name"}),(0,t.jsx)(r.td,{children:"Name of the metadata to store"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Values"}),(0,t.jsx)(r.td,{children:"One or more values to be stored for this Meta Name"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'META FSW_TYPE "struct command"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"hazardous",children:"HAZARDOUS"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Designates the current command as hazardous"})}),"\n",(0,t.jsx)(r.p,{children:"Sending a hazardous command causes a dialog asking for confirmation before sending the command"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for why the command is hazardous which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"accessor",children:"ACCESSOR"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines the class used to read and write raw values from the packet"})]}),"\n",(0,t.jsx)(r.p,{children:"Defines the class that is used too read raw values from the packet. Defaults to BinaryAccessor. Provided accessors also include JsonAccessor, CborAccessor, HtmlAccessor, and XmlAccessor."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Accessor Class Name"}),(0,t.jsx)(r.td,{children:"The name of the accessor class"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"template",children:"TEMPLATE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines a template string used to initialize the command before default values are filled in"})]}),"\n",(0,t.jsx)(r.p,{children:"Generally the template string is formatted in JSON or HTML and then values are filled in with command parameters. Must be UTF-8 encoded."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Template"}),(0,t.jsx)(r.td,{children:"The template string which should be enclosed in quotes"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"template_file",children:"TEMPLATE_FILE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines a template file used to initialize the command before default values are filled in"})]}),"\n",(0,t.jsx)(r.p,{children:"Generally the template file is formatted in JSON or HTML and then values are filled in with command parameters. Can be binary or UTF-8."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Template File Path"}),(0,t.jsx)(r.td,{children:"The relative path to the template file. Filename should generally start with an underscore."}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"response",children:"RESPONSE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Indicates the expected telemetry packet response to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of telemetry response packet"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of telemetry response packet"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"error_response",children:"ERROR_RESPONSE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Indicates the expected telemetry packet error response to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of telemetry error response packet"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of telemetry error response packet"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"related_item",children:"RELATED_ITEM"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Defines a related telemetry item to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Name"}),(0,t.jsx)(r.td,{children:"Item Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"screen",children:"SCREEN"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Defines a related telemetry screen to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of related telemetry screen"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Screen Name"}),(0,t.jsx)(r.td,{children:"Screen Name of related telemetry screen"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"virtual",children:"VIRTUAL"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,t.jsx)(r.strong,{children:"Marks this packet as virtual and not participating in identification"})]}),"\n",(0,t.jsx)(r.p,{children:"Used for packet definitions that can be used as structures for items with a given packet."}),"\n",(0,t.jsx)(r.h2,{id:"select_command",children:"SELECT_COMMAND"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Selects an existing command packet for editing"})}),"\n",(0,t.jsx)(r.p,{children:"Typically used in a separate configuration file from where the original command is defined to override or add to the existing command definition. Must be used in conjunction with SELECT_PARAMETER to change an individual parameter."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Name of the target this command is associated with"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Command Name"}),(0,t.jsx)(r.td,{children:"Name of the command to select"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n SELECT_PARAMETER DURATION\n # Add units\n UNITS Seconds S\n"})}),"\n",(0,t.jsx)(r.h2,{id:"example-file",children:"Example File"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Example File: TARGET/cmd_tlm/cmd.txt"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'COMMAND TARGET COLLECT_DATA BIG_ENDIAN "Commands my target to collect data"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 100 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 4 4 4 "CCSDS PRIMARY HEADER PACKET LENGTH"\n PARAMETER ANGLE 48 32 FLOAT -180.0 180.0 0.0 "ANGLE OF INSTRUMENT IN DEGREES"\n POLY_WRITE_CONVERSION 0 0.01745 0 0\n PARAMETER MODE 80 8 UINT 0 1 0 "DATA COLLECTION MODE"\n STATE NORMAL 0\n STATE DIAG 1\nCOMMAND TARGET NOOP BIG_ENDIAN "Do Nothing"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 101 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH"\n PARAMETER DUMMY 48 8 UINT 0 0 0 "DUMMY PARAMETER BECAUSE CCSDS REQUIRES 1 BYTE OF DATA"\nCOMMAND TARGET SETTINGS BIG_ENDIAN "Set the Settings"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 102 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH"\n <% 5.times do |x| %>\n APPEND_PARAMETER SETTING<%= x %> 16 UINT 0 5 0 "Setting <%= x %>"\n <% end %>\n'})})]})}function o(e={}){const{wrapper:r}={...(0,n.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,r,s)=>{s.d(r,{R:()=>d,x:()=>a});var t=s(6540);const n={},i=t.createContext(n);function d(e){const r=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:d(e.components),t.createElement(i.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/72c6d8a8.eb58464b.js b/docs/assets/js/72c6d8a8.eb58464b.js
new file mode 100644
index 0000000000..0e6cabb992
--- /dev/null
+++ b/docs/assets/js/72c6d8a8.eb58464b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[1524],{4785:(e,r,s)=>{s.r(r),s.d(r,{assets:()=>l,contentTitle:()=>d,default:()=>o,frontMatter:()=>i,metadata:()=>a,toc:()=>h});var t=s(4848),n=s(8453);const i={sidebar_position:4,title:"Commands"},d=void 0,a={id:"configuration/command",title:"Commands",description:"Command Definition Files",source:"@site/docs/configuration/command.md",sourceDirName:"configuration",slug:"/configuration/command",permalink:"/docs/configuration/command",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/command.md",tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Commands"},sidebar:"defaultSidebar",previous:{title:"Targets",permalink:"/docs/configuration/target"},next:{title:"Telemetry",permalink:"/docs/configuration/telemetry"}},l={},h=[{value:"Command Definition Files",id:"command-definition-files",level:2},{value:"COMMAND",id:"command",level:2},{value:"COMMAND Modifiers",id:"command-modifiers",level:2},{value:"PARAMETER",id:"parameter",level:3},{value:"PARAMETER Modifiers",id:"parameter-modifiers",level:3},{value:"FORMAT_STRING",id:"format_string",level:4},{value:"UNITS",id:"units",level:4},{value:"DESCRIPTION",id:"description",level:4},{value:"META",id:"meta",level:4},{value:"OVERLAP",id:"overlap",level:4},{value:"KEY",id:"key",level:4},{value:"VARIABLE_BIT_SIZE",id:"variable_bit_size",level:4},{value:"REQUIRED",id:"required",level:4},{value:"MINIMUM_VALUE",id:"minimum_value",level:4},{value:"MAXIMUM_VALUE",id:"maximum_value",level:4},{value:"DEFAULT_VALUE",id:"default_value",level:4},{value:"STATE",id:"state",level:4},{value:"WRITE_CONVERSION",id:"write_conversion",level:4},{value:"POLY_WRITE_CONVERSION",id:"poly_write_conversion",level:4},{value:"SEG_POLY_WRITE_CONVERSION",id:"seg_poly_write_conversion",level:4},{value:"GENERIC_WRITE_CONVERSION_START",id:"generic_write_conversion_start",level:4},{value:"GENERIC_WRITE_CONVERSION_END",id:"generic_write_conversion_end",level:4},{value:"OVERFLOW",id:"overflow",level:4},{value:"APPEND_PARAMETER",id:"append_parameter",level:3},{value:"ID_PARAMETER",id:"id_parameter",level:3},{value:"APPEND_ID_PARAMETER",id:"append_id_parameter",level:3},{value:"ARRAY_PARAMETER",id:"array_parameter",level:3},{value:"APPEND_ARRAY_PARAMETER",id:"append_array_parameter",level:3},{value:"SELECT_PARAMETER",id:"select_parameter",level:3},{value:"DELETE_PARAMETER",id:"delete_parameter",level:3},{value:"HIDDEN",id:"hidden",level:3},{value:"DISABLED",id:"disabled",level:3},{value:"DISABLE_MESSAGES",id:"disable_messages",level:3},{value:"META",id:"meta-1",level:3},{value:"HAZARDOUS",id:"hazardous",level:3},{value:"ACCESSOR",id:"accessor",level:3},{value:"TEMPLATE",id:"template",level:3},{value:"TEMPLATE_FILE",id:"template_file",level:3},{value:"RESPONSE",id:"response",level:3},{value:"ERROR_RESPONSE",id:"error_response",level:3},{value:"RELATED_ITEM",id:"related_item",level:3},{value:"SCREEN",id:"screen",level:3},{value:"VIRTUAL",id:"virtual",level:3},{value:"SELECT_COMMAND",id:"select_command",level:2},{value:"Example File",id:"example-file",level:2}];function c(e){const r={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h2,{id:"command-definition-files",children:"Command Definition Files"}),"\n",(0,t.jsxs)(r.p,{children:["Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the ",(0,t.jsx)(r.a,{href:"http://www.asciitable.com/",children:"ASCII Table"})," is structured, files beginning with capital letters are processed before lower case letters."]}),"\n",(0,t.jsx)(r.p,{children:"When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters."}),"\n",(0,t.jsx)("div",{style:{clear:"both"}}),"\n",(0,t.jsx)(r.h1,{id:"command-keywords",children:"Command Keywords"}),"\n",(0,t.jsx)(r.h2,{id:"command",children:"COMMAND"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a new command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target"}),(0,t.jsx)(r.td,{children:"Name of the target this command is associated with"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Command"}),(0,t.jsx)(r.td,{children:"Name of this command. Also referred to as its mnemonic. Must be unique to commands to this target. Ideally will be as short and clear as possible."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description of this command which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'COMMAND INST COLLECT BIG_ENDIAN "Start collect"\n'})}),"\n",(0,t.jsx)(r.h2,{id:"command-modifiers",children:"COMMAND Modifiers"}),"\n",(0,t.jsx)(r.p,{children:"The following keywords must follow a COMMAND keyword."}),"\n",(0,t.jsx)(r.h3,{id:"parameter",children:"PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'PARAMETER SYNC 0 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern"\nPARAMETER DATA 32 32 INT MIN MAX 0 "Data value"\nPARAMETER VALUE 64 32 FLOAT 0 10.5 2.5\nPARAMETER LABEL 96 96 STRING "OPENC3" "The label to apply"\nPARAMETER BLOCK 192 0 BLOCK 0x0 "Block of binary data"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"parameter-modifiers",children:"PARAMETER Modifiers"}),"\n",(0,t.jsx)(r.p,{children:"The following keywords must follow a PARAMETER keyword."}),"\n",(0,t.jsx)(r.h4,{id:"format_string",children:"FORMAT_STRING"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds printf style formatting"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Format"}),(0,t.jsx)(r.td,{children:"How to format using printf syntax. For example, '0x%0X' will display the value in hex."}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'FORMAT_STRING "0x%0X"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"units",children:"UNITS"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Add displayed units"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Full Name"}),(0,t.jsx)(r.td,{children:"Full name of the units type, e.g. Celsius"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Abbreviated"}),(0,t.jsx)(r.td,{children:"Abbreviation for the units, e.g. C"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"UNITS Celsius C\nUNITS Kilometers KM\n"})}),"\n",(0,t.jsx)(r.h4,{id:"description",children:"DESCRIPTION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined description"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new description"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"meta",children:"META"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Stores custom user metadata"})}),"\n",(0,t.jsx)(r.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Name"}),(0,t.jsx)(r.td,{children:"Name of the metadata to store"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Values"}),(0,t.jsx)(r.td,{children:"One or more values to be stored for this Meta Name"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'META TEST "This parameter is for test purposes only"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"overlap",children:"OVERLAP"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,t.jsx)(r.strong,{children:"This item is allowed to overlap other items in the packet"})]}),"\n",(0,t.jsx)(r.p,{children:"If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message."}),"\n",(0,t.jsx)(r.h4,{id:"key",children:"KEY"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines the key used to access this raw value in the packet."})]}),"\n",(0,t.jsx)(r.p,{children:"Keys are often JsonPath or XPath strings"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Key string"}),(0,t.jsx)(r.td,{children:"The key to access this item"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"KEY $.book.title\n"})}),"\n",(0,t.jsx)(r.h4,{id:"variable_bit_size",children:"VARIABLE_BIT_SIZE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,t.jsx)(r.strong,{children:"Marks an item as having its bit size defined by another length item"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Item Name"}),(0,t.jsx)(r.td,{children:"The name of the associated length item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Bits Per Count"}),(0,t.jsx)(r.td,{children:"Bits per count of the length item. Defaults to 8"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Length Value Bit Offset"}),(0,t.jsx)(r.td,{children:"Offset in Bits to Apply to Length Field Value. Defaults to 0"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.h4,{id:"required",children:"REQUIRED"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Parameter is required to be populated in scripts"})}),"\n",(0,t.jsx)(r.p,{children:"When sending the command via Script Runner a value must always be given for the current command parameter. This prevents the user from relying on a default value. Note that this does not affect Command Sender which will still populate the field with the default value provided in the PARAMETER definition."}),"\n",(0,t.jsx)(r.h4,{id:"minimum_value",children:"MINIMUM_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined minimum value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new minimum value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"maximum_value",children:"MAXIMUM_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined maximum value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new maximum value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"default_value",children:"DEFAULT_VALUE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Override the defined default value"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The new default value for the parameter"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h4,{id:"state",children:"STATE"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a key/value pair for the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"Key value pairs allow for user friendly strings. For example, you might define states for ON = 1 and OFF = 0. This allows the word ON to be used rather than the number 1 when sending the command parameter and allows for much greater clarity and less chance for user error."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Key"}),(0,t.jsx)(r.td,{children:"The string state name"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Value"}),(0,t.jsx)(r.td,{children:"The numerical state value"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Hazardous / Disable Messages"}),(0,t.jsxs)(r.td,{children:["Indicates the state is hazardous. This will cause a popup to ask for user confirmation when sending this command. For non-hazardous states you can also set DISABLE_MESSAGES which will not print the command when using that state.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"HAZARDOUS"})]}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Hazardous Description"}),(0,t.jsx)(r.td,{children:"String describing why this state is hazardous"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_PARAMETER ENABLE 32 UINT 0 1 0 "Enable setting"\n STATE FALSE 0\n STATE TRUE 1\nAPPEND_PARAMETER STRING 1024 STRING "NOOP" "String parameter"\n STATE "NOOP" "NOOP" DISABLE_MESSAGES\n STATE "ARM LASER" "ARM LASER" HAZARDOUS "Arming the laser is an eye safety hazard"\n STATE "FIRE LASER" "FIRE LASER" HAZARDOUS "WARNING! Laser will be fired!"\n'})}),"\n",(0,t.jsx)(r.h4,{id:"write_conversion",children:"WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Applies a conversion when writing the current command parameter"})}),"\n",(0,t.jsxs)(r.p,{children:["Conversions are implemented in a custom Ruby or Python file which should be\nlocated in the target's lib folder. The class must inherit from Conversion.\nIt must implement the ",(0,t.jsx)(r.code,{children:"initialize"})," (Ruby) or ",(0,t.jsx)(r.code,{children:"__init__"})," (Python) method if it\ntakes extra parameters and must always implement the ",(0,t.jsx)(r.code,{children:"call"})," method. The conversion\nfactor is applied to the value entered by the user before it is written into\nthe binary command packet and sent."]}),"\n",(0,t.jsx)(r.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,t.jsx)(r.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Class Filename"}),(0,t.jsx)(r.td,{children:"The filename which contains the Ruby or Python class. The filename must be named after the class such that the class is a CamelCase version of the underscored filename. For example, 'the_great_conversion.rb' should contain 'class TheGreatConversion'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Additional parameter values for the conversion which are passed to the class constructor."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"WRITE_CONVERSION the_great_conversion.rb 1000\n\nDefined in the_great_conversion.rb:\n\nrequire 'openc3/conversions/conversion'\nmodule OpenC3\n class TheGreatConversion < Conversion\n def initialize(multiplier)\n super()\n @multiplier = multiplier.to_f\n end\n def call(value, packet, buffer)\n return value * multiplier\n end\n end\nend\n"})}),"\n",(0,t.jsx)(r.p,{children:"Python Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-python",children:"WRITE_CONVERSION the_great_conversion.py 1000\n\nDefined in the_great_conversion.py:\n\nfrom openc3.conversions.conversion import Conversion\nclass TheGreatConversion(Conversion):\n def __init__(self, multiplier):\n super().__init__()\n self.multiplier = float(multiplier)\n def call(self, value, packet, buffer):\n return value * multiplier\n"})}),"\n",(0,t.jsx)(r.h4,{id:"poly_write_conversion",children:"POLY_WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds a polynomial conversion factor to the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"The conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"C0"}),(0,t.jsx)(r.td,{children:"Coefficient"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Cx"}),(0,t.jsx)(r.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"POLY_WRITE_CONVERSION 10 0.5 0.25\n"})}),"\n",(0,t.jsx)(r.h4,{id:"seg_poly_write_conversion",children:"SEG_POLY_WRITE_CONVERSION"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Adds a segmented polynomial conversion factor to the current command parameter"})}),"\n",(0,t.jsx)(r.p,{children:"This conversion factor is applied to the value entered by the user before it is written into the binary command packet and sent."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Lower Bound"}),(0,t.jsx)(r.td,{children:"Defines the lower bound of the range of values that this segmented polynomial applies to. Is ignored for the segment with the smallest lower bound."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"C0"}),(0,t.jsx)(r.td,{children:"Coefficient"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Cx"}),(0,t.jsx)(r.td,{children:"Additional coefficient values for the conversion. Any order polynomial conversion may be used so the value of 'x' will vary with the order of the polynomial. Note that larger order polynomials take longer to process than shorter order polynomials, but are sometimes more accurate."}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SEG_POLY_WRITE_CONVERSION 0 10 0.5 0.25 # Apply the conversion to all values < 50\nSEG_POLY_WRITE_CONVERSION 50 11 0.5 0.275 # Apply the conversion to all values >= 50 and < 100\nSEG_POLY_WRITE_CONVERSION 100 12 0.5 0.3 # Apply the conversion to all values >= 100\n"})}),"\n",(0,t.jsx)(r.h4,{id:"generic_write_conversion_start",children:"GENERIC_WRITE_CONVERSION_START"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Start a generic write conversion"})}),"\n",(0,t.jsx)(r.p,{children:"Adds a generic conversion function to the current command parameter.\nThis conversion factor is applied to the value entered by the user before it\nis written into the binary command packet and sent. The conversion is specified\nas Ruby or Python code that receives two implied parameters. 'value' which is the raw\nvalue being written and 'packet' which is a reference to the command packet\nclass (Note, referencing the packet as 'myself' is still supported for backwards\ncompatibility). The last line of code should return the converted\nvalue. The GENERIC_WRITE_CONVERSION_END keyword specifies that all lines of\ncode for the conversion have been given."}),"\n",(0,t.jsx)(r.admonition,{title:"Multiple write conversions on command parameters",type:"info",children:(0,t.jsx)(r.p,{children:"When a command is built, each item gets written (and write conversions are run)\nto set the default value. Then items are written (again write conversions are run)\nwith user provided values. Thus write conversions can be run twice. Also there are\nno guarantees which parameters have already been written. The packet itself has a\ngiven_values() method which can be used to retrieve a hash of the user provided\nvalues to the command. That can be used to check parameter values passed in."})}),"\n",(0,t.jsx)(r.admonition,{type:"warning",children:(0,t.jsx)(r.p,{children:"Generic conversions are not a good long term solution. Consider creating a conversion class and using WRITE_CONVERSION instead. WRITE_CONVERSION is easier to debug and higher performance."})}),"\n",(0,t.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return (value * 1.5).to_i # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,t.jsx)(r.p,{children:"Python Example:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-python",children:"APPEND_PARAMETER ITEM1 32 UINT 0 0xFFFFFFFF 0\n GENERIC_WRITE_CONVERSION_START\n return int(value * 1.5) # Convert the value by a scale factor\n GENERIC_WRITE_CONVERSION_END\n"})}),"\n",(0,t.jsx)(r.h4,{id:"generic_write_conversion_end",children:"GENERIC_WRITE_CONVERSION_END"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Complete a generic write conversion"})}),"\n",(0,t.jsx)(r.h4,{id:"overflow",children:"OVERFLOW"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Set the behavior when writing a value overflows the type"})}),"\n",(0,t.jsx)(r.p,{children:"By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Behavior"}),(0,t.jsxs)(r.td,{children:["How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"ERROR, ERROR_ALLOW_HEX, TRUNCATE, SATURATE"})]}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"OVERFLOW TRUNCATE\n"})}),"\n",(0,t.jsx)(r.h3,{id:"append_parameter",children:"APPEND_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_PARAMETER SYNC 32 UINT 0xDEADBEEF 0xDEADBEEF 0xDEADBEEF "Sync pattern"\nAPPEND_PARAMETER VALUE 32 FLOAT 0 10.5 2.5\nAPPEND_PARAMETER LABEL 0 STRING "OPENC3" "The label to apply"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"id_parameter",children:"ID_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines an identification command parameter in the current command packet"})}),"\n",(0,t.jsx)(r.p,{children:"ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"ID Value"}),(0,t.jsx)(r.td,{children:"Identification value for this parameter. The binary data must match this value for the buffer to be identified as this packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'ID_PARAMETER OPCODE 32 32 UINT 2 2 2 "Opcode identifier"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"append_id_parameter",children:"APPEND_ID_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines an identification command parameter in the current command packet"})}),"\n",(0,t.jsx)(r.p,{children:"ID parameters are used to identify the binary block of data as a particular command. A command packet may have one or more ID_PARAMETERs and all must match the binary data for the command to be identified."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of this parameter. Zero or Negative values may be used to indicate that a string fills the packet up to the offset from the end of the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then this is a derived parameter and the Data Type must be set to 'DERIVED'."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of this parameter",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, DERIVED, STRING, BLOCK"})]}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is INT, UINT, FLOAT, DERIVED the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Minimum Value"}),(0,t.jsx)(r.td,{children:"Minimum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Maximum Value"}),(0,t.jsx)(r.td,{children:"Maximum allowed value for this parameter"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"ID Value"}),(0,t.jsx)(r.td,{children:"Identification value for this parameter. The binary data must match this value for the buffer to be identified as this packet."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format. See guide on ",(0,t.jsx)(r.a,{href:"/docs/guides/little-endian-bitfields",children:"Little Endian Bitfields"}),".",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"When Data Type is STRING, BLOCK the remaining parameters are:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Default Value"}),(0,t.jsx)(r.td,{children:"Default value for this parameter. You must provide a default but if you mark the parameter REQUIRED then scripts will be forced to specify a value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for this parameter which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data in this command is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_ID_PARAMETER OPCODE 32 UINT 2 2 2 "Opcode identifier"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"array_parameter",children:"ARRAY_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet that is an array"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Bit Offset"}),(0,t.jsx)(r.td,{children:"Bit offset into the command packet of the Most Significant Bit of this parameter. May be negative to indicate on offset from the end of the packet. Always use a bit offset of 0 for derived parameters."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of each array item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of each array item",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, STRING, BLOCK, DERIVED"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Array Bit Size"}),(0,t.jsx)(r.td,{children:"Total Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'ARRAY_PARAMETER ARRAY 64 64 FLOAT 640 "Array of 10 64bit floats"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"append_array_parameter",children:"APPEND_ARRAY_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Defines a command parameter in the current command packet that is an array"})}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Name"}),(0,t.jsx)(r.td,{children:"Name of the parameter. Must be unique within the command."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Bit Size"}),(0,t.jsx)(r.td,{children:"Bit size of each array item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Data Type"}),(0,t.jsxs)(r.td,{children:["Data Type of each array item",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"INT, UINT, FLOAT, STRING, BLOCK, DERIVED"})]}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Array Bit Size"}),(0,t.jsx)(r.td,{children:"Total Bit Size of the Array. Zero or Negative values may be used to indicate the array fills the packet up to the offset from the end of the packet specified by this value."}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Endianness"}),(0,t.jsxs)(r.td,{children:["Indicates if the data is to be sent in Big Endian or Little Endian format",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Valid Values: ",(0,t.jsx)("span",{class:"values",children:"BIG_ENDIAN, LITTLE_ENDIAN"})]}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'APPEND_ARRAY_PARAMETER ARRAY 64 FLOAT 640 "Array of 10 64bit floats"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"select_parameter",children:"SELECT_PARAMETER"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Selects an existing command parameter for editing"})}),"\n",(0,t.jsx)(r.p,{children:"Must be used in conjunction with SELECT_COMMAND to first select the packet. Typically used to override generated values or make specific changes to commands that only affect a particular instance of a target used multiple times."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Name of the parameter to select for modification"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n SELECT_PARAMETER DURATION\n # Add units\n UNITS Seconds S\n"})}),"\n",(0,t.jsx)(r.h3,{id:"delete_parameter",children:"DELETE_PARAMETER"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 4.4.1)"}),(0,t.jsx)(r.strong,{children:"Deletes an existing command parameter from the packet definition"})]}),"\n",(0,t.jsx)(r.p,{children:'Deleting a parameter from the command definition does not remove the defined space for that parameter. Thus unless you redefine a new parameter, there will be a "hole" in the packet where the data is not accessible. You can use SELECT_COMMAND and then PARAMETER to define a new parameter.'}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Parameter"}),(0,t.jsx)(r.td,{children:"Name of the parameter to delete"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n DELETE_PARAMETER DURATION\n"})}),"\n",(0,t.jsx)(r.h3,{id:"hidden",children:"HIDDEN"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Hides this command from all OpenC3 tools such as Command Sender and Handbook Creator"})}),"\n",(0,t.jsx)(r.p,{children:"Hidden commands do not appear in the Script Runner popup helper when writing scripts. The command still exists in the system and can be sent by scripts."}),"\n",(0,t.jsx)(r.h3,{id:"disabled",children:"DISABLED"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Disables this command from being sent"})}),"\n",(0,t.jsx)(r.p,{children:"Hides the command and also disables it from being sent by scripts. Attempts to send DISABLED commands result in an error message."}),"\n",(0,t.jsx)(r.h3,{id:"disable_messages",children:"DISABLE_MESSAGES"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Disable the Server from printing cmd(...) messages. Commands are still logged."})}),"\n",(0,t.jsx)(r.h3,{id:"meta-1",children:"META"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Stores metadata for the current command"})}),"\n",(0,t.jsx)(r.p,{children:"Meta data is user specific data that can be used by custom tools for various purposes. One example is to store additional information needed to generate source code header files."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Name"}),(0,t.jsx)(r.td,{children:"Name of the metadata to store"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Meta Values"}),(0,t.jsx)(r.td,{children:"One or more values to be stored for this Meta Name"}),(0,t.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'META FSW_TYPE "struct command"\n'})}),"\n",(0,t.jsx)(r.h3,{id:"hazardous",children:"HAZARDOUS"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Designates the current command as hazardous"})}),"\n",(0,t.jsx)(r.p,{children:"Sending a hazardous command causes a dialog asking for confirmation before sending the command"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Description"}),(0,t.jsx)(r.td,{children:"Description for why the command is hazardous which must be enclosed with quotes"}),(0,t.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"accessor",children:"ACCESSOR"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines the class used to read and write raw values from the packet"})]}),"\n",(0,t.jsx)(r.p,{children:"Defines the class that is used too read raw values from the packet. Defaults to BinaryAccessor. Provided accessors also include JsonAccessor, CborAccessor, HtmlAccessor, and XmlAccessor."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Accessor Class Name"}),(0,t.jsx)(r.td,{children:"The name of the accessor class"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"template",children:"TEMPLATE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines a template string used to initialize the command before default values are filled in"})]}),"\n",(0,t.jsx)(r.p,{children:"Generally the template string is formatted in JSON or HTML and then values are filled in with command parameters. Must be UTF-8 encoded."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Template"}),(0,t.jsx)(r.td,{children:"The template string which should be enclosed in quotes"}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"template_file",children:"TEMPLATE_FILE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,t.jsx)(r.strong,{children:"Defines a template file used to initialize the command before default values are filled in"})]}),"\n",(0,t.jsx)(r.p,{children:"Generally the template file is formatted in JSON or HTML and then values are filled in with command parameters. Can be binary or UTF-8."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsx)(r.tbody,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Template File Path"}),(0,t.jsx)(r.td,{children:"The relative path to the template file. Filename should generally start with an underscore."}),(0,t.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,t.jsx)(r.h3,{id:"response",children:"RESPONSE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Indicates the expected telemetry packet response to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of telemetry response packet"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of telemetry response packet"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"error_response",children:"ERROR_RESPONSE"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Indicates the expected telemetry packet error response to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of telemetry error response packet"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of telemetry error response packet"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"related_item",children:"RELATED_ITEM"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Defines a related telemetry item to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Packet Name"}),(0,t.jsx)(r.td,{children:"Packet Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Item Name"}),(0,t.jsx)(r.td,{children:"Item Name of related telemetry item"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"screen",children:"SCREEN"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.14.0)"}),(0,t.jsx)(r.strong,{children:"Defines a related telemetry screen to this command"})]}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Target Name of related telemetry screen"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Screen Name"}),(0,t.jsx)(r.td,{children:"Screen Name of related telemetry screen"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.h3,{id:"virtual",children:"VIRTUAL"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)("div",{class:"right",children:"(Since 5.18.0)"}),(0,t.jsx)(r.strong,{children:"Marks this packet as virtual and not participating in identification"})]}),"\n",(0,t.jsx)(r.p,{children:"Used for packet definitions that can be used as structures for items with a given packet."}),"\n",(0,t.jsx)(r.h2,{id:"select_command",children:"SELECT_COMMAND"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Selects an existing command packet for editing"})}),"\n",(0,t.jsx)(r.p,{children:"Typically used in a separate configuration file from where the original command is defined to override or add to the existing command definition. Must be used in conjunction with SELECT_PARAMETER to change an individual parameter."}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Parameter"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Required"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Target Name"}),(0,t.jsx)(r.td,{children:"Name of the target this command is associated with"}),(0,t.jsx)(r.td,{children:"True"})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"Command Name"}),(0,t.jsx)(r.td,{children:"Name of the command to select"}),(0,t.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,t.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:"SELECT_COMMAND INST COLLECT\n SELECT_PARAMETER DURATION\n # Add units\n UNITS Seconds S\n"})}),"\n",(0,t.jsx)(r.h2,{id:"example-file",children:"Example File"}),"\n",(0,t.jsx)(r.p,{children:(0,t.jsx)(r.strong,{children:"Example File: TARGET/cmd_tlm/cmd.txt"})}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-ruby",children:'COMMAND TARGET COLLECT_DATA BIG_ENDIAN "Commands my target to collect data"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 100 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 4 4 4 "CCSDS PRIMARY HEADER PACKET LENGTH"\n PARAMETER ANGLE 48 32 FLOAT -180.0 180.0 0.0 "ANGLE OF INSTRUMENT IN DEGREES"\n POLY_WRITE_CONVERSION 0 0.01745 0 0\n PARAMETER MODE 80 8 UINT 0 1 0 "DATA COLLECTION MODE"\n STATE NORMAL 0\n STATE DIAG 1\nCOMMAND TARGET NOOP BIG_ENDIAN "Do Nothing"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 101 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH"\n PARAMETER DUMMY 48 8 UINT 0 0 0 "DUMMY PARAMETER BECAUSE CCSDS REQUIRES 1 BYTE OF DATA"\nCOMMAND TARGET SETTINGS BIG_ENDIAN "Set the Settings"\n PARAMETER CCSDSVER 0 3 UINT 0 0 0 "CCSDS PRIMARY HEADER VERSION NUMBER"\n PARAMETER CCSDSTYPE 3 1 UINT 1 1 1 "CCSDS PRIMARY HEADER PACKET TYPE"\n PARAMETER CCSDSSHF 4 1 UINT 0 0 0 "CCSDS PRIMARY HEADER SECONDARY HEADER FLAG"\n ID_PARAMETER CCSDSAPID 5 11 UINT 0 2047 102 "CCSDS PRIMARY HEADER APPLICATION ID"\n PARAMETER CCSDSSEQFLAGS 16 2 UINT 3 3 3 "CCSDS PRIMARY HEADER SEQUENCE FLAGS"\n PARAMETER CCSDSSEQCNT 18 14 UINT 0 16383 0 "CCSDS PRIMARY HEADER SEQUENCE COUNT"\n PARAMETER CCSDSLENGTH 32 16 UINT 0 0 0 "CCSDS PRIMARY HEADER PACKET LENGTH"\n <% 5.times do |x| %>\n APPEND_PARAMETER SETTING<%= x %> 16 UINT 0 5 0 "Setting <%= x %>"\n <% end %>\n'})})]})}function o(e={}){const{wrapper:r}={...(0,n.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,r,s)=>{s.d(r,{R:()=>d,x:()=>a});var t=s(6540);const n={},i=t.createContext(n);function d(e){const r=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:d(e.components),t.createElement(i.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/848bfa8e.97c209d7.js b/docs/assets/js/848bfa8e.7632fffc.js
similarity index 68%
rename from docs/assets/js/848bfa8e.97c209d7.js
rename to docs/assets/js/848bfa8e.7632fffc.js
index 48501807cc..f1bf29723d 100644
--- a/docs/assets/js/848bfa8e.97c209d7.js
+++ b/docs/assets/js/848bfa8e.7632fffc.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[4619],{8912:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"defaultSidebar":[{"type":"link","label":"Introduction","href":"/docs/","docId":"introduction","unlisted":false},{"type":"category","label":"Getting Started","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Installation","href":"/docs/getting-started/installation","docId":"getting-started/installation","unlisted":false},{"type":"link","label":"Getting Started","href":"/docs/getting-started/gettingstarted","docId":"getting-started/gettingstarted","unlisted":false},{"type":"link","label":"Code Generators","href":"/docs/getting-started/generators","docId":"getting-started/generators","unlisted":false},{"type":"link","label":"Upgrading","href":"/docs/getting-started/upgrading","docId":"getting-started/upgrading","unlisted":false},{"type":"link","label":"Key Concepts","href":"/docs/getting-started/key_concepts","docId":"getting-started/key_concepts","unlisted":false},{"type":"link","label":"Requirements and Design","href":"/docs/getting-started/requirements","docId":"getting-started/requirements","unlisted":false},{"type":"link","label":"Podman","href":"/docs/getting-started/podman","docId":"getting-started/podman","unlisted":false}],"href":"/docs/getting-started"},{"type":"category","label":"Configuration","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"File Format","href":"/docs/configuration/format","docId":"configuration/format","unlisted":false},{"type":"link","label":"Plugins","href":"/docs/configuration/plugins","docId":"configuration/plugins","unlisted":false},{"type":"link","label":"Targets","href":"/docs/configuration/target","docId":"configuration/target","unlisted":false},{"type":"link","label":"Commands","href":"/docs/configuration/command","docId":"configuration/command","unlisted":false},{"type":"link","label":"Telemetry","href":"/docs/configuration/telemetry","docId":"configuration/telemetry","unlisted":false},{"type":"link","label":"Interfaces","href":"/docs/configuration/interfaces","docId":"configuration/interfaces","unlisted":false},{"type":"link","label":"Protocols","href":"/docs/configuration/protocols","docId":"configuration/protocols","unlisted":false},{"type":"link","label":"Tables","href":"/docs/configuration/table","docId":"configuration/table","unlisted":false},{"type":"link","label":"Screens","href":"/docs/configuration/telemetry-screens","docId":"configuration/telemetry-screens","unlisted":false},{"type":"link","label":"SSL-TLS","href":"/docs/configuration/ssl-tls","docId":"configuration/ssl-tls","unlisted":false}],"href":"/docs/configuration"},{"type":"category","label":"Tools","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Autonomic (Enterprise)","href":"/docs/tools/autonomic","docId":"tools/autonomic","unlisted":false},{"type":"link","label":"Bucket Explorer","href":"/docs/tools/bucket-explorer","docId":"tools/bucket-explorer","unlisted":false},{"type":"link","label":"Calendar (Enterprise)","href":"/docs/tools/calendar","docId":"tools/calendar","unlisted":false},{"type":"link","label":"Command Sender","href":"/docs/tools/cmd-sender","docId":"tools/cmd-sender","unlisted":false},{"type":"link","label":"Command and Telemetry Server","href":"/docs/tools/cmd-tlm-server","docId":"tools/cmd-tlm-server","unlisted":false},{"type":"link","label":"Data Extractor","href":"/docs/tools/data-extractor","docId":"tools/data-extractor","unlisted":false},{"type":"link","label":"Data Viewer","href":"/docs/tools/data-viewer","docId":"tools/data-viewer","unlisted":false},{"type":"link","label":"Handbooks","href":"/docs/tools/handbooks","docId":"tools/handbooks","unlisted":false},{"type":"link","label":"Limits Monitor","href":"/docs/tools/limits-monitor","docId":"tools/limits-monitor","unlisted":false},{"type":"link","label":"Packet Viewer","href":"/docs/tools/packet-viewer","docId":"tools/packet-viewer","unlisted":false},{"type":"link","label":"Script Runner","href":"/docs/tools/script-runner","docId":"tools/script-runner","unlisted":false},{"type":"link","label":"Table Manager","href":"/docs/tools/table-manager","docId":"tools/table-manager","unlisted":false},{"type":"link","label":"Telemetry Grapher","href":"/docs/tools/tlm-grapher","docId":"tools/tlm-grapher","unlisted":false},{"type":"link","label":"Telemetry Viewer","href":"/docs/tools/tlm-viewer","docId":"tools/tlm-viewer","unlisted":false}],"href":"/docs/tools"},{"type":"category","label":"Guides","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Bridges","href":"/docs/guides/bridges","docId":"guides/bridges","unlisted":false},{"type":"link","label":"COSMOS and NASA cFS","href":"/docs/guides/cfs","docId":"guides/cfs","unlisted":false},{"type":"link","label":"Custom Widgets","href":"/docs/guides/custom-widgets","docId":"guides/custom-widgets","unlisted":false},{"type":"link","label":"Little Endian Bitfields","href":"/docs/guides/little-endian-bitfields","docId":"guides/little-endian-bitfields","unlisted":false},{"type":"link","label":"Local Mode","href":"/docs/guides/local-mode","docId":"guides/local-mode","unlisted":false},{"type":"link","label":"Logging","href":"/docs/guides/logging","docId":"guides/logging","unlisted":false},{"type":"link","label":"Monitoring","href":"/docs/guides/monitoring","docId":"guides/monitoring","unlisted":false},{"type":"link","label":"Performance","href":"/docs/guides/performance","docId":"guides/performance","unlisted":false},{"type":"link","label":"Raspberry Pi","href":"/docs/guides/raspberrypi","docId":"guides/raspberrypi","unlisted":false},{"type":"link","label":"Script Writing Guide","href":"/docs/guides/script-writing","docId":"guides/script-writing","unlisted":false},{"type":"link","label":"Scripting API Guide","href":"/docs/guides/scripting-api","docId":"guides/scripting-api","unlisted":false}],"href":"/docs/guides"},{"type":"category","label":"Development","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Testing with Curl","href":"/docs/development/curl","docId":"development/curl","unlisted":false},{"type":"link","label":"Developing COSMOS","href":"/docs/development/developing","docId":"development/developing","unlisted":false},{"type":"link","label":"Host Install","href":"/docs/development/host-install","docId":"development/host-install","unlisted":false},{"type":"link","label":"JSON API","href":"/docs/development/json-api","docId":"development/json-api","unlisted":false},{"type":"link","label":"Log Structure","href":"/docs/development/log-structure","docId":"development/log-structure","unlisted":false},{"type":"link","label":"Roadmap","href":"/docs/development/roadmap","docId":"development/roadmap","unlisted":false},{"type":"link","label":"Streaming API","href":"/docs/development/streaming-api","docId":"development/streaming-api","unlisted":false},{"type":"link","label":"Testing COSMOS","href":"/docs/development/testing","docId":"development/testing","unlisted":false}],"href":"/docs/development"},{"type":"category","label":"Meta","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Contributing","href":"/docs/meta/contributing","docId":"meta/contributing","unlisted":false},{"type":"link","label":"Understanding Licenses","href":"/docs/meta/licenses","docId":"meta/licenses","unlisted":false},{"type":"link","label":"Philosophy","href":"/docs/meta/philosophy","docId":"meta/philosophy","unlisted":false},{"type":"link","label":"XTCE Support","href":"/docs/meta/xtce","docId":"meta/xtce","unlisted":false}],"href":"/docs/meta"},{"type":"link","label":"OpenC3, Inc. Privacy Policy","href":"/docs/privacy","docId":"privacy","unlisted":false}]},"docs":{"configuration/command":{"id":"configuration/command","title":"Commands","description":"Command Definition Files","sidebar":"defaultSidebar"},"configuration/format":{"id":"configuration/format","title":"File Format","description":"COSMOS configuration files are just text files. They can (and should) be checked into your configuration management system and thus can be easily diffed throughout their history. They support ERB syntax, partials, and various line continuations which make them extremely flexible.","sidebar":"defaultSidebar"},"configuration/interfaces":{"id":"configuration/interfaces","title":"Interfaces","description":"Interfaces are the connection to the external embedded systems called targets. Interfaces are defined by the top level INTERFACE keyword in the plugin.txt file.","sidebar":"defaultSidebar"},"configuration/plugins":{"id":"configuration/plugins","title":"Plugins","description":"Introduction","sidebar":"defaultSidebar"},"configuration/protocols":{"id":"configuration/protocols","title":"Protocols","description":"Protocols process data on behalf of an Interface. They can modify the data being written, data being read, or both. Protocols can also mark a packet as stored instead of real-time which means COSMOS will not update the current value table with the packet data. Protocols can be layered and will be processed in order. For example, if you have a low-level encryption layer that must be first removed before processing a higher level buffer length protocol.","sidebar":"defaultSidebar"},"configuration/ssl-tls":{"id":"configuration/ssl-tls","title":"SSL-TLS","description":"COSMOS 5 is a container based service which does not use SSL/TLS out of the box. This guide will help you configure SSL and TLS. Learn more at the Traefik docs.","sidebar":"defaultSidebar"},"configuration/table":{"id":"configuration/table","title":"Tables","description":"Table Definition Files","sidebar":"defaultSidebar"},"configuration/target":{"id":"configuration/target","title":"Targets","description":"Targets are the external embedded systems that COSMOS connects to. Targets are defined by the top level TARGET keyword in the plugin.txt file. Each target is self contained in a target directory named after the target. In the root of the target directory there is a configuration file named target.txt which configures the individual target.","sidebar":"defaultSidebar"},"configuration/telemetry":{"id":"configuration/telemetry","title":"Telemetry","description":"Telemetry Definition Files","sidebar":"defaultSidebar"},"configuration/telemetry-screens":{"id":"configuration/telemetry-screens","title":"Screens","description":"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application.","sidebar":"defaultSidebar"},"development/curl":{"id":"development/curl","title":"Testing with Curl","description":"This information is just generally used behind the scenes in COSMOS tools","sidebar":"defaultSidebar"},"development/developing":{"id":"development/developing","title":"Developing COSMOS","description":"So you want to help develop COSMOS? All of our open source COSMOS code is on Github so the first thing to do is get an account. Next clone the COSMOS repository. We accept contributions from others as Pull Requests.","sidebar":"defaultSidebar"},"development/host-install":{"id":"development/host-install","title":"Host Install","description":"Installing COSMOS Directly onto a Host (No Containers)","sidebar":"defaultSidebar"},"development/json-api":{"id":"development/json-api","title":"JSON API","description":"If you\'re looking for the methods available to write test procedures using the COSMOS scripting API, refer to the Scripting API Guide page. If you\'re trying to interface to a COSMOS Command and Telemetry Server from an external application using any language then this is the right place.","sidebar":"defaultSidebar"},"development/log-structure":{"id":"development/log-structure","title":"Log Structure","description":"Updated: 8-21-2023 to the format as of OpenC3 COSMOS 5.11.0","sidebar":"defaultSidebar"},"development/roadmap":{"id":"development/roadmap","title":"Roadmap","description":"Key Features Still to Come in OpenC3 COSMOS 5.x:","sidebar":"defaultSidebar"},"development/streaming-api":{"id":"development/streaming-api","title":"Streaming API","description":"This information is just generally used behind the scenes in COSMOS tools","sidebar":"defaultSidebar"},"development/testing":{"id":"development/testing","title":"Testing COSMOS","description":"Playwright","sidebar":"defaultSidebar"},"getting-started/generators":{"id":"getting-started/generators","title":"Code Generators","description":"The COSMOS Code Generators are built into the scripts openc3.sh and openc3.bat that are included in the COSMOS project (more about projects).","sidebar":"defaultSidebar"},"getting-started/gettingstarted":{"id":"getting-started/gettingstarted","title":"Getting Started","description":"Welcome to the OpenC3 COSMOS system... Let\'s get started! This guide is a high level overview that will help with setting up your first COSMOS project.","sidebar":"defaultSidebar"},"getting-started/installation":{"id":"getting-started/installation","title":"Installation","description":"Installing OpenC3 COSMOS","sidebar":"defaultSidebar"},"getting-started/key_concepts":{"id":"getting-started/key_concepts","title":"Key Concepts","description":"Projects","sidebar":"defaultSidebar"},"getting-started/podman":{"id":"getting-started/podman","title":"Podman","description":"OpenC3 COSMOS Using Rootless Podman and Docker-Compose","sidebar":"defaultSidebar"},"getting-started/requirements":{"id":"getting-started/requirements","title":"Requirements and Design","description":"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations.","sidebar":"defaultSidebar"},"getting-started/upgrading":{"id":"getting-started/upgrading","title":"Upgrading","description":"COSMOS Upgrades","sidebar":"defaultSidebar"},"guides/bridges":{"id":"guides/bridges","title":"Bridges","description":"COSMOS Bridges provide an easy solution for getting data from devices that don\'t speak Ethernet into COSMOS.","sidebar":"defaultSidebar"},"guides/cfs":{"id":"guides/cfs","title":"COSMOS and NASA cFS","description":"Working configuration","sidebar":"defaultSidebar"},"guides/custom-widgets":{"id":"guides/custom-widgets","title":"Custom Widgets","description":"COSMOS allows you to build custom widgets which can be deployed with your plugin and used in Telemetry Viewer. Building custom widgets can utilitize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the Widget Generator guide for information about generating the scaffolding for a custom widget.","sidebar":"defaultSidebar"},"guides/little-endian-bitfields":{"id":"guides/little-endian-bitfields","title":"Little Endian Bitfields","description":"Defining little endian bitfields is a little weird but is possible in COSMOS. However, note that APPEND does not work with little endian bitfields.","sidebar":"defaultSidebar"},"guides/local-mode":{"id":"guides/local-mode","title":"Local Mode","description":"Local Mode is a new feature in the 5.0.9 COSMOS release. It is intended to capture the configuration of an edited plugin so it can be configuration managed. It allows you to edit portions of a plugin (scripts and screens) locally in the editor of your choice and instantly have those changes appear in the COSMOS plugin. This avoids the plugin build / install cycle which is required when editing command and telemetry or interface definitions.","sidebar":"defaultSidebar"},"guides/logging":{"id":"guides/logging","title":"Logging","description":"The COSMOS Bucket Explorer tool provides a way to browse the COSMOS bucket storage backend whether you are running locally or in a cloud environment. Browse to http2900/tools/bucketexplorer and you should see the list of buckets at the top:","sidebar":"defaultSidebar"},"guides/monitoring":{"id":"guides/monitoring","title":"Monitoring","description":"Monitoring and observability","sidebar":"defaultSidebar"},"guides/performance":{"id":"guides/performance","title":"Performance","description":"The COSMOS architecture was created with scalability in mind. Our goal is to support an unlimited number of connections and use cloud technologies to scale. Only COSMOS Enterprise Edition supports Kubernetes and the various cloud platforms which allow this level of scalability. While true scalability is only achieved in COSMOS Enterprise, both Open Source and Enterprise have various levels of observability and configuration settings which can affect performance.","sidebar":"defaultSidebar"},"guides/raspberrypi":{"id":"guides/raspberrypi","title":"Raspberry Pi","description":"COSMOS Running on Raspberry Pi 4","sidebar":"defaultSidebar"},"guides/script-writing":{"id":"guides/script-writing","title":"Script Writing Guide","description":"Introduction","sidebar":"defaultSidebar"},"guides/scripting-api":{"id":"guides/scripting-api","title":"Scripting API Guide","description":"This document provides the information necessary to write test procedures using the COSMOS scripting API. Scripting in COSMOS is designed to be simple and intuitive. The code completion ability for command and telemetry mnemonics makes Script Runner the ideal place to write your procedures, however any text editor will do. If there is functionality that you don\'t see here or perhaps an easier syntax for doing something, please submit a ticket.","sidebar":"defaultSidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"This site aims to be a comprehensive guide to OpenC3 COSMOS. We\'ll cover topics such","sidebar":"defaultSidebar"},"meta/contributing":{"id":"meta/contributing","title":"Contributing","description":"So you\'ve got an awesome idea to throw into COSMOS. Great! This is the basic process:","sidebar":"defaultSidebar"},"meta/licenses":{"id":"meta/licenses","title":"Understanding Licenses","description":"OpenC3 COSMOS is offered under a tri-licensing model allowing users to choose between the following three options:","sidebar":"defaultSidebar"},"meta/philosophy":{"id":"meta/philosophy","title":"Philosophy","description":"COSMOS is a C3 (Command, Control and Communication) system with the following primary goals:","sidebar":"defaultSidebar"},"meta/xtce":{"id":"meta/xtce","title":"XTCE Support","description":"COSMOS now has support for the XTCE Command and Telemetry Definition Standard. This is an open standard designed to allow command and telemetry definitions to be transferred between different ground systems. COSMOS can run directly using the .xtce files, or can convert them into the COSMOS configuration file format.","sidebar":"defaultSidebar"},"privacy":{"id":"privacy","title":"OpenC3, Inc. Privacy Policy","description":"OpenC3 Inc. is strongly committed to protecting your privacy and complying with your choices. Both personal and non-personal information collected is safeguarded according to the highest privacy and data protection standards adopted worldwide. We have always had a robust and effective data protection program in place which complies with existing law and abides by the data protection principles. However, we recognise our obligations in updating and expanding this program to meet the demands of the GDPR.","sidebar":"defaultSidebar"},"tools/autonomic":{"id":"tools/autonomic","title":"Autonomic (Enterprise)","description":"Introduction","sidebar":"defaultSidebar"},"tools/bucket-explorer":{"id":"tools/bucket-explorer","title":"Bucket Explorer","description":"Introduction","sidebar":"defaultSidebar"},"tools/calendar":{"id":"tools/calendar","title":"Calendar (Enterprise)","description":"Introduction","sidebar":"defaultSidebar"},"tools/cmd-sender":{"id":"tools/cmd-sender","title":"Command Sender","description":"Introduction","sidebar":"defaultSidebar"},"tools/cmd-tlm-server":{"id":"tools/cmd-tlm-server","title":"Command and Telemetry Server","description":"Introduction","sidebar":"defaultSidebar"},"tools/data-extractor":{"id":"tools/data-extractor","title":"Data Extractor","description":"Introduction","sidebar":"defaultSidebar"},"tools/data-viewer":{"id":"tools/data-viewer","title":"Data Viewer","description":"Introduction","sidebar":"defaultSidebar"},"tools/handbooks":{"id":"tools/handbooks","title":"Handbooks","description":"Introduction","sidebar":"defaultSidebar"},"tools/limits-monitor":{"id":"tools/limits-monitor","title":"Limits Monitor","description":"Introduction","sidebar":"defaultSidebar"},"tools/packet-viewer":{"id":"tools/packet-viewer","title":"Packet Viewer","description":"Introduction","sidebar":"defaultSidebar"},"tools/script-runner":{"id":"tools/script-runner","title":"Script Runner","description":"Introduction","sidebar":"defaultSidebar"},"tools/table-manager":{"id":"tools/table-manager","title":"Table Manager","description":"Introduction","sidebar":"defaultSidebar"},"tools/tlm-grapher":{"id":"tools/tlm-grapher","title":"Telemetry Grapher","description":"Introductions","sidebar":"defaultSidebar"},"tools/tlm-viewer":{"id":"tools/tlm-viewer","title":"Telemetry Viewer","description":"Introduction","sidebar":"defaultSidebar"}}}}')}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[4619],{8912:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"defaultSidebar":[{"type":"link","label":"Introduction","href":"/docs/","docId":"introduction","unlisted":false},{"type":"category","label":"Getting Started","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Installation","href":"/docs/getting-started/installation","docId":"getting-started/installation","unlisted":false},{"type":"link","label":"Getting Started","href":"/docs/getting-started/gettingstarted","docId":"getting-started/gettingstarted","unlisted":false},{"type":"link","label":"Code Generators","href":"/docs/getting-started/generators","docId":"getting-started/generators","unlisted":false},{"type":"link","label":"Upgrading","href":"/docs/getting-started/upgrading","docId":"getting-started/upgrading","unlisted":false},{"type":"link","label":"Key Concepts","href":"/docs/getting-started/key_concepts","docId":"getting-started/key_concepts","unlisted":false},{"type":"link","label":"Requirements and Design","href":"/docs/getting-started/requirements","docId":"getting-started/requirements","unlisted":false},{"type":"link","label":"Podman","href":"/docs/getting-started/podman","docId":"getting-started/podman","unlisted":false}],"href":"/docs/getting-started"},{"type":"category","label":"Configuration","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"File Format","href":"/docs/configuration/format","docId":"configuration/format","unlisted":false},{"type":"link","label":"Plugins","href":"/docs/configuration/plugins","docId":"configuration/plugins","unlisted":false},{"type":"link","label":"Targets","href":"/docs/configuration/target","docId":"configuration/target","unlisted":false},{"type":"link","label":"Commands","href":"/docs/configuration/command","docId":"configuration/command","unlisted":false},{"type":"link","label":"Telemetry","href":"/docs/configuration/telemetry","docId":"configuration/telemetry","unlisted":false},{"type":"link","label":"Interfaces","href":"/docs/configuration/interfaces","docId":"configuration/interfaces","unlisted":false},{"type":"link","label":"Protocols","href":"/docs/configuration/protocols","docId":"configuration/protocols","unlisted":false},{"type":"link","label":"Tables","href":"/docs/configuration/table","docId":"configuration/table","unlisted":false},{"type":"link","label":"Screens","href":"/docs/configuration/telemetry-screens","docId":"configuration/telemetry-screens","unlisted":false},{"type":"link","label":"SSL-TLS","href":"/docs/configuration/ssl-tls","docId":"configuration/ssl-tls","unlisted":false}],"href":"/docs/configuration"},{"type":"category","label":"Tools","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Autonomic (Enterprise)","href":"/docs/tools/autonomic","docId":"tools/autonomic","unlisted":false},{"type":"link","label":"Bucket Explorer","href":"/docs/tools/bucket-explorer","docId":"tools/bucket-explorer","unlisted":false},{"type":"link","label":"Calendar (Enterprise)","href":"/docs/tools/calendar","docId":"tools/calendar","unlisted":false},{"type":"link","label":"Command Sender","href":"/docs/tools/cmd-sender","docId":"tools/cmd-sender","unlisted":false},{"type":"link","label":"Command and Telemetry Server","href":"/docs/tools/cmd-tlm-server","docId":"tools/cmd-tlm-server","unlisted":false},{"type":"link","label":"Data Extractor","href":"/docs/tools/data-extractor","docId":"tools/data-extractor","unlisted":false},{"type":"link","label":"Data Viewer","href":"/docs/tools/data-viewer","docId":"tools/data-viewer","unlisted":false},{"type":"link","label":"Handbooks","href":"/docs/tools/handbooks","docId":"tools/handbooks","unlisted":false},{"type":"link","label":"Limits Monitor","href":"/docs/tools/limits-monitor","docId":"tools/limits-monitor","unlisted":false},{"type":"link","label":"Packet Viewer","href":"/docs/tools/packet-viewer","docId":"tools/packet-viewer","unlisted":false},{"type":"link","label":"Script Runner","href":"/docs/tools/script-runner","docId":"tools/script-runner","unlisted":false},{"type":"link","label":"Table Manager","href":"/docs/tools/table-manager","docId":"tools/table-manager","unlisted":false},{"type":"link","label":"Telemetry Grapher","href":"/docs/tools/tlm-grapher","docId":"tools/tlm-grapher","unlisted":false},{"type":"link","label":"Telemetry Viewer","href":"/docs/tools/tlm-viewer","docId":"tools/tlm-viewer","unlisted":false}],"href":"/docs/tools"},{"type":"category","label":"Guides","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Bridges","href":"/docs/guides/bridges","docId":"guides/bridges","unlisted":false},{"type":"link","label":"COSMOS and NASA cFS","href":"/docs/guides/cfs","docId":"guides/cfs","unlisted":false},{"type":"link","label":"Custom Widgets","href":"/docs/guides/custom-widgets","docId":"guides/custom-widgets","unlisted":false},{"type":"link","label":"Little Endian Bitfields","href":"/docs/guides/little-endian-bitfields","docId":"guides/little-endian-bitfields","unlisted":false},{"type":"link","label":"Local Mode","href":"/docs/guides/local-mode","docId":"guides/local-mode","unlisted":false},{"type":"link","label":"Logging","href":"/docs/guides/logging","docId":"guides/logging","unlisted":false},{"type":"link","label":"Monitoring","href":"/docs/guides/monitoring","docId":"guides/monitoring","unlisted":false},{"type":"link","label":"Performance","href":"/docs/guides/performance","docId":"guides/performance","unlisted":false},{"type":"link","label":"Raspberry Pi","href":"/docs/guides/raspberrypi","docId":"guides/raspberrypi","unlisted":false},{"type":"link","label":"Script Writing Guide","href":"/docs/guides/script-writing","docId":"guides/script-writing","unlisted":false},{"type":"link","label":"Scripting API Guide","href":"/docs/guides/scripting-api","docId":"guides/scripting-api","unlisted":false}],"href":"/docs/guides"},{"type":"category","label":"Development","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Testing with Curl","href":"/docs/development/curl","docId":"development/curl","unlisted":false},{"type":"link","label":"Developing COSMOS","href":"/docs/development/developing","docId":"development/developing","unlisted":false},{"type":"link","label":"Host Install","href":"/docs/development/host-install","docId":"development/host-install","unlisted":false},{"type":"link","label":"JSON API","href":"/docs/development/json-api","docId":"development/json-api","unlisted":false},{"type":"link","label":"Log Structure","href":"/docs/development/log-structure","docId":"development/log-structure","unlisted":false},{"type":"link","label":"Roadmap","href":"/docs/development/roadmap","docId":"development/roadmap","unlisted":false},{"type":"link","label":"Streaming API","href":"/docs/development/streaming-api","docId":"development/streaming-api","unlisted":false},{"type":"link","label":"Testing COSMOS","href":"/docs/development/testing","docId":"development/testing","unlisted":false}],"href":"/docs/development"},{"type":"category","label":"Meta","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Contributing","href":"/docs/meta/contributing","docId":"meta/contributing","unlisted":false},{"type":"link","label":"Understanding Licenses","href":"/docs/meta/licenses","docId":"meta/licenses","unlisted":false},{"type":"link","label":"Philosophy","href":"/docs/meta/philosophy","docId":"meta/philosophy","unlisted":false},{"type":"link","label":"XTCE Support","href":"/docs/meta/xtce","docId":"meta/xtce","unlisted":false}],"href":"/docs/meta"},{"type":"link","label":"OpenC3, Inc. Privacy Policy","href":"/docs/privacy","docId":"privacy","unlisted":false}]},"docs":{"configuration/command":{"id":"configuration/command","title":"Commands","description":"Command Definition Files","sidebar":"defaultSidebar"},"configuration/format":{"id":"configuration/format","title":"File Format","description":"COSMOS configuration files are just text files. They can (and should) be checked into your configuration management system and thus can be easily diffed throughout their history. They support ERB syntax, partials, and various line continuations which make them extremely flexible.","sidebar":"defaultSidebar"},"configuration/interfaces":{"id":"configuration/interfaces","title":"Interfaces","description":"Interfaces are the connection to the external embedded systems called targets. Interfaces are defined by the top level INTERFACE keyword in the plugin.txt file.","sidebar":"defaultSidebar"},"configuration/plugins":{"id":"configuration/plugins","title":"Plugins","description":"Introduction","sidebar":"defaultSidebar"},"configuration/protocols":{"id":"configuration/protocols","title":"Protocols","description":"Protocols process data on behalf of an Interface. They can modify the data being written, data being read, or both. Protocols can also mark a packet as stored instead of real-time which means COSMOS will not update the current value table with the packet data. Protocols can be layered and will be processed in order. For example, if you have a low-level encryption layer that must be first removed before processing a higher level buffer length protocol.","sidebar":"defaultSidebar"},"configuration/ssl-tls":{"id":"configuration/ssl-tls","title":"SSL-TLS","description":"COSMOS 5 is a container based service which does not use SSL/TLS out of the box. This guide will help you configure SSL and TLS. Learn more at the Traefik docs.","sidebar":"defaultSidebar"},"configuration/table":{"id":"configuration/table","title":"Tables","description":"Table Definition Files","sidebar":"defaultSidebar"},"configuration/target":{"id":"configuration/target","title":"Targets","description":"Targets are the external embedded systems that COSMOS connects to. Targets are defined by the top level TARGET keyword in the plugin.txt file. Each target is self contained in a target directory named after the target. In the root of the target directory there is a configuration file named target.txt which configures the individual target.","sidebar":"defaultSidebar"},"configuration/telemetry":{"id":"configuration/telemetry","title":"Telemetry","description":"Telemetry Definition Files","sidebar":"defaultSidebar"},"configuration/telemetry-screens":{"id":"configuration/telemetry-screens","title":"Screens","description":"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application.","sidebar":"defaultSidebar"},"development/curl":{"id":"development/curl","title":"Testing with Curl","description":"This information is just generally used behind the scenes in COSMOS tools","sidebar":"defaultSidebar"},"development/developing":{"id":"development/developing","title":"Developing COSMOS","description":"So you want to help develop COSMOS? All of our open source COSMOS code is on Github so the first thing to do is get an account. Next clone the COSMOS repository. We accept contributions from others as Pull Requests.","sidebar":"defaultSidebar"},"development/host-install":{"id":"development/host-install","title":"Host Install","description":"Installing COSMOS Directly onto a Host (No Containers)","sidebar":"defaultSidebar"},"development/json-api":{"id":"development/json-api","title":"JSON API","description":"If you\'re looking for the methods available to write test procedures using the COSMOS scripting API, refer to the Scripting API Guide page. If you\'re trying to interface to a COSMOS Command and Telemetry Server from an external application using any language then this is the right place.","sidebar":"defaultSidebar"},"development/log-structure":{"id":"development/log-structure","title":"Log Structure","description":"Updated: 8-21-2023 to the format as of OpenC3 COSMOS 5.11.0","sidebar":"defaultSidebar"},"development/roadmap":{"id":"development/roadmap","title":"Roadmap","description":"Key Features Still to Come in OpenC3 COSMOS 5.x:","sidebar":"defaultSidebar"},"development/streaming-api":{"id":"development/streaming-api","title":"Streaming API","description":"This information is just generally used behind the scenes in COSMOS tools","sidebar":"defaultSidebar"},"development/testing":{"id":"development/testing","title":"Testing COSMOS","description":"Playwright","sidebar":"defaultSidebar"},"getting-started/generators":{"id":"getting-started/generators","title":"Code Generators","description":"The COSMOS Code Generators are built into the scripts openc3.sh and openc3.bat that are included in the COSMOS project (more about projects).","sidebar":"defaultSidebar"},"getting-started/gettingstarted":{"id":"getting-started/gettingstarted","title":"Getting Started","description":"Welcome to the OpenC3 COSMOS system... Let\'s get started! This guide is a high level overview that will help with setting up your first COSMOS project.","sidebar":"defaultSidebar"},"getting-started/installation":{"id":"getting-started/installation","title":"Installation","description":"Installing OpenC3 COSMOS","sidebar":"defaultSidebar"},"getting-started/key_concepts":{"id":"getting-started/key_concepts","title":"Key Concepts","description":"Projects","sidebar":"defaultSidebar"},"getting-started/podman":{"id":"getting-started/podman","title":"Podman","description":"OpenC3 COSMOS Using Rootless Podman and Docker-Compose","sidebar":"defaultSidebar"},"getting-started/requirements":{"id":"getting-started/requirements","title":"Requirements and Design","description":"OpenC3 COSMOS is a command and control system providing commanding, scripting, and data visualization capabilities for embedded systems and systems of systems. COSMOS is intended for use during all phases of testing (board, box, integrated system) and during operations.","sidebar":"defaultSidebar"},"getting-started/upgrading":{"id":"getting-started/upgrading","title":"Upgrading","description":"COSMOS Upgrades","sidebar":"defaultSidebar"},"guides/bridges":{"id":"guides/bridges","title":"Bridges","description":"COSMOS Bridges provide an easy solution for getting data from devices that don\'t speak Ethernet into COSMOS.","sidebar":"defaultSidebar"},"guides/cfs":{"id":"guides/cfs","title":"COSMOS and NASA cFS","description":"Working configuration","sidebar":"defaultSidebar"},"guides/custom-widgets":{"id":"guides/custom-widgets","title":"Custom Widgets","description":"COSMOS allows you to build custom widgets which can be deployed with your plugin and used in Telemetry Viewer. Building custom widgets can utilize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the Widget Generator guide for information about generating the scaffolding for a custom widget.","sidebar":"defaultSidebar"},"guides/little-endian-bitfields":{"id":"guides/little-endian-bitfields","title":"Little Endian Bitfields","description":"Defining little endian bitfields is a little weird but is possible in COSMOS. However, note that APPEND does not work with little endian bitfields.","sidebar":"defaultSidebar"},"guides/local-mode":{"id":"guides/local-mode","title":"Local Mode","description":"Local Mode is a new feature in the 5.0.9 COSMOS release. It is intended to capture the configuration of an edited plugin so it can be configuration managed. It allows you to edit portions of a plugin (scripts and screens) locally in the editor of your choice and instantly have those changes appear in the COSMOS plugin. This avoids the plugin build / install cycle which is required when editing command and telemetry or interface definitions.","sidebar":"defaultSidebar"},"guides/logging":{"id":"guides/logging","title":"Logging","description":"The COSMOS Bucket Explorer tool provides a way to browse the COSMOS bucket storage backend whether you are running locally or in a cloud environment. Browse to http2900/tools/bucketexplorer and you should see the list of buckets at the top:","sidebar":"defaultSidebar"},"guides/monitoring":{"id":"guides/monitoring","title":"Monitoring","description":"Monitoring and observability","sidebar":"defaultSidebar"},"guides/performance":{"id":"guides/performance","title":"Performance","description":"The COSMOS architecture was created with scalability in mind. Our goal is to support an unlimited number of connections and use cloud technologies to scale. Only COSMOS Enterprise Edition supports Kubernetes and the various cloud platforms which allow this level of scalability. While true scalability is only achieved in COSMOS Enterprise, both Open Source and Enterprise have various levels of observability and configuration settings which can affect performance.","sidebar":"defaultSidebar"},"guides/raspberrypi":{"id":"guides/raspberrypi","title":"Raspberry Pi","description":"COSMOS Running on Raspberry Pi 4","sidebar":"defaultSidebar"},"guides/script-writing":{"id":"guides/script-writing","title":"Script Writing Guide","description":"Introduction","sidebar":"defaultSidebar"},"guides/scripting-api":{"id":"guides/scripting-api","title":"Scripting API Guide","description":"This document provides the information necessary to write test procedures using the COSMOS scripting API. Scripting in COSMOS is designed to be simple and intuitive. The code completion ability for command and telemetry mnemonics makes Script Runner the ideal place to write your procedures, however any text editor will do. If there is functionality that you don\'t see here or perhaps an easier syntax for doing something, please submit a ticket.","sidebar":"defaultSidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"This site aims to be a comprehensive guide to OpenC3 COSMOS. We\'ll cover topics such","sidebar":"defaultSidebar"},"meta/contributing":{"id":"meta/contributing","title":"Contributing","description":"So you\'ve got an awesome idea to throw into COSMOS. Great! This is the basic process:","sidebar":"defaultSidebar"},"meta/licenses":{"id":"meta/licenses","title":"Understanding Licenses","description":"OpenC3 COSMOS is offered under a tri-licensing model allowing users to choose between the following three options:","sidebar":"defaultSidebar"},"meta/philosophy":{"id":"meta/philosophy","title":"Philosophy","description":"COSMOS is a C3 (Command, Control and Communication) system with the following primary goals:","sidebar":"defaultSidebar"},"meta/xtce":{"id":"meta/xtce","title":"XTCE Support","description":"COSMOS now has support for the XTCE Command and Telemetry Definition Standard. This is an open standard designed to allow command and telemetry definitions to be transferred between different ground systems. COSMOS can run directly using the .xtce files, or can convert them into the COSMOS configuration file format.","sidebar":"defaultSidebar"},"privacy":{"id":"privacy","title":"OpenC3, Inc. Privacy Policy","description":"OpenC3 Inc. is strongly committed to protecting your privacy and complying with your choices. Both personal and non-personal information collected is safeguarded according to the highest privacy and data protection standards adopted worldwide. We have always had a robust and effective data protection program in place which complies with existing law and abides by the data protection principles. However, we recognise our obligations in updating and expanding this program to meet the demands of the GDPR.","sidebar":"defaultSidebar"},"tools/autonomic":{"id":"tools/autonomic","title":"Autonomic (Enterprise)","description":"Introduction","sidebar":"defaultSidebar"},"tools/bucket-explorer":{"id":"tools/bucket-explorer","title":"Bucket Explorer","description":"Introduction","sidebar":"defaultSidebar"},"tools/calendar":{"id":"tools/calendar","title":"Calendar (Enterprise)","description":"Introduction","sidebar":"defaultSidebar"},"tools/cmd-sender":{"id":"tools/cmd-sender","title":"Command Sender","description":"Introduction","sidebar":"defaultSidebar"},"tools/cmd-tlm-server":{"id":"tools/cmd-tlm-server","title":"Command and Telemetry Server","description":"Introduction","sidebar":"defaultSidebar"},"tools/data-extractor":{"id":"tools/data-extractor","title":"Data Extractor","description":"Introduction","sidebar":"defaultSidebar"},"tools/data-viewer":{"id":"tools/data-viewer","title":"Data Viewer","description":"Introduction","sidebar":"defaultSidebar"},"tools/handbooks":{"id":"tools/handbooks","title":"Handbooks","description":"Introduction","sidebar":"defaultSidebar"},"tools/limits-monitor":{"id":"tools/limits-monitor","title":"Limits Monitor","description":"Introduction","sidebar":"defaultSidebar"},"tools/packet-viewer":{"id":"tools/packet-viewer","title":"Packet Viewer","description":"Introduction","sidebar":"defaultSidebar"},"tools/script-runner":{"id":"tools/script-runner","title":"Script Runner","description":"Introduction","sidebar":"defaultSidebar"},"tools/table-manager":{"id":"tools/table-manager","title":"Table Manager","description":"Introduction","sidebar":"defaultSidebar"},"tools/tlm-grapher":{"id":"tools/tlm-grapher","title":"Telemetry Grapher","description":"Introductions","sidebar":"defaultSidebar"},"tools/tlm-viewer":{"id":"tools/tlm-viewer","title":"Telemetry Viewer","description":"Introduction","sidebar":"defaultSidebar"}}}}')}}]);
\ No newline at end of file
diff --git a/docs/assets/js/9424f0b3.145b4d6d.js b/docs/assets/js/9424f0b3.145b4d6d.js
deleted file mode 100644
index dc695c7e45..0000000000
--- a/docs/assets/js/9424f0b3.145b4d6d.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[4909],{2111:(e,s,d)=>{d.r(s),d.d(s,{assets:()=>h,contentTitle:()=>i,default:()=>x,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=d(4848),n=d(8453);const t={sidebar_position:9,title:"Screens"},i=void 0,l={id:"configuration/telemetry-screens",title:"Screens",description:"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application.",source:"@site/docs/configuration/telemetry-screens.md",sourceDirName:"configuration",slug:"/configuration/telemetry-screens",permalink:"/docs/configuration/telemetry-screens",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/telemetry-screens.md",tags:[],version:"current",sidebarPosition:9,frontMatter:{sidebar_position:9,title:"Screens"},sidebar:"defaultSidebar",previous:{title:"Tables",permalink:"/docs/configuration/table"},next:{title:"SSL-TLS",permalink:"/docs/configuration/ssl-tls"}},h={},c=[{value:"Definitions",id:"definitions",level:2},{value:"Telemetry Screen Definition Files",id:"telemetry-screen-definition-files",level:2},{value:"New Widgets",id:"new-widgets",level:2},{value:"SCREEN",id:"screen",level:2},{value:"END",id:"end",level:2},{value:"STALE_TIME",id:"stale_time",level:2},{value:"GLOBAL_SETTING",id:"global_setting",level:2},{value:"GLOBAL_SUBSETTING",id:"global_subsetting",level:2},{value:"SETTING",id:"setting",level:2},{value:"WIDTH",id:"width",level:3},{value:"HEIGHT",id:"height",level:3},{value:"MARGIN",id:"margin",level:3},{value:"PADDING",id:"padding",level:3},{value:"BACKCOLOR",id:"backcolor",level:3},{value:"TEXTCOLOR",id:"textcolor",level:3},{value:"BORDERCOLOR",id:"bordercolor",level:3},{value:"RAW",id:"raw",level:3},{value:"SUBSETTING",id:"subsetting",level:2},{value:"NAMED_WIDGET",id:"named_widget",level:2},{value:"Layout Widgets",id:"layout-widgets",level:2},{value:"VERTICAL",id:"vertical",level:3},{value:"VERTICALBOX",id:"verticalbox",level:3},{value:"HORIZONTAL",id:"horizontal",level:3},{value:"HORIZONTALBOX",id:"horizontalbox",level:3},{value:"MATRIXBYCOLUMNS",id:"matrixbycolumns",level:3},{value:"SCROLLWINDOW",id:"scrollwindow",level:3},{value:"TABBOOK",id:"tabbook",level:3},{value:"TABITEM",id:"tabitem",level:3},{value:"IFRAME",id:"iframe",level:3},{value:"Decoration Widgets",id:"decoration-widgets",level:2},{value:"LABEL",id:"label",level:3},{value:"HORIZONTALLINE",id:"horizontalline",level:3},{value:"SECTIONHEADER",id:"sectionheader",level:3},{value:"TITLE",id:"title",level:3},{value:"SPACER",id:"spacer",level:3},{value:"Telemetry Widgets",id:"telemetry-widgets",level:2},{value:"ARRAY",id:"array",level:3},{value:"BLOCK",id:"block",level:3},{value:"FORMATVALUE",id:"formatvalue",level:3},{value:"LABELLED",id:"labelled",level:3},{value:"LED_COLOR",id:"led_color",level:4},{value:"LABELPROGRESSBAR",id:"labelprogressbar",level:3},{value:"LABELVALUE",id:"labelvalue",level:3},{value:"LABELVALUEDESC",id:"labelvaluedesc",level:3},{value:"LABELVALUELIMITSBAR",id:"labelvaluelimitsbar",level:3},{value:"LABELVALUELIMITSCOLUMN",id:"labelvaluelimitscolumn",level:3},{value:"LABELVALUERANGEBAR",id:"labelvaluerangebar",level:3},{value:"LED",id:"led",level:3},{value:"LED_COLOR",id:"led_color-1",level:4},{value:"LIMITSBAR",id:"limitsbar",level:3},{value:"LIMITSCOLUMN",id:"limitscolumn",level:3},{value:"LIMITSCOLOR",id:"limitscolor",level:3},{value:"VALUELIMITSBAR",id:"valuelimitsbar",level:3},{value:"VALUELIMITSCOLUMN",id:"valuelimitscolumn",level:3},{value:"VALUERANGEBAR",id:"valuerangebar",level:3},{value:"LINEGRAPH",id:"linegraph",level:3},{value:"ITEM",id:"item",level:4},{value:"STARTTIME",id:"starttime",level:4},{value:"HISTORY",id:"history",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed",level:4},{value:"POINTSSAVED",id:"pointssaved",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed",level:4},{value:"SIZE",id:"size",level:4},{value:"SPARKLINE",id:"sparkline",level:3},{value:"ITEM",id:"item-1",level:4},{value:"STARTTIME",id:"starttime-1",level:4},{value:"HISTORY",id:"history-1",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed-1",level:4},{value:"POINTSSAVED",id:"pointssaved-1",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed-1",level:4},{value:"SIZE",id:"size-1",level:4},{value:"LABELSPARKLINE",id:"labelsparkline",level:3},{value:"ITEM",id:"item-2",level:4},{value:"STARTTIME",id:"starttime-2",level:4},{value:"HISTORY",id:"history-2",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed-2",level:4},{value:"POINTSSAVED",id:"pointssaved-2",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed-2",level:4},{value:"SIZE",id:"size-2",level:4},{value:"IMAGEVIEWER",id:"imageviewer",level:3},{value:"PROGRESSBAR",id:"progressbar",level:3},{value:"RANGEBAR",id:"rangebar",level:3},{value:"ROLLUP",id:"rollup",level:3},{value:"SIGNAL",id:"signal",level:3},{value:"TEXTBOX",id:"textbox",level:3},{value:"VALUE",id:"value",level:3},{value:"Interactive Widgets",id:"interactive-widgets",level:2},{value:"BUTTON",id:"button",level:3},{value:"CHECKBUTTON",id:"checkbutton",level:3},{value:"COMBOBOX",id:"combobox",level:3},{value:"RADIOGROUP",id:"radiogroup",level:3},{value:"RADIOBUTTON",id:"radiobutton",level:3},{value:"TEXTFIELD",id:"textfield",level:3},{value:"Canvas Widgets",id:"canvas-widgets",level:2},{value:"CANVAS",id:"canvas",level:3},{value:"CANVASLABEL",id:"canvaslabel",level:3},{value:"CANVASLABELVALUE",id:"canvaslabelvalue",level:3},{value:"CANVASIMAGE",id:"canvasimage",level:3},{value:"SCREEN",id:"screen-1",level:4},{value:"CANVASIMAGEVALUE",id:"canvasimagevalue",level:3},{value:"IMAGE",id:"image",level:4},{value:"SCREEN",id:"screen-2",level:4},{value:"CANVASLINE",id:"canvasline",level:3},{value:"CANVASLINEVALUE",id:"canvaslinevalue",level:3},{value:"VALUE_EQ",id:"value_eq",level:4},{value:"CANVASDOT",id:"canvasdot",level:3},{value:"Example File",id:"example-file",level:2}];function a(e){const s={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",hr:"hr",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.p,{children:"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application."}),"\n",(0,r.jsx)("div",{style:{clear:"both"}}),"\n",(0,r.jsx)(s.h2,{id:"definitions",children:"Definitions"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Name"}),(0,r.jsx)(s.th,{children:"Definition"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget"}),(0,r.jsx)(s.td,{children:"A widget is a graphical element on a COSMOS telemetry screen. It could display text, graph data, provide a button, or perform any other display/user input task."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen"}),(0,r.jsx)(s.td,{children:"A screen is a single window that contains any number of widgets which are organized and layed-out in a useful fashion."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen Definition File"}),(0,r.jsx)(s.td,{children:"A screen definition file is an ASCII file that tells Telemetry Viewer how to draw a screen. It is made up of a series of keyword/parameter lines that define the telemetry points that are displayed on the screen and how to display them."})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"telemetry-screen-definition-files",children:"Telemetry Screen Definition Files"}),"\n",(0,r.jsx)(s.p,{children:"Telemetry screen definition files define the the contents of telemetry screens. They take the general form of a SCREEN keyword followed by a series of widget keywords that define the telemetry screen. Screen definition files specific to a particular target go in that target's screens directory. For example: TARGET/screens/version.txt. Screen definition files must be lowercase."}),"\n",(0,r.jsx)(s.h2,{id:"new-widgets",children:"New Widgets"}),"\n",(0,r.jsxs)(s.p,{children:["When a telemetry screen definition is parsed and a keyword is encountered that is unrecognized, it is assumed that a file of the form widgetname_widget.rb exists, and contains a class called WidgetnameWidget. Because of this convention, new widgets can be added to the system without any change to the telemetry screen definition format. For more information about creating custom widgets please read the ",(0,r.jsx)(s.a,{href:"/docs/guides/custom-widgets",children:"Custom Widgets"})," guide."]}),"\n",(0,r.jsx)(s.h1,{id:"screen-keywords",children:"Screen Keywords"}),"\n",(0,r.jsx)(s.h2,{id:"screen",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Define a telemetry viewer screen"})}),"\n",(0,r.jsx)(s.p,{children:"The SCREEN keyword is the first keyword in any telemetry screen definition. It defines the name of the screen and parameters that affect the screen overall."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels or AUTO to let Telemetry Viewer automatically layout the screen"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels or AUTO to let Telemetry Viewer automatically layout the screen"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Polling Period"}),(0,r.jsx)(s.td,{children:"Number of seconds between screen updates"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SCREEN AUTO AUTO 1.0 FIXED\n"})}),"\n",(0,r.jsx)(s.h2,{id:"end",children:"END"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Indicates the close of a layout widget"})}),"\n",(0,r.jsx)(s.p,{children:"All layout widgets must be closed to properly identify where they stop. For example, a VERTICALBOX keyword must be matched with an END keyword to indicate where the VERTICALBOX ends."}),"\n",(0,r.jsx)(s.h2,{id:"stale_time",children:"STALE_TIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.1.0)"}),(0,r.jsx)(s.strong,{children:"Values are marked stale if the packet time is more than Stale Time seconds in the past"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"value"}),(0,r.jsx)(s.td,{children:"Items from packets with RECEIVED_TIMESECONDS greater than this value in the past will be marked stale. The default is 30s. Recommend a minimum of 2s to avoid false positives due to race conditions."}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"STALE_TIME 5 # Number of seconds to wait before marking data stale\n"})}),"\n",(0,r.jsx)(s.h2,{id:"global_setting",children:"GLOBAL_SETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget setting to all widgets of a certain type"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Class Name"}),(0,r.jsx)(s.td,{children:"The name of the class of widgets that this setting will be applied to. For example, LABEL or BUTTON."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"GLOBAL_SETTING LABELVALUELIMITSBAR TEXTCOLOR BLACK\n"})}),"\n",(0,r.jsx)(s.h2,{id:"global_subsetting",children:"GLOBAL_SUBSETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget subsetting to all widgets of a certain type"})}),"\n",(0,r.jsx)(s.p,{children:"Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Class Name"}),(0,r.jsx)(s.td,{children:"The name of the class of widgets that this setting will be applied to. For example, LABELVALUE."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Subwidget Index"}),(0,r.jsx)(s.td,{children:"Index to the desired subwidget"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"# Set all text color to white for labelvaluelimitsbars\nGLOBAL_SUBSETTING LABELVALUELIMITSBAR 0 TEXTCOLOR white\n"})}),"\n",(0,r.jsx)(s.h2,{id:"setting",children:"SETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget setting to the previously defined widget"})}),"\n",(0,r.jsx)(s.p,{children:"Settings allow for additional tweaks and options to be applied to widgets\nthat are not available in their parameters. These settings are all configured\nthrough the SETTING, SUBSETTING, GLOBAL_SETTING and GLOBAL_SUBSETTING keywords.\nSETTING and SUBSETTING applies only to the widget defined immediately before it.\nGLOBAL_SETTING and GLOBAL_SUBSETTING applies to all widgets."}),"\n",(0,r.jsx)(s.p,{children:"Common wiget settings are defined here. Some widgets define their own\nunqiue settings which are documented under that specific widget."}),"\n",(0,r.jsx)(s.h3,{id:"width",children:"WIDTH"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget width"})}),"\n",(0,r.jsxs)(s.p,{children:["WIDTH supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING WIDTH 50\nLABEL "THIS IS A TEST"\n SETTING WIDTH 20em\n'})}),"\n",(0,r.jsx)(s.h3,{id:"height",children:"HEIGHT"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget height"})}),"\n",(0,r.jsxs)(s.p,{children:["HEIGHT supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\n SETTING HEIGHT 50\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING HEIGHT 2em\n'})}),"\n",(0,r.jsx)(s.h3,{id:"margin",children:"MARGIN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget margin"})}),"\n",(0,r.jsxs)(s.p,{children:["MARGIN supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Size"}),(0,r.jsx)(s.td,{children:"Size in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING MARGIN 10\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREEN\n'})}),"\n",(0,r.jsx)(s.h3,{id:"padding",children:"PADDING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget padding"})}),"\n",(0,r.jsxs)(s.p,{children:["PADDING supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Size"}),(0,r.jsx)(s.td,{children:"Size in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING PADDING 10\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREEN\n'})}),"\n",(0,r.jsx)(s.h3,{id:"backcolor",children:"BACKCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The BACKCOLOR setting sets the background color for a widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR red\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"textcolor",children:"TEXTCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The TEXTCOLOR setting sets the text color for a widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING TEXTCOLOR red\nLABEL "THIS IS A TEST"\n SETTING TEXTCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"bordercolor",children:"BORDERCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The BORDERCOLOR setting sets the border color for a layout widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTAL\n LABEL "Label 1"\nEND\nSETTING BORDERCOLOR red\nVERTICAL\n LABEL "Label 2"\nEND\nSETTING BORDERCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"raw",children:"RAW"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Apply a raw CSS stylesheet key and value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Key"}),(0,r.jsx)(s.td,{children:"CSS key like font-size, max-width, etc"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"CSS Value"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "Label 1"\n SETTING RAW font-size 30px\n'})}),"\n",(0,r.jsx)(s.h2,{id:"subsetting",children:"SUBSETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget subsetting to the previously defined widget"})}),"\n",(0,r.jsx)(s.p,{children:"Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Subwidget Index"}),(0,r.jsx)(s.td,{children:"Index to the desired subwidget or 'ALL' to apply the setting to all the subwidgets of this composite widget."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VERTICALBOX\n LABELVALUE INST HEALTH_STATUS TEMP1\n SUBSETTING 0 TEXTCOLOR blue # Change the label's text to blue\n LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP1\n SUBSETTING 0 TEXTCOLOR green # Change the label's text to green\nEND\n"})}),"\n",(0,r.jsx)(s.h2,{id:"named_widget",children:"NAMED_WIDGET"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Name a widget to allow access to it via the getNamedWidget method"})}),"\n",(0,r.jsx)(s.p,{children:"To programatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets."}),"\n",(0,r.jsx)(s.admonition,{type:"warning",children:(0,r.jsx)(s.p,{children:"getNamedWidget returns the widget itself and thus must be operated on using methods native to that widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Name"}),(0,r.jsx)(s.td,{children:"The unique name applied to the following widget instance. Names must be unique per screen."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Type"}),(0,r.jsx)(s.td,{children:"One of the widget types listed in Widget Descriptions"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Parameters"}),(0,r.jsx)(s.td,{children:"The unique parameters for the given widget type"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'NAMED_WIDGET DURATION TEXTFIELD\nBUTTON "Push" "screen.getNamedWidget(\'DURATION\').text()"\n'})}),"\n",(0,r.jsx)(s.h2,{id:"layout-widgets",children:"Layout Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Layout widgets are used to position other widgets on the screen. For example, the HORIZONTAL layout widget places the widgets it encapsulates horizontally on the screen."}),"\n",(0,r.jsx)(s.h3,{id:"vertical",children:"VERTICAL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates vertically"})}),"\n",(0,r.jsx)(s.p,{children:"The screen defaults to a vertical layout, so if no layout widgets are specified, all widgets will be automatically placed within a VERTICAL layout widget. The VERTICAL widget sizes itself to fit its contents."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICAL 5px\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"verticalbox",children:"VERTICALBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates vertically inside a thin border"})}),"\n",(0,r.jsx)(s.p,{children:"The VERTICALBOX widget sizes itself to fit its contents vertically and to fit the screen horizontally"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Title"}),(0,r.jsx)(s.td,{children:"Text to place within the border to label the box"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICALBOX Info\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontal",children:"HORIZONTAL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates horizontally"})}),"\n",(0,r.jsx)(s.p,{children:"The HORIZONTAL widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTAL 100\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontalbox",children:"HORIZONTALBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates horizontally inside a thin border"})}),"\n",(0,r.jsx)(s.p,{children:"The HORIZONTALBOX widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Title"}),(0,r.jsx)(s.td,{children:"Text to place within the border to label the box"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTALBOX Info 10\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"matrixbycolumns",children:"MATRIXBYCOLUMNS"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets into a table-like matrix"})}),"\n",(0,r.jsx)(s.p,{children:"The MATRIXBYCOLUMNS widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Columns"}),(0,r.jsx)(s.td,{children:"The number of columns to create"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'MATRIXBYCOLUMNS 3 10\n LABEL "COL 1"\n LABEL "COL 2"\n LABEL "COL 3"\n LABEL "100"\n LABEL "200"\n LABEL "300"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"scrollwindow",children:"SCROLLWINDOW"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets inside of it into a scrollable area"})}),"\n",(0,r.jsx)(s.p,{children:"The SCROLLWINDOW widget sizes itself to fit the screen in which it is contained"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Maximum height of the scroll window in pixels (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'SCROLLWINDOW 100 10\n VERTICAL\n LABEL "100"\n LABEL "200"\n LABEL "300"\n LABEL "400"\n LABEL "500"\n LABEL "600"\n LABEL "700"\n LABEL "800"\n LABEL "900"\n END\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"tabbook",children:"TABBOOK"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a tabbed area in which to place TABITEM widgets"})}),"\n",(0,r.jsx)(s.h3,{id:"tabitem",children:"TABITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a VERTICAL layout tab into which to place widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Tab text"}),(0,r.jsx)(s.td,{children:"Text to diplay in the tab"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'TABBOOK\n TABITEM "Tab 1"\n LABEL "100"\n LABEL "200"\n END\n TABITEM "Tab 2"\n LABEL "300"\n LABEL "400"\n END\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"iframe",children:"IFRAME"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open external tools in an Iframe within OpenC3"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"URL"}),(0,r.jsx)(s.td,{children:"The path to the page to display in the iframe"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"IFRAME https://openc3.com 900 450\n"})}),"\n",(0,r.jsx)(s.h2,{id:"decoration-widgets",children:"Decoration Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Decoration widgets are used to enhance the appearance of the screen. They do not respond to input, nor does the output vary with telemetry."}),"\n",(0,r.jsx)(s.h3,{id:"label",children:"LABEL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays text on the screen"})}),"\n",(0,r.jsx)(s.p,{children:"Generally, label widgets contain a telemetry mnemonic and are placed next to the telemetry VALUE widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display on the label"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "Note: This is only a warning"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontalline",children:"HORIZONTALLINE"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Displays a horizontal line on the screen that can be used as a separator"})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABEL Over\nHORIZONTALLINE\nLABEL Under\n"})}),"\n",(0,r.jsx)(s.h3,{id:"sectionheader",children:"SECTIONHEADER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"DEPRECATED - Displays a label that is underlined with a horizontal line"})}),"\n",(0,r.jsx)(s.p,{children:"Use a VERTICALBOX or HORIZONTALBOX with title parameter instead of SECTIONHEADER"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h3,{id:"title",children:"TITLE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a large centered title on the screen"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'TITLE "Title"\nHORIZONTALLINE\nLABEL "Label"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"spacer",children:"SPACER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places a fixed size spacer in between widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the spacer in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the spacer in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICAL 3\n LABEL "Spacer below"\n SPACER 0 100\n LABEL "Spacer above"\nEND\n'})}),"\n",(0,r.jsx)(s.h2,{id:"telemetry-widgets",children:"Telemetry Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Telemetry widgets are used to display telemetry values. The first parameters to each of these widgets is a telemetry mnemonic. Depending on the type and purpose of the telemetry item, the screen designer may select from a wide selection of widgets to display the value in the most useful format."}),"\n",(0,r.jsx)(s.h3,{id:"array",children:"ARRAY"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays ARRAY data organized into rows and space separated"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Format string applied to each array item (default = nil)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Items per row"}),(0,r.jsx)(s.td,{children:"Number of array items per row (default = 4)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'ARRAY INST HEALTH_STATUS ARY 250 80 "0x%x" 6 FORMATTED\nARRAY INST HEALTH_STATUS ARY2 200 100 nil 4 WITH_UNITS\n'})}),"\n",(0,r.jsx)(s.h3,{id:"block",children:"BLOCK"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays BLOCK data organized into rows and space separated"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Format string applied to each array item (default = nil)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Bytes per word"}),(0,r.jsx)(s.td,{children:"Number of bytes per word (default = 4)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Words per row"}),(0,r.jsx)(s.td,{children:"Number of words per row (default = 4"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Address format"}),(0,r.jsx)(s.td,{children:"Format for the address printed at the beginning of each line (default = nil which means do not print an address)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'BLOCK INST IMAGE IMAGE 400 130 "%02X" 4 4 "0x%08X:"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"formatvalue",children:"FORMATVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a box with a formatted value"})}),"\n",(0,r.jsx)(s.p,{children:"Data is formatted by the specified string rather than by a format string given in the telemetry definition files. The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits)."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Printf style format string to apply to the telemetry item"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"FORMATVALUE INST LATEST TIMESEC %012u CONVERTED 20\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelled",children:"LABELLED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL followed by a LED"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Justification"}),(0,r.jsxs)(s.td,{children:["How to justify the label and LED together. The default of 'SPLIT' aligns the label to the left and the LED to the right with any additional space going between them. 'CENTER' pushes the label and LED together with any additional space to the left and right. 'LEFT' or 'RIGHT' pushes them to the respective side with the space going on the opposite.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"SPLIT, CENTER, LEFT, RIGHT"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELLED INST PARAMS VALUE1\n SETTING LED_COLOR GOOD GREEN\n SETTING LED_COLOR BAD RED\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LABELLED. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"led_color",children:"LED_COLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map a state or value to a color"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value. ANY used to match any value or state not declared."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"LED color"}),(0,r.jsx)(s.td,{children:"Color of the LED"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelprogressbar",children:"LABELPROGRESSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a PROGRESSBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Scale factor"}),(0,r.jsx)(s.td,{children:"Value to multiply the telemetry item by before displaying in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0."}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the progress bar (default = 80 pixels"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELPROGRESSBAR INST ADCS POSPROGRESS 2 200 RAW\nLABELPROGRESSBAR INST ADCS POSPROGRESS\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvalue",children:"LABELVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a VALUE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUE INST LATEST TIMESEC CONVERTED 18\nLABELVALUE INST LATEST COLLECT_TYPE\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluedesc",children:"LABELVALUEDESC"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the items description followed by a VALUE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Description"}),(0,r.jsx)(s.td,{children:"The description to display in the label (default is to display the description text associated with the telemetry item)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABELVALUEDESC INST HEALTH_STATUS TEMP1 "Temperature number 1" RAW 18\nLABELVALUEDESC INST HEALTH_STATUS COLLECT_TYPE\n'})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluelimitsbar",children:"LABELVALUELIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and LIMITSBAR widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluelimitscolumn",children:"LABELVALUELIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and LIMITSCOLUMN widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18\nLABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluerangebar",children:"LABELVALUERANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and RANGEBAR widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40\nLABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120\n"})}),"\n",(0,r.jsx)(s.h3,{id:"led",children:"LED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LED which changes color based on telemetry values"})}),"\n",(0,r.jsx)(s.p,{children:"By default TRUE is green and FALSE is red and all other values are black. Additional values can be added by using the LED_COLOR setting. For example LED INST PARAMS VALUE3 RAW can be followed by SETTING LED_COLOR 0 GREEN, SETTING LED_COLOR 1 RED, and SETTING LED_COLOR ANY ORANGE."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LED INST PARAMS VALUE5 RAW 25 20 # Ellipse\n SETTING LED_COLOR 0 GREEN\n SETTING LED_COLOR 1 RED\n SETTING LED_COLOR ANY YELLOW\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LED. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"led_color-1",children:"LED_COLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map a state or value to a color"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value. ANY used to match any value or state not declared."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"LED color"}),(0,r.jsx)(s.td,{children:"Color of the LED"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"limitsbar",children:"LIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item's current value within its colored limits horizontally"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 200 50\nLIMITSBAR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"limitscolumn",children:"LIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item's current value within its colored limits vertically"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 50 200\nLIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"limitscolor",children:"LIMITSCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a circle depicting the limits color of an item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Radius"}),(0,r.jsx)(s.td,{children:"Radius of the circle (default is 10)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Full Item Name"}),(0,r.jsx)(s.td,{children:"Show the full item name (default is false)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSCOLOR INST HEALTH_STATUS TEMP1 CONVERTED 30 TRUE\nLIMITSCOLOR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuelimitsbar",children:"VALUELIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by LIMITSBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUELIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUELIMITSBAR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuelimitscolumn",children:"VALUELIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by LIMITSCOLUMN"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 8)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuerangebar",children:"VALUERANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by RANGEBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40\nVALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120\n"})}),"\n",(0,r.jsx)(s.h3,{id:"linegraph",children:"LINEGRAPH"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a line graph of a telemetry item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LINEGRAPH INST HEALTH_STATUS TEMP1\n SETTING ITEM INST ADCS Q1 # Add additional item to graph\nLINEGRAPH INST HEALTH_STATUS TEMP2 RAW\nLINEGRAPH INST HEALTH_STATUS TEMP3 CONVERTED REDUCED_MINUTE MIN\n SETTING SIZE 600 500 # width height\n SETTING HISTORY 1h # load 1 hour of data into graph\nLINEGRAPH INST HEALTH_STATUS TEMP4\n SETTING HISTORY 30m # load 30 minutes of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LINEGRAPH. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"sparkline",children:"SPARKLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a sparkline graph (no cursor, scale or legend) of a telemetry item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SPARKLINE INST HEALTH_STATUS TEMP1\n SETTING SIZE 400 50\n SETTING HISTORY 30s # Add 30 seconds of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to SPARKLINE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item-1",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime-1",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history-1",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed-1",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved-1",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed-1",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size-1",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelsparkline",children:"LABELSPARKLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a SPARKLINE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELSPARKLINE INST HEALTH_STATUS TEMP1\n SETTING HISTORY 5m # Add 5 minutes of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LABELSPARKLINE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item-2",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime-2",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history-2",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed-2",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved-2",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed-2",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size-2",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"imageviewer",children:"IMAGEVIEWER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display a base64 image from a TLM packet"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name to pull the CONVERTED value from. If additional processing (base64 encoding) is needed consider using a DERIVED item."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format"}),(0,r.jsx)(s.td,{children:"The image format of the base64 data (e.g. jpg, png, etc)"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"IMAGEVIEWER INST IMAGE IMAGE jpg\n"})}),"\n",(0,r.jsx)(s.h3,{id:"progressbar",children:"PROGRESSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a progress bar that is useful for displaying percentages"})}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"PROGRESSBAR INST ADCS POSPROGRESS 0.5 200\nPROGRESSBAR INST ADCS POSPROGRESS\n"})}),"\n",(0,r.jsx)(s.h3,{id:"rangebar",children:"RANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a custom range bar displaying the item value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"RANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 200 50\nRANGEBAR INST HEALTH_STATUS TEMP1 -100 100\n"})}),"\n",(0,r.jsx)(s.h3,{id:"rollup",children:"ROLLUP"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.17.1)"}),(0,r.jsx)(s.strong,{children:"Displays a notification icon which changes color based on a rollup telemetry"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon name"}),(0,r.jsxs)(s.td,{children:["The astro UX icon to display. Valid choices are 'astro' icons taken from ",(0,r.jsx)(s.a,{href:"https://github.com/RocketCommunicationsInc/astro-components/blob/master/static/json/rux-icons.json",children:"https://github.com/RocketCommunicationsInc/astro-components/blob/master/static/json/rux-icons.json"}),"."]}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon label"}),(0,r.jsx)(s.td,{children:"Text to apply to the icon label"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon sublabel"}),(0,r.jsx)(s.td,{children:"Text to apply to the icon sublabel"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'ROLLUP satellite-transmit "SAT 1" "Details"\n # Screen to open on click\n SETTING SCREEN INST HS\n # Telemetry items to rollup status\n SETTING TLM INST HEALTH_STATUS TEMP1\n SETTING TLM INST HEALTH_STATUS TEMP2\nROLLUP antenna "GND 2" "Location"\n # Screen to open on click\n SETTING SCREEN INST HS\n # Telemetry items to rollup status\n SETTING TLM INST HEALTH_STATUS TEMP3\n SETTING TLM INST HEALTH_STATUS TEMP4\n'})}),"\n",(0,r.jsx)(s.h3,{id:"signal",children:"SIGNAL"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.17.2)"}),(0,r.jsx)(s.strong,{children:"Displays a cellular signal icon which changes based on telemetry value"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SIGNAL INST HEALTH_STATUS TEMP1\n # Screen to open on click\n SETTING SCREEN INST HS\n # Values to compare when setting the 1-bar, 2-bar and 3-bar icons\n # Default is 30, 60, 90 (e.g. 0 to 100 range)\n # Value < -50 display no bars\n # Value >= -50 and < 0 displays 1 bar\n # Value >= 0 and < 50 displays 2 bars\n # Value >= 50 displays 5 bars\n SETTING RANGE -50 0 50\n"})}),"\n",(0,r.jsx)(s.h3,{id:"textbox",children:"TEXTBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Provides a large box for multiline text"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the textbox in px (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the textbox in px (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"TEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED 150 70\nTEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED\n"})}),"\n",(0,r.jsx)(s.h3,{id:"value",children:"VALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a box with a telemetry item value"})}),"\n",(0,r.jsx)(s.p,{children:"The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits)."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUE INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUE INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h2,{id:"interactive-widgets",children:"Interactive Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Interactive widgets are used to gather input from the user. Unlike all other widgets, which only output some graphical representation, interactive widgets permit input either from the keyboard or mouse."}),"\n",(0,r.jsx)(s.h3,{id:"button",children:"BUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a rectangular clickable button"})}),"\n",(0,r.jsxs)(s.p,{children:["Upon clicking, the button executes the Javascript code assigned. Buttons\ncan be used to send commands and perform other tasks. If you want your button\nto use values from other widgets, define them as named widgets and read their\nvalues using the ",(0,r.jsx)(s.code,{children:'screen.getNamedWidget("WIDGET_NAME").text()'})," method.\nSee the example in CHECKBUTTON."]}),"\n",(0,r.jsxs)(s.p,{children:["Button code can get rather complex so remember to use string concatenation\nto make things more readable. If you use ",(0,r.jsx)(s.code,{children:"+"})," newlines are inserted automatically\nduring string concatenation. If you use ",(0,r.jsx)(s.code,{children:"\\"})," you'll need to separate lines with a\nsingle semicolon ",(0,r.jsx)(s.code,{children:";"}),". COSMOS uses double semicolon ",(0,r.jsx)(s.code,{children:";;"})," to indicate lines should\nbe evaluated separately. Note that all OpenC3 commands (using api.cmd) must be\nseparated by ",(0,r.jsx)(s.code,{children:";;"}),"."]}),"\n",(0,r.jsx)(s.p,{children:"You can send commands with buttons using api.cmd(). The cmd() syntax looks exactly\nlike the standard COSMOS scripting syntax. You can also request and use\ntelemetry in screens using Javascript Promises."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.code,{children:"api.tlm('INST PARAMS VALUE3', 'RAW').then(dur => api.cmd('INST COLLECT with TYPE NORMAL, DURATION '+dur))\""})}),"\n",(0,r.jsx)(s.p,{children:"The api.tlm() function returns a Promise which is resolved with then()\nat which point we send the command with the telemetry value we received."}),"\n",(0,r.jsxs)(s.p,{children:["Scripts can be launched from a BUTTON using the ",(0,r.jsx)(s.code,{children:"runScript()"})," method. ",(0,r.jsx)(s.code,{children:"runScript()"})," takes three parameters,\nthe name of the script, whether to open the script in the foreground of Script Runner (default = true), and a hash of\nenvironment variables. For example: ",(0,r.jsx)(s.code,{children:"runScript('INST/procedures/script.rb', false, {'VAR': 'VALUE'})"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Button Text"}),(0,r.jsx)(s.td,{children:"Text displayed on the button"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Button Code"}),(0,r.jsx)(s.td,{children:"Javascript code to execute when the button is pressed"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"BUTTON 'Start Collect' 'api.cmd(\"INST COLLECT with TYPE NORMAL, DURATION 5\")'\nBUTTON 'Run Checks' 'runScript(\"INST/procedures/checks.rb\")'\n# More complex example with background checkbox and env vars\nNAMED_WIDGET SCRIPTNAME COMBOBOX collect.rb checks.rb\nNAMED_WIDGET BG CHECKBUTTON 'Background'\nBUTTON 'Run Script' \"var script=screen.getNamedWidget('SCRIPTNAME').text();\" \\\n # Set an environment variable to be used by the script as ENV['TYPE']\n \"var env = {}; env['TYPE'] = 'TEST';\" \\\n \"runScript('INST/procedures/'+script, !screen.getNamedWidget('BG').checked(), env)\"\n"})}),"\n",(0,r.jsx)(s.h3,{id:"checkbutton",children:"CHECKBUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a check box"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Checkbox Text"}),(0,r.jsx)(s.td,{children:"Text displayed next to the checkbox"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks'\nBUTTON 'Send' 'screen.getNamedWidget(\"CHECK\").checked() ? ' \\\n 'api.cmd_no_hazardous_check(\"INST CLEAR\") : api.cmd(\"INST CLEAR\")'\n"})}),"\n",(0,r.jsx)(s.h3,{id:"combobox",children:"COMBOBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a drop down list of text items"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Option Text 1"}),(0,r.jsx)(s.td,{children:"Text to display in the selection drop down"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Option Text n"}),(0,r.jsx)(s.td,{children:"Text to display in the selection drop down"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"BUTTON 'Start Collect' 'var type = screen.getNamedWidget(\"COLLECT_TYPE\").text();' +\n 'api.cmd(\"INST COLLECT with TYPE \"+type+\", DURATION 10.0\")'\nNAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL\n"})}),"\n",(0,r.jsx)(s.h3,{id:"radiogroup",children:"RADIOGROUP"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a group of RADIOBUTTONs"})}),"\n",(0,r.jsx)(s.p,{children:"RADIOBUTTONs must be part of a group to enable selection logic"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Initial selected button"}),(0,r.jsx)(s.td,{children:"Selects a radio button at initialization (0-based)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.h3,{id:"radiobutton",children:"RADIOBUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a radio button and text"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET. It must be contained by a RADIOGROUP to enable typical selection of a single RADIOBUTTON."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display next to the radio button"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index\n RADIOBUTTON 'Abort'\n RADIOBUTTON 'Clear'\nEND\nBUTTON 'Send' \"screen.getNamedWidget('GROUP').selected() === 0 ? \" +\n \"api.cmd('INST ABORT') : api.cmd('INST CLEAR')\"\n"})}),"\n",(0,r.jsx)(s.h3,{id:"textfield",children:"TEXTFIELD"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a rectangular box where the user can enter text"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Characters"}),(0,r.jsx)(s.td,{children:"Width of the text field in characters (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Default text to put in the text field (default is blank)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'NAMED_WIDGET DURATION TEXTFIELD 12 "10.0"\nBUTTON \'Start Collect\' \'var dur = screen.getNamedWidget("DURATION").text();\' +\n \'api.cmd("INST COLLECT with TYPE NORMAL, DURATION "+dur+"")\'\n'})}),"\n",(0,r.jsx)(s.h2,{id:"canvas-widgets",children:"Canvas Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Canvas Widgets are used to draw custom displays into telemetry screens. The canvas coordinate frame places (0,0) in the upper-left corner of the canvas."}),"\n",(0,r.jsx)(s.h3,{id:"canvas",children:"CANVAS"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Layout widget for the other canvas widgets"})}),"\n",(0,r.jsx)(s.p,{children:"All canvas widgets must be enclosed within a CANVAS widget."}),"\n",(0,r.jsx)(s.admonition,{type:"warning",children:(0,r.jsx)(s.p,{children:"The canvas coordinate frame places (0,0) in the upper-left corner of the canvas."})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvaslabel",children:"CANVASLABEL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws text onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to draw onto the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Font Size"}),(0,r.jsx)(s.td,{children:"Font size of the text (Default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the text"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 100 100\n CANVASLABEL 5 34 "Label1" 24 red\n CANVASLABEL 5 70 "Label2" 18 blue\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"canvaslabelvalue",children:"CANVASLABELVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws the text value of a telemetry item onto the canvas in an optional frame"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Font Size"}),(0,r.jsx)(s.td,{children:"Font size of the text (Default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the text"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 200 100\n CANVASLABELVALUE INST HEALTH_STATUS TEMP1 5 34 12 red\n CANVASLABELVALUE INST HEALTH_STATUS TEMP2 5 70 10 blue WITH_UNITS\nEND\n"})}),"\n",(0,r.jsx)(s.h3,{id:"canvasimage",children:"CANVASIMAGE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an image on the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image filename"}),(0,r.jsx)(s.td,{children:"Name of a image file. The file must be in the plugin's targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 250 430\n CANVASIMAGE "satellite.png" 10 10 200 200\n SETTING SCREEN INST HS\n CANVASIMAGE "https://images.pexels.com/photos/256152/pexels-photo-256152.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=640&w=426" 0 250 250 150\nEND\n'})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASIMAGE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"screen-1",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open another screen when clicked"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"Name of the target"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen name"}),(0,r.jsx)(s.td,{children:"Name of the screen"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasimagevalue",children:"CANVASIMAGEVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an image on the canvas that changes with a telemetry value"})}),"\n",(0,r.jsx)(s.p,{children:'Use various SETTING values to indicate which images should be displayed based on telemetry. For example, SETTING IMAGE CONNECTED "ground_on.png" 400 100. See the DEMO for a complete example.'}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Default image filename"}),(0,r.jsx)(s.td,{children:"The default image to display. The file must be in the targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image width"}),(0,r.jsx)(s.td,{children:"Width of the image (default is 100%)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image height"}),(0,r.jsx)(s.td,{children:"Height of the image (default is 100%)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 230 230\n CANVASIMAGEVALUE INST HEALTH_STATUS GROUND1STATUS CONVERTED "ground_error.png" 10 10 180 180\n SETTING IMAGE CONNECTED "ground_on.png" 10 10\n SETTING IMAGE UNAVAILABLE "ground_off.png" 10 10\n SETTING SCREEN INST HS\nEND\n'})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASIMAGEVALUE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"image",children:"IMAGE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map an image to a state or value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image filename"}),(0,r.jsx)(s.td,{children:"Image to display. The file must be in the targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"screen-2",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open another screen when clicked"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"Name of the target"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen name"}),(0,r.jsx)(s.td,{children:"Name of the screen"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasline",children:"CANVASLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a line onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start X Position"}),(0,r.jsx)(s.td,{children:"X position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End X Position"}),(0,r.jsx)(s.td,{children:"X position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the line"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the line in pixels (default = 1)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 100 50\n CANVASLINE 5 5 95 5\n CANVASLINE 5 5 5 45 green 2\n CANVASLINE 95 5 95 45 blue 3\nEND\n"})}),"\n",(0,r.jsx)(s.h3,{id:"canvaslinevalue",children:"CANVASLINEVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a color changing line onto the canvas"})}),"\n",(0,r.jsx)(s.p,{children:"The line is represented by one of two colors based on the value of the associated telemetry item"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start X Position"}),(0,r.jsx)(s.td,{children:"X position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End X Position"}),(0,r.jsx)(s.td,{children:"X position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the line in pixels (default = 3)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 120 50\n CANVASLABELVALUE INST HEALTH_STATUS GROUND1STATUS 0 12 12 black\n CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 25 115 25 5 RAW\n SETTING VALUE_EQ 1 GREEN\n SETTING VALUE_EQ 0 RED\n CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 45 115 45\n SETTING VALUE_EQ CONNECTED GREEN\n SETTING VALUE_EQ UNAVAILABLE RED\nEND\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASLINEVALUE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"value_eq",children:"VALUE_EQ"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Map a value to a color"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the line"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasdot",children:"CANVASDOT"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a dot onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Radius"}),(0,r.jsx)(s.td,{children:"Radius of the dot in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 50 50\n CANVASDOT 10 15 BLUE 5\nEND\n"})}),"\n",(0,r.jsx)(s.h2,{id:"example-file",children:"Example File"}),"\n",(0,r.jsx)(s.p,{children:"Example File: TARGET/myscreen.txt"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SCREEN AUTO AUTO 0.5\nVERTICAL\n TITLE \"<%= target_name %> Commanding Examples\"\n LABELVALUE INST HEALTH_STATUS COLLECTS\n LABELVALUE INST HEALTH_STATUS COLLECT_TYPE\n LABELVALUE INST HEALTH_STATUS DURATION\n VERTICALBOX \"Send Collect Command:\"\n HORIZONTAL\n LABEL \"Type: \"\n NAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL\n END\n HORIZONTAL\n LABEL \" Duration: \"\n NAMED_WIDGET DURATION TEXTFIELD 12 \"10.0\"\n END\n BUTTON 'Start Collect' \"api.cmd('INST COLLECT with TYPE '+screen.getNamedWidget('COLLECT_TYPE').text()+', DURATION '+screen.getNamedWidget('DURATION').text())\"\n END\n SETTING BACKCOLOR 163 185 163\n VERTICALBOX \"Parameter-less Commands:\"\n NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index\n RADIOBUTTON 'Abort'\n RADIOBUTTON 'Clear'\n END\n NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks' # No option is by default UNCHECKED\n BUTTON 'Send' \"screen.getNamedWidget('GROUP').selected() === 0 ? api.cmd('INST ABORT') : (screen.getNamedWidget('CHECK').checked() ? api.cmd_no_hazardous_check('INST CLEAR') : api.cmd('INST CLEAR'))\"\n END\n SETTING BACKCOLOR 163 185 163\nEND\n"})})]})}function x(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},8453:(e,s,d)=>{d.d(s,{R:()=>i,x:()=>l});var r=d(6540);const n={},t=r.createContext(n);function i(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/9424f0b3.7a8a7d67.js b/docs/assets/js/9424f0b3.7a8a7d67.js
new file mode 100644
index 0000000000..e8a444173e
--- /dev/null
+++ b/docs/assets/js/9424f0b3.7a8a7d67.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[4909],{2111:(e,s,d)=>{d.r(s),d.d(s,{assets:()=>h,contentTitle:()=>i,default:()=>x,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=d(4848),n=d(8453);const t={sidebar_position:9,title:"Screens"},i=void 0,l={id:"configuration/telemetry-screens",title:"Screens",description:"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application.",source:"@site/docs/configuration/telemetry-screens.md",sourceDirName:"configuration",slug:"/configuration/telemetry-screens",permalink:"/docs/configuration/telemetry-screens",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/telemetry-screens.md",tags:[],version:"current",sidebarPosition:9,frontMatter:{sidebar_position:9,title:"Screens"},sidebar:"defaultSidebar",previous:{title:"Tables",permalink:"/docs/configuration/table"},next:{title:"SSL-TLS",permalink:"/docs/configuration/ssl-tls"}},h={},c=[{value:"Definitions",id:"definitions",level:2},{value:"Telemetry Screen Definition Files",id:"telemetry-screen-definition-files",level:2},{value:"New Widgets",id:"new-widgets",level:2},{value:"SCREEN",id:"screen",level:2},{value:"END",id:"end",level:2},{value:"STALE_TIME",id:"stale_time",level:2},{value:"GLOBAL_SETTING",id:"global_setting",level:2},{value:"GLOBAL_SUBSETTING",id:"global_subsetting",level:2},{value:"SETTING",id:"setting",level:2},{value:"WIDTH",id:"width",level:3},{value:"HEIGHT",id:"height",level:3},{value:"MARGIN",id:"margin",level:3},{value:"PADDING",id:"padding",level:3},{value:"BACKCOLOR",id:"backcolor",level:3},{value:"TEXTCOLOR",id:"textcolor",level:3},{value:"BORDERCOLOR",id:"bordercolor",level:3},{value:"RAW",id:"raw",level:3},{value:"SUBSETTING",id:"subsetting",level:2},{value:"NAMED_WIDGET",id:"named_widget",level:2},{value:"Layout Widgets",id:"layout-widgets",level:2},{value:"VERTICAL",id:"vertical",level:3},{value:"VERTICALBOX",id:"verticalbox",level:3},{value:"HORIZONTAL",id:"horizontal",level:3},{value:"HORIZONTALBOX",id:"horizontalbox",level:3},{value:"MATRIXBYCOLUMNS",id:"matrixbycolumns",level:3},{value:"SCROLLWINDOW",id:"scrollwindow",level:3},{value:"TABBOOK",id:"tabbook",level:3},{value:"TABITEM",id:"tabitem",level:3},{value:"IFRAME",id:"iframe",level:3},{value:"Decoration Widgets",id:"decoration-widgets",level:2},{value:"LABEL",id:"label",level:3},{value:"HORIZONTALLINE",id:"horizontalline",level:3},{value:"SECTIONHEADER",id:"sectionheader",level:3},{value:"TITLE",id:"title",level:3},{value:"SPACER",id:"spacer",level:3},{value:"Telemetry Widgets",id:"telemetry-widgets",level:2},{value:"ARRAY",id:"array",level:3},{value:"BLOCK",id:"block",level:3},{value:"FORMATVALUE",id:"formatvalue",level:3},{value:"LABELLED",id:"labelled",level:3},{value:"LED_COLOR",id:"led_color",level:4},{value:"LABELPROGRESSBAR",id:"labelprogressbar",level:3},{value:"LABELVALUE",id:"labelvalue",level:3},{value:"LABELVALUEDESC",id:"labelvaluedesc",level:3},{value:"LABELVALUELIMITSBAR",id:"labelvaluelimitsbar",level:3},{value:"LABELVALUELIMITSCOLUMN",id:"labelvaluelimitscolumn",level:3},{value:"LABELVALUERANGEBAR",id:"labelvaluerangebar",level:3},{value:"LED",id:"led",level:3},{value:"LED_COLOR",id:"led_color-1",level:4},{value:"LIMITSBAR",id:"limitsbar",level:3},{value:"LIMITSCOLUMN",id:"limitscolumn",level:3},{value:"LIMITSCOLOR",id:"limitscolor",level:3},{value:"VALUELIMITSBAR",id:"valuelimitsbar",level:3},{value:"VALUELIMITSCOLUMN",id:"valuelimitscolumn",level:3},{value:"VALUERANGEBAR",id:"valuerangebar",level:3},{value:"LINEGRAPH",id:"linegraph",level:3},{value:"ITEM",id:"item",level:4},{value:"STARTTIME",id:"starttime",level:4},{value:"HISTORY",id:"history",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed",level:4},{value:"POINTSSAVED",id:"pointssaved",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed",level:4},{value:"SIZE",id:"size",level:4},{value:"SPARKLINE",id:"sparkline",level:3},{value:"ITEM",id:"item-1",level:4},{value:"STARTTIME",id:"starttime-1",level:4},{value:"HISTORY",id:"history-1",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed-1",level:4},{value:"POINTSSAVED",id:"pointssaved-1",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed-1",level:4},{value:"SIZE",id:"size-1",level:4},{value:"LABELSPARKLINE",id:"labelsparkline",level:3},{value:"ITEM",id:"item-2",level:4},{value:"STARTTIME",id:"starttime-2",level:4},{value:"HISTORY",id:"history-2",level:4},{value:"SECONDSGRAPHED",id:"secondsgraphed-2",level:4},{value:"POINTSSAVED",id:"pointssaved-2",level:4},{value:"POINTSGRAPHED",id:"pointsgraphed-2",level:4},{value:"SIZE",id:"size-2",level:4},{value:"IMAGEVIEWER",id:"imageviewer",level:3},{value:"PROGRESSBAR",id:"progressbar",level:3},{value:"RANGEBAR",id:"rangebar",level:3},{value:"ROLLUP",id:"rollup",level:3},{value:"SIGNAL",id:"signal",level:3},{value:"TEXTBOX",id:"textbox",level:3},{value:"VALUE",id:"value",level:3},{value:"Interactive Widgets",id:"interactive-widgets",level:2},{value:"BUTTON",id:"button",level:3},{value:"CHECKBUTTON",id:"checkbutton",level:3},{value:"COMBOBOX",id:"combobox",level:3},{value:"RADIOGROUP",id:"radiogroup",level:3},{value:"RADIOBUTTON",id:"radiobutton",level:3},{value:"TEXTFIELD",id:"textfield",level:3},{value:"Canvas Widgets",id:"canvas-widgets",level:2},{value:"CANVAS",id:"canvas",level:3},{value:"CANVASLABEL",id:"canvaslabel",level:3},{value:"CANVASLABELVALUE",id:"canvaslabelvalue",level:3},{value:"CANVASIMAGE",id:"canvasimage",level:3},{value:"SCREEN",id:"screen-1",level:4},{value:"CANVASIMAGEVALUE",id:"canvasimagevalue",level:3},{value:"IMAGE",id:"image",level:4},{value:"SCREEN",id:"screen-2",level:4},{value:"CANVASLINE",id:"canvasline",level:3},{value:"CANVASLINEVALUE",id:"canvaslinevalue",level:3},{value:"VALUE_EQ",id:"value_eq",level:4},{value:"CANVASDOT",id:"canvasdot",level:3},{value:"Example File",id:"example-file",level:2}];function a(e){const s={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",hr:"hr",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.p,{children:"This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application."}),"\n",(0,r.jsx)("div",{style:{clear:"both"}}),"\n",(0,r.jsx)(s.h2,{id:"definitions",children:"Definitions"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Name"}),(0,r.jsx)(s.th,{children:"Definition"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget"}),(0,r.jsx)(s.td,{children:"A widget is a graphical element on a COSMOS telemetry screen. It could display text, graph data, provide a button, or perform any other display/user input task."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen"}),(0,r.jsx)(s.td,{children:"A screen is a single window that contains any number of widgets which are organized and layed-out in a useful fashion."})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen Definition File"}),(0,r.jsx)(s.td,{children:"A screen definition file is an ASCII file that tells Telemetry Viewer how to draw a screen. It is made up of a series of keyword/parameter lines that define the telemetry points that are displayed on the screen and how to display them."})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"telemetry-screen-definition-files",children:"Telemetry Screen Definition Files"}),"\n",(0,r.jsx)(s.p,{children:"Telemetry screen definition files define the the contents of telemetry screens. They take the general form of a SCREEN keyword followed by a series of widget keywords that define the telemetry screen. Screen definition files specific to a particular target go in that target's screens directory. For example: TARGET/screens/version.txt. Screen definition files must be lowercase."}),"\n",(0,r.jsx)(s.h2,{id:"new-widgets",children:"New Widgets"}),"\n",(0,r.jsxs)(s.p,{children:["When a telemetry screen definition is parsed and a keyword is encountered that is unrecognized, it is assumed that a file of the form widgetname_widget.rb exists, and contains a class called WidgetnameWidget. Because of this convention, new widgets can be added to the system without any change to the telemetry screen definition format. For more information about creating custom widgets please read the ",(0,r.jsx)(s.a,{href:"/docs/guides/custom-widgets",children:"Custom Widgets"})," guide."]}),"\n",(0,r.jsx)(s.h1,{id:"screen-keywords",children:"Screen Keywords"}),"\n",(0,r.jsx)(s.h2,{id:"screen",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Define a telemetry viewer screen"})}),"\n",(0,r.jsx)(s.p,{children:"The SCREEN keyword is the first keyword in any telemetry screen definition. It defines the name of the screen and parameters that affect the screen overall."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels or AUTO to let Telemetry Viewer automatically layout the screen"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels or AUTO to let Telemetry Viewer automatically layout the screen"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Polling Period"}),(0,r.jsx)(s.td,{children:"Number of seconds between screen updates"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SCREEN AUTO AUTO 1.0 FIXED\n"})}),"\n",(0,r.jsx)(s.h2,{id:"end",children:"END"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Indicates the close of a layout widget"})}),"\n",(0,r.jsx)(s.p,{children:"All layout widgets must be closed to properly identify where they stop. For example, a VERTICALBOX keyword must be matched with an END keyword to indicate where the VERTICALBOX ends."}),"\n",(0,r.jsx)(s.h2,{id:"stale_time",children:"STALE_TIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.1.0)"}),(0,r.jsx)(s.strong,{children:"Values are marked stale if the packet time is more than Stale Time seconds in the past"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"value"}),(0,r.jsx)(s.td,{children:"Items from packets with RECEIVED_TIMESECONDS greater than this value in the past will be marked stale. The default is 30s. Recommend a minimum of 2s to avoid false positives due to race conditions."}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"STALE_TIME 5 # Number of seconds to wait before marking data stale\n"})}),"\n",(0,r.jsx)(s.h2,{id:"global_setting",children:"GLOBAL_SETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget setting to all widgets of a certain type"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Class Name"}),(0,r.jsx)(s.td,{children:"The name of the class of widgets that this setting will be applied to. For example, LABEL or BUTTON."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"GLOBAL_SETTING LABELVALUELIMITSBAR TEXTCOLOR BLACK\n"})}),"\n",(0,r.jsx)(s.h2,{id:"global_subsetting",children:"GLOBAL_SUBSETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget subsetting to all widgets of a certain type"})}),"\n",(0,r.jsx)(s.p,{children:"Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Class Name"}),(0,r.jsx)(s.td,{children:"The name of the class of widgets that this setting will be applied to. For example, LABELVALUE."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Subwidget Index"}),(0,r.jsx)(s.td,{children:"Index to the desired subwidget"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"# Set all text color to white for labelvaluelimitsbars\nGLOBAL_SUBSETTING LABELVALUELIMITSBAR 0 TEXTCOLOR white\n"})}),"\n",(0,r.jsx)(s.h2,{id:"setting",children:"SETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget setting to the previously defined widget"})}),"\n",(0,r.jsx)(s.p,{children:"Settings allow for additional tweaks and options to be applied to widgets\nthat are not available in their parameters. These settings are all configured\nthrough the SETTING, SUBSETTING, GLOBAL_SETTING and GLOBAL_SUBSETTING keywords.\nSETTING and SUBSETTING applies only to the widget defined immediately before it.\nGLOBAL_SETTING and GLOBAL_SUBSETTING applies to all widgets."}),"\n",(0,r.jsx)(s.p,{children:"Common wiget settings are defined here. Some widgets define their own\nunique settings which are documented under that specific widget."}),"\n",(0,r.jsx)(s.h3,{id:"width",children:"WIDTH"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget width"})}),"\n",(0,r.jsxs)(s.p,{children:["WIDTH supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING WIDTH 50\nLABEL "THIS IS A TEST"\n SETTING WIDTH 20em\n'})}),"\n",(0,r.jsx)(s.h3,{id:"height",children:"HEIGHT"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget height"})}),"\n",(0,r.jsxs)(s.p,{children:["HEIGHT supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\n SETTING HEIGHT 50\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING HEIGHT 2em\n'})}),"\n",(0,r.jsx)(s.h3,{id:"margin",children:"MARGIN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget margin"})}),"\n",(0,r.jsxs)(s.p,{children:["MARGIN supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Size"}),(0,r.jsx)(s.td,{children:"Size in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING MARGIN 10\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREEN\n'})}),"\n",(0,r.jsx)(s.h3,{id:"padding",children:"PADDING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Sets the widget padding"})}),"\n",(0,r.jsxs)(s.p,{children:["PADDING supports ",(0,r.jsx)(s.a,{href:"https://www.w3schools.com/cssref/css_units.php",children:"css units"})," with the default (no units) of px (pixels)"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Size"}),(0,r.jsx)(s.td,{children:"Size in pixels or explicitly declared with units"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR BLUE\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREY\n SETTING PADDING 10\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR GREEN\n'})}),"\n",(0,r.jsx)(s.h3,{id:"backcolor",children:"BACKCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The BACKCOLOR setting sets the background color for a widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING BACKCOLOR red\nLABEL "THIS IS A TEST"\n SETTING BACKCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"textcolor",children:"TEXTCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The TEXTCOLOR setting sets the text color for a widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "THIS IS A TEST"\n SETTING TEXTCOLOR red\nLABEL "THIS IS A TEST"\n SETTING TEXTCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"bordercolor",children:"BORDERCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"The BORDERCOLOR setting sets the border color for a layout widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color name or Red value"}),(0,r.jsx)(s.td,{children:"Common name for the color, e.g. 'black', 'red', etc. Alternatively if two more parameters are passed this is the Red value of the RGB value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Green value"}),(0,r.jsx)(s.td,{children:"Green value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Blue value"}),(0,r.jsx)(s.td,{children:"Blue value of the RGB value"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTAL\n LABEL "Label 1"\nEND\nSETTING BORDERCOLOR red\nVERTICAL\n LABEL "Label 2"\nEND\nSETTING BORDERCOLOR 155 50 155\n'})}),"\n",(0,r.jsx)(s.h3,{id:"raw",children:"RAW"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Apply a raw CSS stylesheet key and value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Key"}),(0,r.jsx)(s.td,{children:"CSS key like font-size, max-width, etc"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"CSS Value"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "Label 1"\n SETTING RAW font-size 30px\n'})}),"\n",(0,r.jsx)(s.h2,{id:"subsetting",children:"SUBSETTING"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Applies a widget subsetting to the previously defined widget"})}),"\n",(0,r.jsx)(s.p,{children:"Subsettings are only valid for widgets that are made up of more than one subwidget. For example, LABELVALUE is made up of a LABEL at subwidget index 0 and a VALUE at subwidget index 1. This allows for passing settings to specific subwidgets. Some widgets are made up of multiple subwidgets, e.g. LABELVALUELIMITSBAR. To set the Label widget, pass 0 as the Subwidget Index, pass 1 for the Value widget, and 2 for the LimitsBar widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Subwidget Index"}),(0,r.jsx)(s.td,{children:"Index to the desired subwidget or 'ALL' to apply the setting to all the subwidgets of this composite widget."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Name"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Setting Value(s)"}),(0,r.jsx)(s.td,{children:"See SETTING for details."}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VERTICALBOX\n LABELVALUE INST HEALTH_STATUS TEMP1\n SUBSETTING 0 TEXTCOLOR blue # Change the label's text to blue\n LABELVALUELIMITSBAR INST HEALTH_STATUS TEMP1\n SUBSETTING 0 TEXTCOLOR green # Change the label's text to green\nEND\n"})}),"\n",(0,r.jsx)(s.h2,{id:"named_widget",children:"NAMED_WIDGET"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Name a widget to allow access to it via the getNamedWidget method"})}),"\n",(0,r.jsx)(s.p,{children:"To programmatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets."}),"\n",(0,r.jsx)(s.admonition,{type:"warning",children:(0,r.jsx)(s.p,{children:"getNamedWidget returns the widget itself and thus must be operated on using methods native to that widget"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Name"}),(0,r.jsx)(s.td,{children:"The unique name applied to the following widget instance. Names must be unique per screen."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Type"}),(0,r.jsx)(s.td,{children:"One of the widget types listed in Widget Descriptions"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Widget Parameters"}),(0,r.jsx)(s.td,{children:"The unique parameters for the given widget type"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'NAMED_WIDGET DURATION TEXTFIELD\nBUTTON "Push" "screen.getNamedWidget(\'DURATION\').text()"\n'})}),"\n",(0,r.jsx)(s.h2,{id:"layout-widgets",children:"Layout Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Layout widgets are used to position other widgets on the screen. For example, the HORIZONTAL layout widget places the widgets it encapsulates horizontally on the screen."}),"\n",(0,r.jsx)(s.h3,{id:"vertical",children:"VERTICAL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates vertically"})}),"\n",(0,r.jsx)(s.p,{children:"The screen defaults to a vertical layout, so if no layout widgets are specified, all widgets will be automatically placed within a VERTICAL layout widget. The VERTICAL widget sizes itself to fit its contents."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICAL 5px\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"verticalbox",children:"VERTICALBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates vertically inside a thin border"})}),"\n",(0,r.jsx)(s.p,{children:"The VERTICALBOX widget sizes itself to fit its contents vertically and to fit the screen horizontally"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Title"}),(0,r.jsx)(s.td,{children:"Text to place within the border to label the box"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICALBOX Info\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontal",children:"HORIZONTAL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates horizontally"})}),"\n",(0,r.jsx)(s.p,{children:"The HORIZONTAL widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTAL 100\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontalbox",children:"HORIZONTALBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets it encapsulates horizontally inside a thin border"})}),"\n",(0,r.jsx)(s.p,{children:"The HORIZONTALBOX widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Title"}),(0,r.jsx)(s.td,{children:"Text to place within the border to label the box"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'HORIZONTALBOX Info 10\n LABEL "TEST"\n LABEL "SCREEN"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"matrixbycolumns",children:"MATRIXBYCOLUMNS"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets into a table-like matrix"})}),"\n",(0,r.jsx)(s.p,{children:"The MATRIXBYCOLUMNS widget sizes itself to fit its contents"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Columns"}),(0,r.jsx)(s.td,{children:"The number of columns to create"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'MATRIXBYCOLUMNS 3 10\n LABEL "COL 1"\n LABEL "COL 2"\n LABEL "COL 3"\n LABEL "100"\n LABEL "200"\n LABEL "300"\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"scrollwindow",children:"SCROLLWINDOW"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places the widgets inside of it into a scrollable area"})}),"\n",(0,r.jsx)(s.p,{children:"The SCROLLWINDOW widget sizes itself to fit the screen in which it is contained"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Maximum height of the scroll window in pixels (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Margin"}),(0,r.jsx)(s.td,{children:"Margin between widgets (default = 0px)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'SCROLLWINDOW 100 10\n VERTICAL\n LABEL "100"\n LABEL "200"\n LABEL "300"\n LABEL "400"\n LABEL "500"\n LABEL "600"\n LABEL "700"\n LABEL "800"\n LABEL "900"\n END\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"tabbook",children:"TABBOOK"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a tabbed area in which to place TABITEM widgets"})}),"\n",(0,r.jsx)(s.h3,{id:"tabitem",children:"TABITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a VERTICAL layout tab into which to place widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Tab text"}),(0,r.jsx)(s.td,{children:"Text to display in the tab"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'TABBOOK\n TABITEM "Tab 1"\n LABEL "100"\n LABEL "200"\n END\n TABITEM "Tab 2"\n LABEL "300"\n LABEL "400"\n END\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"iframe",children:"IFRAME"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open external tools in an Iframe within OpenC3"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"URL"}),(0,r.jsx)(s.td,{children:"The path to the page to display in the iframe"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"IFRAME https://openc3.com 900 450\n"})}),"\n",(0,r.jsx)(s.h2,{id:"decoration-widgets",children:"Decoration Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Decoration widgets are used to enhance the appearance of the screen. They do not respond to input, nor does the output vary with telemetry."}),"\n",(0,r.jsx)(s.h3,{id:"label",children:"LABEL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays text on the screen"})}),"\n",(0,r.jsx)(s.p,{children:"Generally, label widgets contain a telemetry mnemonic and are placed next to the telemetry VALUE widget."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display on the label"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABEL "Note: This is only a warning"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"horizontalline",children:"HORIZONTALLINE"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Displays a horizontal line on the screen that can be used as a separator"})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABEL Over\nHORIZONTALLINE\nLABEL Under\n"})}),"\n",(0,r.jsx)(s.h3,{id:"sectionheader",children:"SECTIONHEADER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"DEPRECATED - Displays a label that is underlined with a horizontal line"})}),"\n",(0,r.jsx)(s.p,{children:"Use a VERTICALBOX or HORIZONTALBOX with title parameter instead of SECTIONHEADER"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h3,{id:"title",children:"TITLE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a large centered title on the screen"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'TITLE "Title"\nHORIZONTALLINE\nLABEL "Label"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"spacer",children:"SPACER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Places a fixed size spacer in between widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the spacer in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the spacer in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'VERTICAL 3\n LABEL "Spacer below"\n SPACER 0 100\n LABEL "Spacer above"\nEND\n'})}),"\n",(0,r.jsx)(s.h2,{id:"telemetry-widgets",children:"Telemetry Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Telemetry widgets are used to display telemetry values. The first parameters to each of these widgets is a telemetry mnemonic. Depending on the type and purpose of the telemetry item, the screen designer may select from a wide selection of widgets to display the value in the most useful format."}),"\n",(0,r.jsx)(s.h3,{id:"array",children:"ARRAY"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays ARRAY data organized into rows and space separated"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Format string applied to each array item (default = nil)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Items per row"}),(0,r.jsx)(s.td,{children:"Number of array items per row (default = 4)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'ARRAY INST HEALTH_STATUS ARY 250 80 "0x%x" 6 FORMATTED\nARRAY INST HEALTH_STATUS ARY2 200 100 nil 4 WITH_UNITS\n'})}),"\n",(0,r.jsx)(s.h3,{id:"block",children:"BLOCK"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays BLOCK data organized into rows and space separated"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the widget (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the widget (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Format string applied to each array item (default = nil)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Bytes per word"}),(0,r.jsx)(s.td,{children:"Number of bytes per word (default = 4)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Words per row"}),(0,r.jsx)(s.td,{children:"Number of words per row (default = 4"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Address format"}),(0,r.jsx)(s.td,{children:"Format for the address printed at the beginning of each line (default = nil which means do not print an address)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'BLOCK INST IMAGE IMAGE 400 130 "%02X" 4 4 "0x%08X:"\n'})}),"\n",(0,r.jsx)(s.h3,{id:"formatvalue",children:"FORMATVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a box with a formatted value"})}),"\n",(0,r.jsx)(s.p,{children:"Data is formatted by the specified string rather than by a format string given in the telemetry definition files. The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits)."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format string"}),(0,r.jsx)(s.td,{children:"Printf style format string to apply to the telemetry item"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"FORMATVALUE INST LATEST TIMESEC %012u CONVERTED 20\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelled",children:"LABELLED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL followed by a LED"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Justification"}),(0,r.jsxs)(s.td,{children:["How to justify the label and LED together. The default of 'SPLIT' aligns the label to the left and the LED to the right with any additional space going between them. 'CENTER' pushes the label and LED together with any additional space to the left and right. 'LEFT' or 'RIGHT' pushes them to the respective side with the space going on the opposite.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"SPLIT, CENTER, LEFT, RIGHT"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELLED INST PARAMS VALUE1\n SETTING LED_COLOR GOOD GREEN\n SETTING LED_COLOR BAD RED\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LABELLED. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"led_color",children:"LED_COLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map a state or value to a color"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value. ANY used to match any value or state not declared."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"LED color"}),(0,r.jsx)(s.td,{children:"Color of the LED"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelprogressbar",children:"LABELPROGRESSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a PROGRESSBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Scale factor"}),(0,r.jsx)(s.td,{children:"Value to multiply the telemetry item by before displaying in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0."}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the progress bar (default = 80 pixels"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELPROGRESSBAR INST ADCS POSPROGRESS 2 200 RAW\nLABELPROGRESSBAR INST ADCS POSPROGRESS\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvalue",children:"LABELVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a VALUE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUE INST LATEST TIMESEC CONVERTED 18\nLABELVALUE INST LATEST COLLECT_TYPE\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluedesc",children:"LABELVALUEDESC"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the items description followed by a VALUE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Description"}),(0,r.jsx)(s.td,{children:"The description to display in the label (default is to display the description text associated with the telemetry item)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'LABELVALUEDESC INST HEALTH_STATUS TEMP1 "Temperature number 1" RAW 18\nLABELVALUEDESC INST HEALTH_STATUS COLLECT_TYPE\n'})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluelimitsbar",children:"LABELVALUELIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and LIMITSBAR widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluelimitscolumn",children:"LABELVALUELIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and LIMITSCOLUMN widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18\nLABELVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"labelvaluerangebar",children:"LABELVALUERANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by VALUE and RANGEBAR widgets"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40\nLABELVALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120\n"})}),"\n",(0,r.jsx)(s.h3,{id:"led",children:"LED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LED which changes color based on telemetry values"})}),"\n",(0,r.jsx)(s.p,{children:"By default TRUE is green and FALSE is red and all other values are black. Additional values can be added by using the LED_COLOR setting. For example LED INST PARAMS VALUE3 RAW can be followed by SETTING LED_COLOR 0 GREEN, SETTING LED_COLOR 1 RED, and SETTING LED_COLOR ANY ORANGE."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the LED circle (default = 15)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LED INST PARAMS VALUE5 RAW 25 20 # Ellipse\n SETTING LED_COLOR 0 GREEN\n SETTING LED_COLOR 1 RED\n SETTING LED_COLOR ANY YELLOW\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LED. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"led_color-1",children:"LED_COLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map a state or value to a color"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value. ANY used to match any value or state not declared."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"LED color"}),(0,r.jsx)(s.td,{children:"Color of the LED"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"limitsbar",children:"LIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item's current value within its colored limits horizontally"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 200 50\nLIMITSBAR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"limitscolumn",children:"LIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item's current value within its colored limits vertically"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 50 200\nLIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"limitscolor",children:"LIMITSCOLOR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a circle depicting the limits color of an item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Radius"}),(0,r.jsx)(s.td,{children:"Radius of the circle (default is 10)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Full Item Name"}),(0,r.jsx)(s.td,{children:"Show the full item name (default is false)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LIMITSCOLOR INST HEALTH_STATUS TEMP1 CONVERTED 30 TRUE\nLIMITSCOLOR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuelimitsbar",children:"VALUELIMITSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by LIMITSBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUELIMITSBAR INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUELIMITSBAR INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuelimitscolumn",children:"VALUELIMITSCOLUMN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by LIMITSCOLUMN"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 8)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUELIMITSCOLUMN INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h3,{id:"valuerangebar",children:"VALUERANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an item VALUE followed by RANGEBAR"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 160)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUERANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 18 200 40\nVALUERANGEBAR INST HEALTH_STATUS TEMP1 -120 120\n"})}),"\n",(0,r.jsx)(s.h3,{id:"linegraph",children:"LINEGRAPH"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a line graph of a telemetry item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LINEGRAPH INST HEALTH_STATUS TEMP1\n SETTING ITEM INST ADCS Q1 # Add additional item to graph\nLINEGRAPH INST HEALTH_STATUS TEMP2 RAW\nLINEGRAPH INST HEALTH_STATUS TEMP3 CONVERTED REDUCED_MINUTE MIN\n SETTING SIZE 600 500 # width height\n SETTING HISTORY 1h # load 1 hour of data into graph\nLINEGRAPH INST HEALTH_STATUS TEMP4\n SETTING HISTORY 30m # load 30 minutes of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LINEGRAPH. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"sparkline",children:"SPARKLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a sparkline graph (no cursor, scale or legend) of a telemetry item"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SPARKLINE INST HEALTH_STATUS TEMP1\n SETTING SIZE 400 50\n SETTING HISTORY 30s # Add 30 seconds of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to SPARKLINE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item-1",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime-1",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history-1",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed-1",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved-1",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed-1",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size-1",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"labelsparkline",children:"LABELSPARKLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a LABEL with the item name followed by a SPARKLINE"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"LABELSPARKLINE INST HEALTH_STATUS TEMP1\n SETTING HISTORY 5m # Add 5 minutes of data into graph\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to LABELSPARKLINE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"item-2",children:"ITEM"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Add a telemetry item to the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced"}),(0,r.jsxs)(s.td,{children:["Whether to display reduced data. Default is DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"DECOM, REDUCED_MINUTE, REDUCED_HOUR, REDUCED_DAY"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Reduced Type"}),(0,r.jsxs)(s.td,{children:["The type of reduce data to display. Only applies if Reduced is not DECOM.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"MIN, MAX, AVG, STDDEV"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"starttime-2",children:"STARTTIME"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Start the graph history at the designated Time"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Time"}),(0,r.jsxs)(s.td,{children:["Start time as formatted 'YYYY/MM/DD HH:MM",":SS","'"]}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"history-2",children:"HISTORY"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Display an initial history of data"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"Value(d,h,m,s). For example 1d, 2h, 30m, 15s"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"secondsgraphed-2",children:"SECONDSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display the specified number of seconds in the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to display"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointssaved-2",children:"POINTSSAVED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Save the number of seconds in graph memory"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of seconds to save"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"pointsgraphed-2",children:"POINTSGRAPHED"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Number of points to display on the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Time"}),(0,r.jsx)(s.td,{children:"Number of points to graph"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.h4,{id:"size-2",children:"SIZE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Size of the graph"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width in pixels"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"imageviewer",children:"IMAGEVIEWER"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Display a base64 image from a TLM packet"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name to pull the CONVERTED value from. If additional processing (base64 encoding) is needed consider using a DERIVED item."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Format"}),(0,r.jsx)(s.td,{children:"The image format of the base64 data (e.g. jpg, png, etc)"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"IMAGEVIEWER INST IMAGE IMAGE jpg\n"})}),"\n",(0,r.jsx)(s.h3,{id:"progressbar",children:"PROGRESSBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a progress bar that is useful for displaying percentages"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Scale factor"}),(0,r.jsx)(s.td,{children:"Value to multiple the telemetry item by before displaying the in the progress bar. Final value should be in the range of 0 to 100. Default is 1.0."}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the progress bar (default = 100 pixels)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"PROGRESSBAR INST ADCS POSPROGRESS 0.5 200\nPROGRESSBAR INST ADCS POSPROGRESS\n"})}),"\n",(0,r.jsx)(s.h3,{id:"rangebar",children:"RANGEBAR"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a custom range bar displaying the item value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Low Value"}),(0,r.jsx)(s.td,{children:"Minimum value to display on the range bar. If the telemetry item goes below this value the bar is \u201cpegged\u201d on the low end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"High Value"}),(0,r.jsx)(s.td,{children:"Maximum value to display on the range bar. If the telemetry item goes above this value the bar is \u201cpegged\u201d on the high end."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the range bar (default = 100)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the range bar (default = 25)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"RANGEBAR INST HEALTH_STATUS TEMP1 0 100000 RAW 200 50\nRANGEBAR INST HEALTH_STATUS TEMP1 -100 100\n"})}),"\n",(0,r.jsx)(s.h3,{id:"rollup",children:"ROLLUP"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.17.1)"}),(0,r.jsx)(s.strong,{children:"Displays a notification icon which changes color based on a rollup telemetry"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon name"}),(0,r.jsxs)(s.td,{children:["The astro UX icon to display. Valid choices are 'astro' icons taken from ",(0,r.jsx)(s.a,{href:"https://github.com/RocketCommunicationsInc/astro-components/blob/master/static/json/rux-icons.json",children:"https://github.com/RocketCommunicationsInc/astro-components/blob/master/static/json/rux-icons.json"}),"."]}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon label"}),(0,r.jsx)(s.td,{children:"Text to apply to the icon label"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Icon sublabel"}),(0,r.jsx)(s.td,{children:"Text to apply to the icon sublabel"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'ROLLUP satellite-transmit "SAT 1" "Details"\n # Screen to open on click\n SETTING SCREEN INST HS\n # Telemetry items to rollup status\n SETTING TLM INST HEALTH_STATUS TEMP1\n SETTING TLM INST HEALTH_STATUS TEMP2\nROLLUP antenna "GND 2" "Location"\n # Screen to open on click\n SETTING SCREEN INST HS\n # Telemetry items to rollup status\n SETTING TLM INST HEALTH_STATUS TEMP3\n SETTING TLM INST HEALTH_STATUS TEMP4\n'})}),"\n",(0,r.jsx)(s.h3,{id:"signal",children:"SIGNAL"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.17.2)"}),(0,r.jsx)(s.strong,{children:"Displays a cellular signal icon which changes based on telemetry value"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SIGNAL INST HEALTH_STATUS TEMP1\n # Screen to open on click\n SETTING SCREEN INST HS\n # Values to compare when setting the 1-bar, 2-bar and 3-bar icons\n # Default is 30, 60, 90 (e.g. 0 to 100 range)\n # Value < -50 display no bars\n # Value >= -50 and < 0 displays 1 bar\n # Value >= 0 and < 50 displays 2 bars\n # Value >= 50 displays 5 bars\n SETTING RANGE -50 0 50\n"})}),"\n",(0,r.jsx)(s.h3,{id:"textbox",children:"TEXTBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Provides a large box for multiline text"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the textbox in px (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the textbox in px (default = 200)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"TEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED 150 70\nTEXTBOX INST HEALTH_STATUS PACKET_TIMEFORMATTED\n"})}),"\n",(0,r.jsx)(s.h3,{id:"value",children:"VALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a box with a telemetry item value"})}),"\n",(0,r.jsx)(s.p,{children:"The white portion of the box darkens to gray while the value remains stagnant, then brightens to white each time the value changes. Additionally the value is colored based on the items limits state (Red for example if it is out of limits)."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Number of characters"}),(0,r.jsx)(s.td,{children:"The number of characters wide to make the value box (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"VALUE INST HEALTH_STATUS TEMP1 CONVERTED 18\nVALUE INST HEALTH_STATUS TEMP1\n"})}),"\n",(0,r.jsx)(s.h2,{id:"interactive-widgets",children:"Interactive Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Interactive widgets are used to gather input from the user. Unlike all other widgets, which only output some graphical representation, interactive widgets permit input either from the keyboard or mouse."}),"\n",(0,r.jsx)(s.h3,{id:"button",children:"BUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a rectangular clickable button"})}),"\n",(0,r.jsxs)(s.p,{children:["Upon clicking, the button executes the Javascript code assigned. Buttons\ncan be used to send commands and perform other tasks. If you want your button\nto use values from other widgets, define them as named widgets and read their\nvalues using the ",(0,r.jsx)(s.code,{children:'screen.getNamedWidget("WIDGET_NAME").text()'})," method.\nSee the example in CHECKBUTTON."]}),"\n",(0,r.jsxs)(s.p,{children:["Button code can get rather complex so remember to use string concatenation\nto make things more readable. If you use ",(0,r.jsx)(s.code,{children:"+"})," newlines are inserted automatically\nduring string concatenation. If you use ",(0,r.jsx)(s.code,{children:"\\"})," you'll need to separate lines with a\nsingle semicolon ",(0,r.jsx)(s.code,{children:";"}),". COSMOS uses double semicolon ",(0,r.jsx)(s.code,{children:";;"})," to indicate lines should\nbe evaluated separately. Note that all OpenC3 commands (using api.cmd) must be\nseparated by ",(0,r.jsx)(s.code,{children:";;"}),"."]}),"\n",(0,r.jsx)(s.p,{children:"You can send commands with buttons using api.cmd(). The cmd() syntax looks exactly\nlike the standard COSMOS scripting syntax. You can also request and use\ntelemetry in screens using Javascript Promises."}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.code,{children:"api.tlm('INST PARAMS VALUE3', 'RAW').then(dur => api.cmd('INST COLLECT with TYPE NORMAL, DURATION '+dur))\""})}),"\n",(0,r.jsx)(s.p,{children:"The api.tlm() function returns a Promise which is resolved with then()\nat which point we send the command with the telemetry value we received."}),"\n",(0,r.jsxs)(s.p,{children:["Scripts can be launched from a BUTTON using the ",(0,r.jsx)(s.code,{children:"runScript()"})," method. ",(0,r.jsx)(s.code,{children:"runScript()"})," takes three parameters,\nthe name of the script, whether to open the script in the foreground of Script Runner (default = true), and a hash of\nenvironment variables. For example: ",(0,r.jsx)(s.code,{children:"runScript('INST/procedures/script.rb', false, {'VAR': 'VALUE'})"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Button Text"}),(0,r.jsx)(s.td,{children:"Text displayed on the button"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Button Code"}),(0,r.jsx)(s.td,{children:"Javascript code to execute when the button is pressed"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"BUTTON 'Start Collect' 'api.cmd(\"INST COLLECT with TYPE NORMAL, DURATION 5\")'\nBUTTON 'Run Checks' 'runScript(\"INST/procedures/checks.rb\")'\n# More complex example with background checkbox and env vars\nNAMED_WIDGET SCRIPTNAME COMBOBOX collect.rb checks.rb\nNAMED_WIDGET BG CHECKBUTTON 'Background'\nBUTTON 'Run Script' \"var script=screen.getNamedWidget('SCRIPTNAME').text();\" \\\n # Set an environment variable to be used by the script as ENV['TYPE']\n \"var env = {}; env['TYPE'] = 'TEST';\" \\\n \"runScript('INST/procedures/'+script, !screen.getNamedWidget('BG').checked(), env)\"\n"})}),"\n",(0,r.jsx)(s.h3,{id:"checkbutton",children:"CHECKBUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a check box"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Checkbox Text"}),(0,r.jsx)(s.td,{children:"Text displayed next to the checkbox"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks'\nBUTTON 'Send' 'screen.getNamedWidget(\"CHECK\").checked() ? ' \\\n 'api.cmd_no_hazardous_check(\"INST CLEAR\") : api.cmd(\"INST CLEAR\")'\n"})}),"\n",(0,r.jsx)(s.h3,{id:"combobox",children:"COMBOBOX"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a drop down list of text items"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Option Text 1"}),(0,r.jsx)(s.td,{children:"Text to display in the selection drop down"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Option Text n"}),(0,r.jsx)(s.td,{children:"Text to display in the selection drop down"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"BUTTON 'Start Collect' 'var type = screen.getNamedWidget(\"COLLECT_TYPE\").text();' +\n 'api.cmd(\"INST COLLECT with TYPE \"+type+\", DURATION 10.0\")'\nNAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL\n"})}),"\n",(0,r.jsx)(s.h3,{id:"radiogroup",children:"RADIOGROUP"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Creates a group of RADIOBUTTONs"})}),"\n",(0,r.jsx)(s.p,{children:"RADIOBUTTONs must be part of a group to enable selection logic"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Initial selected button"}),(0,r.jsx)(s.td,{children:"Selects a radio button at initialization (0-based)"}),(0,r.jsx)(s.td,{children:"False"})]})})]}),"\n",(0,r.jsx)(s.h3,{id:"radiobutton",children:"RADIOBUTTON"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a radio button and text"})}),"\n",(0,r.jsx)(s.p,{children:"Note this is of limited use by itself and is primarily used in conjunction with NAMED_WIDGET. It must be contained by a RADIOGROUP to enable typical selection of a single RADIOBUTTON."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to display next to the radio button"}),(0,r.jsx)(s.td,{children:"True"})]})})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index\n RADIOBUTTON 'Abort'\n RADIOBUTTON 'Clear'\nEND\nBUTTON 'Send' \"screen.getNamedWidget('GROUP').selected() === 0 ? \" +\n \"api.cmd('INST ABORT') : api.cmd('INST CLEAR')\"\n"})}),"\n",(0,r.jsx)(s.h3,{id:"textfield",children:"TEXTFIELD"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays a rectangular box where the user can enter text"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Characters"}),(0,r.jsx)(s.td,{children:"Width of the text field in characters (default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Default text to put in the text field (default is blank)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'NAMED_WIDGET DURATION TEXTFIELD 12 "10.0"\nBUTTON \'Start Collect\' \'var dur = screen.getNamedWidget("DURATION").text();\' +\n \'api.cmd("INST COLLECT with TYPE NORMAL, DURATION "+dur+"")\'\n'})}),"\n",(0,r.jsx)(s.h2,{id:"canvas-widgets",children:"Canvas Widgets"}),"\n",(0,r.jsx)(s.hr,{}),"\n",(0,r.jsx)(s.p,{children:"Canvas Widgets are used to draw custom displays into telemetry screens. The canvas coordinate frame places (0,0) in the upper-left corner of the canvas."}),"\n",(0,r.jsx)(s.h3,{id:"canvas",children:"CANVAS"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Layout widget for the other canvas widgets"})}),"\n",(0,r.jsx)(s.p,{children:"All canvas widgets must be enclosed within a CANVAS widget."}),"\n",(0,r.jsx)(s.admonition,{type:"warning",children:(0,r.jsx)(s.p,{children:"The canvas coordinate frame places (0,0) in the upper-left corner of the canvas."})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Height"}),(0,r.jsx)(s.td,{children:"Height of the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvaslabel",children:"CANVASLABEL"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws text onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Text"}),(0,r.jsx)(s.td,{children:"Text to draw onto the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Font Size"}),(0,r.jsx)(s.td,{children:"Font size of the text (Default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the text"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 100 100\n CANVASLABEL 5 34 "Label1" 24 red\n CANVASLABEL 5 70 "Label2" 18 blue\nEND\n'})}),"\n",(0,r.jsx)(s.h3,{id:"canvaslabelvalue",children:"CANVASLABELVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws the text value of a telemetry item onto the canvas in an optional frame"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the text on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Font Size"}),(0,r.jsx)(s.td,{children:"Font size of the text (Default = 12)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the text"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED.",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 200 100\n CANVASLABELVALUE INST HEALTH_STATUS TEMP1 5 34 12 red\n CANVASLABELVALUE INST HEALTH_STATUS TEMP2 5 70 10 blue WITH_UNITS\nEND\n"})}),"\n",(0,r.jsx)(s.h3,{id:"canvasimage",children:"CANVASIMAGE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an image on the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image filename"}),(0,r.jsx)(s.td,{children:"Name of a image file. The file must be in the plugin's targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 250 430\n CANVASIMAGE "satellite.png" 10 10 200 200\n SETTING SCREEN INST HS\n CANVASIMAGE "https://images.pexels.com/photos/256152/pexels-photo-256152.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=640&w=426" 0 250 250 150\nEND\n'})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASIMAGE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"screen-1",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open another screen when clicked"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"Name of the target"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen name"}),(0,r.jsx)(s.td,{children:"Name of the screen"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasimagevalue",children:"CANVASIMAGEVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Displays an image on the canvas that changes with a telemetry value"})}),"\n",(0,r.jsx)(s.p,{children:'Use various SETTING values to indicate which images should be displayed based on telemetry. For example, SETTING IMAGE CONNECTED "ground_on.png" 400 100. See the DEMO for a complete example.'}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Default image filename"}),(0,r.jsx)(s.td,{children:"The default image to display. The file must be in the targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image width"}),(0,r.jsx)(s.td,{children:"Width of the image (default is 100%)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image height"}),(0,r.jsx)(s.td,{children:"Height of the image (default is 100%)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:'CANVAS 230 230\n CANVASIMAGEVALUE INST HEALTH_STATUS GROUND1STATUS CONVERTED "ground_error.png" 10 10 180 180\n SETTING IMAGE CONNECTED "ground_on.png" 10 10\n SETTING IMAGE UNAVAILABLE "ground_off.png" 10 10\n SETTING SCREEN INST HS\nEND\n'})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASIMAGEVALUE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"image",children:"IMAGE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Map an image to a state or value"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Image filename"}),(0,r.jsx)(s.td,{children:"Image to display. The file must be in the targets/TARGET/public directory."}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the upper-left corner of the image on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h4,{id:"screen-2",children:"SCREEN"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Open another screen when clicked"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"Name of the target"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Screen name"}),(0,r.jsx)(s.td,{children:"Name of the screen"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasline",children:"CANVASLINE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a line onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start X Position"}),(0,r.jsx)(s.td,{children:"X position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End X Position"}),(0,r.jsx)(s.td,{children:"X position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the line"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the line in pixels (default = 1)"}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 100 50\n CANVASLINE 5 5 95 5\n CANVASLINE 5 5 5 45 green 2\n CANVASLINE 95 5 95 45 blue 3\nEND\n"})}),"\n",(0,r.jsx)(s.h3,{id:"canvaslinevalue",children:"CANVASLINEVALUE"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a color changing line onto the canvas"})}),"\n",(0,r.jsx)(s.p,{children:"The line is represented by one of two colors based on the value of the associated telemetry item"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Target name"}),(0,r.jsx)(s.td,{children:"The target name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Packet name"}),(0,r.jsx)(s.td,{children:"The packet name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Item name"}),(0,r.jsx)(s.td,{children:"The item name"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start X Position"}),(0,r.jsx)(s.td,{children:"X position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Start Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the start of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End X Position"}),(0,r.jsx)(s.td,{children:"X position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"End Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the end of the line on the canvas"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Width"}),(0,r.jsx)(s.td,{children:"Width of the line in pixels (default = 3)"}),(0,r.jsx)(s.td,{children:"False"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value type"}),(0,r.jsxs)(s.td,{children:["The type of the value to display. Default is CONVERTED",(0,r.jsx)("br",{}),(0,r.jsx)("br",{}),"Valid Values: ",(0,r.jsx)("span",{class:"values",children:"RAW, CONVERTED, FORMATTED, WITH_UNITS"})]}),(0,r.jsx)(s.td,{children:"False"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 120 50\n CANVASLABELVALUE INST HEALTH_STATUS GROUND1STATUS 0 12 12 black\n CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 25 115 25 5 RAW\n SETTING VALUE_EQ 1 GREEN\n SETTING VALUE_EQ 0 RED\n CANVASLINEVALUE INST HEALTH_STATUS GROUND1STATUS 5 45 115 45\n SETTING VALUE_EQ CONNECTED GREEN\n SETTING VALUE_EQ UNAVAILABLE RED\nEND\n"})}),"\n",(0,r.jsx)(s.p,{children:"The following settings apply to CANVASLINEVALUE. They are applied using the SETTING keyword."}),"\n",(0,r.jsx)(s.h4,{id:"value_eq",children:"VALUE_EQ"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)("div",{class:"right",children:"(Since 5.5.1)"}),(0,r.jsx)(s.strong,{children:"Map a value to a color"})]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Value"}),(0,r.jsx)(s.td,{children:"State or value"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the line"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"canvasdot",children:"CANVASDOT"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Draws a dot onto the canvas"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Parameter"}),(0,r.jsx)(s.th,{children:"Description"}),(0,r.jsx)(s.th,{children:"Required"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"X Position"}),(0,r.jsx)(s.td,{children:"X position of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Y Position"}),(0,r.jsx)(s.td,{children:"Y position of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Color"}),(0,r.jsx)(s.td,{children:"Color of the dot"}),(0,r.jsx)(s.td,{children:"True"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Radius"}),(0,r.jsx)(s.td,{children:"Radius of the dot in pixels"}),(0,r.jsx)(s.td,{children:"True"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:"Example Usage:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"CANVAS 50 50\n CANVASDOT 10 15 BLUE 5\nEND\n"})}),"\n",(0,r.jsx)(s.h2,{id:"example-file",children:"Example File"}),"\n",(0,r.jsx)(s.p,{children:"Example File: TARGET/myscreen.txt"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-ruby",children:"SCREEN AUTO AUTO 0.5\nVERTICAL\n TITLE \"<%= target_name %> Commanding Examples\"\n LABELVALUE INST HEALTH_STATUS COLLECTS\n LABELVALUE INST HEALTH_STATUS COLLECT_TYPE\n LABELVALUE INST HEALTH_STATUS DURATION\n VERTICALBOX \"Send Collect Command:\"\n HORIZONTAL\n LABEL \"Type: \"\n NAMED_WIDGET COLLECT_TYPE COMBOBOX NORMAL SPECIAL\n END\n HORIZONTAL\n LABEL \" Duration: \"\n NAMED_WIDGET DURATION TEXTFIELD 12 \"10.0\"\n END\n BUTTON 'Start Collect' \"api.cmd('INST COLLECT with TYPE '+screen.getNamedWidget('COLLECT_TYPE').text()+', DURATION '+screen.getNamedWidget('DURATION').text())\"\n END\n SETTING BACKCOLOR 163 185 163\n VERTICALBOX \"Parameter-less Commands:\"\n NAMED_WIDGET GROUP RADIOGROUP 1 # Select 'Clear' initially, 0-based index\n RADIOBUTTON 'Abort'\n RADIOBUTTON 'Clear'\n END\n NAMED_WIDGET CHECK CHECKBUTTON 'Ignore Hazardous Checks' # No option is by default UNCHECKED\n BUTTON 'Send' \"screen.getNamedWidget('GROUP').selected() === 0 ? api.cmd('INST ABORT') : (screen.getNamedWidget('CHECK').checked() ? api.cmd_no_hazardous_check('INST CLEAR') : api.cmd('INST CLEAR'))\"\n END\n SETTING BACKCOLOR 163 185 163\nEND\n"})})]})}function x(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},8453:(e,s,d)=>{d.d(s,{R:()=>i,x:()=>l});var r=d(6540);const n={},t=r.createContext(n);function i(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]);
\ No newline at end of file
diff --git a/docs/assets/js/99581c43.b0751f07.js b/docs/assets/js/99581c43.b0751f07.js
new file mode 100644
index 0000000000..724fc1ff21
--- /dev/null
+++ b/docs/assets/js/99581c43.b0751f07.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[413],{2888:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>n,metadata:()=>d,toc:()=>r});var s=i(4848),o=i(8453);const n={title:"Custom Widgets"},l=void 0,d={id:"guides/custom-widgets",title:"Custom Widgets",description:"COSMOS allows you to build custom widgets which can be deployed with your plugin and used in Telemetry Viewer. Building custom widgets can utilize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the Widget Generator guide for information about generating the scaffolding for a custom widget.",source:"@site/docs/guides/custom-widgets.md",sourceDirName:"guides",slug:"/guides/custom-widgets",permalink:"/docs/guides/custom-widgets",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/guides/custom-widgets.md",tags:[],version:"current",frontMatter:{title:"Custom Widgets"},sidebar:"defaultSidebar",previous:{title:"COSMOS and NASA cFS",permalink:"/docs/guides/cfs"},next:{title:"Little Endian Bitfields",permalink:"/docs/guides/little-endian-bitfields"}},c={},r=[{value:"Custom Widgets",id:"custom-widgets",level:2},{value:"Helloworld Widget",id:"helloworld-widget",level:3}];function a(e){const t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["COSMOS allows you to build custom widgets which can be deployed with your ",(0,s.jsx)(t.a,{href:"/docs/configuration/plugins",children:"plugin"})," and used in ",(0,s.jsx)(t.a,{href:"/docs/tools/tlm-viewer",children:"Telemetry Viewer"}),". Building custom widgets can utilize any javascript frameworks but since COSMOS is written with Vue.js, we will use that framework in this tutorial. Please see the ",(0,s.jsx)(t.a,{href:"../getting-started/generators#widget-generator",children:"Widget Generator"})," guide for information about generating the scaffolding for a custom widget."]}),"\n",(0,s.jsx)(t.h2,{id:"custom-widgets",children:"Custom Widgets"}),"\n",(0,s.jsxs)(t.p,{children:["We're basically going to follow the COSMOS ",(0,s.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos/tree/main/openc3-cosmos-init/plugins/packages/openc3-cosmos-demo",children:"Demo"})," and explain how that custom widget was created."]}),"\n",(0,s.jsxs)(t.p,{children:["If you look at the bottom of the Demo's ",(0,s.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos/blob/main/openc3-cosmos-init/plugins/packages/openc3-cosmos-demo/plugin.txt",children:"plugin.txt"})," file you'll see we declare the widgets:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ruby",children:"WIDGET BIG\nWIDGET HELLOWORLD\n"})}),"\n",(0,s.jsxs)(t.p,{children:["When the plugin is deployed this causes COSMOS to look for the as-built widgets. For the BIG widget it will look for the widget at ",(0,s.jsx)(t.code,{children:"tools/widgets/BigWidget/BigWidget.umd.min.js"}),". Similarly it looks for HELLOWORLD at ",(0,s.jsx)(t.code,{children:"tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js"}),". These directories and file names may seem mysterious but it's all about how the widgets get built."]}),"\n",(0,s.jsx)(t.h3,{id:"helloworld-widget",children:"Helloworld Widget"}),"\n",(0,s.jsxs)(t.p,{children:["The Helloworld Widget source code is found in the plugin's src directory and is called ",(0,s.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos/blob/main/openc3-cosmos-init/plugins/packages/openc3-cosmos-demo/src/HelloworldWidget.vue",children:"HelloworldWidget.vue"}),". The basic structure is as follows:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-vue",children:'\n \x3c!-- Implement widget here --\x3e\n\n\n
-
+
+
This site aims to be a comprehensive guide to OpenC3 COSMOS. We'll cover topics such
diff --git a/docs/docs/configuration.html b/docs/docs/configuration.html
index fcfe23b31d..f292c4cdbe 100644
--- a/docs/docs/configuration.html
+++ b/docs/docs/configuration.html
@@ -4,8 +4,8 @@
Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters.
+
Command definition files define the command packets that can be sent to COSMOS targets. One large file can be used to define the command packets, or multiple files can be used at the user's discretion. Command definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some command files that depend on others, e.g. they override or extend existing commands, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have cmd.txt you can create cmd_override.txt for commands that depends on the definitions in cmd.txt. Also note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters.
When defining command parameters you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. The only difference between a STRING and BLOCK is when COSMOS reads the binary command log it stops reading a STRING type when it encounters a null byte (0). This shows up in the text log produced by Data Extractor. Note that this does NOT affect the data COSMOS writes as it's still legal to pass null bytes (0) in STRING parameters.
This item is allowed to overlap other items in the packet
-
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
Set the behavior when writing a value overflows the type
-
By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value.
+
By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value.
Parameter
Description
Required
Behavior
How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.
COSMOS configuration files are just text files. They can (and should) be checked into your configuration management system and thus can be easily diffed throughout their history. They support ERB syntax, partials, and various line continuations which make them extremely flexible.
Interfaces are the connection to the external embedded systems called targets. Interfaces are defined by the top level INTERFACE keyword in the plugin.txt file.
See INTERFACE for a description of the INTERFACE keyword. See Interface Modifiers for a description of the keywords which can follow the INTERFACE keyword. Note, SerialInterface processes the OPTION modifier.
Streams are low level classes that implement read, read_nonblock, write, connect, connected? and disconnect methods. The build-in Stream classes are SerialStream, TcpipSocketStream and TcpipClientStream and they are automatically used when creating a Serial Interface, TCP/IP Server Interface, or TCP/IP Client Interface.
+
Streams are low level classes that implement read, read_nonblock, write, connect, connected? and disconnect methods. The built-in Stream classes are SerialStream, TcpipSocketStream and TcpipClientStream and they are automatically used when creating a Serial Interface, TCP/IP Server Interface, or TCP/IP Client Interface.
Protocols define the behaviour of an Interface, including differentiating packet boundaries and modifying data as necessary. COSMOS defines the following built-in protocols which can be used with the above interfaces:
Indicates the plugin needs dependencies and sets the GEM_HOME environment variable
-
If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kuberentes pod.
+
If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise Edition, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kubernetes pod.
Interfaces are what OpenC3 uses to talk to a particular piece of hardware. Interfaces require a Ruby or Python file which implements all the interface methods necessary to talk to the hardware. OpenC3 defines many built in interfaces or you can define your own as long as it implements the interface protocol.
@@ -73,7 +73,7 @@
RECONNECT_DE
Parameter
Description
Required
Delay
Delay in seconds between reconnect attempts. The default is 15 seconds.
Disable the Disconnect button on the Interfaces tab in the Server
-
Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertantly disconnect from a target.
+
Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertently disconnect from a target.
Defines a custom widget that can be used in Telemetry Viewer screens.
-
Parameter
Description
Required
Widget Name
The name of the widget wil be used to build a path to the widget implementation. For example, WIDGET HELLOWORLD will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the Custom Widgets guide for more details.
True
+
Parameter
Description
Required
Widget Name
The name of the widget will be used to build a path to the widget implementation. For example, WIDGET HELLOWORLD will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the Custom Widgets guide for more details.
Protocols process data on behalf of an Interface. They can modify the data being written, data being read, or both. Protocols can also mark a packet as stored instead of real-time which means COSMOS will not update the current value table with the packet data. Protocols can be layered and will be processed in order. For example, if you have a low-level encryption layer that must be first removed before processing a higher level buffer length protocol.
@@ -101,9 +101,9 @@
disconnect_
The base class disconnect_reset implementation just calls the reset method to ensure common reset logic is run.
The read_data method is used to analyze and potentially modify any raw data read by an Interface. It takes one parameter as the current state of the data to be analyzed. It can return either a string of data, STOP, or DISCONNECT. If it returns a string, then it believes that data may be ready to be a full packet, and is ready for processing by any following Protocols. If STOP is returned then the Protocol believes it needs more data to complete a full packet. If DISCONNECT is returned then the Protocol believes the Interface should be disconnected (and typically automatically reconnected).
-
Base class Ruby implemenation:
+
Base class Ruby implementation:
defread_data(data) if(data.length <=0) if@allow_empty_data.nil? if@interfaceand@interface.read_protocols[-1]==self# Last read interface in chain with auto @allow_empty_data return:STOP end elsif!@allow_empty_data# Don't @allow_empty_data means STOP return:STOP end end data end
-
Base class Python implemenation:
+
Base class Python implementation:
defread_data(self, data, extra=None): iflen(data)<=0: if self.allow_empty_data isNone: if self.interface and self.interface.read_protocols[-1]== self: # Last read interface in chain with auto self.allow_empty_data return("STOP", extra) elif self.allow_empty_data: # Don't self.allow_empty_data means STOP return("STOP", extra) return(data, extra)
The base class implementation does nothing except return the data it was given. The only exception to this is when handling an empty string. If the allow_empty_data flag is false / False or if it is nil / None and the Protocol is the last in the chain, then the base implementation will return STOP to indicate that it is time to call the Interface read_interface() method to get more data. Blank strings are used to signal Protocols that they have an opportunity to return a cached packet.
COSMOS 5 is a container based service which does not use SSL/TLS out of the box. This guide will help you configure SSL and TLS. Learn more at the Traefik docs.
Table definition files define the binary tables that can be displayed in COSMOS Table Manager
-. Table definitions are defined in the target's tables/config directory and are typically named after the table such as PPSSelectionTable_def.txt. The _def.txt extention helps to identify the file as a table definition. Table definitions can be combined using the TABLEFILE keyword. This allows you to build individual table components into a larger binary.
+. Table definitions are defined in the target's tables/config directory and are typically named after the table such as PPSSelectionTable_def.txt. The _def.txt extension helps to identify the file as a table definition. Table definitions can be combined using the TABLEFILE keyword. This allows you to build individual table components into a larger binary.
The Table definition files share a lot of similarity with the Command Configuration. You have the same data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data.
This item is allowed to overlap other items in the packet
-
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
Set the behavior when writing a value overflows the type
-
By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be writen, e.g. you can successfully write 255 to a 8 bit signed value.
+
By default OpenC3 throws an error if you try to write a value which overflows its specified type, e.g. writing 255 to a 8 bit signed value. Setting the overflow behavior also allows for OpenC3 to 'TRUNCATE' the value by eliminating any high order bits. You can also set 'SATURATE' which causes OpenC3 to replace the value with the maximum or minimum allowable value for that type. Finally you can specify 'ERROR_ALLOW_HEX' which will allow for a maximum hex value to be written, e.g. you can successfully write 255 to a 8 bit signed value.
Parameter
Description
Required
Behavior
How OpenC3 treats an overflow value. Only applies to signed and unsigned integer data types.
Targets are the external embedded systems that COSMOS connects to. Targets are defined by the top level TARGET keyword in the plugin.txt file. Each target is self contained in a target directory named after the target. In the root of the target directory there is a configuration file named target.txt which configures the individual target.
This document provides the information necessary to generate and use COSMOS Telemetry Screens, which are displayed by the COSMOS Telemetry Viewer application.
Name a widget to allow access to it via the getNamedWidget method
-
To programatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets.
+
To programmatically access parts of a telemetry screen you need to name the widget. This is useful when creating screens with buttons that read values from other widgets.
warning
getNamedWidget returns the widget itself and thus must be operated on using methods native to that widget
Parameter
Description
Required
Widget Name
The unique name applied to the following widget instance. Names must be unique per screen.
True
Widget Type
One of the widget types listed in Widget Descriptions
Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easist way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters.
+
Telemetry definition files define the telemetry packets that can be received and processed from COSMOS targets. One large file can be used to define the telemetry packets, or multiple files can be used at the user's discretion. Telemetry definition files are placed in the target's cmd_tlm directory and are processed alphabetically. Therefore if you have some telemetry files that depend on others, e.g. they override or extend existing telemetry, they must be named last. The easiest way to do this is to add an extension to an existing file name. For example, if you already have tlm.txt you can create tlm_override.txt for telemetry that depends on the definitions in tlm.txt. Note that due to the way the ASCII Table is structured, files beginning with capital letters are processed before lower case letters.
When defining telemetry items you can choose from the following data types: INT, UINT, FLOAT, STRING, BLOCK. These correspond to integers, unsigned integers, floating point numbers, strings and binary blocks of data. Within COSMOS, the only difference between a STRING and BLOCK is when COSMOS reads a STRING type it stops reading when it encounters a null byte (0). This shows up when displaying the value in Packet Viewer or Tlm Viewer and in the output of Data Extractor. You should strive to store non-ASCII data inside BLOCK items and ASCII strings in STRING items.
Printing Data
Most data types can be printed in a COSMOS script simply by doing print(tlm("TGT PKT ITEM")). However, if the ITEM is a BLOCK data type and contains binary (non-ASCII) data then that won't work. COSMOS comes with a built-in method called formatted to help you view binary data. If ITEM is a BLOCK type containing binary try puts tlm("TGT PKT ITEM").formatted (Ruby) and print(formatted(tlm("TGT PKT ITEM"))) (Python) which will print the bytes out as hex.
ITEM PACKET_TIME 00 DERIVED "Python time based on TIMESEC and TIMEUS" READ_CONVERSION openc3/conversions/unix_time_conversion.py TIMESEC TIMEUS
-
Definining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
+
Defining PACKET_TIME allows the PACKET_TIMESECONDS and PACKET_TIMEFORMATTED to be calculated against an internal Packet time rather than the time COSMOS receives the packet.
This item is allowed to overlap other items in the packet
-
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and supresses the warning message.
+
If an item's bit offset overlaps another item, OpenC3 issues a warning. This keyword explicitly allows an item to overlap another and suppresses the warning message.
% cd openc3-cosmos-cmd-tlm-api openc3-cosmos-cmd-tlm-api % dockerps # Look for the container with name including cmd-tlm-api openc3-cosmos-cmd-tlm-api % docker stop cosmos-openc3-cosmos-cmd-tlm-api-1 # Run the following on Windows: openc3-cosmos-cmd-tlm-api> dev_server.bat # In Linux, set all the environment variables in the .env file, but override REDIS to be local openc3-cosmos-cmd-tlm-api % set -a;source../.env;set +a openc3-cosmos-cmd-tlm-api % exportOPENC3_REDIS_HOSTNAME=127.0.0.1 openc3-cosmos-cmd-tlm-api % exportOPENC3_REDIS_EPHEMERAL_HOSTNAME=127.0.0.1 openc3-cosmos-cmd-tlm-api % bundle install openc3-cosmos-cmd-tlm-api % bundle exec rails s
-
Once the bundle exec rails s command returns you should see API requests coming from interations in the frontend code. If you add code (like Ruby debugging statements) to the cmd-tlm-api code you need to stop the server (CTRL-C) and restart it to see the effect.
+
Once the bundle exec rails s command returns you should see API requests coming from interactions in the frontend code. If you add code (like Ruby debugging statements) to the cmd-tlm-api code you need to stop the server (CTRL-C) and restart it to see the effect.