Volver a la wiki

Agente · dev-signage

Agente · dev-signage

Propósito

Desarrollo y mantenimiento del módulo Digital Signage SaaS de CreaRack-Pro. Cubre la app signage/ (CMS), los servicios de contenido, playlists, schedules, deployment y el portal de clientes.


Estructura de archivos

signage/
├── models.py                    # 7 modelos core
├── models_portal.py             # ClientShareLink + PortalChangeLog
├── tasks.py                     # 5 Huey tasks
├── views.py                     # Client portal (public, token-based)
├── urls.py                      # /client/<token> route
├── api/
│   ├── __init__.py              # Router assembly (10 sub-routers)
│   ├── schemas.py               # Pydantic schemas
│   ├── content.py               # 11 endpoints media CRUD
│   ├── players.py               # 6 endpoints player CRUD
│   ├── playlists.py             # 7 endpoints playlist CRUD
│   ├── schedules.py             # 6 endpoints schedule CRUD
│   ├── deployments.py           # 6 endpoints deployment
│   ├── display_control.py       # 6 endpoints display control
│   ├── proof_of_play.py         # 8 endpoints proof-of-play
│   ├── share_links.py           # 6 endpoints link management
│   ├── portal.py                # 12 endpoints client portal (public)
│   └── approvals.py             # 4 endpoints approval workflow
├── services/
│   ├── file_storage.py          # Upload, validación, paths
│   ├── thumbnail.py             # Pillow + ffmpeg thumbnails
│   ├── transcode.py             # ffmpeg H.264/H.265 pipeline
│   ├── deployment.py            # Push content via VAL
│   ├── svg_composer.py          # Genera project.svg dinámico
│   ├── adapters/
│   │   ├── base.py              # Abstract SignageDeviceAdapter
│   │   ├── registry.py          # Factory: resolve by slug
│   │   ├── spinetix.py          # JSON-RPC + WebDAV
│   │   ├── brightsign.py        # BSN.cloud REST
│   │   ├── samsung.py           # MagicINFO API
│   │   ├── lg.py                # SuperSign API
│   │   └── generic_snmp.py      # Fallback SNMP-only
│   ├── scheduling/
│   │   ├── engine.py            # Evaluate rules → active playlist
│   │   └── smil_generator.py    # JSON → SMIL XML
│   ├── display_control/
│   │   ├── samsung_mdc.py       # TCP:1515 binary
│   │   ├── lg_protocol.py       # TCP:9761 ASCII
│   │   ├── pjlink.py            # TCP:4352 standard
│   │   └── controller.py        # Unified dispatcher
│   └── proof_of_play/
│       ├── collector.py          # Fetch logs via VAL
│       ├── screenshot.py         # Capture + cleanup
│       └── reporter.py           # JSON/HTML/CSV reports
└── migrations/
    ├── 0001_initial.py
    ├── 0002_seed_adapters.py     # 12 vendor adapters seeded
    ├── 0003_portal_share_links.py
    ├── 0004_portal_approval_fields.py
    ├── 0006_signage_operations.py # SignageOperation (rollback)
    └── 0008_client_projects.py    # ClientProject (multi-client)

Modelos

ModeloScopeDescripción
SignageVendorAdapterGlobalConfig por vendor (12 seeded)
SignagePlayerOrgPlayer físico vinculado a DeviceProfile
MediaAssetOrgArchivo multimedia (imagen/vídeo/HTML5)
PlaylistOrgColección ordenada de assets (is_auto para auto-generadas)
ScheduleOrgReglas temporales → playlists
PlaybackLogOrgRegistro de reproducción (alto volumen)
ContentDeploymentOrgTracking de despliegues a players
ClientShareLinkOrgLink compartible UUID para clientes externos
PortalChangeLogOrgAuditoría + cola de aprobación del portal
SignageOperationOrgHistorial para rollback (últimas 50 por org)
ClientProjectOrgProyecto multi-cliente con scope aislado

Huey Tasks

TaskFrecuenciaFunción
process_media_assetOn uploadThumbnail + metadata + transcode
run_deploymentOn demandPush content via VAL
collect_playback_logsCada 15 minRecolectar logs de players
capture_screenshotsCada 30 minCapturar screenshots
cleanup_old_dataDiario 3AMScreenshots >30d + logs >90d + auto-playlists >24h

Flujo de publicación (Publish)

