UartRemote Library
This library implements a class with methods that help to set up robust communication between instances running MicroPython which are connected over a UART interface.
The library is available on github: UartRemote on GitHub.
Platforms
The following platforms are supported:
Lego EV3
Lego Mindstroms Robot Inventor 51515
Lego SPIKE Prime
Espressif ESP8266
Espressif ESP32
Espressif ESP32-S2
OpenMV H7 and M7 (STM32 chipset)
MaixPy (K210 chipset)
Windows
Mac OSX
These platforms are automatically detected by querying sys.platform
. Within uartremote.py
these platforms are defined by the constants: _EV3,_SPIKE,_ESP8266,_ESP32,_ESP32_S2,_H7,_K210,_MAC,_WIN32
, respectively. There are small differences in the implementation of MicroPython for these platforms. The UartRemote
takes these into account based on the platform type.
Constructor
- class uartremote.UartRemote(port=0, baudrate=115200, timeout=1500, debug=False, rx_pin=18, tx_pin=19)
Construct a UartRemote object on the port given by:
port
identifies a port for using the UART.
port
is board specific:SPIKE: port = : has one I2S bus with id=2.
ESP8266: port = 0.
ESP32: Use 1 for UART1.
The following keyword arguments are supported on all platforms:
port
is the hardware uart port used to by UartRemote class; for LEGO it indicated the harware port, i.e. “A”baudrate
is the baudrate at which the UART communicates, defaults to 115200timeout
is the timeout (in ms) for waiting for data coming in on the UART in thereceive_command()
, default to 1500debug
is a Boolean flag to generate debug output, default to False
Only for ESP32 platform:
rx_pin
is only used for ESP32 and indicates the pin on which the UART will receive information, default to 18tx_pin
is the pin on which the UART will receive information, default to 19
Methods
- UartRemote.flush()
Flushes the read buffer, by reading all remaining bytes from the Uart.
- UartRemote.available()
Return a non zero value if there is a received command available. Note: on the SPIKE prime, you should use the
receive_command
or theexecute_command
, always with the parameterreply=False
, after using theavailable()
method.
- UartRemote.send_command(command, *type_data)
Sends a command
command
.*type_data
are a number of argument that consist of a type defintiont
, followed by one ore more variables of the type corresponding with the paramatert
.For example:
ur=UartRemote() ur.send_command('led_color','4B',n,t,g,b) # will encode a command to remotely calls the function ``led_color`` # where the values of the variables ``n,t,g,b`` are passed to that function.
- UartRemote.receive_command(wait=True)
Receives a command and returns a tuple
(<command>, <data>)
. If there is a failure, the<command>
will be equal to ‘err’. Ifwait
is True, the methods waits until it receives a command.
- UartRemote.call(command, *type_data, **kwargs)
Sends a command to a remote host that is waiting for a call and will wait until an answer comes back. Optionally a parameter
timeout=...
for the answer is self.timout, or passable as timeout=…
- UartRemote.process_uart(self, sleep=-2)
Processes a remote call if there is any. Upon receiving a remote call, the command is processed and the result is send back by internally calling the
reply_command
method. Sleeps forsleep
ms after every listen. This method is only used in a loop and is non-blocking (as not for the sleep period).
- UartRemote.reply_command(self, command, value)
Processes the received command by calling the function with name command(value) and passes the arguments as defined in
value
. The result of this function call is send back by calling thesend_command(ack_command,result)
method with with theack_command
is the received command prepended with ack_ and the result (if any) is the return value of the function formatted according to the functions format string.
- UartRemote.loop()
This is an endless loop around the
process_uart
method, replying on all incoming calls. The slave side instants typically has the following code running:from uartremote import * ur = UartRemote() ur.loop() # wait for incoming commands
- UartRemote.add_module(module_name)
Sends a command to the other side instructing it to import the module with name
module_name
. Themodule_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. See for usage Example load module.
- UartRemote.add_command(command_function, format='', name=None)
Adds a command command to the dictionary of
UartRemote.commands
together with a function namecommand_function
. Optionally, if thecommand_function
returns any parameters, theformat_string
describes the type of the returned parameters. If thecommand_function
does not return a value, the format_string is ommited. The dictionary with commands is used by theUartRemote.reply_command()
method to call the function as defined upon receiving a specific command. As an argument thedata
that is received is used.Below is an example of how to use the
add_command
method:def example(a,b): # example function receiving two arguments and returning the sum of a and b return (a+b) ur.add_command(example,'f')
Here
ur
is the instantiation of theUartRemote
class and the functionexample
will return the sum as type float.
- UartRemote.get_remote_commands()
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. See for usage Example load module.
Helper Methods
The methods below are internally called by the methods listed above. You can use these methods should you like to have more low level control.
- Uartremote.command
Dictionary with the mapping of command name to corresponding functions.
- UartRemote.encode(command, *typedata)
Encodes a command
command
.*type_data
are a number of arguments that consist of a type defintiont
, followed by one ore more variables of the type corresponding with the paramatert
.For example:
ur=UartRemote() ur.encode('led_color','4B',1,2,3,4) >>> b'\x11\tled_color\x024B\x01\x02\x03\x04'
- UartRemote.decode(bytestr)
Decodes an encoded bytestring
bytestr
as a tuple with the command and the parameters. If a command without parameters was encoded, the parameters will beNone
.For example:
ur=UartRemote() ur.decode(b'\x11\tled_color\x024B\x01\x02\x03\x04') >>> ('led_color', (1, 2, 3, 4))
- UartRemote.read_all()
Returns all bytes that are available in the UART receive buffer.
- UartRemote.force_read(self, size=1, timeout=50)
Some platforms read too fast from the UART and return 0 or None. This method loops until it receives a valid number of
size
bytes withintimeout
ms.