Files
julioandClaude Opus 5.5 c5fd54c1d9 feat(celular): rosto e app usam SSE e token; remove telas legadas
- carinha.html assina /eventos (expressao, app_config, conversa, reacao,
  recarregar) e volta ao polling de /fila sozinho se o SSE cair; foto dos
  ajustes a cada (re)conexao; token (?t=) vai em todo fetch ao servidor
- APK 0.8-token: token nas preferencias e no menu de toque longo, enviado
  na pagina, no HTTP do Java e ao llama-server (--api-key); trocar servidor
  por Intent exige o token salvo; camera/microfone so para o servidor
  configurado ou a copia local
- cerebro/conversa mandam a chave ao llama-server do S10
- servidor: evento SSE 'recarregar'; remove /camera/frame e /app/connect;
  enderecos antigos redirecionam para a secao do painel novo
- remove dashboard, painel, conversa, emojis, treinamento, braco, servos,
  api, scripts e CSS antigos, audio-robot.js e servir-local.bat
- logica pura do painel em web/src/lib/nucleo.ts com testes node --test
  (substitui test_movimentos.js e test_rastreamento.js)
- testes de navegador portados para o painel novo (rtc, rosto, rastreamento)
- README, docs/PAINEL.md e docs/SEGURANCA.md reescritos; versao 0.8.0;
  carinha-pc.service le /etc/carinha.env

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:11:58 -03:00

58 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Painel 0.8 — Svelte + SSE
Substitui as oito páginas antigas (dashboard, painel, conversa, emojis, treinamento, braço,
servos, api). Os endereços antigos redirecionam para a seção equivalente (`/braco` → `/#/movimento`).
## Arquitetura
- `web/`: Vite + Svelte 5 + TypeScript. `npm run build` gera `web/dist/`, que o servidor entrega em `/`.
`web/dist` não vai para o git; o `deploy.ps1` compila e copia.
- **Estado único** (`web/src/lib/estado.svelte.ts`): uma foto inicial (`GET /estado`) e um `EventSource`
em `/eventos`. Eventos: `expressao`, `telemetria`, `app_config`, `aparencia`, `motores`, `estop`,
`conversa`, `ia`, `reacao`, `treinamento`, `recarregar`. Ao reconectar, o navegador manda
`Last-Event-ID` e o servidor reenvia o que estiver no buffer; o painel ainda recarrega a foto.
- **Comandos**: `POST /comando {tipo, valor}` com `tipo` = `gesto` | `rosto` | `cor` | `reacao` |
`parar_reacao` | `recarregar`. Gestos e rostos são validados no servidor.
- **Prévia do rosto**: um único iframe de `carinha.html?espelho=1&painel=1`, sem polling; o painel repassa
os eventos por `postMessage`. A câmera (WebRTC) só existe na tela Ao vivo, então não há disputa pela sessão.
- **Celular**: `carinha.html` também assina `/eventos` (com `?t=<token>`) e volta ao polling de `/fila`
sozinho se o SSE cair. O batimento `POST /app/status` (1/s) continua.
Carga típica: antes 15–20 pedidos/s ao Orange Pi com o dashboard aberto; agora 1 conexão SSE por
painel + o batimento do celular + a sinalização do vídeo enquanto ele conecta.
## Segurança dos controles
| Controle | Comportamento |
|---|---|
| Parar tudo | `POST /parar-tudo`: desliga as 16 saídas, cancela interpolação, para reações, rosto `calma`. Motores travados (409) até `POST /rearmar`. |
| Homem-morto | O painel renova `POST /braco/mover {angulos, velocidade, ttl_ms: 450}` a cada 150 ms enquanto o botão/slider está pressionado. Sem renovação o watchdog desliga os canais. |
| Velocidade | Interpolação a 50 Hz no servidor (`braco.py`), 5–360 °/s. Sem `velocidade` o comando é direto (compatível com scripts antigos). |
| Dono do PCA9685 | Braço e diagnóstico não disputam o hardware: o segundo recebe 409 enquanto o primeiro tem canais ligados. |
| Aba escondida / E-Stop | O painel solta o braço e desativa o movimento físico. |
| Token | Opcional, recomendado: veja [SEGURANCA.md](SEGURANCA.md). |
## Atalhos
`Ctrl+K` paleta · `1`–`9` gestos favoritos · `Shift+Espaço` ou `Esc Esc` parar tudo ·
`g v/c/r/m/a` navegar · `Espaço` segurado no botão do braço = segurar.
## Design
Tokens em `web/src/lib/tema.css`: tema escuro (padrão) e claro, contraste AA, fontes locais
(Outfit e JetBrains Mono, sem Google Fonts). Vidro só em superfícies flutuantes (barra superior,
paleta, mini-rosto); cards sólidos. Estado nunca só por cor: selos com texto. Navegação lateral a
partir de 1024 px, barra inferior abaixo disso; sem rolagem horizontal a 400 px.
Componentes: `Card`, `Selo`, `Toggle`, `Slider`, `Abas`, `Modal` (`<dialog>` nativo), `Avisos`
(toasts com Desfazer, no lugar de alert/confirm/prompt), `Paleta`, `EStop`, `Gestos`,
`RostoPrevia`, `MiniRosto`, `Miniatura`, `BracoDesenho`.
## Testes
- `tests/test_servidor.py`: token, SSE, `/estado`, `/comando`, fila, E-Stop, trava, interpolação e prazo.
- `web/tests/nucleo.test.ts` (`npm test`): escolha de alvo, encaixe, faixas e sequências do braço.
- `tests/test_painel_web_browser.py`: token, gestos (botão, 1–9, paleta), E-Stop, ajustes, conversa,
memória, reações com desfazer, braço com homem-morto, 400 px e tema.
- `tests/test_rtc_browser.py`: vídeo WebRTC real no painel novo, canal de rastreamento e ajustes por SSE.