rpc — biblioteca rpc¶
El módulo rpc de la OpenMV Cam le permite conectar su OpenMV Cam a otro microcontrolador o computadora y ejecutar llamadas remotas de python (o procedimientos) en su OpenMV Cam. El módulo rpc también permite hacerlo a la inversa si desea que su OpenMV Cam pueda ejecutar llamadas a procedimientos remotos (o python) en otro microcontrolador o computadora.
Cómo usar la biblioteca¶
Un esclavo mínimo que expone una función de retorno (callback) a través de UART:
import rpc
import csi
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
interface = rpc.rpc_uart_slave(baudrate=115200)
def snapshot(_):
return csi0.snapshot().compress().bytearray()
interface.register_callback(snapshot)
interface.loop() # Does not return.
El maestro correspondiente que solicita al esclavo un fotograma JPEG:
import rpc
interface = rpc.rpc_uart_master(baudrate=115200)
result = interface.call("snapshot")
if result is None:
print("communication failed")
elif len(result) == 0:
print("remote function not registered on the slave")
else:
# result is a memoryview of the JPEG bytes returned by the slave.
print("received", len(result), "bytes")
Intercambie rpc_uart_master / rpc_uart_slave por el par can, i2c o spi correspondiente para usar un transporte distinto.
En general, para que el dispositivo controlador use la biblioteca rpc deberá crear un objeto de interfaz mediante la biblioteca rpc. Por ejemplo:
interface = rpc.rpc_uart_master(baudrate=115200)
Esto crea una interfaz UART para comunicarse con un esclavo rpc.
Una vez creada la interfaz solo necesita hacer:
memory_view_object_result = interface.call("remote_function_or_method_name", bytes_object_argument)
Y la biblioteca rpc intentará ejecutar ese "remote_function_or_method_name" en el esclavo. La función o método remoto recibirá el bytes_object_argument, que puede tener un tamaño de hasta 2^32-1 bytes. Una vez que el método remoto termine de ejecutarse devolverá un memory_view_object_result, que también puede tener hasta 2^32-1 bytes de tamaño. Dado que tanto el argumento como la respuesta son contenedores genéricos de bytes, puede pasar cualquier cosa a través de la biblioteca rpc y recibir cualquier tipo de respuesta. Una forma sencilla de pasar argumentos es usar struct.pack() para crear el argumento y struct.unpack() para recibir el argumento en el otro lado. En cuanto a la respuesta, el otro lado puede enviar un objeto de cadena o una cadena json como resultado, que el maestro puede luego interpretar.
En cuanto a los errores, si intenta ejecutar un nombre de función o método inexistente, el método rpc_master.call() devolverá un objeto bytes() vacío. Si la biblioteca rpc no logró comunicarse con el esclavo, la biblioteca rpc devolverá None.
Para mantener la simplicidad, la biblioteca rpc no mantiene una conexión entre los dispositivos maestro y esclavo. El método rpc_master.call() encapsula el intento de conectarse al esclavo, el inicio de la ejecución de la función o método remoto y la obtención del resultado.
Ahora, del lado del esclavo debe crear una interfaz rpc para comunicarse con el maestro. Esto se ve así:
interface = rpc.rpc_uart_slave(baudrate=115200)
Esto creará la capa de interfaz UART para comunicarse con un maestro rpc.
Una vez que cree la interfaz del esclavo, deberá registrar funciones de retorno (callbacks) que el maestro pueda llamar mediante el objeto de interfaz:
def remote_function_or_method_name(memoryview_object_argument):
<lots of code>
return bytes_object_result
interface.register_callback(remote_function_or_method_name)
Puede registrar tantas funciones de retorno (callbacks) como desee en el esclavo. Finalmente, una vez que haya terminado de registrar las funciones de retorno, solo necesita ejecutar:
interface.loop()
En el esclavo, para iniciar la biblioteca rpc y comenzar a escuchar al maestro. Tenga en cuenta que el método rpc_slave.loop() no retorna.
class rpc – clase base rpc¶
La clase base rpc es reimplementada por las clases rpc_master y rpc_slave para crear las interfaces maestro y esclavo. No está pensada para usarse directamente.
- class rpc.rpc¶
Crea un objeto
rpc. No está pensado para usarse directamente.- get_bytes(buff: bytearray | memoryview, timeout_ms: int) bytes | None¶
Reimplementado por subclases específicas de transporte. Rellena
buffcon bytes de la interfaz subyacente dentro detimeout_msmilisegundos. DevuelveNonesi se agota el tiempo de espera.
- put_bytes(data: bytes | memoryview, timeout_ms: int) None¶
Reimplementado por subclases específicas de transporte. Envía
dataa través de la interfaz subyacente dentro detimeout_msmilisegundos.
- stream_reader(call_back: Callable[[memoryview], None], queue_depth: int = 1, read_timeout_ms: int = 5000) None¶
Recibe un flujo de cargas útiles desde un
rpc.stream_writerremoto. Debe llamarse desde dentro de una función de retorno derpc_slave(o directamente después de una llamadarpc_master.callexitosa) una vez que ambos lados se hayan sincronizado.call_back– objeto invocable llamado una vez por cada carga útil recibida comocall_back(data), dondedataes unmemoryview. El valor de retorno se ignora.queue_depth– número de fotogramas en tránsito que el escritor puede enviar antes de esperar al lector. Valores más altos aumentan el rendimiento a costa de memoria.read_timeout_ms– milisegundos a esperar por cada carga útil.
Retorna ante cualquier error. Para cancelar, lance una excepción dentro de
call_back; el lado remoto agotará el tiempo de espera.
- stream_writer(call_back: Callable[[], bytes | memoryview], write_timeout_ms: int = 5000) None¶
Envía un flujo de cargas útiles a un
rpc.stream_readerremoto. Debe llamarse desde dentro de una función de retorno derpc_slave(o directamente después de una llamadarpc_master.callexitosa) una vez que ambos lados se hayan sincronizado.call_back– objeto invocable llamado sin argumentos que devuelve la siguiente carga útilbytesomemoryviewa enviar.write_timeout_ms– milisegundos a esperar al enviar cada carga útil.
Retorna ante cualquier error. Para cancelar, lance una excepción dentro de
call_back; el lado remoto agotará el tiempo de espera.
class rpc_master – clase base rpc_master¶
rpc_master es una clase base. Use una de las subclases específicas de transporte (rpc_can_master, rpc_i2c_master, rpc_spi_master, rpc_uart_master).
- class rpc.rpc_master¶
Crea un objeto
rpc_master. No está pensado para usarse directamente.- call(name: str, data: bytes = bytes(), send_timeout: int = 1000, recv_timeout: int = 1000) memoryview | None¶
Ejecuta una llamada remota en el dispositivo esclavo.
name– nombre en forma de cadena de la función o método remoto a ejecutar.data– objeto de tipobytesque se pasa como argumento a la función remota.send_timeout– milisegundos a esperar mientras se conecta al esclavo y se inicia la ejecución de la función remota. Una vez que el maestro comienza a enviar el argumento esto deja de aplicar; la biblioteca permite hasta 5 segundos para la transferencia del argumento.recv_timeout– milisegundos a esperar a que el esclavo comience a devolver una respuesta. Una vez que el maestro comienza a recibir la respuesta esto deja de aplicar; la biblioteca permite hasta 5 segundos para la transferencia de la respuesta.
Devuelve un
memoryviewde la respuesta en caso de éxito, unbytes()vacío si el nombre remoto no existe en el esclavo, oNonesi falla la comunicación.
class rpc_slave – clase base rpc_slave¶
rpc_slave es una clase base. Use una de las subclases específicas de transporte (rpc_can_slave, rpc_i2c_slave, rpc_spi_slave, rpc_uart_slave).
- class rpc.rpc_slave¶
Crea un objeto
rpc_slave. No está pensado para usarse directamente.- register_callback(cb: Callable[[memoryview], bytes | memoryview]) None¶
Registra una función de retorno (callback) que el maestro puede invocar por nombre.
cbes un objeto invocable que toma un argumentomemoryviewy devuelve un objeto de tipobytes. El__name__de la función de retorno se usa como clave de búsqueda.
- schedule_callback(cb: Callable[[], None]) None¶
Programa
cb(un objeto invocable que no toma argumentos) para que se ejecute una vez, inmediatamente después de que la función de retorno rpc actualmente en ejecución devuelva correctamente su respuesta al maestro. Debe llamarse desde dentro de una función de retorno rpc. Permite que un trabajo de larga duración o transferencias de paso directorpc.get_bytes/rpc.put_bytesse ejecuten entre transacciones rpc. Vuelva a registrarla en cada invocación si se requiere su ejecución repetida.
- setup_loop_callback(cb: Callable[[], None]) None¶
Registra
cb(un objeto invocable que no toma argumentos) para que se invoque en cada iteración derpc_slave.loop. A diferencia derpc_slave.schedule_callback, esta función de retorno permanece registrada. Debe ser no bloqueante; la frecuencia de llamada es variable.
- loop(recv_timeout: int = 1000, send_timeout: int = 1000) None¶
Ejecuta el bucle de despacho del esclavo rpc. No retorna salvo por una excepción lanzada desde una función de retorno.
recv_timeout– milisegundos a esperar por un comando del maestro antes de reintentar.send_timeout– milisegundos a esperar a que el maestro confirme la respuesta antes de volver a recibir.
class rpc_can_master – Interfaz Maestro CAN¶
Controla otro dispositivo rpc a través de CAN.
- class rpc.rpc_can_master(message_id: int = 0x7FF, bit_rate: int = 250000, sample_point: float = 75, can_bus: int = 2)¶
message_id– id de mensaje CAN de 11 bits usado para el transporte de datos.bit_rate– tasa de bits CAN en bits por segundo.sample_point– porcentaje del punto de muestreo Tseg1/Tseg2 (p. ej. 50.0, 62.5, 75, 87.5).can_bus– número de periférico CAN.
El
message_idy elbit_ratedel maestro y del esclavo deben coincidir. El bus debe terminarse con 120 ohmios.
class rpc_can_slave – Interfaz Esclavo CAN¶
Ser controlado por otro dispositivo rpc a través de CAN.
class rpc_i2c_master – Interfaz Maestro I2C¶
Controla otro dispositivo rpc a través de I2C.
- class rpc.rpc_i2c_master(slave_addr: int = 0x12, rate: int = 100000, i2c_bus: int = 2)¶
slave_addr– dirección I2C de 7 bits del dispositivo esclavo.rate– frecuencia de reloj del bus I2C en Hz.i2c_bus– número de periférico I2C.
Las direcciones del maestro y del esclavo deben coincidir. Se requieren resistencias pull-up externas en SCL y SDA, y ambos dispositivos deben compartir una masa común.
class rpc_i2c_slave – Interfaz Esclavo I2C¶
Ser controlado por otro dispositivo rpc a través de I2C.
class rpc_spi_master – Interfaz Maestro SPI¶
Controla otro dispositivo rpc a través de SPI.
- class rpc.rpc_spi_master(cs_pin: str = 'P3', freq: int = 1000000, clk_polarity: int = 1, clk_phase: int = 0, spi_bus: int = 2)¶
cs_pin– nombre del pin de selección de chip (chip-select).freq– frecuencia de reloj del bus SPI en Hz.clk_polarity– nivel de reloj en reposo (0 o 1).clk_phase– muestrea los datos en el primer (0) o segundo (1) flanco de reloj.spi_bus– número de periférico SPI.
Los ajustes del maestro y del esclavo deben coincidir. Conecte CS, SCLK, MOSI, MISO directamente. Ambos dispositivos deben compartir una masa común.
class rpc_spi_slave – Interfaz Esclavo SPI¶
Ser controlado por otro dispositivo rpc a través de SPI.
- class rpc.rpc_spi_slave(cs_pin: str = 'P3', clk_polarity: int = 1, clk_phase: int = 0, spi_bus: int = 2)¶
cs_pin– nombre del pin de entrada de selección de chip (chip-select).clk_polarity– nivel de reloj en reposo (0 o 1).clk_phase– muestrea los datos en el primer (0) o segundo (1) flanco de reloj.spi_bus– número de periférico SPI.
class rpc_uart_master – Interfaz Maestro UART¶
Controla otro dispositivo rpc a través de serie asíncrona (UART).
- class rpc.rpc_uart_master(baudrate: int = 9600, uart_port: int = 3)¶
baudrate– velocidad en baudios serie.uart_port– número de periférico UART.
Las velocidades en baudios del maestro y del esclavo deben coincidir. Conecte el TX del maestro al RX del esclavo y el RX del maestro al TX del esclavo. Ambos dispositivos deben compartir una masa común.
class rpc_uart_slave – Interfaz Esclavo UART¶
Ser controlado por otro dispositivo rpc a través de serie asíncrona (UART).