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ä).