protocol — OpenMV Protokol Kanalları#

protocol modülü, OpenMV ana bilgisayar protokolünü Python’a sunar. Aygıt yazılımı tarafındaki protokol yığınının başlatılmasına ve yapılandırılmasına olanak tanır ve kullanıcı kodunun, kanal arayüzünü (read, write, size, poll vb.) uygulayan bir Python nesnesi tarafından desteklenen özel mantıksal kanallar kaydetmesine izin verir. Masaüstü yardımcı araçlar, görüntü verisi akıttıklarında veya bağlı bir kameraya etkileşimli widget’lar sunduklarında işte bununla iletişim kurarlar.

Örnekler#

Ham kanal arayüzünü (backend.size(), backend.shape(), backend.poll(), backend.read()) uygulayan özel bir arka uç kullanarak bir ana bilgisayar aracına bir RGB565 görüntüsü akıtın:

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

Bağlanmak, kamera üzerindeki betiği göndermek ve her çerçeveyi çekmek için openmv Python paketini (pip install openmv) kullanan eşleşen ana bilgisayar tarafı betik:

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

/dev/ttyACM0 ifadesini kameranın seri portuyla değiştirin (ör. Windows’ta COM3). openmv.camera.Camera yapıcısı, kamera tarafı yığın eşleşecek şekilde yeniden yapılandırıldığında init ile aynı protokol parametrelerini (crc / seq / ack / events / max_payload / max_retry / timeout) kabul eder.

Fonksiyonlar#

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#

Protokol yığınını başlatır (veya yeniden yapılandırır) ve varsayılan mantıksal veri kanallarını (stdin, stdout, stream ve derlemeye dahil edilmişse profile) kaydeder. Başlatma başarısız olursa RuntimeError yükseltir. Aygıt yazılımı, varsayılan bir USB protokol yığını zaten çalışır durumdayken açılır; bu nedenle bunun çağrılması yalnızca aktarımı değiştirmek veya varsayılan çerçeveleme parametrelerini geçersiz kılmak için gereklidir. Yeniden çağrılması yığını yeniden başlatır: önceki yoklama zamanlayıcısı kaldırılır ve kanallar yeniden kaydedilir.

crc, protokol çerçevelerinde CRC doğrulamasını etkinleştirir.

seq, sıra numarası takibini etkinleştirir.

ack, çerçeve başına onaylamaları etkinleştirir.

events, kanal olayı bildirimlerini etkinleştirir.

max_payload, bayt cinsinden maksimum yük boyutudur. Atlanırsa aşağıdaki kamera başına varsayılan değer kullanılır; bu değer her kartın protokol arabellek boyutundan buffer - 10 (header) - 4 (CRC) olarak türetilir.

Kamera

Arabellek boyutu

Maksimum yük

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, yeniden iletim denemelerinin sayısıdır. Varsayılan 3.

rtx_timeout_ms, milisaniye cinsinden yeniden iletim zaman aşımıdır (her zaman aşımından sonra ikiye katlanır). Varsayılan 500.

lock_interval_ms, milisaniye cinsinden minimum kilit aralığıdır. Varsayılan 10.

poll_ms, milisaniye cinsinden yoklama aralığıdır. 0 (varsayılan) zamanlayıcı yoklamasını devre dışı bırakır.

protocol.is_active() → bool#

Bir ana bilgisayar şu anda bağlıysa ve protokol yığını etkinse True, aksi takdirde False döndürür.

protocol.poll() → int#

Protokol görevinin bir yinelemesini çalıştırır: aktarımın alma arabelleğini boşaltır, tamamlanmış çerçeveleri ayrıştırır, komutları dağıtır ve kanal olaylarına hizmet verir. Aygıt yazılımı bunu normalde sizin için USB kesmesinden ve poll_ms zamanlayıcısından yapar; bu nedenle yalnızca bunların hiçbiri tarafından sürülmeyen özel aktarımlar için gereklidir – örneğin poll_ms=0 olduğunda ve aktarım betiğin ana döngüsünden yoklandığında.

Başarı durumunda 0, kayıtlı etkin bir aktarım yoksa veya çağrı bir kesme bağlamından yapıldıysa -1 döndürür.

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

Bir Python backend nesnesini yeni bir mantıksal kanal olarak kaydeder ve bir ProtocolChannel tutamacı döndürür. backend nesnesinin mevcut metotları (aşağıdaki Arka Uç Arayüzü bölümüne bakın) kanalın yeteneklerini belirler; ilgili metotlar uygulandığında protocol.CHANNEL_FLAG_READ, protocol.CHANNEL_FLAG_WRITE ve protocol.CHANNEL_FLAG_LOCK otomatik olarak flags değerine eklenir.

name, dize olarak kanal adıdır. Aygıt yazılımının kanal adı arabellek boyutuna kısaltılır. Gerekli.

