From 97e1033ae9109e30c4bce49ffc1b32fef9fbf9c8 Mon Sep 17 00:00:00 2001 From: joaquin Date: Thu, 9 Jul 2026 21:40:47 +0200 Subject: [PATCH] =?UTF-8?q?A=C3=B1adir=20proyecto.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- proyecto.md | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 proyecto.md diff --git a/proyecto.md b/proyecto.md new file mode 100644 index 0000000..9ed7275 --- /dev/null +++ b/proyecto.md @@ -0,0 +1,157 @@ +--- +name: home-ai-assistant-project +description: "New project: entrance camera with face recognition greeting + AI home assistant/secretary (cloud LLM + local STT/TTS) across phones and Asterisk telephony + per-person memory (Joaquin/Rocio/Victor) with proactive reminders. Architecture decisions and infra facts, nothing implemented yet." +metadata: + node_type: memory + type: project + originSessionId: 07de6ee5-a395-4291-a8b4-51707e6841d1 +--- + +# Proyecto: Cámara entrada + Asistente IA doméstico + +**Estado: fase de diseño/viabilidad, nada implementado aún** (2026-07-09). + +## Objetivo +- Cámara IP en la entrada de casa que reconozca caras y salude por nombre. +- Asistente de IA para la casa, con varios móviles como "satélites" de interacción. +- Reconocimiento de voz (speaker ID) para que el sistema sepa quién habla y mantenga memoria por usuario. +- Asistente tipo "Jarvis"/secretario personal para los 3 miembros de la familia — **Joaquín** (el usuario), **Rocío** y **Víctor** — que interpreta lo que se le dice, decide qué merece guardarse en memoria (explícito o inferido), y decide de forma proactiva cuándo avisar/recordar algo a cada uno. + +## Infraestructura relevante ya existente (descubierta, no creada por este proyecto) +- **Cluster Proxmox** con nodos: server1-4, kirapc, minipc1. Acceso actual desde server3. +- **Home Assistant OS ya desplegado**: VM 112 "kirahomeassistant" en server4 (2 vCPU/4GB RAM, instalación limpia vía community-scripts, sin addons de voz configurados aún — sin SSH directo, típico de HAOS sin addon SSH). Es la base natural para todo el proyecto (Assist pipeline, integraciones de cámara/Frigate, agentes conversacionales Ollama/OpenAI-compatible). +- **GPU compartida con KiraStream** (ver [[kirastream-project]] y [[kirastreamer-source-server]]): RTX 4060Ti 8GB pasada por PCI passthrough completo a VM 211 (kirapc). Passthrough es exclusivo — nada más puede usar esa GPU salvo que viva dentro de esa misma VM. + - Medido en vivo: NVENC/VLC de KiraStream usa VLC (CPU) para decode + solo el encoder final pasa por NVENC (bloque de silicio separado de los CUDA cores). Uso real medido: 1MiB-~1GB VRAM incluso con 8 slots activos, nunca más. Esto deja ~7GB VRAM libres de forma consistente, incluso en hora punta. + +## Decisiones de arquitectura tomadas + +### 1. Reconocimiento facial (cámara entrada) — habrá varias cámaras por la casa +- **100% local, CPU, no necesita GPU.** Stack recomendado: Frigate + double-take/CompreFace (o face-recognition nativo de Frigate 0.15+). +- Los modelos de embedding facial (ArcFace-like) son ligeros, corren de sobra en CPU de cualquier nodo con margen (server1/server3). +- **Enrolamiento de personas nuevas (ej. hermana, cuñado) — dos vías, combinables**: + 1. **Reactivo**: Frigate/double-take guarda como "desconocido" el recorte de cara de quien no reconoce; se etiqueta a posteriori en la interfaz de double-take con el nombre — no requiere sesión de fotos, usa lo que ya grabó la cámara. + 2. **Proactivo**: subir 3-5 fotos ya existentes (móvil, WhatsApp) de la persona antes de su próxima visita, para que quede reconocida desde el primer día sin pasar por el estado "desconocido". Mejor varias fotos con ángulos/luz distintos que una sola, por fiabilidad frente a condiciones reales de cámara. + 3. **Mejora conversacional (encaja con la filosofía Jarvis, sección 7)**: si la misma cara "desconocida" aparece repetida (no un repartidor puntual), la IA pregunta por voz sola "he visto a alguien que no reconozco varias veces, ¿quién es?" y da de alta el perfil con la respuesta — enrolamiento como parte de la conversación normal, no como tarea de administración aparte. +- **Alcance del reconocimiento facial es independiente del tratamiento completo de familia**: un visitante (hermana, cuñado) solo necesita reconocimiento facial para el saludo — no requiere speaker ID, Caller ID mapeado, ni memoria personal tipo Jarvis (secciones 5-7), salvo que se quiera dar ese nivel también. Por defecto, "visitante conocido" es un nivel más ligero que "familia nuclear" (Joaquín/Rocío/Víctor). + +### 2. LLM conversacional del asistente (DECISIÓN ACTUALIZADA 2026-07-09, sustituye a la original) +- **Decisión final: el "cerebro" (LLM) va en la nube vía API barata de texto (DeepSeek V4 Flash o Qwen3), no local.** STT y TTS siguen 100% locales en la GPU de VM 211 (Whisper + TTS acelerado por GPU tipo XTTS/Kokoro), aprovechando el margen de VRAM ya medido (~7GB libres constantes). Solo el texto (transcripción y respuesta) viaja a la nube, nunca el audio en crudo. +- **Motivo del cambio**: se comparó contra APIs de audio nativo (Gemini Live, OpenAI Realtime) y contra correr un LLM 7-8B local. Los tokens de texto son ~5-8x más compactos que los de audio para el mismo contenido hablado, y DeepSeek V4 Flash ($0.14/$0.28 por 1M input/output) o Qwen3 ($0.06/$0.12) salen **prácticamente gratis** (~$0.06/mes estimado para ~900 min/mes de conversación) frente a los ~$10-20/mes de Gemini Live (la opción de audio nativo más barata) — y frente a comprar/dedicar más VRAM para un modelo local, que además sería menos potente en conocimiento/razonamiento que estas APIs. +- **Usar esta IA (DeepSeek/Qwen) para todo lo posible** en vez de modelos locales pequeños: asistente de casa, llamadas telefónicas, generación de saludos dinámicos, etc. — dado el coste marginal casi nulo, ya no tiene sentido limitarse a un 7-8B local salvo que falle el internet. +- **Importante**: usar la variante rápida/no razonadora (V4 Flash, no R1) — los modelos "reasoning" añaden varios segundos de latencia de pensamiento, inaceptable para voz en tiempo real. +- **Trade-offs aceptados conscientemente**: + - Dependencia total de internet para la parte conversacional — si se cae la conexión, el asistente de IA no responde (los intents nativos de HA para control del hogar sin LLM siguen funcionando). + - Privacidad: el texto de las conversaciones (no el audio) viaja a APIs operadas por empresas chinas (DeepSeek/Qwen) — exposición menor que mandar audio crudo, pero no nula. Alternativa más cara si esto preocupa: proveedor de infraestructura occidental. + - Latencia por turno estimada ~1-2.5s (STT local + red + inferencia + TTS local) — peor que audio nativo (~300-500ms) pero mucho más barato; no se ha probado aún en la práctica. +- Riesgo operativo a vigilar (ya no aplica a un LLM local, pero sí a STT/TTS): aislar esos servicios en su propio systemd dentro de VM 211 para no arriesgar la estabilidad del streaming de KiraStream. +- **Corrección (2026-07-09)**: Ollama **ya está desplegado** en VM 211 (`10.10.10.239:11434`, modelo `mistral:7b`) — se descubrió al inspeccionar KiraBot (ver sección 8). No es "pendiente probar", ya existe como fallback en producción de un componente distinto. No cambia la decisión de usar API barata como cerebro principal. +- Explorado y descartado por ahora: **Kyutai Moshi** (open source, audio-nativo real, ~200ms latencia, un solo GPU) — requiere 16-20GB VRAM (no cabe en los 8GB de la 4060Ti) y es solo inglés a día de hoy. Revisar en el futuro si sacan versión multilingüe/más ligera. +- Explorado y descartado por ahora: plataformas "todo incluido" de agente telefónico (Vapi, Retell AI, Bland AI) — $0.12-0.35/min todo incluido, mucho más caro que hacerlo con Asterisk propio + esta arquitectura, y el usuario ya tiene experiencia con Asterisk/FreePBX. + +### 3. Hardware físico de los asistentes por casa (decisión 2026-07-09) +- **Descartado usar los Google Nest Hub (2ª gen) / Nest Mini como cerebro del asistente** — investigado a fondo: el Nest Mini no tiene ni interfaz JTAG ni UART de depuración conocida (callejón sin salida); el Nest Hub 2ª gen sí tiene un exploit de bootloader documentado (`chipicopwn`, rompe secure boot y arranca Ubuntu) pero requiere desmontaje + soldadura de un adaptador UART + una Raspberry Pi Pico, es investigación académica de 2021-2022 sin mantenimiento activo, y **no hay evidencia de drivers funcionales de micrófono/altavoz** bajo el Linux custom — el esfuerzo no compensa frente a hardware abierto. +- **Decisión final: 2 tablets + 2 móviles (ya disponibles) como satélites completos del asistente** repartidos por la casa — mismo patrón que el móvil de la entrada: **`media_player` local** (Fully Kiosk Browser o similar) al que HA le manda `play_media` directo por red local (casi instantáneo, 0.3-1s, sin depender de internet), **no notificaciones push** (pasan por Firebase Cloud Messaging, lentas e impredecibles). +- **Los Google Nest Hub (2 unidades, con pantalla) se mantienen pero solo como receptores Cast**: el servidor les "emite" contenido (cámara, dashboard, notificaciones) vía **Google Cast nativo** (integración Google Cast de HA, `media_player.play_media` a un Chromecast) — uso legítimo de su función de fábrica, sin rootear nada. No son cerebro del asistente, son pantallas de salida. +- **Pre-cachear saludos por persona conocida** (no generarlos con el LLM en cada entrada) para minimizar latencia — el LLM se reserva para cuando alguien le pide algo, no para el "hola" automático. + +### 4. Latencia estimada end-to-end (persona entra → saludo suena) +- Mejor caso: ~2-3s. Típico (saludo dinámico vía LLM): ~4-7s. +- **El cuello de botella real no es cómputo, es la colocación de la cámara**: conseguir un frame frontal de cara utilizable tarda 1-4s dependiendo del ángulo/altura de la cámara y cómo entra la persona. Vale la pena poner la cámara a la altura de la cara apuntando hacia donde la gente mira al entrar (cerradura/timbre), más que optimizar el modelo. + +### 5. Reconocimiento de voz (speaker ID) + memoria por usuario +- Viable y recomendado 100% local: no existe apenas oferta cloud gratuita seria para esto (a diferencia de caras); Azure Speaker Recognition fue retirado, Amazon Voice ID es solo para Connect. +- Stack: embeddings de voz vía **SpeechBrain (ECAPA-TDNN)** o **pyannote.audio**, comparación por similitud coseno contra huellas enroladas por cada persona. <200ms en CPU, nunca es el cuello de botella. +- **HA no trae esto de fábrica** — el pipeline Assist (wake word → STT Whisper → LLM → TTS Piper) no tiene paso nativo de "quién habla". Requiere un servicio intermedio custom que capture el mismo audio del wake word/STT, calcule el embedding, identifique al hablante, e inyecte esa identidad en el system prompt del LLM antes de generar respuesta. +- Memoria por usuario: DB ligera (SQLite/JSON) por persona con preferencias/historial, recuperada e inyectada en el prompt en cada turno. +- Limitaciones a esperar: precisión baja en ambiente ruidoso (necesita fallback tipo "no te reconozco, ¿quién eres?"), necesita ≥2-3s de audio limpio (no solo el fragmento de wake word), no resuelve bien voces simultáneas/solapadas (eso es diarización, más complejo). Es dato biométrico sensible (categoría especial RGPD) — razón adicional para mantenerlo local. + +### 6. Telefonía — llamar a la IA / la IA llama (usuario ya tiene experiencia con Asterisk/FreePBX) +- **Descartado modem GSM físico + SIM** (la mayoría de dongles USB no exponen audio de voz utilizable; los que sí, tipo SIM7600, necesitan chan_dongle/chan_quectel). **Descartado también Telegram como sustituto de llamada** (la Bot API no soporta llamadas de voz/vídeo en absoluto; el workaround con userbot+pytgcalls es solo para chats de voz en grupo, no llamadas 1:1, y roza el ToS de Telegram). +- **Decisión: Asterisk/FreePBX + troncal SIP (VoIP)** de un proveedor (Twilio, Telnyx, voip.ms — verificar cobertura de DID español). Evita todo el hardware/firmware GSM. +- **Puente hacia la IA**: aplicación de dialplan `AudioSocket()` (streaming de audio crudo PCM por TCP a un servicio propio) en vez de rutar a extensión/cola. Alternativa más flexible pero más código: ARI + externalMedia channel. Si se sigue usando FreePBX GUI, enganchar vía "Custom Destination" a un contexto de dialplan a mano. +- **Identificación de quién llama**: trivial vía `${CALLERID(num)}` en el dialplan — tabla número→persona, sin necesidad de speaker ID biométrico para el canal telefónico (eso es solo para reconocimiento por voz en persona en casa, ver sección 5). +- **Llamadas salientes** (recordatorios, avisos proactivos tipo "el salón está que arde"): `originate` vía AMI/ARI conectando al mismo AudioSocket. La decisión de cuándo llamar (sensor temp + hora habitual de llegada + AC apagado) es automatización simple de HA con reglas, no necesita IA para la lógica de disparo — el LLM solo pone la voz natural al mensaje. +- **Diálogo en llamadas automáticas**: usar respuesta corta guiada (sí/no o DTMF), no conversación abierta — más fiable dado el audio banda estrecha y la latencia de telefonía. +- **Conversación fluida real (llamar a charlar de verdad)**: usar la arquitectura de la sección 2 (STT/TTS local + DeepSeek/Qwen) puenteada al audio de `AudioSocket`. Nota técnica a favor: en llamada telefónica no hay eco acústico que cancelar (audio ya viene separado por canal, no es micro+altavoz en la misma sala), así que el barge-in (cortar al hablar) es más simple de implementar que en un altavoz de casa. + +### 7. Memoria tipo "secretario/Jarvis" por persona (Joaquín, Rocío, Víctor) +- **Esquema**: SQLite ligera con entradas `{persona, tipo, contenido, disparador, estado, confianza}`. + - `persona`: joaquin / rocio / victor / *familia* (cajón compartido para cosas relevantes a los tres, ej. "hay que comprar leche"). + - `tipo`: recordatorio (con disparador fecha/hora/evento) / preferencia (duradera, ej. alergias, gustos) / hecho / episódica (resumen de conversación reciente). + - `estado`: pendiente / avisado / descartado. +- **Quién decide qué se guarda**: dos vías, no mutuamente excluyentes: + 1. Explícito: el usuario dice "recuérdame X" → se guarda directo. + 2. Inferido: tras cada conversación, una **pasada de extracción en segundo plano** (no bloquea la respuesta en vivo) manda el intercambio a DeepSeek/Qwen con un prompt de "extrae hechos/compromisos/recordatorios dignos de guardar, o nada". Coste marginal casi nulo dado el precio de estas APIs (sección 2), así que hacerlo tras cada turno es viable. + - **Umbral de confianza**: si el modelo no está seguro de si algo merece guardarse, debe preguntar ("¿quieres que te lo recuerde?") en vez de guardarlo silenciosamente — evita ruido y sensación de vigilancia excesiva. +- **Cómo decide avisar proactivamente**: un servicio con ciclo periódico (barato, cada pocos minutos) que recupera pendientes + contexto actual (hora, sensores, ubicación del móvil) por persona, y le pregunta al LLM si debe contactar ahora y con qué mensaje. Requiere un **umbral de urgencia/límite de avisos al día** por persona para no volverse cansino — solo urgencia real (ej. temperatura+llegada inminente) dispara llamada; el resto, notificación pasiva. +- **Enganche con identidad**: el "cajón" de memoria que se lee/escribe en cada interacción lo determina el speaker ID (voz en casa, sección 5) o el Caller ID (teléfono, sección 6) ya diseñados — Joaquín, Rocío y Víctor no comparten contexto salvo el cajón *familia*. +- **Analogía de referencia**: este es el mismo patrón que el propio sistema de memoria de Claude Code (el asistente con el que se diseñó este documento) — decidir qué persistir, distinguir tipos, e indexar por relevancia futura. + +### 8. Integración con KiraStream (EPG, "pon esto en la tele", grabación bajo demanda) +- **Descubrimiento clave (2026-07-09): gran parte de esto ya existe como prototipo funcional dentro de KiraStream, no hay que construirlo desde cero.** Módulo `kirabot` en PCT 119 (`/opt/kirastream/backend/`): + - `core/chatbot.py`: IA ya integrada — **Groq (Llama 3.3 70B, gratis)** como principal, **Ollama** (`10.10.10.239:11434`, VM 211) como fallback. Detección de intención por palabras clave en español (EPG vs grabación vs alias de canal tipo "la1"→"la 1"), luego inyecta contexto real de la guía en el prompt. + - EPG ya expuesto por API y funcional: `/api/v1/epg/grid`, `/now-next`, `/schedule/{tvg_id}`, `/search`. + - Grabación bajo demanda ya implementada: `POST /api/user/kirabot/recordings` (`ScheduleRequest`: canal, título, hora inicio/fin) → `core/recording_service.py` (lógica real, 395 líneas, no un stub). + - **Control remoto de la TV ya tiene transporte listo**: `api/user/remote_ws.py` — cada TV emparejada (webOS/Android) mantiene un WebSocket persistente (`/tv/{device_uuid}`), y el backend ya tiene `push_to_tv(device_uuid, payload)` (usado hoy solo para el evento de emparejamiento `PAIRED`). +- **Lo único que falta de verdad**: un tipo de comando nuevo sobre ese mismo WebSocket (ej. `{"type": "PLAY_CHANNEL", "channel_id": X}`) para que la IA pueda cambiar remotamente lo que se reproduce en una TV concreta por voz — el transporte ya existe, falta el comando y que la app (webOS/Android) sepa reaccionar a él (no verificado del lado de la app). +- **Decisión sobre el "cerebro" para esto (2026-07-09): unificar todo bajo el mismo modelo barato de la sección 2 (DeepSeek V4 Flash o Qwen3)** en vez de mantener a KiraBot con su propio Groq+enrutado por palabras clave — cuando se implemente, jubilar el enrutado por keywords a favor de function-calling real desde el mismo cerebro que usa el resto del asistente (llamadas, memoria, casa). Un solo modelo para todo el proyecto, el más barato disponible en cada momento. + +### 9. Monitorización de infraestructura + IA que llama y ayuda a reparar (agente de operaciones) +- **Herramienta de monitorización**: preferir **Prometheus + Alertmanager** (con `pve-exporter` para métricas nativas de Proxmox) o, si se busca algo más rápido de montar, **Uptime Kuma** — mejor que Nagios clásico (configuración anticuada) para este caso. Cubre nodos, VMs/LXCs, y estado de VPNs (wireguard/gluetun). +- **Disparo de la llamada**: la alerta (webhook de Alertmanager/Uptime Kuma) activa una llamada saliente reutilizando la telefonía ya diseñada (sección 6: Asterisk + AudioSocket) hacia Joaquín. +- **Decisión de diseño clave — dos niveles, NO shell libre sin restricciones**: + 1. **Diagnóstico: libre y sin restricciones.** La IA puede ejecutar cualquier comando de solo lectura (`pvesh get`, `qm status`, `journalctl`, `systemctl status`, logs) sin pedir permiso, y reporta por voz lo que encuentra (qué falla, qué servicios afectados, recursos disponibles en otros nodos). + 2. **Reparación: catálogo cerrado de "playbooks" predefinidos, no comandos bash arbitrarios generados libremente por el modelo.** Ej. `reiniciar_servicio(nodo, servicio)`, `migrar_vm(vmid, nodo_destino)` — esta última con comprobación automática de recursos en destino antes de proponerla siquiera. Acciones de bajo riesgo (reiniciar un LXC no crítico) se permiten directas; acciones de alto impacto (tocar VM 211/KiraStream, reiniciar un nodo entero) **requieren confirmación de voz explícita** antes de ejecutar. +- **Motivo de este diseño**: dar autonomía total de shell a un LLM sobre infraestructura de producción (KiraStream sirve streaming en vivo) durante un incidente es el peor momento para que actúe sin control — incluso equipos de SRE profesionales evitan la autonomía total en este escenario. Confirmado explícitamente por el usuario como el diseño a seguir (2026-07-09). +- **Restricción real que la IA debe conocer**: VM 211 (kirastream-gpu1) **no se puede migrar en vivo a otro nodo** por tener la RTX 4060Ti en passthrough exclusivo — cualquier plan de "migrar la VM a otro nodo" ante un fallo de kirapc es inviable de raíz y la IA debe saberlo antes de proponerlo (ver sección "Infraestructura relevante"). +- **Trazabilidad**: registrar (log) cada acción propuesta y ejecutada durante un incidente, con el motivo dado por el modelo, para poder auditar después qué hizo el agente. + +### 10. Sensor de papel higiénico + aviso humorístico a toda la casa +- **Sensor: LED + fotorresistor (LDR)**, ~2€, leído por un ESP32 vía ESPHome (mismo stack que el resto de sensores DIY del proyecto). Montaje: el par LED-LDR se coloca **tangencial al rollo, a la altura del radio mínimo aceptable** (no a lo largo del tubo, ya que el hueco del cartón está vacío siempre independientemente del papel restante) — mientras quede papel a ese grosor, el rollo bloquea el haz (LDR en oscuro); al bajar de ese diámetro, el haz pasa libre (LDR se ilumina) → entidad de sensor en HA. +- **Lógica de aviso**: + 1. LDR cruza el umbral de "vacío" → arranca un temporizador de 20s en HA. + 2. Si se repone el rollo antes de que acabe (LDR vuelve a "oscuro") → se cancela, sin aviso. + 3. Si pasan los 20s sin reponer → **aviso simultáneo a todos los `media_player` de la casa** (2 tablets + 2 móviles + Nest Hub por Cast, sección 3) con mensaje de broma tipo "quién acaba de plantar un pino y no ha repuesto el papel". +- **Mensaje: frases precacheadas, no generadas en el momento** — al ser un aviso no personalizado (grita a toda la casa, no a una persona), mejor un puñado de 5-10 variantes pregrabadas elegidas al azar, para que salga instantáneo sin depender de latencia de red justo en el momento de la broma. Ampliar el repertorio generando variantes nuevas con el LLM en segundo plano de vez en cuando, no en el momento del disparo (mismo principio que los saludos de la entrada, sección 3). +- **Sobre identificar "quién fue"**: descartado usar cámara/micrófono dentro del baño para averiguarlo — línea de privacidad que no se cruza ni en broma. El aviso es genérico a toda la casa, no dirigido a una persona concreta (evita necesitar atribución real). + +### 11. Cocina: vitrocerámica desatendida — sensores + escalado de seguridad + corte remoto +- **Sensores**: presencia en cocina vía **mmWave (LD2410 o similar, ESPHome)** — no PIR, porque alguien de pie cocinando sin moverse apenas puede leerse como "sin presencia" en un PIR normal, justo el fallo que no se puede permitir aquí. Consumo de la vitro vía **pinza de corriente (CT clamp)** + módulo de energía (Shelly EM o ESP32+componente de energía ESPHome) para vatios reales, no solo on/off. +- **Detector de humo: mantener uno certificado e independiente**, que suene por sí mismo sin depender de wifi/HA/IA — la integración smart (Zigbee tipo Aqara/Sonoff) es una capa extra para disparar avisos/llamadas, **nunca sustituto** del detector autónomo, por si la red o el servidor caen justo durante una emergencia real. +- **Escalado de aviso** (mismo patrón de sección 9: avisar → interpretar → re-avisar → llamar → acción de alto impacto): + 1. Vitro consumiendo + cocina sin presencia durante X min → **aviso 1** a toda la casa. + 2. Alguien responde por voz (ej. "estamos cociendo espaguetis") → la IA estima un tiempo de cocción razonable y calla hasta que pase. + 3. Pasado ese tiempo, sigue sin presencia → **aviso 2**, más insistente. + 4. Nadie responde/aparece → **llamada telefónica** (sección 6). + 5. **Último recurso, sin confirmación humana**: si nadie contesta a la llamada, la IA **corta la vitro con el contactor**. Diferencia clave frente a la sección 9 (cluster): ahí siempre se pedía confirmación antes de tocar algo crítico; aquí el riesgo de incendio justifica que la última acción sea automática si de verdad nadie responde a nada. +- **Contactor de corte remoto**: la vitro tira bastante corriente (16-30A típico en España) — requiere un contactor correctamente dimensionado, no un relé de hobby. **Instalación asumida por el propio usuario, que es electricista de profesión** — sin necesidad de contratar a nadie externo para esta parte. + +### 12. Impresora 3D: aviso de pieza terminada (cámara sobre pantalla, sin API nativa) +- **Confirmado: la impresora no tiene OctoPrint/Klipper/API propia** — la única fuente de progreso es una cámara apuntando a la pantalla física del contador/porcentaje. Se lee por **OCR** (Tesseract, o matching de plantilla si el display es de segmentos — más robusto que OCR genérico para una fuente fija). Es más frágil que una API nativa (brillos, ángulo, enfoque) pero es la única vía disponible aquí. +- **Secuencia de automatización al detectar impresión completada**: + 1. Enciende la bombilla inteligente (permanece apagada el resto del tiempo, solo se enciende para la foto). + 2. Toma foto de la pieza terminada. + 3. Apaga la bombilla. + 4. Envía la foto **por Telegram (bot)** — uso correcto de Telegram como canal de notificación con foto/texto (a diferencia de lo descartado en la sección 6 para llamadas de voz reales, aquí encaja perfecto porque no es una llamada). + 5. **Llama por teléfono** (reutilizando sección 6) para avisar de viva voz que la pieza está lista. + 6. Apaga el enchufe inteligente de la impresora (corta corriente a motores/resistencias una vez terminado — eficiencia y no dejar el hotend energizado sin necesidad). +- **Componentes**: enchufe inteligente (Shelly/Sonoff/Tasmota) para la impresora, bombilla inteligente (Zigbee/WiFi) para iluminación bajo demanda, todo orquestado como automatización de HA disparada por el resultado del OCR. + +## Pendiente / próximos pasos (no decidido aún) +- Elegir dónde correr Frigate (qué nodo/LXC). +- Montar el sensor LED+LDR del papel higiénico y definir el umbral/temporizador exacto en ESPHome+HA. +- Montar el OCR de la pantalla de la impresora 3D (Tesseract o matching de plantilla) y la automatización de bombilla/enchufe/Telegram/llamada. +- Instalar sensor mmWave de presencia + pinza de corriente en la vitro, detector de humo Zigbee, y el contactor de corte (usuario lo instala él mismo). +- Configurar Fully Kiosk Browser en las 2 tablets + 2 móviles y darlos de alta como `media_player` en HA. +- Configurar la integración Google Cast de HA para emitir a los 2 Nest Hub (cámara/dashboard/notificaciones). +- Elegir e instalar la herramienta de monitorización (Prometheus+Alertmanager vs Uptime Kuma) y definir qué se vigila (nodos, VMs/LXCs, VPNs). +- Definir el catálogo cerrado de playbooks de reparación y qué acciones requieren confirmación de voz vs. cuáles se permiten directas. +- Probar en la práctica la latencia real de STT local (GPU) + DeepSeek V4 Flash/Qwen3 + TTS local (GPU) antes de comprometer la arquitectura — nunca medido, solo estimado. +- Diseñar el servicio intermedio de speaker ID y su enganche al pipeline Assist. +- Definir cámara concreta y su ubicación/ángulo en la entrada. +- Elegir proveedor de troncal SIP (verificar cobertura de DID español). +- Decidir postura ante la dependencia total de internet para el asistente conversacional (ya no hay fallback local del LLM). +- Diseñar el prompt exacto de extracción de memoria y el umbral de confianza/urgencia para guardar y para avisar proactivamente. +- Definir el enrolamiento inicial de Rocío y Víctor (huella de voz para speaker ID, número de teléfono para Caller ID). +- Diseñar el comando `PLAY_CHANNEL` (o similar) sobre `remote_ws.py` y verificar/implementar el handler en las apps webOS y Android de KiraStream. +- Migrar KiraBot de Groq+keywords a function-calling real sobre el modelo único barato (DeepSeek/Qwen) cuando se unifique el cerebro del proyecto.