rpc — biblioteka rpc¶
Moduł rpc w OpenMV Cam pozwala połączyć OpenMV Cam z innym mikrokontrolerem lub komputerem i wykonywać zdalne wywołania pythona (lub procedur) na OpenMV Cam. Moduł rpc umożliwia również działanie w odwrotną stronę, jeśli chcesz, aby OpenMV Cam mógł wykonywać zdalne wywołania procedur (lub pythona) na innym mikrokontrolerze lub komputerze.
Jak korzystać z biblioteki¶
Minimalny slave, który udostępnia jedno wywołanie zwrotne przez 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.
Pasujący master, który prosi slave o ramkę 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")
Zamień rpc_uart_master / rpc_uart_slave na pasującą parę can, i2c lub spi, aby użyć innego transportu.
Ogólnie rzecz biorąc, aby urządzenie sterujące mogło korzystać z biblioteki rpc, utworzysz obiekt interfejsu przy użyciu biblioteki rpc. Na przykład:
interface = rpc.rpc_uart_master(baudrate=115200)
Tworzy to interfejs UART do komunikacji ze slave rpc.
Po utworzeniu interfejsu wystarczy wykonać:
memory_view_object_result = interface.call("remote_function_or_method_name", bytes_object_argument)
A biblioteka rpc spróbuje wykonać tę "remote_function_or_method_name" na slave. Zdalna funkcja lub metoda otrzyma bytes_object_argument, który może mieć rozmiar do 2^32-1 bajtów. Po zakończeniu wykonywania zdalna metoda zwróci memory_view_object_result, który również może mieć rozmiar do 2^32-1 bajtów. Ponieważ zarówno argument, jak i odpowiedź są ogólnymi kontenerami bajtów, możesz przekazać dowolne dane przez bibliotekę rpc i otrzymać dowolny typ odpowiedzi. Prostym sposobem przekazywania argumentów jest użycie struct.pack() do utworzenia argumentu oraz struct.unpack() do odebrania argumentu po drugiej stronie. W przypadku odpowiedzi druga strona może wysłać jako wynik obiekt łańcuchowy lub łańcuch json, który master może następnie zinterpretować.
Jeśli chodzi o błędy, jeśli spróbujesz wykonać nieistniejącą nazwę funkcji lub metody, metoda rpc_master.call() zwróci pusty obiekt bytes(). Jeśli bibliotece rpc nie uda się nawiązać komunikacji ze slave, biblioteka rpc zwróci None.
Aby wszystko było proste, biblioteka rpc nie utrzymuje połączenia między urządzeniami master i slave. Metoda rpc_master.call() obejmuje próbę połączenia ze slave, rozpoczęcie wykonywania zdalnej funkcji lub metody oraz pobranie wyniku.
Teraz po stronie slave musisz utworzyć interfejs rpc do komunikacji z masterem. Wygląda to tak:
interface = rpc.rpc_uart_slave(baudrate=115200)
Tworzy to warstwę interfejsu UART do komunikacji z masterem rpc.
Po utworzeniu interfejsu slave musisz zarejestrować wywołania zwrotne, które master może wywołać przy użyciu obiektu interfejsu:
def remote_function_or_method_name(memoryview_object_argument):
<lots of code>
return bytes_object_result
interface.register_callback(remote_function_or_method_name)
Na slave możesz zarejestrować dowolną liczbę wywołań zwrotnych. Na koniec, gdy zakończysz rejestrowanie wywołań zwrotnych, wystarczy wykonać:
interface.loop()
Na slave, aby uruchomić bibliotekę rpc i rozpocząć nasłuchiwanie mastera. Zwróć uwagę, że metoda rpc_slave.loop() nie zwraca sterowania.
klasa rpc – klasa bazowa rpc¶
Klasa bazowa rpc jest reimplementowana przez klasy rpc_master i rpc_slave w celu utworzenia interfejsów master i slave. Nie jest przeznaczona do bezpośredniego użycia.
- class rpc.rpc¶
Tworzy obiekt
rpc. Nie jest przeznaczony do bezpośredniego użycia.- get_bytes(buff: bytearray | memoryview, timeout_ms: int) bytes | None¶
Reimplementowana przez podklasy specyficzne dla transportu. Wypełnia
buffbajtami z bazowego interfejsu w ciągutimeout_msmilisekund. ZwracaNonepo przekroczeniu limitu czasu.
- put_bytes(data: bytes | memoryview, timeout_ms: int) None¶
Reimplementowana przez podklasy specyficzne dla transportu. Wysyła
dataprzez bazowy interfejs w ciągutimeout_msmilisekund.
- stream_reader(call_back: Callable[[memoryview], None], queue_depth: int = 1, read_timeout_ms: int = 5000) None¶
Odbiera strumień ładunków od zdalnego
rpc.stream_writer. Powinna być wywoływana wewnątrz wywołania zwrotnegorpc_slave(lub bezpośrednio po pomyślnymrpc_master.call), gdy obie strony są zsynchronizowane.call_back– obiekt wywoływalny wywoływany raz na każdy odebrany ładunek jakocall_back(data), gdziedatatomemoryview. Wartość zwracana jest ignorowana.queue_depth– liczba ramek w locie, które writer może wysłać przed oczekiwaniem na readera. Wyższe wartości zwiększają przepustowość kosztem pamięci.read_timeout_ms– liczba milisekund oczekiwania na każdy ładunek.
Zwraca sterowanie przy dowolnym błędzie. Aby anulować, zgłoś wyjątek wewnątrz
call_back; zdalna strona przekroczy limit czasu.
- stream_writer(call_back: Callable[[], bytes | memoryview], write_timeout_ms: int = 5000) None¶
Wysyła strumień ładunków do zdalnego
rpc.stream_reader. Powinna być wywoływana wewnątrz wywołania zwrotnegorpc_slave(lub bezpośrednio po pomyślnymrpc_master.call), gdy obie strony są zsynchronizowane.call_back– obiekt wywoływalny wywoływany bez argumentów, który zwraca następny ładunekbyteslubmemoryviewdo wysłania.write_timeout_ms– liczba milisekund oczekiwania przy wysyłaniu każdego ładunku.
Zwraca sterowanie przy dowolnym błędzie. Aby anulować, zgłoś wyjątek wewnątrz
call_back; zdalna strona przekroczy limit czasu.
klasa rpc_master – klasa bazowa rpc_master¶
rpc_master jest klasą bazową. Użyj jednej z podklas specyficznych dla transportu (rpc_can_master, rpc_i2c_master, rpc_spi_master, rpc_uart_master).
- class rpc.rpc_master¶
Tworzy obiekt
rpc_master. Nie jest przeznaczony do bezpośredniego użycia.- call(name: str, data: bytes = bytes(), send_timeout: int = 1000, recv_timeout: int = 1000) memoryview | None¶
Wykonuje zdalne wywołanie na urządzeniu slave.
name– łańcuchowa nazwa zdalnej funkcji lub metody do wykonania.data– obiekt typubytesprzekazywany jako argument do zdalnej funkcji.send_timeout– liczba milisekund oczekiwania podczas łączenia się ze slave i rozpoczynania wykonywania zdalnej funkcji. Gdy master rozpocznie wysyłanie argumentu, ta wartość przestaje obowiązywać; biblioteka pozwala na maksymalnie 5 sekund na transfer argumentu.recv_timeout– liczba milisekund oczekiwania, aż slave zacznie zwracać odpowiedź. Gdy master rozpocznie odbieranie odpowiedzi, ta wartość przestaje obowiązywać; biblioteka pozwala na maksymalnie 5 sekund na transfer odpowiedzi.
Zwraca
memoryviewodpowiedzi w przypadku powodzenia, pustybytes(), jeśli zdalna nazwa nie istnieje na slave, lubNonew przypadku niepowodzenia komunikacji.
klasa rpc_slave – klasa bazowa rpc_slave¶
rpc_slave jest klasą bazową. Użyj jednej z podklas specyficznych dla transportu (rpc_can_slave, rpc_i2c_slave, rpc_spi_slave, rpc_uart_slave).
- class rpc.rpc_slave¶
Tworzy obiekt
rpc_slave. Nie jest przeznaczony do bezpośredniego użycia.- register_callback(cb: Callable[[memoryview], bytes | memoryview]) None¶
Rejestruje wywołanie zwrotne, które master może wywołać po nazwie.
cbto obiekt wywoływalny przyjmujący jeden argumentmemoryviewi zwracający obiekt typubytes. Jako klucz wyszukiwania używane jest__name__wywołania zwrotnego.
- schedule_callback(cb: Callable[[], None]) None¶
Planuje jednorazowe wykonanie
cb(obiektu wywoływalnego nieprzyjmującego argumentów), bezpośrednio po tym, jak aktualnie działające wywołanie zwrotne rpc pomyślnie zwróci swoją odpowiedź do mastera. Musi być wywoływana wewnątrz wywołania zwrotnego rpc. Pozwala na uruchamianie długotrwałych zadań lub transferów typu cut-throughrpc.get_bytes/rpc.put_bytespomiędzy transakcjami rpc. Jeśli wymagane jest powtarzane wykonywanie, zarejestruj ponownie przy każdym wywołaniu.
- setup_loop_callback(cb: Callable[[], None]) None¶
Rejestruje
cb(obiekt wywoływalny nieprzyjmujący argumentów), który ma być wywoływany przy każdej iteracjirpc_slave.loop. W przeciwieństwie dorpc_slave.schedule_callback, to wywołanie zwrotne pozostaje zarejestrowane. Musi być nieblokujące; częstotliwość wywołań jest zmienna.
- loop(recv_timeout: int = 1000, send_timeout: int = 1000) None¶
Uruchamia pętlę dyspozytora slave rpc. Nie zwraca sterowania, chyba że wyjątek zostanie zgłoszony z wywołania zwrotnego.
recv_timeout– liczba milisekund oczekiwania na polecenie od mastera przed ponowieniem próby.send_timeout– liczba milisekund oczekiwania, aż master potwierdzi odpowiedź, przed powrotem do odbioru.
klasa rpc_can_master – interfejs master CAN¶
Steruj innym urządzeniem rpc przez CAN.
- class rpc.rpc_can_master(message_id: int = 0x7FF, bit_rate: int = 250000, sample_point: float = 75, can_bus: int = 2)¶
message_id– 11-bitowy identyfikator wiadomości CAN używany do transportu danych.bit_rate– szybkość transmisji bitów CAN w bitach na sekundę.sample_point– procentowy punkt próbkowania Tseg1/Tseg2 (np. 50.0, 62.5, 75, 87.5).can_bus– numer urządzenia peryferyjnego CAN.
message_idibit_ratemastera i slave muszą się zgadzać. Magistrala musi być zakończona rezystorem 120 omów.
klasa rpc_can_slave – interfejs slave CAN¶
Bądź sterowany przez inne urządzenie rpc przez CAN.
klasa rpc_i2c_master – interfejs master I2C¶
Steruj innym urządzeniem rpc przez I2C.
- class rpc.rpc_i2c_master(slave_addr: int = 0x12, rate: int = 100000, i2c_bus: int = 2)¶
slave_addr– 7-bitowy adres I2C urządzenia slave.rate– częstotliwość zegara magistrali I2C w Hz.i2c_bus– numer urządzenia peryferyjnego I2C.
Adresy mastera i slave muszą się zgadzać. Wymagane są zewnętrzne rezystory podciągające na SCL i SDA, a oba urządzenia muszą mieć wspólną masę.
klasa rpc_i2c_slave – interfejs slave I2C¶
Bądź sterowany przez inne urządzenie rpc przez I2C.
klasa rpc_spi_master – interfejs master SPI¶
Steruj innym urządzeniem rpc przez 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– nazwa pinu chip-select.freq– częstotliwość zegara magistrali SPI w Hz.clk_polarity– poziom zegara w stanie spoczynku (0 lub 1).clk_phase– próbkowanie danych na pierwszym (0) lub drugim (1) zboczu zegara.spi_bus– numer urządzenia peryferyjnego SPI.
Ustawienia mastera i slave muszą się zgadzać. Połącz bezpośrednio CS, SCLK, MOSI, MISO. Oba urządzenia muszą mieć wspólną masę.
klasa rpc_spi_slave – interfejs slave SPI¶
Bądź sterowany przez inne urządzenie rpc przez SPI.
- class rpc.rpc_spi_slave(cs_pin: str = 'P3', clk_polarity: int = 1, clk_phase: int = 0, spi_bus: int = 2)¶
cs_pin– nazwa wejściowego pinu chip-select.clk_polarity– poziom zegara w stanie spoczynku (0 lub 1).clk_phase– próbkowanie danych na pierwszym (0) lub drugim (1) zboczu zegara.spi_bus– numer urządzenia peryferyjnego SPI.
klasa rpc_uart_master – interfejs master UART¶
Steruj innym urządzeniem rpc przez asynchroniczny port szeregowy (UART).
- class rpc.rpc_uart_master(baudrate: int = 9600, uart_port: int = 3)¶
baudrate– szybkość transmisji szeregowej (baud).uart_port– numer urządzenia peryferyjnego UART.
Szybkości transmisji (baud) mastera i slave muszą się zgadzać. Połącz TX mastera z RX slave oraz RX mastera z TX slave. Oba urządzenia muszą mieć wspólną masę.
klasa rpc_uart_slave – interfejs slave UART¶
Bądź sterowany przez inne urządzenie rpc przez asynchroniczny port szeregowy (UART).