Detailed contiuation of uartremote.py library README.md
When a command with its accompanying values is transmitted over the Uart, the following packet format is used:
| delimiter | total len | command len | command | format len | format | data | delimiter |
|---|---|---|---|---|---|---|---|
< |
ln |
lc |
cmd |
lf |
f |
binary data | > |
with
lnthe length of the total packet encoded as a single byte,lcthe length of the command string<cmd>as a single byte,cmdthe command specified as a string,lfthe length of the format stringfthe Format encapsulation to pack the values; This can bereprfor encapsulating arbitrary objects,rawfor no encapsulation, or a Python struct format string.dataa number of values encapsulated according tof.
When the method
ur.send_command('test','repr',[1,2,3,4,5])
is used, the following packet will be transmitted over the line:
b'<b'\x1c\x04test\x04repr([1, 2, 3, 4, 5],)>'
This option interpretes the Format string f as the format string of the struct.pack/unpack method (see https://docs.python.org/3/library/struct.html), for example
send_command('test_struct','3b3s1f',1,2,3,"ale",1.3).
This is the fastest method (1ms) but is limited to c-types, like int, unsigned int etc...
This uses the string representation of data, repr() to encode it. Then eval() is used on the receiving end.
ur.encode('test_command', 'repr', [[1,2],[3,4]])
will be encoded as:
b'%\x0ctest_command\x04repr([[1, 2], [3, 4]],)'
Here's the power of repr:
ur.encode('test_command','repr',[[1,2],[3,str],[len,True],[2+3]])
becomes
b"W\x0ctest_command\x04repr([[1, 2], [3, <class 'str'>], [<built-in function len>, True], [5]],)"
This is slower (7ms) and incompatible with Arduino but it is more flexible.
This is the fastest option of all, but you'll have to do your own decoding/encoding.
ur.encode('test_command','raw',b'abcd')
is encoded as:
b'\x15\x0ctest_command\x03rawabcd'
The call method allows the Master to send a command to the Slave. When no values need to be passed with the command, the <type> and <data> can be omitted. The <data> can be a single value, a string or a list of values.
The Slave acknowledges a command by sending back an acknowledge command, where the string ack is appended to the command, and return values of the function being called are sent back. When an error occurs, the <cmd> that is sent back, contains err and the value is the type of error.
The type of <data> is given according to the struct Format characters, of which the most commonly used are shown below:
| Format character | type | number of bytes |
|---|---|---|
b |
byte | 1 |
B |
unsigned byte | 1 |
i |
int | 4 |
I |
unsigned int | 4 |
f |
float | 4 |
d |
double | 8 |
s |
string[] | one per char |
example:
ur.call('mycommand','bb3sb',-3,-2,"aha",120)
Note that struct DOES NOT decode utf-8. You will always get a bytestring on the other side. It uses about 1ms to encode/decode.
repr: use for a pickle-like serialized string encoding/decodingraw: skip encoding altogether and just pas one raw byte string.
example:
ur.call('mycommand','repr',[[12,34],[56,78]],"tekst",(1,2,3))
This will get all the python types across, but uses about 7ms to encode/decode.
ur.call('mycommand','raw',b"Raw byte string")
If the encoder fails it resorts to raw bytes by default.
Constructs a Uart communication class for Uart port port. Baudrate and timeout definitions for the Uart port can be changed. The boolean debug allows for debugging this class. For the SPIKE prime the port can be abbreviated as a single character string "A".
Flushes the read buffer, by reading all remaining bytes from the Uart.
Return a non zero value if there is a received command available. Note: on the SPIKE prime, you should use the receive_command or the execute_command, always with the parameter reply=False, after using the available() method.
Sends a command command. When t and data are omitted, the corresponding function on the Slave is called with no arguments. Otherwise,data is encoded as type t, where command is a string and data is a string or a list of values, or multiple values.
Receives a command and returns a tuple (<command>, <data>). If there is a failure, the <command> will be equal to 'err'. If wait is True, the methods waits until it receives a command.
Combines the send and receive functions as defined above. When t and data are omitted, a dummy value \x00 of type z will be send. The parameter data can be a string, a single value or a list of values.
If wait is True, this medthods Waits for the reception of a command, otherwise, it immediately starts receiving a command. Is the flasg check is True, it checks for errors or for an ack of onother command. It then calls the function corresponding with the received command (prior set by add_command) and sends back the result of the executed function.
Loops the UartRemote.wait-for_command() command.
Adds a command command to the dictionary of UartRemote.commands together with a function name command_function. Optionally, if the command_function returns parameters, the format_string describes the type of the returned parameters. If the command_function does not return a value, the format_string is omirted. The dictionary with commands is used by the UartRemote.wait_for_command() method to call the function as defined upon receiving a specific command. As an argument the data that is received is used.
This command send a command to the other side instructing it to import the module with name module_name. The module_name argument has type string. After importing the module, the remote side calls the function <module>.add_commands(). This is a function that you should add to the modules you want to remotely import. continued here
This command returns an array containing the commands available by the remote uartremote. You will see a number of default built-in commands such as echo. This method can be used to query the commands that are added by remotely importing a new module. continued here