Serial Schema¶
The configuration schema for SerialCodec
is a crucial aspect of setting up and using the codec effectively. It helps define all the Command/Query interfaces that you can use for testing and development. A schema is defined to enforce the structure and types of the configuration options that the SerialCodec
expects.
Overview¶
The configuration schema is defined in a YAML file and includes several key components, such as encoding settings, signal definitions, and message configurations. Each component has specific types and default values.
Command/Query Signals¶
Commands are instructions that indicate a desired change in the state or behavior of an something. These commands execute operations such as 'led set', and are not expected to return/capture data. Each command signal is an object containing a name and the command to perform the operation.
Queries are instructions to retrieve information from something. These commands execute operations such as 'led get', and are expected to make no modifications to something. They should be used solely for data retrieval. Each query signal is an object containing a name and the query to perform the operation.
CommandQueries are a combination of the two above. They encapsulate instructions that indicate a desired change in the state or behavior of an something, along with instructions to retrieve information from something. For example, you may want to encapsulate led set
and led get
into a single led object. Each command query signal is an object containing a name and both the command and query to perform the operations.
Note
Queries also contain an optional field for pattern matching. This is useful for when a query may return a large output stream, while you may only be interested in some unique part of it. Patterns use regex to extract the desired output!
Query Messages¶
Query Messages are very similar to signals in that they contain instructions to retrieve information from something. The main difference is that a single query may return multiple values of interest. These values of interest are represented as individual signals within the larger payload of the message query.
For example, a query such as temp info
maybe retrieve a message that looks like:
> temp info
Temperature Info
Ambient: 25.5
CPU: 47.3
GPU: 50.1
>
Schema Components¶
Basic Settings¶
These settings define the fundamental behavior and properties of the SerialCodec
.
Field | Type | Default | Description |
---|---|---|---|
encoding |
string | "utf-8" | Character encoding for communication. Specifies how text data is encoded during transmission. Common values are "utf-8", "ascii", etc. |
prompt_pattern |
string | None | A regular expression pattern that the codec uses to recognize the readiness of the device to accept commands. This is crucial for syncing communication. Example: "^>", which matches a line starting with '>'. Optional but recommended for reliable communication. |
prompt_timeout_s |
integer | 1 | The maximum time in seconds the codec will wait for the prompt pattern to appear in the device's response. This timeout helps in handling cases where the device is unresponsive or slow. |
cmd_termination |
string | "\r\n" | Characters that are appended to the end of every command sent to the device. It signifies the end of a command. Common values are "\r\n" (carriage return and newline) and "\n" (newline). |
query_termination |
string | "\r\n" | Similar to cmd_termination , but for query commands. This tells the device that the end of the query has been reached. |
Field | Type | Required | Description |
---|---|---|---|
signals |
dict | Yes | Dictionary of signal names and their configurations. |
Signal Configuration¶
Field | Type | Description |
---|---|---|
cmd |
string | Command to be sent. |
query |
string or dict | Query command, or dictionary with command and pattern. |
data_type |
string | Type of data expected in response (e.g., "float", "int", "string"). |
timeout_s |
integer | Timeout in seconds for the signal. |
Messages¶
Messages are collections of signals sent via a single query.
Field | Type | Description |
---|---|---|
messages |
dict | Dictionary of message names and configurations. |
Message Configuration¶
Field | Type | Description |
---|---|---|
query |
string or dict | Query command or dictionary containing command and pattern. |
data_type |
string | Type of data expected in response. |
timeout_s |
integer | Timeout in seconds for the message. |
sub_signals |
dict | Additional signals within the message, with patterns and data types. |
Example Configuration¶
cli.yml¶
# NOTE: This is meant to serve as an example configuration for a serial codec.
# More information about the attributes and schema in this file can be found in the docs:
# https://docs.zeloscloud.io/py/codecs/serial/serial-schema/
encoding: "utf-8"
prompt_pattern: '\x1b\[[0-9;]*muart:~\$ \x1b\[[0-9;]*m$' # Example zephyr-shell prompt pattern -> 'uart:~$'
prompt_timeout_s: 2
echo: True
cmd_termination: "\r\n"
query_termination: "\r\n"
signals:
# This is an example CmdSignal. It contains only a command, no query
device_restart:
cmd: "restart now"
# This is an example CmdSignal that takes a value. It uses format specifiers to determine
# where the command you want to place the value. Additionally, you send multiple values -> "led {} {}"
led_enable:
cmd: "led enable {}"
# This is an example QuerySignal. It contains only a query, no command
wifi_status:
query: "status get wifi"
# This will convert the decoded response to a int. You can do this for any signal
data_type: int
# This is an example QuerySignal with pattern matching. It contains only a query and a regex pattern.
device_uptime:
query:
cmd: "uptime get"
pattern: (\\d+\\.\\d+\\.\\d+)"
# This is an example CmdQuerySignal. It contains both a command and a query.
wifi_psk:
cmd: "settings set wifi/psk {}"
query: "settings get wifi/psk"
# This is an example CmdQuerySignal. It contains both a command and a query, with pattern matching.
hardware_revision:
cmd: "hwrev set {}"
query:
cmd: "hwrev get"
pattern: "(?<=Current hardware revision: ).*"
# These define messages that can contain multiple points of interest
messages:
# Message example: Contains multiple signals
device_info:
query: "info get all"
signals:
firmware_version:
pattern: "Firmware: (\\d+\\.\\d+\\.\\d+)"
battery_level:
pattern: "Battery: (\\d+\\.\\d+)%"
# This will convert the decoded response to a float. You can do this for each signal
data_type: float
Format Strings
You may set multiple values for a command by adding multiple {}
in to the cmd
. When setting this data, you would send the data ordered as a tuple like such: codec.signal.set((1,2,3))
.
Examples transactions Link¶
Message: Device Information¶
- Query Sent:
"info get all\r\n"
- Response:
"Device Info: Firmware: 1.2.3, Battery: 80.0%"
- Signal Data Parsed:
firmware_version
: "1.2.3"battery_level
: 80.0
Signal Data Types¶
The SerialCodec
schema supports the use of custom data types for parsing the data returned by signals.
The data_type
field in a signal's configuration can reference any data type that can be resolved by Python's pydoc.locate
. This function dynamically locates a Python object by its name and returns the object itself, allowing you to use built-in types (like int
, float
, str
) as well as custom or third-party types.
Utilizing Built-In types¶
For example, if a device returns a float string in response to a query, you can use float
to parse this response:
signals:
device_temperature:
query: "device temperature"
data_type: float
If a device returns a JSON string in response to a query, you can use json.loads
to parse this response and covert to a json dict object:
signals:
device_status:
query: "status get"
data_type: json.loads
Utilizing Custom types¶
Example:¶
Suppose you have a custom data type defined in your project:
# In my_custom_types.py
class CustomDataType:
def __init__(self, value):
# Custom initialization logic
self.value = value
# Custom methods or properties
You can use CustomDataType
as a data_type
in your schema:
signals:
custom_signal:
query: "get custom data"
data_type: "my_custom_types.CustomDataType"
In this example, when custom_signal
receives data, the SerialCodec
will use CustomDataType
to parse and represent this data.