protocol — OpenMV protokollcsatornák

A protocol modul az OpenMV gazdaprotokollt teszi elérhetővé a Python számára. Lehetővé teszi a firmware-oldali protokollverem inicializálását és konfigurálását, és lehetővé teszi a felhasználói kód számára, hogy egyéni logikai csatornákat regisztráljon, amelyek mögött egy a csatornainterfészt megvalósító Python-objektum áll (read, write, size, poll stb.). Ezzel kommunikálnak az asztali kísérőeszközök, amikor képadatot streamelnek vagy interaktív widgeteket jelenítenek meg egy csatlakoztatott kamerán.

Példák

RGB565 kép streamelése egy gazdaeszköz felé egyéni háttérprogrammal, amely megvalósítja a nyers csatornainterfészt (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

A hozzá tartozó gazdaoldali szkript, amely az openmv Python-csomagot (pip install openmv) használja a csatlakozáshoz, a kamerán futó szkript feltöltéséhez és az egyes képkockák lekéréséhez:

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()

Cseréld le a /dev/ttyACM0 értéket a kamera soros portjára (pl. COM3 Windows alatt). Az openmv.camera.Camera konstruktor ugyanazokat a protokollparamétereket fogadja el, mint az init (crc / seq / ack / events / max_payload / max_retry / timeout), ha a kameraoldali vermet ehhez illeszkedően újrakonfigurálták.

Függvények

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

Inicializálja (vagy újrakonfigurálja) a protokollvermet, és regisztrálja az alapértelmezett logikai adatcsatornákat (stdin, stdout, stream és, ha be van fordítva, profile). RuntimeError kivételt vált ki, ha az inicializálás meghiúsul. A firmware egy már futó, alapértelmezett USB-protokollveremmel indul, így ennek hívására csak a transzport megváltoztatásához vagy az alapértelmezett keretezési paraméterek felülbírálásához van szükség.

A crc engedélyezi a CRC-ellenőrzést a protokollkereteken.

A seq engedélyezi a sorszámkövetést.

Az ack engedélyezi a keretenkénti nyugtázásokat.

Az events engedélyezi a csatorna-eseményértesítéseket.

A max_payload a maximális hasznosadat-méret bájtban. Ha elhagyod, az alábbi, kameránkénti alapértelmezés érvényesül; ez az egyes lapok protokollpuffer-méretéből származik a buffer - 10 (header) - 4 (CRC) képlet szerint.

Kamera

Pufferméret

Maximális hasznos adat

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

Az rtx_retries az újraküldési kísérletek száma. Alapértelmezés: 3.

Az rtx_timeout_ms az újraküldési időtúllépés ezredmásodpercben (minden időtúllépés után megduplázódik). Alapértelmezés: 500.

A lock_interval_ms a minimális zárolási időköz ezredmásodpercben. Alapértelmezés: 10.

A poll_ms a lekérdezési időköz ezredmásodpercben. A 0 (az alapértelmezés) letiltja az időzítő alapú lekérdezést.

protocol.is_active() bool

True értéket ad vissza, ha jelenleg csatlakozik egy gazda, és a protokollverem aktív, egyébként False értéket.

protocol.register(name: str, *, backend: object, flags: int = 0) ProtocolChannel

Regisztrál egy Python backend objektumot új logikai csatornaként, és visszaad egy ProtocolChannel leírót. A backend objektum elérhető metódusai (lásd alább: Háttérprogram-interfész) határozzák meg a csatorna képességeit; a protocol.CHANNEL_FLAG_READ, a protocol.CHANNEL_FLAG_WRITE és a protocol.CHANNEL_FLAG_LOCK automatikusan hozzáadódik a flags értékhez, amikor a megfelelő metódusok meg vannak valósítva.

A name a csatorna neve karakterláncként. A firmware csatornanév-pufferének méretére csonkolódik. Kötelező.

A backend a háttérprogram-interfészt megvalósító Python-objektum. Kötelező. Jellemzően kulcsszóval adják át (backend=...).

A flags további csatorna-jelzőbitek (lásd a CHANNEL_FLAG_* konstansokat). Opcionális; alapértelmezése 0.

RuntimeError kivételt vált ki, ha a csatorna nem regisztrálható (pl. nincs szabad csatornahely).

Osztályok

class protocol.ProtocolChannel

A protocol.register által visszaadott leíró. A példányok nem hozhatók létre közvetlenül.

send_event(event: int, wait_ack: bool = False) None

Csatorna-eseményértesítés küldése a gazdának.

Az event az esemény azonosítója (egész szám).

A wait_ack ha True, blokkol, amíg a gazda nyugtázza az eseményt.

RuntimeError kivételt vált ki, ha az esemény küldése meghiúsul.

Háttérprogram-interfész

A protocol.register függvénynek átadott háttérprogram-objektum az alábbi metódusok bármely részhalmazát megvalósíthatja. Csak az objektumon ténylegesen jelen lévő metódusok kapcsolódnak a C protokollréteghez; a hiányzó metódusok letiltják a megfelelő képességet.

class protocol.backend

A protocol.register függvénynek átadott csatorna-háttérprogram objektum. Az alábbi metódusok azt az opcionális interfészt írják le, amelyet egy Python-háttérprogram megvalósíthat.

init() object

Egyszer hívódik meg, amikor a csatorna inicializálódik. Sikeresség esetén bármely nem None értéket adjon vissza; a kivétel vagy a hiányzó visszatérési érték hibának számít.

poll() bool

True értéket ad vissza, ha a csatornán van olvasásra kész adat a gazda számára.

lock() bool

Lefoglalja a csatornát egy átvitelhez. Sikeresség esetén True értéket ad vissza.

unlock() bool

Felszabadítja a csatornát egy átvitel után. Sikeresség esetén True értéket ad vissza.

size() int

Visszaadja a csatornáról jelenleg olvasható bájtok számát.

shape() tuple

Visszaad egy legfeljebb négy egész számból álló rekordot, amely az adat alakját írja le (pl. képméreteket). A protokollréteg legfeljebb négy elemet használ fel.

flush() object

Kiüríti az összes függőben lévő adatot. Sikeresség esetén bármely nem None értéket adjon vissza.

read(offset: int, size: int) bytes

Legfeljebb size bájtot ad vissza az offset pozíciótól kezdve, egy bytes-szerű objektumként, amely támogatja a pufferprotokollt.

readp(offset: int, size: int) bytes

A read nullamásolásos (zero-copy) változata. Olyan puffert ad vissza, amelynek mögöttes memóriáját közvetlenül a protokollréteg olvassa; a puffernek érvényesnek kell maradnia az átvitel teljes idejére.

write(offset: int, data: bytearray) int

data írása az offset pozícióba. A data egy bytearray, amely közvetlenül a C puffert hivatkozza. Visszaadja a kiírt bájtok számát, vagy 0 értéket alapértelmezett siker esetén.

ioctl(cmd: int, length: int, arg: bytearray | None) int

Kezel egy ioctl-t. Az arg None, ha a length nulla, egyébként egy bytearray, amely a C puffert hivatkozza. Sikeresség esetén 0 vagy None értéket ad vissza, hiba esetén pedig negatív egész számot.

is_active() bool

Transzportcsatornák esetén True értéket ad vissza, ha a mögöttes transzport jelenleg csatlakozik.

class protocol.CBORChannel(on_read: Callable | None = None, on_write: Callable | None = None)

Egy magasabb szintű Python-háttérprogram (amelyet a befagyasztott protocol csomag biztosít), amely a megnevezett mezőket CBOR-ba sorosítja SenML-kompatibilis egész kulcsok használatával. Támogat megjelenítő widgeteket (label, depth) és interaktív vezérlőket (toggle, slider, select) on_read/on_write visszahívásokkal.

Az on_read egy opcionális on_read(channel) hívható objektum, amely a csatorna gazda felé történő sorosítása előtt hívódik meg. Használd a mezőértékek frissítésére.

Az on_write egy opcionális on_write(channel, name, value) hívható objektum, amely akkor hívódik meg, amikor a gazda új értéket ír egy megnevezett mezőbe.

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

Megnevezett mező hozzáadása a csatornához.

A name a megjelenítendő név; ezen a csatornán belül egyedinek kell lennie.

A type a widget típusa: "label", "toggle", "slider", "select" vagy "depth".

A value a kezdőérték. Az alapértelmezés a type értékétől függ.

A unit a label/slider mértékegység-karakterlánca (pl. "Cel", "%RH").

A min a minimális érték (csúszka- vagy mélységtartomány).

A max a maximális érték (csúszka- vagy mélységtartomány).

A step a lépésköz (csúszka).

Az options az opció-karakterláncok listája (select).

A width a képpontban megadott szélesség (depth).

A height a képpontban megadott magasság (depth).

__getitem__(name: str) object

Visszaadja a megnevezett mező aktuális értékét. depth mezők esetén a bináris adatpuffert adja vissza, egyébként a skalárértéket.

__setitem__(name: str, value: Any) None

Beállítja a megnevezett mező értékét. slider mezők esetén egy (min, max, value) rekord egyszerre frissíti a tartományt és az aktuális értéket. depth mezők esetén a value a bináris adatpuffer.

poll() bool

Háttérprogram-interfész metódus. True értéket ad vissza, ha sorosított adat áll rendelkezésre a gazda számára.

size() int

Háttérprogram-interfész metódus. Meghívja az on_read függvényt (ha be van állítva), és visszaadja a sorosított puffer méretét.

read(offset: int, size: int) bytes

Háttérprogram-interfész metódus. A sorosított puffer egy szeletét adja vissza.

write(offset: int, data: bytearray) int

Háttérprogram-interfész metódus. Dekódol egy CBOR frissítési listát, és az értékeket az illeszkedő megnevezett mezőkre alkalmazza, mindegyikhez meghívva az on_write függvényt.

Konstansok

Csatorna-jelzőbitek (bitenkénti VAGY művelettel kombinálva; a protocol.register függvénynek a flags paraméteren keresztül átadva, vagy a háttérprogram metódusai alapján automatikusan beállítva).

protocol.CHANNEL_FLAG_READ: int

A csatorna támogatja az olvasást.

protocol.CHANNEL_FLAG_WRITE: int

A csatorna támogatja az írást.

protocol.CHANNEL_FLAG_LOCK: int

A csatorna megvalósítja a lock/unlock műveleteket.

protocol.CHANNEL_FLAG_PHYSICAL: int

A csatorna fizikai transzportot képvisel (szemben a logikai adatcsatornával).

Beépített csatornaazonosítók.

protocol.CHANNEL_ID_TRANSPORT: int

Az aktív transzporthoz fenntartott csatornaazonosító.

protocol.CHANNEL_ID_STDIN: int

A beépített stdin csatorna azonosítója.

protocol.CHANNEL_ID_STDOUT: int

A beépített stdout csatorna azonosítója.

protocol.CHANNEL_ID_STREAM: int

A beépített stream csatorna azonosítója.

protocol.CHANNEL_ID_PROFILE: int

A beépített profilozó csatorna azonosítója (csak akkor van jelen, ha a firmware engedélyezett profilozóval készült).