backend, arka uç arayüzünü uygulayan Python nesnesidir. Gerekli. Genellikle anahtar kelime ile geçirilir (backend=...).

flags, ek kanal bayrak bitleridir (CHANNEL_FLAG_* sabitlerine bakın). İsteğe bağlı; varsayılan değer 0.

Kanal kaydedilemezse (ör. boş kanal yuvası yoksa) RuntimeError yükseltir.

Sınıflar#

class protocol.ProtocolChannel#

protocol.register tarafından döndürülen tutamaç. Örnekler doğrudan oluşturulmaz.

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

Ana bilgisayara bir kanal olayı bildirimi gönderir.

event, olay tanımlayıcısıdır (tam sayı).

wait_ack, True ise ana bilgisayar olayı onaylayana kadar bloke eder.

Olay gönderimi başarısız olursa RuntimeError yükseltir.

Arka Uç Arayüzü#

protocol.register fonksiyonuna geçirilen bir arka uç nesnesi, aşağıdaki metotların herhangi bir alt kümesini uygulayabilir. Yalnızca nesnede mevcut olan metotlar C protokol katmanına bağlanır; eksik metotlar ilgili yeteneği devre dışı bırakır.

class protocol.backend#

protocol.register fonksiyonuna geçirilen kanal arka uç nesnesi. Aşağıdaki metotlar, bir Python arka ucunun uygulayabileceği isteğe bağlı arayüzü açıklar.

init() → object#

Kanal başlatıldığında bir kez çağrılır. Başarı durumunda None olmayan herhangi bir değer döndürün; bir istisna veya eksik dönüş hata olarak değerlendirilir.

poll() → bool#

Kanalda ana bilgisayar tarafından okunmaya hazır veri varsa True döndürür.

lock() → bool#

Bir aktarım için kanalı edinir. Başarı durumunda True döndürür.

unlock() → bool#

Bir aktarımdan sonra kanalı serbest bırakır. Başarı durumunda True döndürür.

size() → int#

Kanaldan şu anda okunabilen bayt sayısını döndürür.

shape() → tuple#

Veri şeklini açıklayan en fazla dört tam sayıdan oluşan bir demet döndürür (ör. görüntü boyutları). Protokol katmanı en fazla dört öğe tüketir.

flush() → object#

Bekleyen herhangi bir veriyi boşaltır. Başarı durumunda None olmayan herhangi bir değer döndürün.

read(offset: int, size: int) → bytes#

offset konumundan başlayarak en fazla size bayt, arabellek protokolünü destekleyen bytes benzeri bir nesne olarak döndürür.

readp(offset: int, size: int) → bytes#

read metodunun sıfır kopyalı (zero-copy) varyantı. Altta yatan belleği protokol katmanı tarafından doğrudan okunan bir arabellek döndürür; arabellek, aktarım süresince geçerli kalmalıdır.

write(offset: int, data: bytearray) → int#

offset konumunda data verisini yazar. data, doğrudan C arabelleğine referans veren bir bytearray nesnesidir. Yazılan bayt sayısını veya varsayılan başarı durumunda 0 döndürür.

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

Bir ioctl işler. length sıfır ise arg değeri None, aksi takdirde C arabelleğine referans veren bir bytearray nesnesidir. Başarı durumunda 0 veya None, hata durumunda negatif bir tam sayı döndürün.

is_active() → bool#

Taşıma kanalları için, altta yatan taşıma şu anda bağlıysa True döndürür.

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

Adlandırılmış alanları SenML uyumlu tamsayı anahtarlar kullanarak CBOR’a serileştiren, daha üst düzey bir Python arka ucu (dondurulmuş protocol paketi tarafından sağlanır). Görüntüleme widget’larını (label, text, depth, waveform) ve on_read/on_write geri çağrılarına sahip etkileşimli denetimleri (toggle, pushbutton, slider, spinbox, select, radio, lineedit) destekler.

on_read, kanal ana bilgisayar için serileştirilmeden önce çağrılan isteğe bağlı bir çağrılabilir on_read(channel) nesnesidir. Alan değerlerini yenilemek için kullanın.

on_write, ana bilgisayar adlandırılmış bir alan için yeni bir değer yazdığında çağrılan isteğe bağlı bir çağrılabilir on_write(channel, name, value) nesnesidir.

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, sample_rate: float | None = None, series: int = 1, typecode: str | None = None) → None#

Kanala adlandırılmış bir alan ekler.

name, görüntülenen addır; bu kanal içinde benzersiz olmalıdır.

