14.3.2. Watchdog¶
Hardverski watchdog je temelj na kojem počiva svaki drugi izbor učvršćivanja. To je sićušni neovisni mjerač vremena koji resetira procesor kada mu predugo nije rečeno drugačije. Skripta koja zapne na nepouzdanom senzoru, mrežni poziv koji blokira preko svojeg vremenskog ograničenja, alokator memorije zaglavljen u kutu gomile (heap), iznimka koja je pobjegla iz petlje – ništa od toga ne zaustavlja watchdog. Mjerač vremena odbrojava bez obzira na sve, i kamera se ponovno pokreće.
Za isporučeni proizvod, watchdog nije neobavezan. Bez njega, bilo koji od gore navedenih načina kvara ostavlja kameru mrtvom dok netko ne primijeti i ne isključi i ponovno uključi napajanje. S njim, kamera se sama vraća u rad, a jedini dokaz kvara je jedan redak u zapisniku.
Više informacija
Stranica mjerač vremena watchdog u poglavlju o hardveru pokriva što je watchdog na hardverskoj razini i osnove machine.WDT API-ja. Ova stranica pokriva što se mijenja za proizvodnu implementaciju.
14.3.2.1. Pokretanje watchdoga¶
machine.WDT je API. Podržan je hardverom: jednom konstruiran, mjerač vremena radi do sljedećeg reseta. Nema stop(), nema deinit(), nema bijega putem Ctrl-C. To je upravo poanta.
Tipično postavljanje na vrhu main.py, neposredno prije petlje koju štiti:
from machine import WDT
wdt = WDT(timeout=10_000) # milliseconds
main.py je pravi dom za watchdog jer se tamo nalazi petlja. Reset watchdoga je hardverski reset, pa se put hladnog pokretanja ponovno izvodi i main.py se sam ponovno uključuje u petlju – oporavak radi bez ikakvog ožičenja u boot.py. Pokretanje watchdoga u boot.py umjesto toga znači da svaki meki reset (na primjer, developerov Ctrl-D) predaje aplikaciji hardverski mjerač vremena koji nema načina zaustaviti, što je smetnja na stolu i zamka u proizvodnom kodu za postavljanje koji se izvodi prije nego što je petlja spremna.
Odaberite vremensko ograničenje 2 do 3 puta dulje od najgoreg promatranog vremena iteracije glavne petlje. Treperenje brzine sličica, sporo čitanje hladnog senzora, kratki Wi-Fi prekid – ništa od toga ne bi smjelo aktivirati watchdog. Stvarno zaglavljivanje (beskonačna petlja, blokirani I/O poziv) bi trebalo. Prekratka vremenska ograničenja pretvaraju watchdog u izvor lažnih reseta; preduga vremenska ograničenja ostavljaju kameru neodgovornom minutama prije nego što se pokrene oporavak.
14.3.2.2. Hranjenje¶
wdt.feed() resetira odbrojavanje. Pozovite ga jednom po iteraciji glavne petlje, na vrhu tijela petlje kako bi se hranjenje dogodilo bezuvjetno prije bilo kakvog posla koji bi mogao zapeti:
while True:
wdt.feed()
frame = csi0.snapshot()
process(frame)
14.3.2.3. Preživljavanje iznimki¶
Watchdog rješava zaglavljivanja. Iznimke su drugačiji način kvara. Neobrađena iznimka izbija na najvišu razinu skripte, main.py izlazi, a kamera pada na REPL. Watchdog se tada aktivira nakon svojeg vremenskog ograničenja jer ga ništa ne hrani iz REPL-a, kamera se resetira i main.py se ponovno izvodi – pa oporavak radi, ali teren plaća puno vremensko ograničenje plus ponovno pokretanje za svaki pad, ispis greške (traceback) ide na USB stdout koji nitko ne čita, a svako stanje u memoriji koje je aplikacija čuvala je izgubljeno.
Omatanje glavne petlje u try / except na najvišoj razini pretvara pad u zabilježeni događaj kroz koji aplikacija nastavlja, bez plaćanja reseta:
import logging
log = logging.getLogger(__name__)
while True:
wdt.feed()
try:
frame = csi0.snapshot()
process(frame)
except Exception:
log.exception("frame loop iteration failed")
Hvatanje Exception (ne BaseException) održava KeyboardInterrupt i SystemExit u funkciji, što je ono što developer spojen putem USB-a želi.
Ovaj obrazac je softverska polovica životnosti: watchdog hvata zaglavljivanja, omot hvata padove, a zapisnik bilježi što je bilo koji od njih uhvatio.
14.3.2.4. Znati zašto se pokretanje dogodilo¶
Svaki meki reset i svaki reset watchdoga na kraju se pojavi kao novo pokretanje. Pomoćnik za dijagnostiku pri pokretanju bilježi machine.reset_cause() pri svakom hladnom pokretanju; redak reset cause je ono što terenu govori je li se oporavak stvarno pokrenuo ili se kamera samo normalno isključila i ponovno uključila.
Redak s uzrokom reseta je ono što čini rad watchdoga vidljivim u zapisniku. Zapisnik pun watchdog timeout reseta govori da je aplikacija zaglavljivala i da ju je watchdog oporavljao. Zapisnik bez njih govori da watchdog nije morao reagirati – što obično znači da je aplikacija zdrava, ali može značiti i da je vremensko ograničenje postavljeno predugo da uhvati zaglavljivanja koja se stvarno događaju.
14.3.2.5. Potpuni početni predložak¶
main.py koji povezuje watchdog, postavljanje zapisivanja, dijagnostiku pri pokretanju i omot izgleda ovako:
import logging
from machine import WDT
from app.logging_setup import setup_logging, log_boot_diagnostics
setup_logging('/sdcard/logs/app.log')
log_boot_diagnostics()
log = logging.getLogger(__name__)
wdt = WDT(timeout=10_000)
while True:
wdt.feed()
try:
step()
except Exception:
log.exception("loop iteration failed")
step() je posao aplikacije po iteraciji; ostatak ove skele ne mijenja se između proizvoda. Učvršćivanje je jedan watchdog, jedan omot i zabilježeno pokretanje pri svakom hladnom startu – ne baš mnogo koda, a razlika između kamere koja se oporavlja sama i one kojoj treba servisni poziv.