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: a bal oldalon az interaktív terminál a saját eszköztárával, a jobb oldalon a képkocka-puffer és a hisztogram

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.