App PWA che dice cosa fare nell'orto e, soprattutto, quanta acqua dare a ogni coltura, calcolandolo sul meteo reale invece che su un calendario fisso. Motore idrico (metodo FAO-56) - il terreno come serbatoio: capacità dal tipo di suolo per la profondità radicale, prelievo giornaliero pari a ET0 × Kc, ricarica da pioggia efficace e irrigazioni al netto dell'efficienza del metodo - bilancio ricostruito su 21 giorni reali e proiettato su 10 di previsione, così si sa anche fra quanti giorni servirà il prossimo turno e quando saltarlo - soglia di intervento dipendente dal metodo: con la goccia si bagna al 55% della riserva utile, con l'aspersione all'85%, a mano si sfrutta tutto - correzioni per pacciamatura, serra e coltura in vaso Dati - 58 schede fra ortaggi, frutta e aromatiche con coefficienti colturali, profondità radicali e fattori di deplezione da FAO-56, più calendario, sesti, consociazioni, cure e problemi tipici - ricerca che capisce i nomi dialettali: cocomero, popone, petonciano, ramerino - meteo ed evapotraspirazione da Open-Meteo, senza chiave API, con cache offline Automazione - generatore di programma per centraline a settori: ritmo di regime da impostare e giorni esatti con le piogge già scontate - agente Node che custodisce lo stato, esegue i turni un settore alla volta e registra nel diario quello che ha davvero erogato - driver per ESP32, Shelly Gen1/Gen2, Tasmota, più modalità simulata predefinita - sonde Watermark: veto sui turni, riancoraggio del bilancio su misura reale, confronto fra sonda e calcolo - sicurezze: tetti su minuti e litri, blocchi gelo/vento/pioggia, chiusura all'avvio e all'uscita, doppia chiusura a tempo lato dispositivo, un settore per volta, sospensione dei settori con sonda muta o guasta Firmware ESP32 incluso, con schema di collegamento e istruzioni di posa. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFnqupGt8T5HNNhPPHCjKs
53 lines
1.5 KiB
JavaScript
53 lines
1.5 KiB
JavaScript
/* Service worker minimale: l'app deve aprirsi anche in fondo all'orto senza campo.
|
|
- guscio dell'app: cache-first, aggiornata in sottofondo
|
|
- meteo: rete per prima, con l'ultima risposta buona come rete di sicurezza */
|
|
const CACHE = "pollice-verde-v1"
|
|
const GUSCIO = ["/", "/index.html", "/manifest.webmanifest", "/icon.svg"]
|
|
|
|
self.addEventListener("install", (e) => {
|
|
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(GUSCIO)).then(() => self.skipWaiting()))
|
|
})
|
|
|
|
self.addEventListener("activate", (e) => {
|
|
e.waitUntil(
|
|
caches.keys().then((chiavi) => Promise.all(chiavi.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
|
.then(() => self.clients.claim())
|
|
)
|
|
})
|
|
|
|
self.addEventListener("fetch", (e) => {
|
|
const req = e.request
|
|
if (req.method !== "GET") return
|
|
const url = new URL(req.url)
|
|
|
|
if (url.hostname.endsWith("open-meteo.com")) {
|
|
e.respondWith(
|
|
fetch(req)
|
|
.then((r) => {
|
|
const copia = r.clone()
|
|
caches.open(CACHE).then((c) => c.put(req, copia))
|
|
return r
|
|
})
|
|
.catch(() => caches.match(req))
|
|
)
|
|
return
|
|
}
|
|
|
|
if (url.origin !== location.origin) return
|
|
|
|
e.respondWith(
|
|
caches.match(req).then((colpo) => {
|
|
const rete = fetch(req)
|
|
.then((r) => {
|
|
if (r.ok) {
|
|
const copia = r.clone()
|
|
caches.open(CACHE).then((c) => c.put(req, copia))
|
|
}
|
|
return r
|
|
})
|
|
.catch(() => colpo || caches.match("/index.html"))
|
|
return colpo || rete
|
|
})
|
|
)
|
|
})
|