type widget türüdür:

  • "label" – isteğe bağlı bir unit ile salt okunur sayısal gösterge.

  • "text" – salt okunur dize göstergesi.

  • "toggle" – boolean anahtar.

  • "pushbutton" – anlık eylem (tetikleme, kalibrasyon, …). Ana bilgisayar tıklandığında True yazar ve herhangi bir durum göstermez.

  • "slider" – min/max/step ile sayısal denetim.

  • "spinbox" – hassas adımlı sayısal giriş; kaydırıcı alanlarını ve (min, max, value) demet güncelleme biçimini paylaşır.

  • "select" – options dizelerinden oluşan açılır liste.

  • "radio" – bir radyo düğmesi grubu olarak gösterilen options seçenekleri.

  • "lineedit" – yazılabilir dize girişi.

  • "depth" – width x height boyutunda 2B derinlik haritası göstergesi.

  • "waveform" – aralıklı (interleaved) örneklerden oluşan 1B zaman serisi grafiği.

value başlangıç değeridir. Varsayılan, type değerine bağlıdır: label için 0, text/lineedit/select/ radio için "", toggle/pushbutton için False, slider/spinbox için min.

unit, label/slider/spinbox/ waveform için birim dizesidir (ör. "Cel", "%RH").

min minimum değerdir (slider/spinbox aralığı veya depth/waveform görüntüleme aralığı).

max maksimum değerdir (slider/spinbox aralığı veya depth/waveform görüntüleme aralığı).

step adım boyutudur (slider/spinbox).

options seçenek dizelerinin listesi (select/radio) veya seri başına adların listesidir (waveform).

width, piksel cinsinden genişliktir (depth).

height, piksel cinsinden yüksekliktir (depth).

sample_rate saniyedeki örnek sayısı cinsinden örnekleme hızıdır (waveform). Ana bilgisayara örnekleme periyodu olarak gönderilir.

series her örnek bloğundaki aralıklı (interleaved) seri sayısıdır (waveform), ör. bir XYZ ivmeölçer izi için 3.

typecode dalga biçimi örneklerinin array tür kodudur (ör. "H", "h", "f"). Varsayılan "H" (işaretsiz 16 bit).

__getitem__(name: str) → object#

Adlandırılmış alanın geçerli değerini döndürür. depth ve waveform alanları için ikili veri arabelleği, aksi halde skaler değer döndürülür.

__setitem__(name: str, value: Any) → None#

Adlandırılmış alanın değerini ayarlar. slider ve spinbox alanları için bir (min, max, value) demeti aralığı ve geçerli değeri aynı anda günceller. depth alanları için value ikili veri arabelleğidir. waveform alanları için value, alanın typecode türünde aralıklı örneklerden oluşan bayt benzeri bir bloktur; seri başına örnek sayısı bloğun uzunluğundan türetilir ve ana bilgisayarın parçayı zaman eksenine yerleştirebilmesi için monoton bir zaman damgası (mikrosaniye cinsinden, time.ticks_us() üzerinden biriktirilen) eklenir.

poll() → bool#

Arka uç arayüzü metodu. Ana bilgisayar için serileştirilmiş veri mevcut olduğunda True döndürür.

size() → int#

Arka uç arayüzü metodu. on_read metodunu (ayarlanmışsa) çağırır ve serileştirilmiş arabelleğin boyutunu döndürür.

read(offset: int, size: int) → bytes#

Arka uç arayüzü metodu. Serileştirilmiş arabelleğin bir dilimini döndürür.

write(offset: int, data: bytearray) → int#

Arka uç arayüzü metodu. Bir CBOR güncelleme listesini çözer ve değerleri eşleşen adlandırılmış alanlara uygular; her biri için on_write metodunu çağırır.

Sabitler#

Kanal bayrak bitleri (bit düzeyinde birleştirilir; flags aracılığıyla protocol.register fonksiyonuna geçirilir veya arka ucun metotlarına göre otomatik olarak ayarlanır).

protocol.CHANNEL_FLAG_READ: int#

Kanal okumaları destekler.

protocol.CHANNEL_FLAG_WRITE: int#

Kanal yazmaları destekler.

protocol.CHANNEL_FLAG_LOCK: int#

Kanal lock/unlock işlemlerini uygular.

protocol.CHANNEL_FLAG_PHYSICAL: int#

Kanal fiziksel bir taşımayı temsil eder (mantıksal bir veri kanalının aksine).

Yerleşik kanal tanımlayıcıları.

protocol.CHANNEL_ID_TRANSPORT: int#

Etkin taşıma için ayrılmış kanal kimliği.

protocol.CHANNEL_ID_STDIN: int#

Yerleşik stdin kanalının kanal kimliği.

protocol.CHANNEL_ID_STDOUT: int#

Yerleşik stdout kanalının kanal kimliği.

protocol.CHANNEL_ID_STREAM: int#

Yerleşik stream kanalının kanal kimliği.

protocol.CHANNEL_ID_PROFILE: int#

Yerleşik profil oluşturucu kanalının kanal kimliği (yalnızca aygıt yazılımı profil oluşturucu etkinleştirilerek derlendiğinde mevcuttur).