12.6. Nimetyt kanavat¶
Kunkin paketin otsakkeessa oleva kanavatunnus mahdollistaa jopa 32 itsenäisen virran jakamisen samaan fyysiseen siirtotiehen. Kanavakerros muuntaa nämä numeeriset tunnukset nimetyiksi, sovellukselle näkyviksi päätepisteiksi, joihin isäntäkoodi voi viitata merkkijonolla.
12.6.1. Neljä sisäänrakennettua kanavaa¶
Kamera rekisteröi käynnistyksessä neljä kanavaa, ennen kuin mikään sovelluskoodi suoritetaan:
stdin– skriptitavut, jotka isäntä työntää kameralle suoritettavaksi. IDE käyttää tätä kanavaa lähettääkseen muokattavaa skriptiä; isäntä-SDK:nexec()on vastaava kutsu Python-ohjelmasta.stdout– tavut kameranprint()-kutsuista ja käsittelemättömistä poikkeusten jäljitystiedoista. IDE:n sarjakonsoli lukee tätä kanavaa.stream– reaaliaikaisen esikatselun kanava. IDE hakee siitä JPEG-kehyksiä; mikä tahansa isäntäskripti voi tehdä samanread_frame()-metodilla.profile– profilointitapahtumat, läsnä vain kun kamera on käännetty profilointi käytössä. Useimmat julkaisukäännökset jättävät sen pois.
Sovelluskoodin tarvitsee harvoin koskea mihinkään sisäänrakennetuista; mielenkiintoinen työ tapahtuu kanavilla, jotka sovellus rekisteröi itse.
12.6.2. Kanavan rekisteröinti¶
Kameran puolen skripti rekisteröi uuden kanavan kutsumalla protocol.register() -funktiota nimellä ja Python-backend-objektilla:
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())
Backend-objektin metodit päättävät, mitä kanava voi tehdä. Backend, jossa on vain size ja read, on vain luettava datakanava; lisää write, ja siitä tulee kaksisuuntainen; lisää poll, ja isäntä voi kysyä, onko uutta dataa valmiina, ennen kuin maksaa luvusta. Datan näytteenotto size-metodin sisällä on yksinkertaisin malli, kun hyötykuorma on tarpeeksi pieni mahtuakseen yhteen fragmenttiin – puskuri luodaan pyynnöstä, sitä ei koskaan välimuistiteta eikä siihen tule kilpailutilannetta. Suuremmat hyötykuormat – kuvakehykset, sensorijäljet – tarvitsevat lukitsevan mallin, joka pitää puskurin, kunnes isäntä on saanut usean fragmentin lukunsa valmiiksi; tämä käsitellään kehyskanavan yhteydessä.
Pieni määrä kirjanpitoa tapahtuu automaattisesti:
Kirjasto määrittää seuraavan vapaan kanavatunnuksen (välillä 0–31).
Ominaisuuslippu johdetaan läsnä olevista metodeista:
CHANNEL_FLAG_READ, josreadon määritelty,CHANNEL_FLAG_WRITE, joswriteon määritelty,CHANNEL_FLAG_LOCK, joslock/unlockon määritelty.CHANNEL_REGISTERED-tapahtumapaketti lähetetään jokaiselle yhdistetylle isännälle, jotta sen kanavalista päivittyy.
Paluuarvo on protocol.ProtocolChannel -kahva, jonka sovellus voi pitää tallessa. Kahvan send_event() -metodi on kameran puolen koukku, jolla kerrotaan isännälle, että ”tällä kanavalla tapahtui jotain muuttamatta luettavaa dataa” – liipaisin laukesi, painiketta painettiin, näytemäärän virstanpylväs saavutettiin.
12.6.3. Kanavien lukeminen isännältä¶
Isäntä-SDK toimitetaan openmv-pakettina PyPI:ssä (pip install openmv), ja se on rakennettu pyserial-kirjaston päälle siirtotietä varten. Sen openmv.camera.Camera -luokka tuo kameran nimetyt kanavat esiin korkean tason metodien kautta:
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)
Varoitus
openmv-paketti vaatii CPython 3.12:n tai uudemman. Vanhemmista tulkeista puuttuu ominaisuuksia, joista SDK riippuu; asenna 3.12+ -käännös ennen komentoa pip install openmv.
Muutama asetuksiin liittyvä huomio:
Sarjaporttimerkkijono – tässä
/dev/ttyACM0– on WindowsissaCOM3-tyylinen, macOS:ssä/dev/cu.usbmodemXXXXja Linuxissa/dev/ttyACM*. Varsinainen numero riippuu siitä, mihin porttiin kamera ilmaantui.Siirtonopeus on protokollan taikaluku
921600, jonka kameran USB-CDC-pino tunnistaa merkitsevän ”tämä asiakas puhuu protokollaa, ei REPL:iä”. Mikä tahansa muu nopeus palautuu tavalliseksi sarjalinjaksi.with Camera(...) as cam:-kontekstinhallinta avaa siirtotien, suorittaaPROTO_SYNC-toiminnon, vaihtaa ominaisuustiedot ja sulkee portin siististi poistuttaessa. Eksplisiittinenupdate_channels()-kutsu sisäänkirjautumisen jälkeen päivittää paikallisen kanavalistan kaikilla kanavilla, jotka sovellus rekisteröi käynnistyksen jälkeen.
channel_size() ja channel_read() ovat työjuhtametodit; channel_write() lähettää puskurin edestakaisin kameralle, jos backendissa on write-metodi; has_channel() on turvallinen tapa tarkistaa, että nimi on rekisteröity ennen sen käyttöä. Kanavan nimi haetaan kerran kanavatunnukseksi, jonka kamera määritti register-vaiheessa, ja sitä käytetään siitä eteenpäin jokaisessa paketissa.
Kukin channel_size() / channel_read() -pari maksaa kaksi edestakaista kierrosta: yksi paketti koon pyytämiseen, yksi tavujen pyytämiseen. USB-CDC:n kautta molemmat valmistuvat yhteensä noin millisekunnissa; UARTin kautta sama vaihto kestää pidempään suhteessa sarjalinjan siirtonopeuteen. Tiukassa silmukassa lukeva sovelluskoodi kutsukoon channel_size() -metodia vain silloin, kun koko voi todella muuttua – kiinteäkokoiselle datalle ensimmäisen kutsun koko voidaan välimuistittaa.
12.6.4. Kanavien riippumattomuus¶
Kolme asiaa kanavien vuorovaikutuksesta on hyvä tietää:
Riippumaton vuonohjaus. Kullakin kanavalla on oma keskeneräinen lukutilansa, oma datansa ja omat
size/read/write-takaisinkutsunsa. Pitkäkestoinen lukustream-kanavalla ei estä lukuja sovelluksenconfig-kanavalla.Peräkkäinen kanavakohtaisesti. Yhden kanavan sisällä paketit toimitetaan järjestyksessä. Luotettavuuskerros takaa tämän myös silloin, kun mukana on uudelleenlähetyksiä.
Jaettu siirtotie, jaettu uudelleenlähetysbudjetti. Kaikki kanavat jakavat saman fyysisen linkin, joten liikennetulva yhdellä kanavalla hidastaa muita varaamalla johdon itselleen.
CHANNEL_LOCK-mekanismi antaa yhden kanavan varata johdon atomista usean paketin lukua varten; backend ottaa tämän käyttöön toteuttamallalock/unlock-takaisinkutsut.
Kanava on pienin pinta-ala, jolla isäntäohjelma ja kameraohjelma sopivat yhteistyöstä. Nimi, suuntaisuus (luku tai kirjoitus tai molemmat), kameran puolen takaisinkutsumetodit ja niitä vastaavat metodikutsut isännän puolella muodostavat koko sopimuksen.