Saltar al contenido principal

Pulsador de dispositivo (deviceButton)

Es un botón físico del DVR (N9M) que el chofer puede presionar para generar una alarma de pánico/urgencia. A nivel protocolo llega como una alarma EVEM más, con ALARMTYPE 7:

{
"MODULE": "EVEM",
"OPERATION": "SENDALARMINFO",
"PARAMETER": {
"ALARMAS": 1,
"ALARMCOUNT": 1,
"ALARMNAME": "Truck Urgent Alarm",
"ALARMTYPE": 7,
"ALARMUID": 1,
"CMDNO": 289013761,
"CMDTYPE": 1,
"CURRENTTIME": 1786014911,
"L": 8,
"LCH": 1,
"P": {
"C": 11010,
"J": "-64.186667",
"S": 0,
"T": "20260806141510",
"V": 0,
"W": "-31.398204"
},
"SER": "urgent_alarm",
"TRIGGERTYPE": 1
},
"SESSION": "00000AB5F1372EC1B64BE60F1DEED55A"
}

Lo particular de esta alarma es que, además de generar el incidente, automáticamente le pide una foto al dispositivo (vía el comando REQUESTCATCHPIC) y esa foto queda asociada al incidente en la base — es la primera alarma que dispara este flujo de snapshots.

Cómo se ve en el frontend​

El incidente aparece con el tipo Pulsador de dispositivo. Desde el detalle del incidente, la solapa Galería (ícono de cámara) muestra las fotos que el dispositivo mandó automáticamente al dispararse la alarma, con la superposición estándar de canal, velocidad, fecha/hora y coordenadas GPS:

Galería de fotos del incidente, tomadas automáticamente al presionar el pulsador de dispositivo

Proyectos involucrados​

ProyectoRol
n9m-signal-processorRecibe el EVEM/SENDALARMINFO del DVR. Mapea ALARMTYPE 7 → AlarmType.DEVICE_BUTTON y setea evento.tipo = 'deviceButton' antes de mandar el evento a la nube.
rules-create-incidentCrea el incidente en MySQL (acá recién existe el incident.id). En el afterSave, si el tipo.nombreCorto del incidente matchea la lista configurada (SNAPSHOTS_TYPES/SNAPSHOTS_ENABLED_TYPES, o por lugares con SNAPSHOTS_ENABLED_PLACES), publica a Redis (hur_catch_pic) pidiendo la foto, incluyendo el incidentId recién generado.
n9m-centerSuscripto a hur_catch_pic. Le manda al DVR el comando MEDIASTREAMMODEL/REQUESTCATCHPIC, armando un STREAMNAME que codifica series, tipo e incidentId juntos (ver detalle técnico más abajo).
n9m-media-goEl DVR se conecta ahí para mandar las fotos (JPEG_SNAPSHOT). Sube cada una al bucket y, si pudo extraer el incidentId del STREAMNAME, le avisa al backend (POST /api/incidenteSnapshot) el nombre del archivo subido.
apis (plataforma)Expone POST /api/incidenteSnapshot, que persiste la relación incidentId ↔ nombre del archivo en el bucket (una fila por foto — un incidente puede tener varias).
rules-complete-tipoeventosYa no participa de este flujo: la lógica de snapshots vivía acá originalmente, pero se movió a rules-create-incident porque en ese punto del pipeline todavía no existe el id del incidente en la base.

Flujo de información​

  1. El chofer presiona el botón del DVR → llega EVEM/SENDALARMINFO con ALARMTYPE 7.
  2. n9m-signal-processor lo traduce a tipo: 'deviceButton' y lo manda al pipeline de eventos (rules-complete-* → motor-reglas → rules-create-incident), igual que cualquier otra alarma.
  3. rules-create-incident inserta el incidente en mysql y, ya con el id asignado, publica a Redis (hur_catch_pic) con series, tipo, incidentId y los parámetros de la foto (count, interval, r, q, pt — con defaults si no vienen).
  4. n9m-center recibe ese mensaje y le manda al DVR el REQUESTCATCHPIC, con STREAMNAME: "<series>_<tipo>_<incidentId>".
  5. El DVR toma la(s) foto(s) y las manda como JPEG_SNAPSHOT a n9m-media-go, que las sube al bucket.
  6. Por cada foto subida con éxito, n9m-media-go extrae el incidentId del STREAMNAME y hace POST /api/incidenteSnapshot con {incidentId, fileName}.
  7. El frontend, al abrir el incidente, lista esas fotos en la solapa Galería.

Detalles técnicos relevantes​

  • Protocolo: MODULE: MEDIASTREAMMODEL, OPERATION: REQUESTCATCHPIC para pedir la foto — mismo módulo que usan Monitor/Intercom (REQUESTTALK) y Live Video (REQUESTALIVEVIDEO), pero sin CATCHPICSTART: el DVR confirma el pedido vía CREATESTREAM (igual que en video en vivo), y n9m-media-go usa ese STREAMNAME como base del nombre del archivo.
  • Parámetros configurables de la foto: count, interval, r, q, pt se leen del mensaje de Redis si vienen, y si no, caen a los defaults 5, 2, 7, 1, 6 respectivamente (mismos valores que ya se usaban antes de este cambio).
  • STREAMNAME como transporte del incidentId: no hay un campo dedicado en REQUESTCATCHPIC para asociar la foto a un incidente, así que se aprovecha el STREAMNAME (formato series_tipo_incidentId) — n9m-media-go extrae todo lo que sigue al último _ como incidentId al armar el callback.
  • Tabla incidenteSnapshot: relación belongsTo incidentes por incidentId, con createdAt autogenerado por MySQL (DEFAULT a nivel de columna, no seteado por la app). Como puede haber varias fotos por incidente, no hay clave única sobre incidentId.
  • Autenticación del callback: POST /api/incidenteSnapshot usa el mismo mecanismo que ya existía para /api/playbackSessions/callback (Basic auth con un token de servicio, no login de usuario) — hubo que agregarlo explícitamente a la lista de rutas permitidas para ese esquema de auth.