9.0 KiB
9.0 KiB
Integración Videollamadas Juphoon — Resumen del progreso
Contexto
SaveFamily S.L (Bizkaia) está integrando videollamadas y chat entre su app móvil Flutter y sus smartwatches infantiles (RTOS/Android), usando el SDK de Juphoon (jc_sdk).
Actores:
- Grupo SaveFamily S.L — Cliente, dueño de la app y backend
- Shenzhen i365-Tech Co., Limited (Jane Zhang, Carmen) — Fabricante hardware, intermediario comercial
- Juphoon/JUQU (Allen) — Proveedor del SDK de videollamadas
- SeTracker — Proveedor del firmware del reloj y servidores auxiliares
Cotización aprobada: $8,835 (Integración $2,200 + Chat $2,950 + Cloud Photo Album $735 + Encryption $2,950)
Lo que se hizo
1. Análisis de documentación (3 rondas)
- Ronda 1 (31-03-2026): 50 preguntas técnicas → 27/50 respondidas (54%)
- Ronda 2 (01-04-2026): 17 preguntas generales → 17/17 respondidas (calidad desigual)
- Ronda 3 (09-04-2026): Documentación oficial SDK recibida — Quickstart V1.1 Flutter (13 páginas), sequence diagrams, protocolo TCP, connection/mutual dialing process
- Documentos generados: análisis completo, conclusiones, preguntas bilingües ES/EN, análisis cruzado de respuestas
2. Cuenta Juphoon Cloud creada (16-04-2026)
- Consola: juphoon.com (+34)
- App creada: "SaveFamily" (tipo IoT, escenario Smartwatch)
- AppKey:
9efcf2d889dc8a0320925096 - AppSecret:
ui7pr73ggl5rr0gf01np(solo backend) - AES_KEY IoT:
8e3637pG7E9144E0(solo backend) - Token auth activado en consola
3. Paquete packages/videocall_sdk/ creado
Wrapper 100% del jc_sdk v2.16.5 con arquitectura sólida (patrón sca_treezor del monorepo):
- 7 servicios cubriendo toda la API pública del SDK:
VideocallClient→ JCClient (auth, login, logout, messaging)VideocallCallService→ JCCall (llamadas 1-to-1)VideocallDeviceService→ JCMediaDevice (cámara, mic, speaker)VideocallChannelService→ JCMediaChannel (llamadas grupales)VideocallPushService→ JCPush (push notifications)VideocallNetService→ JCNet (estado de red)VideocallLogService→ JCLog (logging)
- Constructor injection (no singletons estáticos)
- GetIt module (
videocallSdkModule(config)) VideocallSdkManagerorquestador de inicialización (Client → Device → Call/Channel/Push)VideocallSdkConfigabstracto para config por entorno- Riverpod providers + StreamProviders para UI reactiva
- Callbacks del SDK → Dart Streams
4. Permisos nativos configurados
- Android: RECORD_AUDIO, ACCESS_WIFI_STATE, MODIFY_AUDIO_SETTINGS, BLUETOOTH + uses-feature (camera, bluetooth) + ProGuard rules (juphoon, justalk)
- iOS: NSMicrophoneUsageDescription, NSPhotoLibraryUsageDescription, NSCameraUsageDescription actualizado + Podfile GCC_PREPROCESSOR_DEFINITIONS (PERMISSION_CAMERA, PHOTOS, MICROPHONE)
5. AppKey configurado por entorno
juphoonAppKeyen development.json, staging.json, production.jsonEnvironment.juphoonAppKeyviaString.fromEnvironment()SaveFamilyVideocallConfigimplementaVideocallSdkConfigvideocallSdkModule(config)integrado eninit_app.dart
6. Feature videocall/ creada en device_management
Feature completa siguiendo el patrón del monorepo (builder + domain + data + presentation):
Domain:
videocall_error.dart— enums de error/success/screenModevideocall_participant.dart— entidad Freezed para participantes grupalesvideocall_signaling_repository.dart— interface señalización backend
Data:
videocall_signaling_datasource.dart— interfacevideocall_signaling_datasource_impl.dart— placeholder (TODO cuando backend dé spec)videocall_signaling_repository_impl.dart— impl
State:
videocall_view_state.dart— Freezed state 1-to-1 (screenMode, sdk ready, mic/speaker/camera, canvas, error/success events)videocall_view_model.dart— Notifier 1-to-1 (init, login, call, answer, hangup, mute, speaker, camera, streams del SDK)group_call_view_state.dart— Freezed state grupalgroup_call_view_model.dart— Notifier grupal (join, leave, participants, streams)
Widgets:
video_view_widget.dart— renderiza JCMediaDeviceVideoCanvas (iOS/Android)call_controls_widget.dart— mic, speaker, camera, hangup (botones circulares)call_status_indicator.dart— "Llamando...", "Conectando..."incoming_call_overlay.dart— aceptar/rechazar llamada entrante (fullscreen)participant_tile_widget.dart— tile individual con video + nombreparticipant_grid_widget.dart— grid responsivo de participantes
Screen:
videocall_screen.dart— 4 modos: idle (input userID + botón llamar), outgoing (llamando...), incoming (overlay aceptar/rechazar), inCall (video fullscreen + PIP + controles)
Routing:
videocall_builder.dart— GoRouter builder- Ruta:
/legacy/dashboard/device_management/videocall
7. Code review realizado
Score: 6/10 — Request changes
Issues identificados (pendientes de corregir):
- Hardcoded test credentials (
p_test1/test123) en UI de producción → guardar conkDebugMode _onCallItemRemovellama async sin await → race condition- Todos los errores mapean a
I18n.errorGeneric→ sin diferenciación para el usuario videocall_screen.dart(310 líneas) demasiado grande → extraer_IdleViewy_InCallViewa ficheros separados comoConsumerWidgetgroup_call_view_model.dartes dead code (no lo consume ninguna screen)- Signaling placeholder con
throw UnimplementedError→ cambiar a no-op VideocallParticipant(domain) expone tipo SDK (JCMediaDeviceVideoCanvas) → mover al ViewModel
Dónde quedamos
- Rama:
feature/videocall-sdk-integration - Los cambios del paquete
videocall_sdkestán commiteados y pusheados (3 commits) - Los cambios de la feature están en disco pero sin commitear (necesitan correcciones del code review)
fusion-appavanzó y revirtió algunos cambios compartidos (permisos, rutas) → hay que re-sincronizar
Pendiente
Correcciones del code review
- Guardar test credentials con
kDebugMode - Fix async race en
_onCallItemRemove - Implementar mensajes de error diferenciados
- Extraer
_IdleViewy_InCallViewa ficheros separados - Integrar o excluir group call ViewModel
- Cambiar signaling placeholder de throw a no-op
- Remover SDK type de domain entity
Pruebas APP↔APP (primera llamada real)
- Login con 2 userIDs de prueba (
p_test1,p_test2) - Videollamada entre dos teléfonos físicos
- Probar incoming call, reject, hangup, mute, camera switch
- Probar app cerrada en iOS (riesgo #1 — push/background)
Integración con backend
- Obtener API REST del backend SaveFamily para señalización
- Definir formato userID con backend (
p_<cuenta>+ sanitización emails) - Implementar datasource de señalización
Pruebas APP↔Reloj
- Llamada APP → Reloj
- Llamada Reloj → APP
- Llamadas grupales
Producción
- Token auth (backend genera tokens con AppSecret)
- AppKeys separadas por entorno
- Push/background iOS (PushKit + CallKit si necesario)
3 riesgos abiertos antes del pago ($8,835)
| # | Riesgo | Estado |
|---|---|---|
| 1 | Push/background iOS — la doc no menciona FCM/APNs, CallKit ni ConnectionService. App cerrada = no recibe llamadas. Posible deal-breaker | ❌ Sin respuesta |
| 2 | GDPR sin DPA — servidores UE pero sin DPA, sin control routing, datos de menores | ❌ Email enviado 01-04, sin respuesta |
| 3 | Chat sin spec — $2,950 sin lista de features, "mira SeTracker2" | ❌ Sin spec |
| + | Encryption — $2,950 pagados, cero documentación del módulo | ❌ Sin spec |
Arquitectura confirmada
APP (Flutter + jc_sdk) ←→ Juphoon Cloud (solo media)
↕ API REST
Backend SaveFamily ←→ Backend i365/SeTracker ←→ Smartwatch (firmware + jrtc_* C API)
↕ TCP plano
- El "Server" del protocolo TCP es i365, NO Juphoon
- Juphoon Cloud solo rutea audio/video (media plane)
- La señalización (quién llama a quién) va por el backend
Naming conventions (protocolo TCP)
| Tipo | Formato | Ejemplo |
|---|---|---|
| Watch userID | w_ + IMEI |
w_000078932675810 |
| Mobile userID | p_ + APP account |
p_abc10086 |
| Group room | did + _group |
0245423235_group |
| Single room | did + _ + APP account |
0245423235_abc10086 |
@ y . se reemplazan por _ en room numbers y userIDs.
Documentación de referencia
- Quickstart V1.1:
~/Downloads/Video call API_ Juphoon Flutter SDK quickstart V1.1.pdf - TCP Protocol:
~/Downloads/Juphoon Video Call TCP Protocol.docx - Connection process:
~/Downloads/video call connection process Rev2.docx - Mutual dialing:
~/Downloads/video call mutual dialing process.docx - Schematics:
~/Downloads/schematics _2025.03.26 (2)/ - pub.dev: https://pub.dev/packages/jc_sdk
- Consola Juphoon: https://developer.juphoon.com