12.9. Dvosmjerni tok¶
Kanali nisu jednosmjerni. Pozadinski dio koji implementira write omogućuje računalu da gura bajtove prema kameri, a kamera reagira. To je obrazac iza svakog stvarnog interaktivnog alata: operater okrene gumb na grafičkom sučelju računala, računalo upiše novu vrijednost u konfiguracijski kanal, a kamera je pročita pri sljedećem snimanju.
12.9.1. Konfiguracijski kanal¶
Nadograđujući skriptu na strani kamere za strujanje, izložite drugi kanal za JPEG kvalitetu:
class ConfigChannel:
def __init__(self):
self.quality = 85
def size(self):
return 0
def read(self, offset, size):
# Not used for "host writes to cam" -- but the library
# still needs the method present.
return b''
def write(self, offset, data):
# data is a bytearray view into the protocol buffer.
# Copy out the contents before doing anything with it.
new_q = int(bytes(data))
if 1 <= new_q <= 100:
self.quality = new_q
return len(data)
config = ConfigChannel()
protocol.register(name='config', backend=config)
Petlja snimanja čita iz config.quality svaki put kad komprimira sličicu:
while True:
img = csi0.snapshot()
latest_jpeg = bytes(
img.compress(quality=config.quality).bytearray()
)
ch.send_event(0x01)
Računalo sada ima gumb. Postavite ga na 50 i sljedeća sličica je manja (i ružnija); postavite ga na 95 i sljedeća sličica je veća (i oštrija). Kamera nastavlja snimati bez ponovnog pokretanja; računalo ne mora slati novu skriptu.
12.9.2. Poziv za pisanje s računala¶
Na strani računala, channel_write() šalje bajtove imenovanom kanalu:
cam.channel_write('config', b'50')
Host SDK kodira bajtove kao jedan (ili fragmentirani) CHANNEL_WRITE paket, sloj protokola ga isporučuje kameri, izvodi se write(offset=0, data=...) kamere i strana kamere potvrđuje. Do trenutka kada se poziv vrati, kamera je primila i prihvatila novu vrijednost.
Pisanje je atomarno iz perspektive kamere – biblioteka protokola jamči da se write pozadinskog dijela izvrši do kraja prije nego što bilo koja druga operacija na tom kanalu nastavi. Aplikacijski kod može čitati config.quality iznutra petlje snimanja bez brige da računalo nešto pregazi usred snimke.
12.9.3. Veličina kao zaglušak i čitanje na kanalu samo za pisanje¶
Čisti kanal za pisanje i dalje treba definirane size i read, čak i ako su to zaglušci koji vraćaju 0 i b''. Biblioteka koristi prisutnost metoda za izvođenje zastavica sposobnosti kanala; pozadinski dio kojem nedostaje read neće dobiti postavljen CHANNEL_FLAG_READ i računalo će odbiti pokušaj čitanja.
Bajtovi vraćeni iz read na kanalu samo za pisanje ipak su korisni za drugu svrhu: vraćanje trenutne vrijednosti kako bi računalo koje se upravo spojilo moglo pitati kameru „koja je trenutna postavka?” umjesto da kreće od zadane. Da bi to radilo, oba smjera moraju se složiti oko serijalizacije. Sirovo parsiranje bajtova int(bytes(data)) u ranijem primjeru radi za jedno cjelobrojno polje, ali neće se skalirati čim postoji drugi gumb za postavljanje. Prebacivanje write na parsiranje JSON-a i uparivanje s read koji vraća odgovarajući JSON ispis pretvara kanal u pravu pohranu konfiguracije s povratnim putom:
import json
class ConfigChannel:
def __init__(self):
self.quality = 85
self._buf = b''
def size(self):
self._buf = json.dumps({'quality': self.quality}).encode()
return len(self._buf)
def read(self, offset, size):
return self._buf[offset:offset + size]
def write(self, offset, data):
new = json.loads(bytes(data))
if 'quality' in new:
self.quality = int(new['quality'])
return len(data)
Računalo sada piše cam.channel_write('config', b'{"quality": 50}') za postavljanje vrijednosti i cam.channel_read('config') za čitanje trenutnog stanja natrag. Kamera serijalizira svjež JSON ispis pri svakom čitanju tako da računalo uvijek vidi najnovije vrijednosti, a dodavanje još jednog gumba (threshold, exposure, orientation) jedan je redak u JSON rječniku na svakoj strani.
12.9.4. Potpuna petlja¶
S kanalom za sličice za podatke kamera → računalo, konfiguracijskim kanalom za upravljanje računalo → kamera i malom količinom ljepila, aplikacija je interaktivni alat:
Računalo otvara kameru, počinje povlačiti sličice i prikazuje ih u prozoru.
Kada operater povuče klizač, računalo upisuje novu vrijednost na
config.Petlja snimanja kamere preuzima vrijednost na sljedećoj sličici.
Nove sličice teku kroz isti
framekanal.
To je cijeli model. Dva kanala, po dva povratna poziva svaki, petlja snimanja na kameri, petlja čitanja i pisanja na računalu. Nema vidljive logike uokvirivanja, nema vidljivog rukovanja pogreškama – biblioteka protokola čini pouzdano premještanje bajtova nevidljivim.
Sve nakon ove točke je aplikacijski kod. Dodavanje trećeg kanala za histogram, četvrtog za telemetriju ili petog za okidače senzora isti je recept s pozadinskom klasom i protocol.register, ponovljen. Kada projekt s kamerom dosegne ovu točku, protokol prestaje biti zanimljiv problem; to postaje vlastita logika aplikacije.