14.3.2. Watchdog

Watchdog hardware adalah dasar tempat semua pilihan penguatan lainnya bertumpu. Ini adalah timer independen kecil yang mereset prosesor ketika tidak diberitahu sebaliknya terlalu lama. Skrip yang tersangkut pada sensor yang tidak stabil, panggilan jaringan yang memblokir melewati batas waktunya, pengalokasi memori yang terjebak di sudut heap, pengecualian yang lolos dari loop -- tidak ada yang menghentikan watchdog. Timer terus menghitung mundur tanpa peduli, dan kamera reboot.

Untuk produk yang dikirimkan, watchdog bukanlah opsional. Tanpanya, salah satu mode kegagalan di atas membuat kamera mati sampai seseorang menyadari dan melakukan power-cycle. Dengannya, kamera bangkit kembali dengan sendirinya dan satu-satunya bukti kegagalan adalah satu baris dalam log.

Lihat juga

Halaman watchdog timer pada bab hardware mencakup apa itu watchdog pada tingkat hardware dan dasar-dasar API machine.WDT. Halaman ini mencakup apa yang berubah untuk deployment produksi.

14.3.2.1. Memulai watchdog

machine.WDT adalah API-nya. Ini didukung hardware: setelah dibuat, timer berjalan hingga reset berikutnya. Tidak ada stop(), tidak ada deinit(), tidak ada escape Ctrl-C. Itulah intinya.

Pengaturan tipikal di bagian atas main.py, segera sebelum loop yang dilindunginya:

from machine import WDT

wdt = WDT(timeout=10_000)              # milliseconds

main.py adalah tempat yang tepat untuk watchdog karena di situlah loop berada. Reset watchdog adalah reset hardware, sehingga jalur cold-boot berjalan ulang dan main.py memasuki kembali loop secara mandiri -- pemulihan berfungsi tanpa kabel apa pun di boot.py. Memulai watchdog di boot.py justru berarti setiap soft reset (Ctrl-D dari pengembang, misalnya) memberikan aplikasi sebuah timer hardware yang tidak dapat dihentikan, yang menjadi gangguan di meja dan jebakan dalam kode setup produksi yang berjalan sebelum loop siap.

Pilih timeout agar 2 hingga 3 kali lebih lama dari waktu iterasi terburuk yang diamati dari loop utama. Jitter frame-rate, pembacaan sensor lambat pada sensor dingin, gangguan Wi-Fi singkat -- tidak ada yang seharusnya memicu watchdog. Hang nyata (loop tak terbatas, panggilan I/O yang terblokir) harus memicunya. Timeout yang terlalu pendek mengubah watchdog menjadi sumber reset palsu; timeout yang terlalu panjang membiarkan kamera tidak responsif selama menit sebelum pemulihan terpicu.

14.3.2.2. Memberi makan

wdt.feed() mereset hitungan mundur. Panggil sekali per iterasi loop utama, di bagian atas badan loop sehingga pemberian makan terjadi tanpa syarat sebelum pekerjaan apa pun yang mungkin hang:

while True:
    wdt.feed()
    frame = csi0.snapshot()
    process(frame)

14.3.2.3. Bertahan dari pengecualian

Watchdog menangani hang. Pengecualian adalah mode kegagalan yang berbeda. Pengecualian yang tidak tertangani akan naik ke tingkat atas skrip, main.py keluar, dan kamera turun ke REPL. Watchdog kemudian terpicu setelah timeout-nya karena tidak ada yang memberi makannya dari REPL, kamera reset, dan main.py berjalan lagi -- sehingga pemulihan memang berhasil, tetapi lapangan membayar timeout penuh ditambah reboot untuk setiap crash, traceback pergi ke stdout USB yang tidak dibaca oleh siapa pun, dan setiap state dalam memori yang disimpan aplikasi hilang.

Membungkus loop utama dalam try / except tingkat atas mengubah crash menjadi event yang dicatat yang terus dilanjutkan aplikasi, tanpa membayar untuk reset:

import logging

log = logging.getLogger(__name__)

while True:
    wdt.feed()
    try:
        frame = csi0.snapshot()
        process(frame)
    except Exception:
        log.exception("frame loop iteration failed")

Menangkap Exception (bukan BaseException) membuat KeyboardInterrupt dan SystemExit tetap berfungsi, yang diperlukan oleh pengembang yang terhubung melalui USB.

Pola ini adalah separuh perangkat lunak dari liveness: watchdog menangkap hang, wrapper menangkap crash, dan log mencatat apa yang ditangkap oleh keduanya.

14.3.2.4. Mengetahui mengapa boot terjadi

Setiap soft reset dan setiap reset watchdog pada akhirnya muncul sebagai boot baru. Helper diagnostik boot-time mencatat machine.reset_cause() pada setiap cold start; baris reset cause adalah yang memberi tahu lapangan apakah pemulihan benar-benar terpicu versus kamera hanya power-cycling secara normal.

Baris reset-cause adalah yang membuat pekerjaan watchdog terlihat dalam log. Log yang penuh dengan reset watchdog timeout mengatakan bahwa aplikasi telah hang dan watchdog telah memulihkannya. Log tanpa itu mengatakan watchdog belum harus terpicu -- yang biasanya berarti aplikasi sehat, tetapi juga bisa berarti timeout diatur terlalu lama untuk menangkap hang yang sebenarnya terjadi.

14.3.2.5. Starter yang lengkap

main.py yang menggabungkan watchdog, pengaturan logging, diagnostik boot-time, dan wrapper terlihat seperti:

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() adalah pekerjaan per-iterasi aplikasi; sisa scaffold ini tidak berubah antar produk. Penguatan adalah satu watchdog, satu wrapper, dan boot yang dicatat setiap cold start -- tidak banyak kode, dan perbedaan antara kamera yang pulih sendiri dan yang membutuhkan panggilan layanan.