12.6. Imenovani kanali#
ID kanala u zaglavlju svakog paketa omogućuje da do 32 neovisna toka dijele isti fizički transport. Sloj kanala pretvara te numeričke ID-ove u imenovane, aplikaciji vidljive krajnje točke na koje se kod domaćina može pozivati nizom znakova.
12.6.1. Četiri ugrađena kanala#
Kamera registrira četiri kanala pri pokretanju, prije nego što se izvrši bilo koji aplikacijski kod:
stdin– bajtovi skripte koje domaćin šalje kameri na izvršavanje. IDE koristi ovaj kanal za slanje skripte koja se uređuje;exec()na SDK-u domaćina ekvivalentan je poziv iz Python programa.stdout– bajtovi iz pozivaprint()na kameri i tragovi neuhvaćenih iznimaka. Serijska konzola IDE-a čita ovaj kanal.stream– kanal za prikaz uživo. IDE iz njega povlači JPEG sličice; bilo koja skripta domaćina može učiniti isto pomoćuread_frame().profile– događaji profilera, prisutni samo kada je kamera izgrađena s omogućenim profiliranjem. Većina izdanih verzija to izostavlja.
Aplikacijski kod rijetko treba dirati bilo koji od ugrađenih kanala; zanimljiv rad odvija se na kanalima koje aplikacija sama registrira.
12.6.2. Registriranje kanala#
Skripta na strani kamere registrira novi kanal pozivanjem protocol.register() s imenom i Python pozadinskim objektom:
import json
import protocol
import time
trigger_count = 0
class StatusChannel:
def size(self):
# Refresh the snapshot on every host query.
self._buf = json.dumps({
'uptime_s': time.ticks_ms() // 1000,
'triggers': trigger_count,
}).encode()
return len(self._buf)
def read(self, offset, size):
return self._buf[offset:offset + size]
protocol.register(name='status', backend=StatusChannel())
Metode pozadinskog objekta određuju što kanal može raditi. Pozadinski objekt sa samo size i read je podatkovni kanal samo za čitanje; dodajte write i postaje dvosmjeran; dodajte poll i domaćin može upitati jesu li novi podaci spremni prije nego što plati za čitanje. Uzorkovanje podataka unutar size najjednostavniji je obrazac kada je korisni teret dovoljno malen da stane u jedan fragment – međuspremnik se generira na zahtjev, nikad se ne sprema u predmemoriju, nikad ne dolazi do utrke. Veći korisni tereti – slikovne sličice, senzorski tragovi – trebaju obrazac zasuna koji drži međuspremnik dok domaćin ne završi svoje višefragmentno čitanje, što je obrađeno uz kanal sličica.
Mala količina vođenja evidencije odvija se automatski:
Biblioteka dodjeljuje sljedeći slobodan ID kanala (između 0 i 31).
Zastavice mogućnosti izvode se iz prisutnih metoda:
CHANNEL_FLAG_READako je definiranaread,CHANNEL_FLAG_WRITEako je definiranawrite,CHANNEL_FLAG_LOCKako su definiranelock/unlock.Paket događaja
CHANNEL_REGISTEREDšalje se svakom povezanom domaćinu kako bi se njegov popis kanala ažurirao.
Povratna vrijednost je rukovatelj protocol.ProtocolChannel koji aplikacija može zadržati. Metoda rukovatelja send_event() predstavlja kuku na strani kamere za obavještavanje domaćina da se „nešto dogodilo na ovom kanalu bez promjene podataka za čitanje” – okidač je aktiviran, gumb je pritisnut, prijeđena je prekretnica u broju uzoraka.
12.6.3. Čitanje kanala s domaćina#
SDK domaćina isporučuje se kao paket openmv na PyPI-ju (pip install openmv), izgrađen na pyserial za transport. Njegova klasa openmv.camera.Camera izlaže imenovane kanale kamere putem visokorazinskih metoda:
from openmv.camera import Camera
with Camera('/dev/ttyACM0', baudrate=921600) as cam:
cam.update_channels()
if cam.has_channel('status'):
size = cam.channel_size('status')
data = cam.channel_read('status', size)
Upozorenje
Paket openmv zahtijeva CPython 3.12 ili noviji. Raniji interpreteri nemaju značajke o kojima SDK ovisi; instalirajte verziju 3.12+ prije pip install openmv.
Nekoliko stvari koje treba primijetiti u vezi s postavljanjem:
Niz znakova serijskog priključka – ovdje
/dev/ttyACM0– u stilu jeCOM3na sustavu Windows,/dev/cu.usbmodemXXXXna macOS-u i/dev/ttyACM*na Linuxu. Stvarni broj ovisi o tome kao koji se priključak kamera nabrojala.Brzina prijenosa je magična vrijednost protokola
921600, koju USB-CDC stog kamere prepoznaje kao „ovaj klijent govori protokolom, a ne REPL-om”. Bilo koja druga brzina vraća se na običnu serijsku liniju.Upravitelj konteksta
with Camera(...) as cam:otvara transport, izvodiPROTO_SYNC, razmjenjuje mogućnosti i pri izlazu uredno zatvara priključak. Eksplicitan pozivupdate_channels()nakon ulaska osvježava lokalni popis kanala svim kanalima koje je aplikacija registrirala nakon pokretanja.
channel_size() i channel_read() su radne metode; channel_write() šalje međuspremnik kameri i natrag ako pozadinski objekt ima metodu write; has_channel() siguran je način provjere je li ime registrirano prije njegove uporabe. Ime kanala traži se jednom u ID kanala koji je kamera dodijelila tijekom register i koristi se u svakom paketu od tada nadalje.
Svaki par channel_size() / channel_read() košta dva povratna putovanja: jedan paket za upit o veličini, jedan za upit o bajtovima. Preko USB-CDC-a oba završavaju zajedno za otprilike jednu milisekundu; preko UART-a ista razmjena traje dulje razmjerno brzini prijenosa serijske linije. Aplikacijski kod koji čita u uskoj petlji trebao bi pozivati channel_size() samo kada se veličina zaista može promijeniti – za podatke fiksne veličine, veličina iz prvog poziva može se spremiti u predmemoriju.
12.6.4. Neovisnost među kanalima#
Vrijedi znati tri stvari o tome kako kanali međusobno djeluju:
Neovisna kontrola toka. Svaki kanal ima vlastito stanje čitanja na čekanju, vlastite podatke i vlastite povratne pozive
size/read/write. Dugotrajno čitanje na kanalustreamne blokira čitanja na aplikacijskom kanaluconfig.Sekvencijalno po kanalu. Unutar jednog kanala paketi se isporučuju po redu. Sloj pouzdanosti to jamči čak i kada su uključeni ponovni prijenosi.
Dijeljeni transport, dijeljeni proračun za ponovni prijenos. Svi kanali dijele jednu fizičku vezu, pa bujica prometa na jednom kanalu usporava ostale zaposjedanjem žice. Mehanizam
CHANNEL_LOCKomogućuje jednom kanalu da rezervira žicu za atomarno čitanje višestrukih paketa; pozadinski objekt se uključuje implementiranjem povratnih pozivalock/unlock.
Kanal je minimalna površina na kojoj se program domaćina i program kamere dogovaraju o suradnji. Ime, smjer (čitanje ili pisanje ili oboje), metode povratnih poziva na strani kamere i odgovarajući pozivi metoda na strani domaćina čine cijeli ugovor.