rpc — rpc 라이브러리¶
OpenMV Cam의 rpc 모듈은 OpenMV Cam을 다른 마이크로컨트롤러나 컴퓨터에 연결하여 OpenMV Cam에서 원격 파이썬(또는 프로시저) 호출을 실행할 수 있게 해줍니다. rpc 모듈은 그 반대도 지원하므로, OpenMV Cam이 다른 마이크로컨트롤러나 컴퓨터에서 원격 프로시저(또는 파이썬) 호출을 실행하도록 할 수도 있습니다.
라이브러리 사용 방법¶
UART를 통해 하나의 콜백을 노출하는 최소한의 slave 예제입니다:
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.
slave에게 JPEG 프레임을 요청하는 대응 master 예제입니다:
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)
이는 rpc slave와 통신하기 위한 UART 인터페이스를 생성합니다.
인터페이스가 생성되면 다음을 수행하기만 하면 됩니다:
memory_view_object_result = interface.call("remote_function_or_method_name", bytes_object_argument)
그러면 rpc 라이브러리는 slave에서 해당 "remote_function_or_method_name" 을 실행하려고 시도합니다. 원격 함수 또는 메서드는 최대 2^32-1바이트 크기까지 가능한 bytes_object_argument 를 받습니다. 원격 메서드의 실행이 끝나면 역시 최대 2^32-1바이트 크기까지 가능한 memory_view_object_result 를 반환합니다. 인자와 응답 모두 일반적인 바이트 컨테이너이기 때문에 rpc 라이브러리를 통해 무엇이든 전달할 수 있고 어떤 형식의 응답이든 받을 수 있습니다. 인자를 전달하는 간단한 방법은 struct.pack() 으로 인자를 생성하고 반대편에서 struct.unpack() 으로 인자를 받는 것입니다. 응답의 경우, 반대편에서 문자열 객체나 json 문자열을 결과로 보내면 master가 이를 해석할 수 있습니다.
오류와 관련해서, 존재하지 않는 함수나 메서드 이름을 실행하려고 하면 rpc_master.call() 메서드는 빈 bytes() 객체를 반환합니다. rpc 라이브러리가 slave와의 통신에 실패하면 rpc 라이브러리는 None을 반환합니다.
단순함을 유지하기 위해 rpc 라이브러리는 master와 slave 장치 사이의 연결을 유지하지 않습니다. rpc_master.call() 메서드는 slave에 연결을 시도하고, 원격 함수 또는 메서드의 실행을 시작하며, 결과를 가져오는 과정을 캡슐화합니다.
이제 slave 쪽에서는 master와 통신하기 위한 rpc 인터페이스를 생성해야 합니다. 다음과 같습니다:
interface = rpc.rpc_uart_slave(baudrate=115200)
이는 rpc master와 통신하기 위한 UART 인터페이스 계층을 생성합니다.
slave 인터페이스를 생성한 후에는 인터페이스 객체에 master가 호출할 수 있는 콜백을 등록해야 합니다:
def remote_function_or_method_name(memoryview_object_argument):
<lots of code>
return bytes_object_result
interface.register_callback(remote_function_or_method_name)
slave에는 원하는 만큼 많은 콜백을 등록할 수 있습니다. 마지막으로 콜백 등록을 마치면 다음을 실행하기만 하면 됩니다:
interface.loop()
이를 slave에서 실행하면 rpc 라이브러리가 시작되어 master를 수신 대기하기 시작합니다. rpc_slave.loop() 메서드는 반환하지 않는다는 점에 유의하세요.
class rpc – rpc 기반 클래스¶
rpc 기반 클래스는 master 및 slave 인터페이스를 생성하기 위해 rpc_master 및 rpc_slave 클래스에서 재구현됩니다. 직접 사용하기 위한 것이 아닙니다.
- class rpc.rpc¶
rpc객체를 생성합니다. 직접 사용하기 위한 것이 아닙니다.- get_bytes(buff: bytearray | memoryview, timeout_ms: int) bytes | None¶
전송 방식별 서브클래스에서 재구현됩니다.
timeout_ms밀리초 이내에 기반 인터페이스로부터 받은 바이트로buff를 채웁니다. 타임아웃 시None을 반환합니다.
- put_bytes(data: bytes | memoryview, timeout_ms: int) None¶
전송 방식별 서브클래스에서 재구현됩니다.
timeout_ms밀리초 이내에 기반 인터페이스를 통해data를 전송합니다.
- 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– writer가 reader를 기다리기 전에 전송할 수 있는 진행 중인 프레임의 수입니다. 값이 클수록 메모리를 더 사용하는 대신 처리량이 증가합니다.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¶
slave 장치에서 원격 호출을 실행합니다.
name– 실행할 원격 함수 또는 메서드의 문자열 이름입니다.data– 원격 함수에 인자로 전달되는bytes형 객체입니다.send_timeout– slave에 연결하고 원격 함수 실행을 시작하는 동안 대기할 밀리초입니다. master가 인자 전송을 시작하면 더 이상 적용되지 않으며, 라이브러리는 인자 전송에 최대 5초까지 허용합니다.recv_timeout– slave가 응답을 반환하기 시작하기를 대기할 밀리초입니다. master가 응답 수신을 시작하면 더 이상 적용되지 않으며, 라이브러리는 응답 전송에 최대 5초까지 허용합니다.
성공 시 응답의
memoryview를, slave에 원격 이름이 존재하지 않으면 빈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¶
master가 이름으로 호출할 수 있는 콜백을 등록합니다.
cb는 하나의memoryview인자를 받아bytes형 객체를 반환하는 호출 가능 객체입니다. 콜백의__name__이 조회 키로 사용됩니다.
- schedule_callback(cb: Callable[[], None]) None¶
현재 실행 중인 rpc 콜백이 master에게 응답을 성공적으로 반환한 직후에
cb(인자를 받지 않는 호출 가능 객체)를 한 번 실행하도록 예약합니다. rpc 콜백 내부에서 호출해야 합니다. 이를 통해 장시간 실행되는 작업이나rpc.get_bytes/rpc.put_bytes컷스루 전송이 rpc 트랜잭션 사이에 실행될 수 있습니다. 반복 실행이 필요한 경우 매 호출마다 다시 등록하세요.
- setup_loop_callback(cb: Callable[[], None]) None¶
rpc_slave.loop의 매 반복마다 호출되도록cb(인자를 받지 않는 호출 가능 객체)를 등록합니다.rpc_slave.schedule_callback과 달리 이 콜백은 등록된 상태로 유지됩니다. 비차단이어야 하며, 호출 빈도는 가변적입니다.
class rpc_can_master – CAN Master 인터페이스¶
CAN을 통해 다른 rpc 장치를 제어합니다.
- 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 메시지 id입니다.bit_rate– 초당 비트 단위의 CAN 비트 레이트입니다.sample_point– Tseg1/Tseg2 샘플 포인트 백분율입니다(예: 50.0, 62.5, 75, 87.5).can_bus– CAN 주변장치 번호입니다.
master와 slave의
message_id와bit_rate는 일치해야 합니다. 버스는 120옴으로 종단되어야 합니다.
class rpc_can_slave – CAN Slave 인터페이스¶
CAN을 통해 다른 rpc 장치에 의해 제어됩니다.
class rpc_i2c_master – I2C Master 인터페이스¶
I2C를 통해 다른 rpc 장치를 제어합니다.
class rpc_i2c_slave – I2C Slave 인터페이스¶
I2C를 통해 다른 rpc 장치에 의해 제어됩니다.
class rpc_spi_master – SPI Master 인터페이스¶
SPI를 통해 다른 rpc 장치를 제어합니다.
- 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– 칩 셀렉트 핀 이름입니다.freq– Hz 단위의 SPI 버스 클럭 주파수입니다.clk_polarity– 유휴 클럭 레벨입니다(0 또는 1).clk_phase– 첫 번째(0) 또는 두 번째(1) 클럭 에지에서 데이터를 샘플링합니다.spi_bus– SPI 주변장치 번호입니다.
master와 slave 설정은 일치해야 합니다. CS, SCLK, MOSI, MISO를 직접 연결하세요. 두 장치는 공통 그라운드를 공유해야 합니다.
class rpc_spi_slave – SPI Slave 인터페이스¶
SPI를 통해 다른 rpc 장치에 의해 제어됩니다.
class rpc_uart_master – UART Master 인터페이스¶
비동기 직렬(UART)을 통해 다른 rpc 장치를 제어합니다.
class rpc_uart_slave – UART Slave 인터페이스¶
비동기 직렬(UART)을 통해 다른 rpc 장치에 의해 제어됩니다.