1. Usuario: Publish desde Content/Playlist tab
2. Frontend: SignageModal.selectDevices() → selección con groups + checkboxes
3. Frontend: resolveSignageCredentials() → sessionStorage → Credential Store API → modal prompt
4. SaaS: POST /signage/publish-setup → crea SignagePlayer + bind playlist/schedule
         → devuelve publish_url (SIN passwords)
5. Agent: POST /signage/configure
   a. GET / → sesión + CSRF
   b. POST /user/login (header X-Requested-With: XMLHttpRequest — obligatorio)
   c. POST /controlcenter/main/content → guarda Scheduled Download URL
   d. POST /controlcenter/operation/httpPublish → descarga inmediata
6. SpinetiX: GET spx-listing.xml → GET project.svg → GET media files
7. Frontend: dispara CustomEvent('signage-published') → refresca Content Preview iframe

⚠ El header X-Requested-With: XMLHttpRequest es obligatorio en los POST al SpinetiX. Sin él devuelve HTML en vez de ejecutar la acción AJAX.


SVG Composer

signage/services/svg_composer.py genera project.svg dinámico para SpinetiX.

Tipos de item soportados

TipoImplementación SVG
image<image> fullscreen con preserveAspectRatio
video<video> envuelto en <g> con visibility animation
text<text> con font, color, background rect
colorSlide de color sólido (<rect> fullscreen)
tickerTexto scrolling horizontal (overlay siempre visible)
overlayImagen siempre visible (logo, watermark)

Reglas críticas para vídeo en SVG

Transiciones (9 tipos)

TransiciónImplementación SVG
Cross Dissolveopacity crossfade
Fade to Blackopacity 1→0→1
Slide Left/Right/Up/DownanimateTransform translate
Zoom In/OutanimateTransform scale
Cutvisibility discrete

Endpoints públicos SpinetiX (sin autenticación)

EndpointDescripción
GET /publish/{token}/spx-listing.xmlÍndice WebDAV DAV:multistatus
GET /publish/{token}/project.svgProyecto SVG dinámico
GET /publish/{token}/index.svgAlias de project.svg
GET /publish/{token}/{filename}Media asset file

API Endpoints (48 total)

Content (Media)

POST   /api/signage/signage/media/upload
GET    /api/signage/signage/media
GET    /api/signage/signage/media/{id}
PATCH  /api/signage/signage/media/{id}
DELETE /api/signage/signage/media/{id}
POST   /api/signage/signage/media/{id}/reprocess
POST   /api/signage/signage/media/bulk-delete

Playlists

GET/POST           /api/signage/signage/playlists
GET/PATCH/DELETE   /api/signage/signage/playlists/{id}
POST               /api/signage/signage/playlists/{id}/duplicate
GET                /api/signage/signage/playlists/{id}/preview
POST               /api/signage/signage/playlists/preview-svg  ← preview sin publicar

Schedules

GET/POST           /api/signage/signage/schedules
GET/PATCH/DELETE   /api/signage/signage/schedules/{id}
GET                /api/signage/signage/schedules/{id}/active-playlist

Players

GET/POST           /api/signage/signage/players
GET/PATCH/DELETE   /api/signage/signage/players/{id}
GET                /api/signage/signage/adapters

Display Control

POST /api/signage/signage/players/{id}/power-on
POST /api/signage/signage/players/{id}/power-off
POST /api/signage/signage/players/{id}/volume       # {"level": 75}
POST /api/signage/signage/players/{id}/brightness   # {"level": 75}
POST /api/signage/signage/players/{id}/input        # {"source": "hdmi1"}
POST /api/signage/signage/players/{id}/reboot

Deployments

GET/POST  /api/signage/signage/deployments
GET       /api/signage/signage/deployments/{id}
POST      /api/signage/signage/deployments/{id}/retry
DELETE    /api/signage/signage/deployments/{id}
GET       /api/signage/signage/deployments/{id}/results

Proof of Play

GET  /api/signage/signage/playback-logs
GET  /api/signage/signage/playback-stats
POST /api/signage/signage/playback-logs/collect
POST /api/signage/signage/screenshots/capture
GET  /api/signage/signage/players/{id}/screenshot
GET  /api/signage/signage/reports/proof-of-play         # JSON
GET  /api/signage/signage/reports/proof-of-play/html    # HTML
GET  /api/signage/signage/reports/proof-of-play/csv     # CSV download

Operation History (Rollback)

GET  /api/monitoring/signage/operations                    # ?source=content|playlist
POST /api/monitoring/signage/operations/{id}/restore       # Rollback + httpPublish

