rpc — бібліотека rpc¶
Модуль rpc на OpenMV Cam дозволяє підключити OpenMV Cam до іншого мікроконтролера або комп’ютера та виконувати віддалені виклики Python (або процедур) на OpenMV Cam. Модуль rpc також підтримує зворотний напрямок — якщо потрібно, щоб OpenMV Cam виконував віддалені виклики процедур (або Python) на іншому мікроконтролері чи комп’ютері.
Як користуватися бібліотекою¶
Мінімальний підлеглий (slave), що відкриває один зворотний виклик через 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.
Відповідний головний (master), що запитує у підлеглого кадр 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")
Замініть rpc_uart_master / rpc_uart_slave відповідною парою can, i2c або spi, щоб використати інший транспорт.
Загалом, щоб пристрій-контролер використовував бібліотеку rpc, потрібно створити об’єкт інтерфейсу за допомогою бібліотеки rpc. Наприклад:
interface = rpc.rpc_uart_master(baudrate=115200)
Це створює UART-інтерфейс для зв’язку з підлеглим rpc.
Після створення інтерфейсу достатньо виконати:
memory_view_object_result = interface.call("remote_function_or_method_name", bytes_object_argument)
Бібліотека rpc спробує виконати "remote_function_or_method_name" на підлеглому. Віддалена функція або метод отримає bytes_object_argument, розмір якого може сягати 2^32-1 байтів. Після завершення виконання віддаленого методу він поверне memory_view_object_result, що також може мати розмір до 2^32-1 байтів. Оскільки аргумент і відповідь є узагальненими байтовими контейнерами, через бібліотеку rpc можна передавати будь-які дані та отримувати будь-який тип відповіді. Простий спосіб передачі аргументів — використати struct.pack() для формування аргументу та struct.unpack() для його розпакування на іншому боці. Для відповіді інша сторона може надіслати рядковий об’єкт або рядок JSON як результат, який головний може потім інтерпретувати.
Щодо помилок: якщо спробувати виконати неіснуючу функцію або метод, метод rpc_master.call() поверне порожній об’єкт bytes(). Якщо бібліотека rpc не змогла встановити зв’язок з підлеглим, бібліотека rpc поверне None.
Для простоти бібліотека rpc не підтримує постійне з’єднання між головним і підлеглим пристроями. Метод rpc_master.call() інкапсулює спробу підключитися до підлеглого, запуск виконання віддаленої функції або методу та отримання результату.
На стороні підлеглого необхідно створити інтерфейс rpc для зв’язку з головним. Це виглядає так:
interface = rpc.rpc_uart_slave(baudrate=115200)
Це створить рівень UART-інтерфейсу для зв’язку з головним rpc.
Після створення інтерфейсу підлеглого потрібно зареєструвати зворотні виклики, які головний зможе викликати через об’єкт інтерфейсу:
def remote_function_or_method_name(memoryview_object_argument):
<lots of code>
return bytes_object_result
interface.register_callback(remote_function_or_method_name)
На підлеглому можна зареєструвати скільки завгодно зворотних викликів. Нарешті, після реєстрації всіх зворотних викликів достатньо виконати:
interface.loop()
На підлеглому, щоб запустити бібліотеку rpc та почати прослуховування головного. Зверніть увагу, що метод rpc_slave.loop() не повертається.
class rpc – базовий клас rpc¶
Базовий клас rpc перевизначається класами rpc_master і rpc_slave для створення головного та підлеглого інтерфейсів. Він не призначений для безпосереднього використання.
- class rpc.rpc¶
Створює об’єкт
rpc. Не призначений для безпосереднього використання.- get_bytes(buff: bytearray | memoryview, timeout_ms: int) bytes | None¶
Перевизначається підкласами, що відповідають за конкретний транспорт. Заповнює
buffбайтами з нижнього рівня інтерфейсу протягомtimeout_msмілісекунд. ПовертаєNoneу разі таймауту.
- put_bytes(data: bytes | memoryview, timeout_ms: int) None¶
Перевизначається підкласами, що відповідають за конкретний транспорт. Надсилає
dataчерез нижній рівень інтерфейсу протягомtimeout_msмілісекунд.
- stream_reader(call_back: Callable[[memoryview], None], queue_depth: int = 1, read_timeout_ms: int = 5000) None¶
Отримує потік корисних даних від віддаленого
rpc.stream_writer. Має викликатись всередині зворотного викликуrpc_slave(або безпосередньо після успішногоrpc_master.call), коли обидві сторони синхронізовані.call_back– викликний об’єкт, що викликається один раз для кожного отриманого корисного навантаження якcall_back(data), деdataєmemoryview. Повернуте значення ігнорується.queue_depth– кількість кадрів у польоті, які дозволено надсилати записувачу до очікування від читача. Більші значення збільшують пропускну здатність ціною пам’яті.read_timeout_ms– мілісекунди очікування для кожного корисного навантаження.
Повертається при будь-якій помилці. Щоб скасувати, підніміть виняток всередині
call_back; віддалена сторона виконає таймаут.
- stream_writer(call_back: Callable[[], bytes | memoryview], write_timeout_ms: int = 5000) None¶
Надсилає потік корисних даних до віддаленого
rpc.stream_reader. Має викликатись всередині зворотного викликуrpc_slave(або безпосередньо після успішногоrpc_master.call), коли обидві сторони синхронізовані.call_back– викликний об’єкт без аргументів, що повертає наступнийbytesабоmemoryviewдля надсилання.write_timeout_ms– мілісекунди очікування під час надсилання кожного корисного навантаження.
Повертається при будь-якій помилці. Щоб скасувати, підніміть виняток всередині
call_back; віддалена сторона виконає таймаут.
class rpc_master – базовий клас rpc_master¶
Клас rpc_master є базовим. Використовуйте один із транспортно-специфічних підкласів (rpc_can_master, rpc_i2c_master, rpc_spi_master, rpc_uart_master).
- class rpc.rpc_master¶
Створює об’єкт
rpc_master. Не призначений для безпосереднього використання.- call(name: str, data: bytes = bytes(), send_timeout: int = 1000, recv_timeout: int = 1000) memoryview | None¶
Виконує віддалений виклик на підлеглому пристрої.
name– рядкове ім’я віддаленої функції або методу для виконання.data– об’єкт, схожий наbytes, що передається як аргумент до віддаленої функції.send_timeout– мілісекунди очікування під час підключення до підлеглого та запуску виконання віддаленої функції. Після початку надсилання аргументу головним це обмеження більше не діє; бібліотека допускає до 5 секунд на передачу аргументу.recv_timeout– мілісекунди очікування початку повернення відповіді підлеглим. Після початку отримання відповіді головним це обмеження більше не діє; бібліотека допускає до 5 секунд на передачу відповіді.
Повертає
memoryviewвідповіді в разі успіху, порожнійbytes()якщо вказаного імені не існує на підлеглому, абоNoneу разі помилки зв’язку.
class rpc_slave – базовий клас rpc_slave¶
Клас rpc_slave є базовим. Використовуйте один із транспортно-специфічних підкласів (rpc_can_slave, rpc_i2c_slave, rpc_spi_slave, rpc_uart_slave).
- class rpc.rpc_slave¶
Створює об’єкт
rpc_slave. Не призначений для безпосереднього використання.- register_callback(cb: Callable[[memoryview], bytes | memoryview]) None¶
Реєструє зворотний виклик, який головний може викликати за іменем.
cb— викликний об’єкт, що приймає один аргументmemoryviewі повертає об’єкт, схожий наbytes. Атрибут__name__зворотного виклику використовується як ключ пошуку.
- schedule_callback(cb: Callable[[], None]) None¶
Планує виконання
cb(викликний об’єкт без аргументів) один раз, відразу після того, як поточний rpc-зворотний виклик успішно поверне відповідь головному. Має викликатись всередині rpc-зворотного виклику. Дозволяє виконувати тривалі операції або наскрізні передачіrpc.get_bytes/rpc.put_bytesміж rpc-транзакціями. Якщо потрібне повторне виконання, реєструйте знову при кожному виклику.
- setup_loop_callback(cb: Callable[[], None]) None¶
Реєструє
cb(викликний об’єкт без аргументів) для виклику на кожній ітераціїrpc_slave.loop. На відміну відrpc_slave.schedule_callback, цей зворотний виклик залишається зареєстрованим. Має бути неблокуючим; частота викликів є змінною.
- loop(recv_timeout: int = 1000, send_timeout: int = 1000) None¶
Запускає цикл диспетчеризації підлеглого rpc. Не повертається, якщо не буде піднято виняток з зворотного виклику.
recv_timeout– мілісекунди очікування команди від головного перед повторною спробою.send_timeout– мілісекунди очікування підтвердження відповіді від головного перед поверненням до приймання.
class rpc_can_master – Головний інтерфейс CAN¶
Керування іншим пристроєм rpc через 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-бітний ідентифікатор повідомлення CAN для транспортування даних.bit_rate– швидкість передачі CAN у бітах за секунду.sample_point– відсоток точки вибірки Tseg1/Tseg2 (наприклад, 50.0, 62.5, 75, 87.5).can_bus– номер периферійного пристрою CAN.
message_idіbit_rateголовного і підлеглого мають збігатися. Шина має бути термінована резисторами 120 Ом.
class rpc_can_slave – Підлеглий інтерфейс CAN¶
Керування від іншого пристрою rpc через CAN.
class rpc_i2c_master – Головний інтерфейс I2C¶
Керування іншим пристроєм rpc через I2C.
- class rpc.rpc_i2c_master(slave_addr: int = 0x12, rate: int = 100000, i2c_bus: int = 2)¶
slave_addr– 7-бітна адреса I2C підлеглого пристрою.rate– тактова частота шини I2C у Гц.i2c_bus– номер периферійного пристрою I2C.
Адреси головного і підлеглого мають збігатися. Необхідні зовнішні підтягуючі резистори на SCL і SDA, обидва пристрої мають мати спільну землю.
class rpc_i2c_slave – Підлеглий інтерфейс I2C¶
Керування від іншого пристрою rpc через I2C.
class rpc_spi_master – Головний інтерфейс SPI¶
Керування іншим пристроєм rpc через 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– назва виводу вибору мікросхеми (chip-select).freq– тактова частота шини SPI у Гц.clk_polarity– рівень тактового сигналу в стані спокою (0 або 1).clk_phase– вибірка даних на першому (0) або другому (1) фронті тактового сигналу.spi_bus– номер периферійного пристрою SPI.
Налаштування головного і підлеглого мають збігатися. Підключіть CS, SCLK, MOSI, MISO безпосередньо. Обидва пристрої мають мати спільну землю.
class rpc_spi_slave – Підлеглий інтерфейс SPI¶
Керування від іншого пристрою rpc через SPI.
- class rpc.rpc_spi_slave(cs_pin: str = 'P3', clk_polarity: int = 1, clk_phase: int = 0, spi_bus: int = 2)¶
cs_pin– назва вхідного виводу вибору мікросхеми (chip-select).clk_polarity– рівень тактового сигналу в стані спокою (0 або 1).clk_phase– вибірка даних на першому (0) або другому (1) фронті тактового сигналу.spi_bus– номер периферійного пристрою SPI.
class rpc_uart_master – Головний інтерфейс UART¶
Керування іншим пристроєм rpc через асинхронний послідовний порт (UART).
- class rpc.rpc_uart_master(baudrate: int = 9600, uart_port: int = 3)¶
baudrate– швидкість передачі послідовного порту (бод).uart_port– номер периферійного пристрою UART.
Швидкості передачі головного і підлеглого мають збігатися. Підключіть TX головного до RX підлеглого і RX головного до TX підлеглого. Обидва пристрої мають мати спільну землю.
class rpc_uart_slave – Підлеглий інтерфейс UART¶
Керування від іншого пристрою rpc через асинхронний послідовний порт (UART).