protocol — OpenMV-protocolkanalen¶
De protocol module stelt het OpenMV-hostprotocol beschikbaar aan Python. Het maakt het mogelijk om de protocolstack aan de firmwarezijde te initialiseren en te configureren, en laat gebruikerscode aangepaste logische kanalen registreren die worden ondersteund door een Python-object dat de kanaalinterface implementeert (read, write, size, poll, enz.). Dit is waar desktop-begeleidingstools mee communiceren wanneer ze afbeeldingsgegevens streamen of interactieve widgets beschikbaar maken aan een verbonden camera.
Voorbeelden¶
Stream een RGB565-afbeelding naar een hosttool met behulp van een aangepaste backend die de raw-kanaalinterface implementeert (backend.size(), backend.shape(), backend.poll(), backend.read()):
import csi
import protocol
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.HD)
img = csi0.snapshot()
img_mv = memoryview(img.bytearray())
frame_ready = True
class FrameChannel:
def size(self):
return len(img_mv)
def shape(self):
return (img.height(), img.width(), len(img_mv))
def poll(self):
return frame_ready
def read(self, offset, size):
global frame_ready
end = offset + size
chunk = img_mv[offset:end]
if end >= len(img_mv):
frame_ready = False
return chunk
protocol.register(name="frame", backend=FrameChannel())
while True:
if not frame_ready:
img = csi0.snapshot()
img_mv = memoryview(img.bytearray())
frame_ready = True
Het bijbehorende script aan de hostzijde, dat het openmv Python-pakket (pip install openmv) gebruikt om verbinding te maken, het script op de camera te pushen en elk frame op te halen:
import cv2
import numpy as np
from openmv.camera import Camera
# The on-cam script above, stored as a string (or read from a file).
SCRIPT = open("frame_streamer_on_cam.py").read()
with Camera("/dev/ttyACM0", baudrate=921600) as cam:
cam.stop()
cam.exec(SCRIPT)
while True:
status = cam.read_status()
if not cam.has_channel("frame") or not status.get("frame"):
continue
h, w, size = cam._channel_shape(cam.get_channel(name="frame"))
if cam.channel_size("frame") < size:
continue
data = cam.channel_read("frame", size)
rgb565 = np.frombuffer(data, dtype="<u2").reshape(h, w)
# Unpack RGB565 to an HxWx3 uint8 RGB image.
r = ((rgb565 >> 11) & 0x1F) << 3
g = ((rgb565 >> 5) & 0x3F) << 2
b = ( rgb565 & 0x1F) << 3
frame = np.dstack([r, g, b]).astype(np.uint8)
# Display with OpenCV (cv2 expects BGR, not RGB).
cv2.imshow("OpenMV", cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
Vervang /dev/ttyACM0 door de seriële poort van de camera (bijv. COM3 op Windows). De openmv.camera.Camera constructor accepteert dezelfde protocolparameters als init (crc / seq / ack / events / max_payload / max_retry / timeout) wanneer de stack aan de camerazijde overeenkomstig is geherconfigureerd.
Functies¶
- protocol.init(crc: bool = True, seq: bool = True, ack: bool = True, events: bool = True, max_payload: int = ..., rtx_retries: int = 3, rtx_timeout_ms: int = 500, lock_interval_ms: int = 10, poll_ms: int = 0) None¶
Initialiseert (of herconfigureert) de protocolstack en registreert de standaard logische datakanalen (
stdin,stdout,streamen, indien meegecompileerd,profile). Genereert eenRuntimeErrorals de initialisatie mislukt. De firmware start op met een standaard USB-protocolstack die al draait, dus het aanroepen hiervan is alleen nodig om het transport te wijzigen of de standaard framingparameters te overschrijven.crcschakelt CRC-validatie van protocolframes in.seqschakelt het bijhouden van volgnummers in.ackschakelt bevestigingen per frame in.eventsschakelt kanaalgebeurtenis-notificaties in.max_payloadis de maximale payloadgrootte in bytes. Indien weggelaten wordt de onderstaande standaardwaarde per camera gebruikt; deze is afgeleid van de protocolbuffergrootte van elk board alsbuffer - 10 (header) - 4 (CRC).Camera
Buffergrootte
Max. payload
OpenMV Cam M4 (
OPENMV2)512
498
OpenMV Cam M7 (
OPENMV3)512
498
OpenMV Cam H7 (
OPENMV4)512
498
OpenMV Cam H7 Plus (
OPENMV4P)4096
4082
OpenMV Pure Thermal (
OPENMVPT)4096
4082
OpenMV Cam RT1062 (
OPENMV_RT1060)4096
4082
OpenMV Cam N6 (
OPENMV_N6)8192
8178
OpenMV AE3 (
OPENMV_AE3)8192
8178
Arduino Portenta H7 (
ARDUINO_PORTENTA_H7)4096
4082
Arduino Giga (
ARDUINO_GIGA)4096
4082
Arduino Nicla Vision (
ARDUINO_NICLA_VISION)4096
4082
rtx_retriesis het aantal hertransmissiepogingen. Standaard3.rtx_timeout_msis de hertransmissie-timeout in milliseconden (verdubbeld na elke timeout). Standaard500.lock_interval_msis het minimale vergrendelingsinterval in milliseconden. Standaard10.poll_msis het polling-interval in milliseconden.0(de standaardwaarde) schakelt timer-polling uit.
- protocol.is_active() bool¶
Retourneert
Trueals er momenteel een host verbonden is en de protocolstack actief is, andersFalse.
- protocol.register(name: str, *, backend: object, flags: int = 0) ProtocolChannel¶
Registreert een Python
backendobject als een nieuw logisch kanaal en retourneert eenProtocolChannelhandle. De beschikbare methoden van hetbackendobject (zie Backend-interface hieronder) bepalen de mogelijkheden van het kanaal;protocol.CHANNEL_FLAG_READ,protocol.CHANNEL_FLAG_WRITEenprotocol.CHANNEL_FLAG_LOCKworden automatisch aanflagstoegevoegd wanneer de bijbehorende methoden zijn geïmplementeerd.nameis de kanaalnaam als string. Afgekapt tot de buffergrootte van de kanaalnaam in de firmware. Vereist.backendis het Python-object dat de backend-interface implementeert. Vereist. Wordt doorgaans via een keyword doorgegeven (backend=...).flagszijn aanvullende kanaalvlagbits (zie deCHANNEL_FLAG_*constanten). Optioneel; standaard0.Genereert een
RuntimeErrorals het kanaal niet kan worden geregistreerd (bijv. geen vrije kanaalslots).
Klassen¶
- class protocol.ProtocolChannel¶
Handle die wordt geretourneerd door
protocol.register. Instanties worden niet rechtstreeks geconstrueerd.- send_event(event: int, wait_ack: bool = False) None¶
Stuurt een kanaalgebeurtenis-notificatie naar de host.
eventis de gebeurtenis-identifier (geheel getal).wait_ackindienTrueblokkeert totdat de host de gebeurtenis bevestigt.Genereert een
RuntimeErrorals het verzenden van de gebeurtenis mislukt.
Backend-interface¶
Een backend-object dat aan protocol.register wordt doorgegeven mag elke subset van de volgende methoden implementeren. Alleen de methoden die op het object aanwezig zijn worden gekoppeld aan de C-protocollaag; ontbrekende methoden laten de bijbehorende mogelijkheid uitgeschakeld.
- class protocol.backend¶
Kanaal-backendobject dat aan
protocol.registerwordt doorgegeven. De onderstaande methoden beschrijven de optionele interface die een Python-backend mag implementeren.- init() object¶
Wordt eenmalig aangeroepen wanneer het kanaal wordt geïnitialiseerd. Retourneert bij succes een waarde die niet
Noneis; een uitzondering of ontbrekende retourwaarde wordt als een fout behandeld.
- poll() bool¶
Retourneert
Trueals het kanaal gegevens klaar heeft om door de host te worden gelezen.
- shape() tuple¶
Retourneert een tuple van maximaal vier gehele getallen die de gegevensvorm beschrijven (bijv. afbeeldingsafmetingen). Maximaal vier elementen worden door de protocollaag verbruikt.
- flush() object¶
Spoelt eventuele in behandeling zijnde gegevens door. Retourneert bij succes een waarde die niet
Noneis.
- read(offset: int, size: int) bytes¶
Retourneert maximaal
sizebytes vanafoffsetals eenbytes-achtig object dat het bufferprotocol ondersteunt.
- readp(offset: int, size: int) bytes¶
Zero-copy-variant van
read. Retourneert een buffer waarvan het onderliggende geheugen rechtstreeks door de protocollaag wordt gelezen; de buffer moet geldig blijven gedurende de overdracht.
- write(offset: int, data: bytearray) int¶
Schrijft
dataopoffset.datais eenbytearraydie rechtstreeks naar de C-buffer verwijst. Retourneert het aantal geschreven bytes, of0bij standaard succes.
- class protocol.CBORChannel(on_read: Callable | None = None, on_write: Callable | None = None)¶
Een Python-backend op een hoger niveau (geleverd door het ingevroren
protocolpakket) dat benoemde velden serialiseert naar CBOR met behulp van SenML-compatibele integer-sleutels. Ondersteunt weergavewidgets (label,depth) en interactieve besturingselementen (toggle,slider,select) meton_read/on_writecallbacks.on_readis een optionele aanroepbareon_read(channel)die wordt aangeroepen voordat het kanaal voor de host wordt geserialiseerd. Gebruik het om veldwaarden te vernieuwen.on_writeis een optionele aanroepbareon_write(channel, name, value)die wordt aangeroepen wanneer de host een nieuwe waarde voor een benoemd veld schrijft.- add(name: str, type: str, value: Any = None, unit: str | None = None, min: int | float | None = None, max: int | float | None = None, step: int | float | None = None, options: list | None = None, width: int | None = None, height: int | None = None) None¶
Voegt een benoemd veld toe aan het kanaal.
nameis de weergavenaam; moet uniek zijn binnen dit kanaal.typeis het widgettype:"label","toggle","slider","select", of"depth".valueis de beginwaarde. De standaardwaarde hangt af vantype.unitis de eenheidsstring voorlabel/slider(bijv."Cel","%RH").minis de minimumwaarde (sliderbereik of dieptebereik).maxis de maximumwaarde (sliderbereik of dieptebereik).stepis de stapgrootte (slider).optionsis de lijst met optiestrings (select).widthis de breedte in pixels (depth).heightis de hoogte in pixels (depth).
- __getitem__(name: str) object¶
Retourneert de huidige waarde van het benoemde veld. Voor
depthvelden wordt de binaire gegevensbuffer geretourneerd, anders de scalaire waarde.
- __setitem__(name: str, value: Any) None¶
Stelt de waarde van het benoemde veld in. Voor
slidervelden werkt een(min, max, value)tuple het bereik en de huidige waarde tegelijkertijd bij. Voordepthvelden isvaluede binaire gegevensbuffer.
- poll() bool¶
Methode van de backend-interface. Retourneert
Truewanneer er geserialiseerde gegevens beschikbaar zijn voor de host.
- size() int¶
Methode van de backend-interface. Roept
on_readaan (indien ingesteld) en retourneert de grootte van de geserialiseerde buffer.
Constanten¶
Kanaalvlagbits (bitsgewijs gecombineerd; doorgegeven aan protocol.register via flags of automatisch ingesteld op basis van de methoden van de backend).
- protocol.CHANNEL_FLAG_PHYSICAL: int¶
Het kanaal vertegenwoordigt een fysiek transport (in tegenstelling tot een logisch datakanaal).
Ingebouwde kanaal-identifiers.