Client Portal (público, sin autenticación)

GET  /api/signage/client-portal/{token}/info
POST /api/signage/client-portal/{token}/verify-pin
GET  /api/signage/client-portal/{token}/players
GET  /api/signage/client-portal/{token}/playlists
GET  /api/signage/client-portal/{token}/media
POST /api/signage/client-portal/{token}/media/upload
PATCH /api/signage/client-portal/{token}/playlists/{id}
POST /api/signage/client-portal/{token}/playlists/{id}/replace-asset
GET  /api/signage/client-portal/{token}/history

Client Projects (multi-cliente)

GET/POST           /api/signage/signage/client-projects
GET/PATCH/DELETE   /api/signage/signage/client-projects/{id}
GET                /client/{token}/           # Portal público
POST               /client/{token}/upload
POST               /client/{token}/create-playlist
POST               /client/{token}/publish

Vendors soportados (12)

VendorTipo pushControl display
SpinetiXWebDAV—
BrightSignBSN.cloud REST—
SamsungMagicINFOMDC TCP:1515
LGSuperSignTCP:9761
CrestronREST UploadCIP
PhilipsWave/CMNDSICP
IAdeaSMIL HTTP—
BarcoREST UploadPJLink TCP:4352
ChristieREST UploadPJLink
NEC/SharpREST UploadPJLink
YodeckCloud API—
SignageliveCloud API—

Schedule engine

Tipos de regla

TipoCampos
alwaysplaylist_id, priority
time_rangestart, end, playlist_id, priority
day_of_weekdays[], start, end, playlist_id, priority
date_rangestart_date, end_date, playlist_id, priority

Días: 0=Lunes … 6=Domingo (ISO weekday) Evaluación: filtra reglas válidas → selecciona mayor prioridad → fallback a default_playlist


Schedule Matrix (UI)

Tres vistas: Day (24h timeline) / Week (7 columnas) / Month (calendario).


SignageModalHelper

Módulo JS que reemplaza todos los prompt()/confirm() nativos:

import { SignageModal } from './SignageModalHelper.js';

// Selección de dispositivos unificada
const devices = await SignageModal.selectDevices('Publish', 'Publish');
// Devuelve [{id, name, ip}, ...] — con filtro por groups + Select All + status dots

// Input con campos configurables
const result = await SignageModal.input('Title', [
    { name: 'color', label: 'Color', type: 'color', value: '#ffffff' },
    { name: 'size', label: 'Size', type: 'number', value: 48 },
    { name: 'option', type: 'select', options: [{value:'a', label:'A'}] },
]);

// Confirm / Alert
const ok = await SignageModal.confirm('Delete this item?', 'Delete');
await SignageModal.alert('Message', 'Title');

⚠ Los modales NO se cierran al hacer click fuera (click-outside dismiss deshabilitado).


Credenciales automáticas (SignageCredentials.js)

resolveSignageCredentials() — 3 pasos, primero que resuelve gana:

  1. sessionStorage key signage_creds
  2. GET /api/credentials/ → primera credential sección HTTP → GET /api/credentials/{id}/decrypt
  3. Modal prompt (solo si las anteriores están vacías)

⚠ El endpoint publish-setup NO devuelve passwords. Las credenciales se resuelven en frontend.


Playlist Builder (UI)

Modal split-panel (1500px × 90vh):

Playlists is_auto: Las generadas por Publish from Content tienen prefijo _auto_* y se ocultan en el Playlist tab. Auto-purge tras 24h (máximo 20 retenidas).


Clear Playback / Corporate Image

5 acciones disponibles en el modal Clear Playback:


Monitoreo SNMP SpinetiX

MétricaOIDNota
CPU1.3.6.1.2.1.25.3.3.1.2.196608Index no estándar 196608
Memory1.3.6.1.2.1.25.2.3.1.6.1Valor en KB raw
BandwidthVia interface eth0snmp_bandwidth_in/out_mbps

Client Projects (/api/signage/client-projects/) — 5 endpoints

Modulo nuevo: gestiona proyectos de cliente para Digital Signage.

MetodoEndpointProposito
GET/client-projects/Listar proyectos del portal de cliente
POST/client-projects/Crear proyecto de cliente
GET/client-projects/{id}Detalle de proyecto
PUT/client-projects/{id}Actualizar proyecto
DELETE/client-projects/{id}Eliminar proyecto

Convenciones y restricciones

Véase también

Subir