protocol — OpenMV-protokollakanavat

protocol-moduuli tuo OpenMV-isäntäprotokollan Pythonin käyttöön. Sen avulla laiteohjelmiston puoleinen protokollapino voidaan alustaa ja konfiguroida, ja käyttäjän koodi voi rekisteröidä omia loogisia kanavia, joiden taustalla on Python-olio, joka toteuttaa kanavarajapinnan (read, write, size, poll jne.). Tähän työpöydän kumppanityökalut ottavat yhteyden, kun ne suoratoistavat kuvadataa tai tarjoavat interaktiivisia komponentteja yhdistetylle kameralle.

Esimerkkejä

Suoratoista RGB565-kuva isäntätyökalulle käyttäen omaa taustajärjestelmää, joka toteuttaa raakakanavarajapinnan (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

Vastaava isäntäpuolen skripti, joka käyttää openmv-Python-pakettia (pip install openmv) yhteyden muodostamiseen, kameralla ajettavan skriptin lähettämiseen ja kunkin kehyksen hakemiseen:

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

Korvaa /dev/ttyACM0 kameran sarjaportilla (esim. COM3 Windowsissa). openmv.camera.Camera-konstruktori hyväksyy samat protokollaparametrit kuin init (crc / seq / ack / events / max_payload / max_retry / timeout), kun kameran puoleinen pino on konfiguroitu vastaamaan niitä.

Funktiot

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

Alustaa (tai konfiguroi uudelleen) protokollapinon ja rekisteröi oletusarvoiset loogiset datakanavat (stdin, stdout, stream ja, jos käännetty mukaan, profile). Nostaa poikkeuksen RuntimeError, jos alustus epäonnistuu. Laiteohjelmisto käynnistyy oletusarvoisen USB-protokollapinon ollessa jo käynnissä, joten tämän kutsuminen tarvitaan vain siirtotien vaihtamiseen tai oletusarvoisten kehystysparametrien korvaamiseen.

crc ottaa käyttöön CRC-tarkistuksen protokollakehyksille.

seq ottaa käyttöön järjestysnumeroiden seurannan.

ack ottaa käyttöön kehyskohtaiset kuittaukset.

events ottaa käyttöön kanavatapahtumien ilmoitukset.

max_payload on suurin hyötykuorman koko tavuina. Jos se jätetään pois, käytetään alla olevaa kamerakohtaista oletusarvoa; se johdetaan kunkin kortin protokollapuskurin koosta kaavalla buffer - 10 (header) - 4 (CRC).

Kamera

Puskurin koko

Suurin hyötykuorma

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_retries on uudelleenlähetysyritysten määrä. Oletus 3.

rtx_timeout_ms on uudelleenlähetyksen aikakatkaisu millisekunteina (kaksinkertaistetaan jokaisen aikakatkaisun jälkeen). Oletus 500.

lock_interval_ms on pienin lukitusväli millisekunteina. Oletus 10.

poll_ms on pollausväli millisekunteina. 0 (oletus) poistaa ajastinpollauksen käytöstä.

protocol.is_active() bool

Palauttaa True, jos isäntä on tällä hetkellä yhdistetty ja protokollapino on aktiivinen, muuten False.

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

Rekisteröi Python-olion backend uudeksi loogiseksi kanavaksi ja palauttaa ProtocolChannel-kahvan. backend-olion käytettävissä olevat metodit (katso Taustajärjestelmän rajapinta alla) määrittävät kanavan ominaisuudet; protocol.CHANNEL_FLAG_READ, protocol.CHANNEL_FLAG_WRITE ja protocol.CHANNEL_FLAG_LOCK lisätään flags-arvoon automaattisesti, kun vastaavat metodit on toteutettu.

name on kanavan nimi merkkijonona. Lyhennetään laiteohjelmiston kanavanimipuskurin kokoon. Pakollinen.

backend on Python-olio, joka toteuttaa taustajärjestelmän rajapinnan. Pakollinen. Tyypillisesti välitetään avainsanalla (backend=...).

flags on lisäkanavalippubittejä (katso CHANNEL_FLAG_*-vakiot). Valinnainen; oletusarvo 0.

Nostaa poikkeuksen RuntimeError, jos kanavaa ei voida rekisteröidä (esim. ei vapaita kanavapaikkoja).

Luokat

class protocol.ProtocolChannel

Kahva, jonka protocol.register palauttaa. Ilmentymiä ei muodosteta suoraan.

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

Lähettää kanavatapahtuman ilmoituksen isännälle.

event on tapahtuman tunniste (kokonaisluku).

wait_ack jos True, estää suorituksen kunnes isäntä kuittaa tapahtuman.

Nostaa poikkeuksen RuntimeError, jos tapahtuman lähetys epäonnistuu.

Taustajärjestelmän rajapinta

Funktiolle protocol.register välitetty taustajärjestelmäolio voi toteuttaa minkä tahansa osajoukon seuraavista metodeista. Vain oliossa läsnä olevat metodit kytketään C-protokollakerrokseen; puuttuvat metodit jättävät vastaavan ominaisuuden pois käytöstä.

class protocol.backend

Funktiolle protocol.register välitetty kanavan taustajärjestelmäolio. Alla olevat metodit kuvaavat valinnaisen rajapinnan, jonka Python-taustajärjestelmä voi toteuttaa.

init() object

Kutsutaan kerran, kun kanava alustetaan. Palauta mikä tahansa arvo, joka ei ole None, onnistumisen merkiksi; poikkeus tai puuttuva paluuarvo tulkitaan virheeksi.

poll() bool

Palauttaa True, jos kanavalla on dataa valmiina isännän luettavaksi.

lock() bool

Varaa kanavan siirtoa varten. Palauta True onnistuessa.

unlock() bool

Vapauttaa kanavan siirron jälkeen. Palauta True onnistuessa.

size() int

Palauttaa kanavalta tällä hetkellä luettavissa olevien tavujen määrän.

shape() tuple

Palauttaa enintään neljän kokonaisluvun monikon, joka kuvaa datan muotoa (esim. kuvan mitat). Protokollakerros käyttää enintään neljä elementtiä.

flush() object

Tyhjentää mahdollisen odottavan datan. Palauta mikä tahansa arvo, joka ei ole None, onnistumisen merkiksi.

read(offset: int, size: int) bytes

Palauttaa enintään size tavua alkaen kohdasta offset bytes-tyyppisenä oliona, joka tukee puskuriprotokollaa.

readp(offset: int, size: int) bytes

Zero-copy-muunnelma metodista read. Palauttaa puskurin, jonka taustalla oleva muisti luetaan suoraan protokollakerroksesta; puskurin on pysyttävä voimassa koko siirron ajan.

write(offset: int, data: bytearray) int

Kirjoittaa data kohtaan offset. data on bytearray, joka viittaa suoraan C-puskuriin. Palauta kirjoitettujen tavujen määrä tai 0 oletusarvoisen onnistumisen merkiksi.

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

Käsittelee ioctl-kutsun. arg on None, jos length on nolla, muuten bytearray, joka viittaa C-puskuriin. Palauta 0 tai None onnistuessa tai negatiivinen kokonaisluku virheen merkiksi.

is_active() bool

Siirtokanavien tapauksessa palauta True, jos taustalla oleva siirtotie on tällä hetkellä yhdistetty.

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

Korkeamman tason Python-taustajärjestelmä (jonka tarjoaa jäädytetty protocol-paketti), joka sarjallistaa nimetyt kentät CBOR-muotoon käyttäen SenML-yhteensopivia kokonaislukuavaimia. Tukee näyttökomponentteja (label, depth) ja interaktiivisia ohjaimia (toggle, slider, select) on_read/on_write-takaisinkutsuilla.

on_read on valinnainen kutsuttava on_read(channel), joka kutsutaan ennen kuin kanava sarjallistetaan isännälle. Käytä sitä kenttäarvojen päivittämiseen.

on_write on valinnainen kutsuttava on_write(channel, name, value), joka kutsutaan, kun isäntä kirjoittaa uuden arvon nimetylle kentälle.

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

Lisää kanavalle nimetyn kentän.

name on näyttönimi; sen on oltava yksilöllinen tämän kanavan sisällä.

type on komponentin tyyppi: "label", "toggle", "slider", "select" tai "depth".

value on alkuarvo. Oletusarvo riippuu tyypistä type.

unit on yksikkömerkkijono tyypeille label/slider (esim. "Cel", "%RH").

min on pienin arvo (liukusäätimen tai syvyyden alue).

max on suurin arvo (liukusäätimen tai syvyyden alue).

step on askelkoko (liukusäädin).

options on vaihtoehtomerkkijonojen lista (select).

width on pikselileveys (depth).

height on pikselikorkeus (depth).

__getitem__(name: str) object

Palauttaa nimetyn kentän nykyisen arvon. depth-kentille palautetaan binääridatapuskuri, muuten skalaariarvo.

__setitem__(name: str, value: Any) None

Asettaa nimetyn kentän arvon. slider-kentille (min, max, value)-monikko päivittää alueen ja nykyisen arvon samanaikaisesti. depth-kentille value on binääridatapuskuri.

poll() bool

Taustajärjestelmän rajapintametodi. Palauttaa True, kun sarjallistettua dataa on saatavilla isännälle.

size() int

Taustajärjestelmän rajapintametodi. Kutsuu on_read (jos asetettu) ja palauttaa sarjallistetun puskurin koon.

read(offset: int, size: int) bytes

Taustajärjestelmän rajapintametodi. Palauttaa siivun sarjallistetusta puskurista.

write(offset: int, data: bytearray) int

Taustajärjestelmän rajapintametodi. Purkaa CBOR-päivityslistan ja soveltaa arvot vastaaviin nimettyihin kenttiin kutsuen on_write jokaiselle.

Vakiot

Kanavalippubitit (yhdistetään bittioperaatioin; välitetään funktiolle protocol.register parametrilla flags tai asetetaan automaattisesti taustajärjestelmän metodien perusteella).

protocol.CHANNEL_FLAG_READ: int

Kanava tukee lukuoperaatioita.

protocol.CHANNEL_FLAG_WRITE: int

Kanava tukee kirjoitusoperaatioita.

protocol.CHANNEL_FLAG_LOCK: int

Kanava toteuttaa metodit lock/unlock.

protocol.CHANNEL_FLAG_PHYSICAL: int

Kanava edustaa fyysistä siirtotietä (toisin kuin loogista datakanavaa).

Sisäänrakennettujen kanavien tunnisteet.

protocol.CHANNEL_ID_TRANSPORT: int

Aktiivisen siirtotien varattu kanavatunniste.

protocol.CHANNEL_ID_STDIN: int

Sisäänrakennetun stdin-kanavan kanavatunniste.

protocol.CHANNEL_ID_STDOUT: int

Sisäänrakennetun stdout-kanavan kanavatunniste.

protocol.CHANNEL_ID_STREAM: int

Sisäänrakennetun stream-kanavan kanavatunniste.

protocol.CHANNEL_ID_PROFILE: int

Sisäänrakennetun profilointikanavan kanavatunniste (läsnä vain, kun laiteohjelmisto on käännetty profiloinnin ollessa käytössä).