13.1.10. Önálló terminálablakok¶
A Tools → Open Terminal független terminálablakokat nyit meg – mindegyik egy miniatűr OpenMV IDE munkamenet a saját ablakában, képkocka-puffer nézegetővel, hisztogrammal és egy interaktív terminállal, amely az Ön által választott átviteli csatornán keresztül csatlakozik. A főablak kapcsolatát ez nem érinti, így egy önálló terminállal megfigyelhet egy második kamerát, miközben az első továbbra is csatlakozva marad, vagy egy hálózat túloldalán lévő kamerát hibakereshet.
Egy önálló terminálablak soros porton keresztül: a bal oldalon az interaktív terminál a futtatás / leállítás / visszaállítás eszköztárával, a jobb oldalon a képkocka-puffer és a hisztogram – ezek akkor jelennek meg, amikor a kamera a csatornán belül (in-band) képkockákat továbbít.¶
A New Terminal három átviteli mód egyikét kéri:
Serial port – bármely soros port, bármilyen átviteli sebességen (baud) (alapértelmezetten 115 200). Ez magában foglalja egy második kamera USB-portját, egy USB-UART híddal bekötött kamerát, egy Bluetooth soros kapcsolatot (amely közönséges soros portként jelenik meg), vagy bármely nem OpenMV soros eszközt, amelynek terminálra van szüksége. USB-porton az átviteli sebesség (baud) nem korlátozza a sebességet – az adat mindig az USB-kapcsolat sebességén mozog –, de egy kamera USB-portján kerülje a 921 600 és a 12 000 000 értéket, mivel ezek a kamerát a REPL-ből az IDE hibakereső protokolljára kapcsolják át.
TCP – csatlakozás egy szerverhez egy választott hoston és porton, vagy szerverként figyelés egy választott porton.
UDP – ugyanez a két szerepkör, UDP felett.
Az IDE megjegyzi az utolsó tíz konfigurációt, és felsorolja őket az Open Terminal almenüben az egy kattintásos újranyitáshoz; a Clear Menu elfelejti ezeket.
A főablak csak kimenetet megjelenítő paneljével ellentétben az önálló terminál teljesen interaktív: ez egy REPL. Gépeljen a parancssorba, és a Python soronként hajtja végre a kódot a csatlakoztatott kamerán, az előzményekkel és a tab-kiegészítéssel, amelyeket maga a MicroPython biztosít. Az eszköztár egy kattintásos megfelelőket ad a gyakori vezérlőszekvenciákhoz – az aktuális szerkesztőszkript futtatása, a futó szkript leállítása és a szoft visszaállítás –, valamint ugyanazokat a törlés, mentés és sortörés vezérlőket, mint a fő terminálpanel.
A terminál feletti képkocka-puffer szintén élő. Amikor a csatlakoztatott kamera tömörített képkockákat továbbít a csatornán belül (in-band) – a print kimenetével azonos adatfolyamba ágyazva –, a terminál dekódolja és megjeleníti őket, a Record és Zoom gombok pedig pontosan úgy működnek, mint a főablakban. Ez a kombináció az IDE hálózati hibakeresési megoldása: egy kamera, amely Wi-Fi felett teszi elérhetővé a REPL-jét, megkapja a teljes szerkesztés-futtatás-előnézet ciklust USB-kábel nélkül.
13.1.10.1. Képkockák továbbítása a csatornán belül (in-band)¶
A kódolás, amelyet a terminál ért, egyszerű: egy 0xFE bájt nyit meg egy képkockát, egy második 0xFE zárja le, és minden köztük lévő adatbájt felső bitje be van állítva, és a tömörített kép hat bitjét hordozza – három képbájtból négy adatbájt lesz. A sima szöveg soha nem használja ezeket a bájtértékeket, így a képkockák és a print() kimenet ütközés nélkül osztoznak az adatfolyamon: a terminál megjeleníti a szöveget és megjeleníti a képkockákat is.
Az alábbi szkript rögzít, minden képkockát JPEG formátumra alakít, és ebben a formában nyomtatja ki. A bitcsomagolás az ulab segítségével fut (amelynek nincsenek eltolási operátorai, ezért az eltolások szorzásként és osztásként vannak megírva), és elég gyors ahhoz, hogy lépést tartson a kamerával:
import csi
import sys
import time
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
clock = time.clock()
def encode_for_ide(data):
n = len(data)
n3 = n - (n % 3)
m = (n3 // 3) * 4
out = bytearray(((n * 8) + 5) // 6 + 2)
out[0] = 0xFE
out[-1] = 0xFE
if n3:
src = np.frombuffer(data, dtype=np.uint8)
dst = np.frombuffer(out, dtype=np.uint8)
b0 = src[0:n3:3]
b1 = src[1:n3:3]
b2 = src[2:n3:3]
dst[1:m + 1:4] = (b0 & 0x3F) | 0x80
dst[2:m + 2:4] = (b0 // 64) | ((b1 & 0x0F) * 4) | 0x80
dst[3:m + 3:4] = (b1 // 16) | ((b2 & 0x03) * 16) | 0x80
dst[4:m + 4:4] = (b2 // 4) | 0x80
if n % 3 == 2:
x = data[n - 2] | (data[n - 1] << 8)
out[m + 1] = 0x80 | (x & 0x3F)
out[m + 2] = 0x80 | ((x >> 6) & 0x3F)
out[m + 3] = 0x80 | ((x >> 12) & 0x3F)
elif n % 3 == 1:
out[m + 1] = 0x80 | (data[n - 1] & 0x3F)
out[m + 2] = 0x80 | (data[n - 1] >> 6)
return out
while True:
clock.tick()
img = csi0.snapshot().to_jpeg(quality=80)
sys.stdout.write(encode_for_ide(img.bytearray()))
print(clock.fps())
Ez egy önálló terminálban azért működik, mert a REPL nyomtatás vár: a kamera blokkol, amíg a terminál át nem vette az adatot, így a képkocka minden bájtja megérkezik, egy JPEG pedig gyorsan mozog egy USB full-speed vagy high-speed kapcsolaton. Ugyanez a szkript változatlanul működik egy TCP terminálon keresztül, ami a fentebb említett hálózati hibakeresési útvonal. Az egyetlen hely, ahol nem működik, az az IDE fő hibakereső kapcsolata, amelynek kimeneti csatornája túlcsordulás esetén várakozás helyett visszaállítja magát – ott a képkocka-puffer nézegető már natívan megjeleníti a kamera képkockáit, így semmi nem vész el.