12.6. Elnevezett csatornák¶
Az egyes csomagok fejlécében lévő csatornaazonosító lehetővé teszi, hogy legfeljebb 32 független adatfolyam ossza meg ugyanazt a fizikai átvitelt. A csatornaréteg ezeket a numerikus azonosítókat elnevezett, az alkalmazás számára látható végpontokká alakítja, amelyekre a gazdagép kódja sztring alapján hivatkozhat.
12.6.1. A négy beépített csatorna¶
A kamera négy csatornát regisztrál indításkor, mielőtt bármilyen alkalmazáskód lefutna:
stdin– szkriptbájtok, amelyeket a gazdagép a kamerára küld végrehajtásra. Az IDE ezt a csatornát használja a szerkesztett szkript elküldésére; aexec()a gazdagép SDK-ban az ezzel egyenértékű hívás egy Python programból.stdout– bájtok a kameraprint()hívásaiból és az elkapatlan kivételek visszakövetéseiből. Az IDE soros konzolja ezt a csatornát olvassa.stream– az élő előnézeti csatorna. Az IDE JPEG képkockákat húz ki belőle; bármely gazdagép-szkript ugyanezt megteheti aread_frame()segítségével.profile– profilozási események, amelyek csak akkor vannak jelen, ha a kamera profilozás engedélyezésével lett lefordítva. A legtöbb kiadási build elhagyja.
Az alkalmazáskódnak ritkán kell hozzányúlnia bármelyik beépített csatornához; az érdekes munka azokon a csatornákon történik, amelyeket az alkalmazás maga regisztrál.
12.6.2. Csatorna regisztrálása¶
Egy kamera oldali szkript úgy regisztrál új csatornát, hogy meghívja a protocol.register() függvényt egy névvel és egy Python backend objektummal:
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())
A backend objektum metódusai döntik el, hogy mit tehet a csatorna. Egy olyan backend, amelynek csak size és read metódusa van, egy csak olvasható adatcsatorna; adja hozzá a write metódust, és kétirányúvá válik; adja hozzá a poll metódust, és a gazdagép megkérdezheti, hogy van-e új adat készen, mielőtt megfizetné egy olvasás árát. Az adat mintavételezése a size belsejében a legegyszerűbb minta, amikor a hasznos terhelés elég kicsi ahhoz, hogy egy töredékbe férjen – a puffer igény szerint generálódik, soha nem gyorsítótárazódik, soha nem kerül versenyhelyzetbe. A nagyobb hasznos terhelések – képkockák, érzékelőnyomok – reteszelő mintát igényelnek, amely a puffert addig tartja, amíg a gazdagép be nem fejezi a több töredékből álló olvasását, amit a képkocka-csatorna tárgyal.
Egy kevés könyvelés automatikusan megtörténik:
A könyvtár hozzárendeli a következő szabad csatornaazonosítót (0 és 31 között).
A képességjelzők a jelen lévő metódusokból származnak:
CHANNEL_FLAG_READ, ha areaddefiniált,CHANNEL_FLAG_WRITE, ha awritedefiniált,CHANNEL_FLAG_LOCK, ha alock/unlockdefiniált.Egy
CHANNEL_REGISTEREDeseménycsomag kerül elküldésre minden csatlakoztatott gazdagépnek, hogy a csatornalistája frissüljön.
A visszatérési érték egy protocol.ProtocolChannel leíró, amelyet az alkalmazás megtarthat. A leíró send_event() metódusa a kamera oldali horog, amellyel közölheti a gazdagéppel, hogy „valami történt ezen a csatornán anélkül, hogy az olvasható adat megváltozott volna” – egy trigger elsült, egy gombot megnyomtak, egy mintaszám mérföldkő elérkezett.
12.6.3. Csatornák olvasása a gazdagépről¶
A gazdagép SDK az openmv csomagként szállítódik a PyPI-n (pip install openmv), amely a pyserial könyvtárra épül az átvitelhez. Az openmv.camera.Camera osztálya magas szintű metódusokon keresztül teszi elérhetővé a kamera elnevezett csatornáit:
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)
Figyelem
Az openmv csomag CPython 3.12-t vagy újabbat igényel. A korábbi értelmezőkből hiányoznak azok a funkciók, amelyekre az SDK támaszkodik; telepítsen egy 3.12+ buildet az pip install openmv előtt.
Néhány dolog, amit érdemes megfigyelni a beállításnál:
A soros port sztringje – itt
/dev/ttyACM0–COM3stílusú Windowson,/dev/cu.usbmodemXXXXmacOS-en és/dev/ttyACM*Linuxon. A tényleges szám attól függ, hogy a kamera melyik portként számozódott fel.Az átviteli sebesség a protokoll varázsértéke, a
921600, amelyet a kamera USB-CDC verme úgy ismer fel, hogy „ez a kliens a protokollt beszéli, nem a REPL-t.” Bármilyen más sebesség egyszerű soros vonalra esik vissza.A
with Camera(...) as cam:kontextuskezelő megnyitja az átvitelt, lefuttatja aPROTO_SYNC-et, kicseréli a képességeket, és kilépéskor tisztán bezárja a portot. A belépés utáni explicitupdate_channels()hívás frissíti a helyi csatornalistát minden olyan csatornával, amelyet az alkalmazás indítás után regisztrált.
A channel_size() és a channel_read() az igáslómetódusok; a channel_write() oda-vissza küld egy puffert a kamerára, ha a backendnek van write metódusa; a has_channel() a biztonságos módja annak, hogy ellenőrizze, egy név regisztrálva van-e, mielőtt használná. A csatornanevet egyszer keresi ki arra a csatornaazonosítóra, amelyet a kamera a register során hozzárendelt, és attól kezdve minden csomagban azt használja.
Minden channel_size() / channel_read() páros két oda-vissza utat igényel: egy csomagot a méret lekérdezésére, egyet a bájtok lekérdezésére. USB-CDC-n keresztül mindkettő összesen körülbelül egy ezredmásodperc alatt befejeződik; UART-on keresztül ugyanaz a csere a soros vonal átviteli sebességével arányosan tovább tart. Az olyan alkalmazáskódnak, amely szoros ciklusban olvas, csak akkor szabad meghívnia a channel_size() metódust, amikor a méret ténylegesen változhat – rögzített méretű adatoknál az első hívás mérete gyorsítótárazható.
12.6.4. Csatornák közötti függetlenség¶
Három dolgot érdemes tudni arról, hogyan lépnek kölcsönhatásba a csatornák:
Független folyamatvezérlés. Minden csatornának saját függőben lévő olvasási állapota, saját adata és saját
size/read/writevisszahívásai vannak. Astreamcsatornán futó hosszú olvasás nem blokkolja az alkalmazásconfigcsatornáján történő olvasásokat.Csatornánként szekvenciális. Egyetlen csatornán belül a csomagok sorrendben kézbesülnek. A megbízhatósági réteg ezt akkor is garantálja, ha újraküldések vannak érintve.
Megosztott átvitel, megosztott újraküldési keret. Minden csatorna osztozik az egyetlen fizikai kapcsolaton, így az egyik csatornán zúduló forgalom lelassítja a többit azzal, hogy lefoglalja a vezetéket. A
CHANNEL_LOCKmechanizmus lehetővé teszi, hogy egy csatorna lefoglalja a vezetéket egy atomi, több csomagból álló olvasáshoz; a backend alock/unlockvisszahívások megvalósításával iratkozik fel erre.
A csatorna a minimális felület, amelyen egy gazdagép-program és egy kamera-program megegyezik az együttműködésben. A név, az irányultság (olvasás vagy írás vagy mindkettő), a kamera oldali visszahívás-metódusok és a hozzájuk illő metódushívások a gazdagép oldalán alkotják a teljes szerződést.