12.9. Çift yönlü akış¶
Kanallar tek yönlü değildir. write uygulayan bir arka uç, ana bilgisayarın kameraya bayt göndermesine olanak tanır ve kamera tepki verir. Bu, her gerçek etkileşimli aracın ardındaki desendir: operatör ana bilgisayar grafik arayüzünde bir düğmeyi çevirir, ana bilgisayar yeni değeri bir yapılandırma kanalına yazar, kamera ise bir sonraki yakalama sırasında onu okur.
12.9.1. Bir yapılandırma kanalı¶
Akış yapan kamera tarafı betiğine ekleme yaparak, JPEG kalitesi için ikinci bir kanal sunun:
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)
Yakalama döngüsü, bir çerçeveyi her sıkıştırdığında config.quality değerinden okur:
while True:
img = csi0.snapshot()
latest_jpeg = bytes(
img.compress(quality=config.quality).bytearray()
)
ch.send_event(0x01)
Ana bilgisayar artık bir düğmeye sahip. 50 olarak ayarlayın, bir sonraki çerçeve daha küçük (ve daha çirkin) olur; 95 olarak ayarlayın, bir sonraki çerçeve daha büyük (ve daha keskin) olur. Kamera yeniden başlatmadan yakalamaya devam eder; ana bilgisayarın yeni bir betik göndermesi gerekmez.
12.9.2. Ana bilgisayardan yazma çağrısı¶
Ana bilgisayar tarafında, channel_write() adlandırılmış bir kanala bayt gönderir:
cam.channel_write('config', b'50')
Ana bilgisayar SDK’si baytları tek (veya parçalanmış) bir CHANNEL_WRITE paketi olarak kodlar, protokol katmanı bunu kameraya teslim eder, kameranın write(offset=0, data=...) çağrısı çalışır ve kameranın tarafı onaylar. Çağrı döndüğünde kamera yeni değeri almış ve kabul etmiştir.
Yazma işlemi kameranın bakış açısından atomiktir – protokol kütüphanesi, o kanalda başka herhangi bir işlem ilerlemeden önce arka ucun write çağrısının tamamlanana kadar çalışmasını garanti eder. Uygulama kodu, ana bilgisayarın anlık görüntünün ortasında müdahale etmesinden endişe etmeden yakalama döngüsünün içinden config.quality değerini okuyabilir.
12.9.3. Saplama boyut ve yalnızca yazılabilir bir kanalda okuma¶
Salt yazma kanalı, 0 ve b'' döndüren saplamalar olsalar bile yine de tanımlanmış size ve read gerektirir. Kütüphane, kanalın yetenek bayraklarını türetmek için yöntemlerin varlığını kullanır; read eksik olan bir arka uç CHANNEL_FLAG_READ ayarlanmamış olur ve ana bilgisayar bir okuma girişimini reddeder.
Yine de, salt yazma kanalında read çağrısından dönen baytlar farklı bir amaç için faydalıdır: yeni bağlanan bir ana bilgisayarın bir varsayılandan başlamak yerine kameraya “geçerli ayar nedir?” diye sorabilmesi için mevcut değeri geri yansıtmak. Bunu işe yarar hale getirmek için her iki yönün de bir serileştirme üzerinde anlaşması gerekir. Önceki örnekteki ham bayt int(bytes(data)) ayrıştırması tek bir tam sayı alanı için çalışır ancak ayarlanacak ikinci bir düğme olduğunda ölçeklenmez. write çağrısını JSON ayrıştıracak şekilde değiştirip eşleşen JSON dökümünü döndüren bir read ile eşleştirmek, kanalı gerçek bir gidiş-dönüş yapılandırma deposuna dönüştürür:
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)
Ana bilgisayar artık bir değer ayarlamak için cam.channel_write('config', b'{"quality": 50}') ve geçerli durumu geri okumak için cam.channel_read('config') yazar. Kamera her okumada taze bir JSON dökümü serileştirir, böylece ana bilgisayar her zaman en son değerleri görür ve başka bir düğme (threshold, exposure, orientation) eklemek, her iki taraftaki JSON sözlüğünde tek bir satırdır.
12.9.4. Eksiksiz bir döngü¶
Kameradan ana bilgisayara veri için bir çerçeve kanalı, ana bilgisayardan kameraya denetim için bir yapılandırma kanalı ve az miktarda yapıştırıcı kod ile uygulama etkileşimli bir araçtır:
Ana bilgisayar kamerayı açar, çerçeveleri çekmeye başlar ve bunları bir pencerede görüntüler.
Operatör bir kaydırıcıyı sürüklediğinde, ana bilgisayar yeni değeri
configüzerine yazar.Kameranın yakalama döngüsü değeri bir sonraki çerçevede alır.
Yeni çerçeveler aynı
framekanalı üzerinden akar.
Tüm model budur. İki kanal, her birinde iki geri çağırma, kamerada bir yakalama döngüsü, ana bilgisayarda bir oku-ve-yaz döngüsü. Görünür çerçeveleme mantığı yok, görünür hata işleme yok – protokol kütüphanesi güvenilir bayt hareketini gözden kaybeder.
Bu noktadan sonra her şey uygulama kodudur. Bir histogram için üçüncü bir kanal, telemetri için dördüncü bir kanal veya sensör tetikleyicileri için beşinci bir kanal eklemek, aynı arka-uç-sınıfı-ve-protocol.register tarifinin tekrarıdır. Bir kamera projesi bu noktaya ulaştığında protokol artık ilginç problem olmaktan çıkar; bunun yerine uygulamanın kendi mantığı bu rolü üstlenir.