13.1.13. Editor nastavení#

Mnoho kamerových aplikací potřebuje pár nastavení, která může neprogramátor změnit – práh, režim, heslo Wi-Fi – aniž by se dotkl skriptu. OpenMV Cam Settings Editor je k tomu nástroj IDE: soubor JSON popisuje ovládací prvky, editor tento popis promění ve formulář a váš skript uložené hodnoty načte zpět pomocí json.load(). Soubor je zároveň konfigurací i definicí svého vlastního editoru, takže stejná konfigurace, která uchovává hodnoty, také rozvrhuje GUI pro jejich úpravu.

Podnabídka Tools → OpenMV Cam Settings Editor obsahuje jeho tři akce.

  • Open OpenMV Cam Settings Config File načte konfiguraci z disku připojené kamery a otevře ji v editoru; uložení ji zapíše zpět do kamery.

  • Open Config File dělá totéž pro soubor .json ve vašem počítači, pro přípravu konfigurace offline.

  • Create Default Config zapíše výchozí konfiguraci na disk a otevře ji – příklad, který procvičí každý typ ovládacího prvku, připravený k osekání na nastavení, která potřebuje vaše vlastní aplikace.

The OpenMV Cam Settings Editor showing the default demo configuration -- Camera, Processing, Network, and System tabs, with the Camera tab's exposure and gain sliders, resolution and pixel-format dropdowns, mirror and flip checkboxes, and a digital-zoom slider, above the Save and Cancel buttons

Editor nastavení s otevřenou výchozí konfigurací – ovládací prvky souboru JSON uspořádané do podoby formuláře (karty, posuvníky, rozevírací nabídky, zaškrtávací políčka), s tlačítky Save a Cancel v dolní části.#

13.1.13.1. Anatomie konfiguračního souboru#

Konfigurační soubor je jediný objekt JSON se dvěma klíči:

  • title (string, volitelné) – titulek okna editoru. Výchozí hodnota je OpenMV Cam Settings Editor.

  • controls (array, povinné) – seznam objektů ovládacích prvků, které editor vykresluje, v pořadí, jako řádky formuláře. Toto je celé grafické rozhraní.

{
  "title": "Camera Settings",
  "controls": [
    { "type": "slider", "name": "threshold", "label": "Threshold", "value": 50 },
    { "type": "checkbox", "name": "draw_overlays", "label": "Draw Overlays", "value": true }
  ]
}

Každá položka v controls je jeden ovládací prvek – textové pole, číslo, zaškrtávací políčko, rozevírací seznam, posuvník, skupina, pás karet, statický popisek a tak dále. Jeho type vybírá widget; zbytek objektu jej konfiguruje. Jakékoli klíče, které editor nerozpozná, zůstávají při ukládání souboru nedotčené, takže si v souboru můžete vedle ovládacích prvků uchovávat vlastní metadata.

13.1.13.2. Klíče společné všem ovládacím prvkům#

Každý objekt ovládacího prvku přijímá tyto klíče, ať už je jeho type jakýkoli:

  • type (string, povinné) – který widget se má sestavit, např. "slider" nebo "combobox". Chybějící nebo nerozpoznaný type vykreslí zakázaný zástupný prvek Unknown control místo toho, aby selhal celý soubor, takže překlep vás stojí jeden ovládací prvek, nikoli celý formulář.

  • name (string) – identifikátor pro vaše použití. Editor jej nikdy nečte; pouze jej zachovává. Dejte každému ovládacímu prvku jedinečný name a váš skript jej použije k nalezení uložené hodnoty tohoto ovládacího prvku.

  • label (string) – text zobrazený vedle ovládacího prvku nebo na něm. U většiny ovládacích prvků jde o formátovaný text – HTML značky a odkazy <a href> fungují.

  • tooltip (string) – text zobrazený při najetí myší na ovládací prvek.

  • enabled (boolean, výchozí true) – nastavte na false, aby se ovládací prvek zobrazil zašedlý a jen pro čtení.

Kontejnerové ovládací prvky (group, tabs) používají pro své záhlaví title místo label a tabs přijímá svůj tooltip pro každou kartu zvlášť; rozdíly jsou uvedeny na stránce každého ovládacího prvku.

13.1.13.3. Ukládání a čtení hodnot#

Ovládací prvek, který drží hodnotu – zaškrtávací políčko, posuvník, textové pole – ji nese v klíči value. Když kliknete na Uložit, editor zapíše aktuální value každého ovládacího prvku přímo zpět do téhož objektu ovládacího prvku, na místě, a přepíše soubor. Soubor si zachová svou strukturu: nic se nepřesouvá, mění se pouze klíče value. Neexistuje žádná samostatná plochá mapa z name na hodnotu – hodnoty žijí uvnitř ovládacích prvků, přesně tam, kde jsou definovány.

Proto na rozvržení vašemu skriptu záleží. Pole controls a tabs si zachovávají pořadí, v jakém jste je sestavili, takže soubor nelze indexovat podle názvu jako slovník – config["controls"]["threshold"] nefunguje. Tento malý pomocník tuto mezeru překlenuje: dejte mu cestu názvů až k hodnotě, kterou chcete, a on za vás projde strom.

import json


def find(node, *path):
    """Return the control at a path of names; read its value with
    ["value"]. The tab strip and any unnamed group are transparent,
    so you list only the tabs and controls you gave a name."""
    for key in path:
        match = _child(node, key)
        if match is None:
            raise KeyError(key)
        node = match
    return node


def _child(node, key):
    for member in node.get("controls", []) + node.get("tabs", []):
        if member.get("name") == key or member.get("title") == key:
            return member
        if "name" not in member and ("controls" in member or "tabs" in member):
            match = _child(member, key)   # see through an unnamed group / the tab strip
            if match is not None:
                return match
    return None


with open("config.json") as file:
    config = json.load(file)

threshold = find(config, "threshold")["value"]

Každý krok v cestě je name ovládacího prvku nebo title karty (karta nemá vlastní name, ačkoli jej můžete přidat a bude zachován). Pás karet a jakákoli skupina group, kterou jste nepojmenovali, jsou průhledné – find jimi prochází – takže vypisujete pouze karty a ovládací prvky, které jste pojmenovali, blízko vnořenému vyhledávání config[...][...]. Pojmenovaná skupina group je samostatným krokem, takže find může vrátit i hodnotu jejího zaškrtávacího políčka. Dejte každému ovládacímu prvku jedinečný name, aby cesta nikdy nebyla nejednoznačná. Úplný příklad čte hodnoty z vnořeného ukázkového rozvržení.

Protože konfigurace je prostý JSON, nic ve vašem skriptu nezávisí na editoru – editor pouze zapisuje soubor, který váš skript již čte. Zařízení může nést svou konfiguraci i uživatelsky přívětivý způsob, jak ji změnit, zatímco skript zůstává prostým čtenářem hodnot.

Jeden typ ovládacího prvku vynucuje svůj vstup při ukládání: lineedit s mask nebo regex odmítne nechat editor uložit, dokud je jeho text neplatný nebo neúplný, a pojmenuje pole, která je třeba opravit. Každý jiný ovládací prvek omezuje vstup během úprav – posuvník nemůže opustit svůj rozsah, spinbox se omezuje na své meze – takže uložený soubor je vždy platný.

13.1.13.4. Reference konfiguračního souboru#

Typy ovládacích prvků jsou zdokumentovány na níže uvedených stránkách, seskupené podle toho, co dělají.