feat(historico): deteccoes com foto, sensor PIR na placa e tela apagando no sono

- historico.py: eventos de PIR (gpiomon no pino 11, gpiochip1 linha 70),
  movimento e som do celular em SQLite; ate 200 eventos e 100 fotos;
  cada sensor e a foto ligam/desligam; intervalo minimo por tipo
- PIR acorda o Carinha quando ele esta dormindo
- APK 0.8.3: o app consulta o pedido de foto e envia uma foto da camera
  frontal (quadro da camera de movimento ou do video ao vivo)
- tela apaga depois de X minutos dormindo (preto total + brilho minimo no
  AMOLED); acende com som, movimento, toque, comando ou PIR
- painel: tela Historico (sensores, fotos, filtros, apagar), atalho em Ao
  vivo e no Ctrl+K, ajustes "Apagar a tela quando dormir"
- testes do historico (servico e rotas HTTP)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
julio
2026-10-06 03:40:13 -03:00
co-authored by Claude Opus 5.5
parent 98c9e8803e
commit 788215b49e
20 changed files with 934 additions and 16 deletions
+30
View File
@@ -93,6 +93,22 @@ addEventListener("resize", ajustar);
const PRETO = [6, 8, 14];
const CIANO = [92, 214, 255];
const EXTRAS = { boca: true, sobrancelhas: false, iris: false, subirBoca: 0, distSobrancelha: 16 };
const SONO = { apagar: true, minutos: 5, desde: 0, apagada: false };
/* Dormindo há tempo demais: apaga a tela (preto total) e o app baixa o brilho ao mínimo.
Qualquer coisa que acorde o rosto (som, movimento, toque, comando, PIR) acende de novo. */
function cuidarDaTela() {
const agora = performance.now();
if (!r.dormindo) SONO.desde = 0;
else if (!SONO.desde) SONO.desde = agora;
const apagar = SONO.apagar && r.dormindo && SONO.desde && agora - SONO.desde > SONO.minutos * 60000;
if (apagar !== SONO.apagada) {
SONO.apagada = apagar;
window.carinhaTelaApagada = apagar;
document.body.style.visibility = apagar ? "hidden" : "";
console.log(apagar ? "tela apagada (dormindo ha " + SONO.minutos + " min)" : "tela acesa");
}
}
setInterval(cuidarDaTela, 1000);
const CIANO_E = [150, 232, 255];
const VERM = [255, 78, 78];
const ROSA = [255, 112, 176];
@@ -716,6 +732,16 @@ function checarSilencio(agora) {
journal do carinha-web (so quando o microfone esta ativo). */
function relatarSom(evento, n) {
try { fetch("diag/mic=" + evento + " nivel=" + n.toFixed(2)).catch(() => {}); } catch (e) {}
if (evento !== "adormeceu") registrarEvento("som", evento, n);
}
/* Histórico de detecções no servidor (o app tira a foto do evento). Só o celular registra. */
function registrarEvento(tipo, evento, nivel) {
if (new URLSearchParams(location.search).get("aparelho") !== "1") return;
try {
fetch("/historico/evento", { method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tipo, evento, nivel }) }).catch(() => {});
} catch (e) {}
}
// ------------------------------------------------------ presenca (movimento)
@@ -804,6 +830,7 @@ function movimento(vel, cx, cy) {
/* Conta ao servidor o que a presenca percebeu (aparece no journal do carinha-web). */
function relatarMov(evento, n) {
try { fetch("diag/mov=" + evento + " nivel=" + n.toFixed(2)).catch(() => {}); } catch (e) {}
registrarEvento("movimento", evento, n);
}
// ------------------------------------------------- camera oculta (sensor)
@@ -936,6 +963,8 @@ let configRecebida = null;
function configurarApp(c) {
EXTRAS.boca = c.boca !== false; EXTRAS.sobrancelhas = c.sobrancelhas === true; EXTRAS.iris = c.iris === true;
if (typeof c.subirBoca === 'number') EXTRAS.subirBoca = c.subirBoca;
SONO.apagar = c.apagarTela !== false;
if (typeof c.apagarTelaMin === 'number') SONO.minutos = c.apagarTelaMin;
if (typeof c.distSobrancelha === 'number') EXTRAS.distSobrancelha = c.distSobrancelha;
AUTO = c.auto;
AUDIO.ligado = c.audio && par.get('espelho') !== '1' && par.get('audio') !== '0'; AUDIO.volume = c.volume;
@@ -966,6 +995,7 @@ async function sincronizarApp() {
movimento: MOV.vel, camera_ativa: window.carinhaSensores ? window.carinhaSensores.camera : MOV.ativo && agora - MOV.visto < 2,
centro: [MOV.cx, MOV.cy], config: configRecebida,
brilho: window.carinhaBrilho,
tela_apagada: !!window.carinhaTelaApagada,
bateria: window.carinhaBateria,
aparelho: window.carinhaAparelho,
video: window.carinhaVideo,