rpc --- thư viện rpc¶
Mô-đun rpc trên OpenMV Cam cho phép bạn kết nối OpenMV Cam với một vi điều khiển hoặc máy tính khác và thực thi các lời gọi python (hoặc thủ tục) từ xa trên OpenMV Cam. Mô-đun rpc cũng hỗ trợ chiều ngược lại, cho phép OpenMV Cam thực thi các lời gọi thủ tục (hoặc python) từ xa trên một vi điều khiển hoặc máy tính khác.
Cách sử dụng thư viện¶
Một slave tối giản để hiển thị một hàm gọi lại qua 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 tương ứng yêu cầu slave trả về một khung hình 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")
Thay rpc_uart_master / rpc_uart_slave bằng cặp can, i2c hoặc spi tương ứng để sử dụng giao thức truyền thông khác.
Nhìn chung, để thiết bị điều khiển sử dụng thư viện rpc, bạn sẽ tạo một đối tượng giao diện bằng thư viện rpc. Ví dụ:
interface = rpc.rpc_uart_master(baudrate=115200)
Lệnh này tạo một giao diện UART để giao tiếp với một slave rpc.
Sau khi tạo giao diện, bạn chỉ cần thực hiện:
memory_view_object_result = interface.call("remote_function_or_method_name", bytes_object_argument)
Thư viện rpc sẽ cố thực thi "remote_function_or_method_name" đó trên slave. Hàm hoặc phương thức từ xa sẽ nhận bytes_object_argument có kích thước lên tới 2^32-1 byte. Sau khi phương thức từ xa thực thi xong, nó sẽ trả về memory_view_object_result cũng có thể lên tới 2^32-1 byte. Vì đối số và phản hồi đều là các vùng chứa byte chung, bạn có thể truyền bất kỳ dữ liệu nào qua thư viện rpc và nhận bất kỳ kiểu phản hồi nào. Một cách đơn giản để truyền đối số là dùng struct.pack() để tạo đối số và struct.unpack() để nhận đối số ở phía kia. Phía còn lại có thể gửi một đối tượng chuỗi hoặc chuỗi json làm kết quả để master diễn giải.
Về lỗi: nếu bạn cố thực thi một tên hàm hoặc phương thức không tồn tại, phương thức rpc_master.call() sẽ trả về đối tượng bytes() rỗng. Nếu thư viện rpc không thể giao tiếp với slave, thư viện rpc sẽ trả về None.
Để đơn giản hóa, thư viện rpc không duy trì kết nối liên tục giữa thiết bị master và slave. Phương thức rpc_master.call() đóng gói quá trình kết nối đến slave, khởi động thực thi hàm hoặc phương thức từ xa, và lấy kết quả.
Bây giờ, ở phía slave, bạn phải tạo một giao diện rpc để giao tiếp với master. Cách thực hiện như sau:
interface = rpc.rpc_uart_slave(baudrate=115200)
Lệnh này sẽ tạo lớp giao diện UART để giao tiếp với một master rpc.
Sau khi tạo giao diện slave, bạn cần đăng ký các hàm gọi lại mà master có thể gọi thông qua đối tượng giao diện:
def remote_function_or_method_name(memoryview_object_argument):
<lots of code>
return bytes_object_result
interface.register_callback(remote_function_or_method_name)
Bạn có thể đăng ký bao nhiêu hàm gọi lại tùy ý trên slave. Cuối cùng, sau khi đăng ký xong tất cả hàm gọi lại, bạn chỉ cần thực thi:
interface.loop()
Trên slave để khởi động thư viện rpc và bắt đầu lắng nghe master. Lưu ý rằng phương thức rpc_slave.loop() không trả về.
class rpc -- lớp cơ sở rpc¶
Lớp cơ sở rpc được cài đặt lại bởi các lớp rpc_master và rpc_slave để tạo ra các giao diện master và slave. Lớp này không được sử dụng trực tiếp.
- class rpc.rpc¶
Tạo một đối tượng
rpc. Không dùng trực tiếp.- get_bytes(buff: bytearray | memoryview, timeout_ms: int) bytes | None¶
Được cài đặt lại bởi các lớp con theo giao thức truyền thông. Điền vào
buffcác byte từ giao diện bên dưới trong vòngtimeout_msmili giây. Trả vềNonekhi hết thời gian chờ.
- put_bytes(data: bytes | memoryview, timeout_ms: int) None¶
Được cài đặt lại bởi các lớp con theo giao thức truyền thông. Gửi
dataqua giao diện bên dưới trong vòngtimeout_msmili giây.
- stream_reader(call_back: Callable[[memoryview], None], queue_depth: int = 1, read_timeout_ms: int = 5000) None¶
Nhận một luồng payload từ một
rpc.stream_writertừ xa. Nên được gọi từ bên trong một hàm gọi lại củarpc_slave(hoặc ngay sau khirpc_master.callthành công) sau khi cả hai phía đã đồng bộ.call_back-- hàm gọi lại được gọi mỗi lần nhận một payload dưới dạngcall_back(data)trong đódatalà mộtmemoryview. Giá trị trả về bị bỏ qua.queue_depth-- số lượng khung hình đang truyền mà writer được phép gửi trước khi chờ reader. Giá trị cao hơn tăng thông lượng nhưng tốn thêm bộ nhớ.read_timeout_ms-- mili giây chờ mỗi payload.
Trả về khi có bất kỳ lỗi nào. Để hủy, hãy ném ngoại lệ bên trong
call_back; phía từ xa sẽ hết thời gian chờ.
- stream_writer(call_back: Callable[[], bytes | memoryview], write_timeout_ms: int = 5000) None¶
Gửi một luồng payload đến một
rpc.stream_readertừ xa. Nên được gọi từ bên trong một hàm gọi lại củarpc_slave(hoặc ngay sau khirpc_master.callthành công) sau khi cả hai phía đã đồng bộ.call_back-- hàm gọi lại được gọi không có đối số, trả vềbyteshoặc payloadmemoryviewtiếp theo để gửi.write_timeout_ms-- mili giây chờ khi gửi mỗi payload.
Trả về khi có bất kỳ lỗi nào. Để hủy, hãy ném ngoại lệ bên trong
call_back; phía từ xa sẽ hết thời gian chờ.
class rpc_master -- lớp cơ sở rpc_master¶
The rpc_master là một lớp cơ sở. Hãy sử dụng một trong các lớp con theo giao thức truyền thông (rpc_can_master, rpc_i2c_master, rpc_spi_master, rpc_uart_master).
- class rpc.rpc_master¶
Tạo một đối tượng
rpc_master. Không dùng trực tiếp.- call(name: str, data: bytes = bytes(), send_timeout: int = 1000, recv_timeout: int = 1000) memoryview | None¶
Thực thi một lời gọi từ xa trên thiết bị slave.
name-- tên chuỗi của hàm hoặc phương thức từ xa cần thực thi.data-- đối tượng kiểubytesđược truyền làm đối số cho hàm từ xa.send_timeout-- mili giây chờ khi kết nối đến slave và bắt đầu thực thi hàm từ xa. Sau khi master bắt đầu gửi đối số, tham số này không còn áp dụng; thư viện cho phép tối đa 5 giây để truyền đối số.recv_timeout-- mili giây chờ slave bắt đầu trả về phản hồi. Sau khi master bắt đầu nhận phản hồi, tham số này không còn áp dụng; thư viện cho phép tối đa 5 giây để truyền phản hồi.
Trả về
memoryviewcủa phản hồi khi thành công,bytes()rỗng nếu tên từ xa không tồn tại trên slave, hoặcNonekhi giao tiếp thất bại.
class rpc_slave -- lớp cơ sở rpc_slave¶
The rpc_slave là một lớp cơ sở. Hãy sử dụng một trong các lớp con theo giao thức truyền thông (rpc_can_slave, rpc_i2c_slave, rpc_spi_slave, rpc_uart_slave).
- class rpc.rpc_slave¶
Tạo một đối tượng
rpc_slave. Không dùng trực tiếp.- register_callback(cb: Callable[[memoryview], bytes | memoryview]) None¶
Đăng ký một hàm gọi lại mà master có thể gọi theo tên.
cblà một hàm có thể gọi nhận một đối sốmemoryviewvà trả về một đối tượng kiểubytes. Thuộc tính__name__của hàm gọi lại được dùng làm khóa tra cứu.
- schedule_callback(cb: Callable[[], None]) None¶
Lên lịch cho
cb(một hàm không nhận đối số) được thực thi một lần, ngay sau khi hàm gọi lại rpc đang chạy trả thành công phản hồi về master. Phải được gọi từ bên trong một hàm gọi lại rpc. Cho phép các tác vụ chạy lâu hoặc các lần truyền cắt ngangrpc.get_bytes/rpc.put_byteschạy giữa các giao dịch rpc. Đăng ký lại mỗi lần gọi nếu cần thực thi lặp lại.
- setup_loop_callback(cb: Callable[[], None]) None¶
Đăng ký
cb(một hàm không nhận đối số) để được gọi trong mỗi vòng lặp củarpc_slave.loop. Khác vớirpc_slave.schedule_callback, hàm gọi lại này vẫn được đăng ký sau khi gọi. Phải không chặn; tần suất gọi có thể thay đổi.
class rpc_can_master -- Giao diện Master CAN¶
Điều khiển một thiết bị rpc khác qua 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 thông điệp CAN 11-bit dùng để truyền dữ liệu.bit_rate-- tốc độ bit CAN tính bằng bit trên giây.sample_point-- phần trăm điểm lấy mẫu Tseg1/Tseg2 (ví dụ: 50.0, 62.5, 75, 87.5).can_bus-- số ngoại vi CAN.
message_idvàbit_ratecủa master và slave phải khớp nhau. Bus phải được kết thúc bằng điện trở 120 ohm.
class rpc_can_slave -- Giao diện Slave CAN¶
Được điều khiển bởi một thiết bị rpc khác qua CAN.
class rpc_i2c_master -- Giao diện Master I2C¶
Điều khiển một thiết bị rpc khác qua I2C.
- class rpc.rpc_i2c_master(slave_addr: int = 0x12, rate: int = 100000, i2c_bus: int = 2)¶
slave_addr-- địa chỉ I2C 7-bit của thiết bị slave.rate-- tần số xung nhịp bus I2C tính bằng Hz.i2c_bus-- số ngoại vi I2C.
Địa chỉ master và slave phải khớp nhau. Cần có điện trở kéo lên bên ngoài cho SCL và SDA, và cả hai thiết bị phải dùng chung một nền đất.
class rpc_i2c_slave -- Giao diện Slave I2C¶
Được điều khiển bởi một thiết bị rpc khác qua I2C.
class rpc_spi_master -- Giao diện Master SPI¶
Điều khiển một thiết bị rpc khác qua 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-- tên chân (pin) chip-select.freq-- tần số xung nhịp bus SPI tính bằng Hz.clk_polarity-- mức xung nhịp khi không hoạt động (0 hoặc 1).clk_phase-- lấy mẫu dữ liệu tại cạnh xung nhịp thứ nhất (0) hoặc thứ hai (1).spi_bus-- số ngoại vi SPI.
Các thiết lập của master và slave phải khớp nhau. Kết nối trực tiếp CS, SCLK, MOSI, MISO. Cả hai thiết bị phải dùng chung một nền đất.
class rpc_spi_slave -- Giao diện Slave SPI¶
Được điều khiển bởi một thiết bị rpc khác qua SPI.
- class rpc.rpc_spi_slave(cs_pin: str = 'P3', clk_polarity: int = 1, clk_phase: int = 0, spi_bus: int = 2)¶
cs_pin-- tên chân (pin) đầu vào chip-select.clk_polarity-- mức xung nhịp khi không hoạt động (0 hoặc 1).clk_phase-- lấy mẫu dữ liệu tại cạnh xung nhịp thứ nhất (0) hoặc thứ hai (1).spi_bus-- số ngoại vi SPI.
class rpc_uart_master -- Giao diện Master UART¶
Điều khiển một thiết bị rpc khác qua Async Serial (UART).
- class rpc.rpc_uart_master(baudrate: int = 9600, uart_port: int = 3)¶
baudrate-- tốc độ baud nối tiếp.uart_port-- số ngoại vi UART.
Tốc độ baud của master và slave phải khớp nhau. Kết nối TX của master với RX của slave và RX của master với TX của slave. Cả hai thiết bị phải dùng chung một nền đất.
class rpc_uart_slave -- Giao diện Slave UART¶
Được điều khiển bởi một thiết bị rpc khác qua Async Serial (UART).