You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ADN-DMR-Peer-Server/docs/es/server/protocols/report-v2.md

11 KiB

Protocolo de informes v2 (JSON)

Estado: borrador de esquema. La codificación en wire y la emisión en el servidor están en progreso; el consumidor monitor v2 es un entregable aparte.

Objetivos

Sustituir instantáneas al monitor que hoy usan pickle (CONFIG_SND, BRIDGE_SND) y CSV (BRDG_EVENT) por JSON tipado.

Política de releases: adn-server 1.0.x + adn-monitor 1.0.x = report v1 (tags congelados). El servidor 2.x emite solo report v2 (sin shim pickle ni dual); requiere adn-monitor 2.x en la misma línea.

Transporte (sin cambios)

  • TCP netstring (Twisted NetstringReceiver), mismo puerto que v1 (REPORTS.REPORT_PORT).
  • Cada trama: 1 byte de opcode + payload JSON UTF-8 (v2) o pickle/CSV (v1).

Opcodes

Opcode Hex Payload v1 Payload v2
HELLO 0xFF JSON hello (protocol: 1) JSON hello (report_protocol: 2)
CONFIG_SND 0x01 pickle SYSTEMS — (TOPOLOGY_SND)
BRIDGE_SND 0x03 pickle BRIDGES — (ROUTING_TABLE_SND)
BRDG_EVENT 0x07 texto CSV — (VOICE_EVENT_SND)
TOPOLOGY_SND 0x10 — JSON topology
ROUTING_TABLE_SND 0x11 — JSON routing_table
VOICE_EVENT_SND 0x12 — JSON voice_event
DELTA_SND 0x13 — JSON delta

Los opcodes 0x10–0x13 están reservados en esta fase; pueden ajustarse antes de P1-002.

flowchart TB
  subgraph v1 [Informe v1 — adn-server 1.0.x + monitor 1.0.x]
    H1[HELLO protocol 1] --> C1[CONFIG_SND pickle]
    C1 --> B1[BRIDGE_SND pickle]
    B1 --> V1[BRDG_EVENT CSV]
  end

  subgraph v2 [Informe v2 — adn-server 2.x + monitor 2.x]
    H2[HELLO report_protocol 2] --> T2[TOPOLOGY_SND JSON]
    T2 --> R2[ROUTING_TABLE_SND JSON]
    R2 --> V2[VOICE_EVENT_SND JSON]
    R2 -.-> D2[DELTA_SND opcional]
  end

Handshake (hello)

Al conectar, el servidor envía HELLO (0xFF) primero. Clientes v2 miran report_protocol:

{
  "type": "hello",
  "server": "adn-server",
  "version": "2.0.0-alpha.1",
  "report_protocol": 2,
  "features": ["INGRESS", "END_TX_FORWARD", "PUSH_ON_CONNECT", "REPORT_V2", "TOPOLOGY_JSON", "ROUTING_TABLE_JSON", "VOICE_EVENT_JSON", "DELTA_UPDATES"],
  "systems": ["MASTER-A", "OBP-CL"]
}
Campo Notas
report_protocol 2 para este esquema. Distinto del campo legacy protocol: 1.
features Tokens v1 sin cambios; v2 añade REPORT_V2 y capacidades de payload.

Tipos de mensaje

type Sustituye Uso
topology CONFIG_SND Sistemas, peers, piernas OBP (sin secretos).
routing_table BRIDGE_SND Piernas de bridge por TG / reflector.
voice_event BRDG_EVENT Inicio/fin/ingress de llamadas.
delta — Parche incremental desde since_seq.

Payloads de referencia

Cada trama lleva un único objeto JSON con type obligatorio. Los ejemplos usan IDs anonimizados.

topology

{
  "type": "topology",
  "seq": 1,
  "ts": 1717555200.0,
  "systems": [
    {
      "name": "MASTER-A",
      "mode": "MASTER",
      "enabled": true,
      "ip": "10.0.0.1",
      "port": 62030,
      "repeat": true,
      "peers": [
        { "id": 3120001, "connected": true, "ip": "10.0.0.50", "port": 62031 }
      ]
    },
    {
      "name": "OBP-CL",
      "mode": "OPENBRIDGE",
      "enabled": true,
      "ip": "10.0.0.2",
      "port": 62044,
      "enhanced_obp": true,
      "peers": []
    }
  ]
}
Campo Tipo Obligatorio Notas
seq, ts int, float sí Secuencia monótona y epoch.
systems[].name string sí Clave de sistema (config).
systems[].mode string sí MASTER, PEER u OPENBRIDGE.
systems[].enabled bool sí Flag enabled de config.
systems[].ip, port string, int no Endpoint de escucha/conexión.
systems[].repeat bool no Repeat en master.
systems[].enhanced_obp bool no OBP enhanced.
systems[].peers[] array no {id, connected, ip?, port?} por radio peer.

Sin contraseñas ni material de cifrado (a diferencia del pickle legacy).

routing_table

{
  "type": "routing_table",
  "seq": 42,
  "ts": 1717555260.5,
  "routes": [
    {
      "bridge_key": "52090",
      "legs": [
        {
          "system": "MASTER-A",
          "ts": 2,
          "tgid": 52090,
          "active": true,
          "to_type": "ON",
          "timer_expires_at": 1717555320.0
        },
        {
          "system": "MASTER-B",
          "ts": 2,
          "tgid": 52090,
          "active": true,
          "to_type": "ON"
        }
      ]
    },
    {
      "bridge_key": "#310",
      "legs": [
        {
          "system": "MASTER-A",
          "ts": 2,
          "tgid": 310,
          "active": false,
          "to_type": "NONE"
        }
      ]
    }
  ]
}
Campo Tipo Obligatorio Notas
routes[].bridge_key string sí TG o clave reflector (#nnn).
legs[].system string sí Nombre del sistema destino.
legs[].ts 1 | 2 sí Timeslot (legacy TS).
legs[].tgid int sí Talkgroup (1–16777215).
legs[].active bool sí Pierna activa en BRIDGES.
legs[].to_type string sí ON, OFF, STAT o NONE.
legs[].timer_expires_at float no Expiración rule_timer (legacy TIMER).

voice_event

CSV legacy:

GROUP VOICE,START,RX,MASTER-A,2155905152,1001,3120001,2,52090

Equivalente v2:

{
  "type": "voice_event",
  "ts": 1717555201.234,
  "call_family": "GROUP",
  "phase": "START",
  "direction": "RX",
  "system": "MASTER-A",
  "stream_id": 2155905152,
  "peer_id": 1001,
  "src_id": 3120001,
  "slot": 2,
  "dst_id": 52090,
  "duration_s": null
}
Campo Tipo Obligatorio Valores / notas
call_family string sí GROUP, PRIVATE, UNIT, VCSSBK.
phase string sí INGRESS, START, END.
direction string sí RX, TX.
stream_id int sí Stream HBP 32 bits.
peer_id, src_id, dst_id int sí IDs DMR (1–16777215).
slot int sí 1 o 2.
duration_s float | null no En eventos END.

Semántica OpenBridge INGRESS/START: ver Monitor e informes.

delta

{
  "type": "delta",
  "seq": 43,
  "ts": 1717555261.0,
  "since_seq": 42,
  "patch": {
    "type": "routing_table",
    "seq": 43,
    "ts": 1717555261.0,
    "routes": [
      {
        "bridge_key": "52090",
        "legs": [
          {
            "system": "MASTER-A",
            "ts": 2,
            "tgid": 52090,
            "active": false,
            "to_type": "ON"
          }
        ]
      }
    ]
  }
}
Campo Tipo Obligatorio Notas
since_seq int sí Último seq aplicado por el cliente.
patch object sí Parcial topology o routing_table (misma forma).

Secuenciación

  • topology y routing_table llevan seq (uint) y ts (epoch float).
  • delta indica since_seq respecto al último seq aplicado por el cliente.

Configuración

REPORTS:
  REPORT: true
  REPORT_PORT: 4321

Sin PROTOCOL en 2.x — wire siempre JSON (wire.py). Mapeo: application/report/.

Espejo MQTT opcional

Por defecto los informes salen solo por TCP netstring (adn-monitor y otros clientes TCP). MQTT queda deshabilitado salvo activación explícita.

Activar solo cuando se cumplen ambas condiciones:

  1. REPORTS.MQTT.ENABLED: true (booleano true, no basta con existir la clave)
  2. REPORTS.MQTT.URL — URL del broker (mqtt://host:1883 o mqtts://host:8883)
REPORTS:
  REPORT: true
  REPORT_PORT: 4321
  MQTT:
    ENABLED: true
    URL: mqtt://127.0.0.1:1883
    TOPIC_PREFIX: adn/73010   # opcional; por defecto adn/{GLOBAL.SERVER_ID}
    USERNAME: my-mqtt-user     # opcional; sustituye al usuario en la URL
    PASSWORD: my-mqtt-secret   # opcional; sustituye a la contraseña en la URL
    CAFILE: /path/to/ca.pem    # opcional; CA del broker con mqtts://
    QOS: 0                    # opcional, 0–2

Client ID: generado al arrancar como adn-server-{GLOBAL.SERVER_ID}-{random} (no configurable; el sufijo aleatorio evita colisiones de sesión en el broker al reiniciar).

Autenticación: usuario/contraseña con USERNAME y PASSWORD, o embebidos en la URL (mqtt://user:pass@host:1883). Las credenciales YAML tienen prioridad sobre la URL. La contraseña puede ir vacía si el broker lo permite. Con mqtts://, indique CAFILE si el broker usa una CA propia.

Dependencia opcional: pip install 'adn-server[mqtt]' (paho-mqtt). Si MQTT está habilitado pero falta la librería, el servidor registra error y sigue solo con TCP.

Wire MQTT (fijo, no configurable): solo voice_event (telemetría) y state (snapshot). Los tipos solo-TCP (topology, routing_table, delta, hello) no se publican por MQTT.

Convención de topics (compartidos bajo {prefix}):

Topic Dirección type JSON Retain
voice_event servidor → broker voice_event no
state servidor → broker dashboard_state sí

state incluye masters con peers conectados, peers sueltos y openbridges (equivalente WebSocket conf,lnksys + conf,opb). Va con retain para que nuevos suscriptores reciban el último snapshot sin pedirlo. Los refrescos por topología republican {prefix}/state cuando cambia el dashboard (dedup).

Disparadores: voice_event en vivo; {prefix}/state retenido al cambiar topología y tras conectar MQTT (dedup).

Ejemplo (SERVER_ID 7302):

mosquitto_sub -h BROKER -p 1883 -u USER -P PASS -t 'adn/7302/state' -v
mosquitto_sub -h BROKER -p 1883 -u USER -P PASS -t 'adn/7302/voice_event' -v

ACL TBMQ: consumidores con subscribe en adn/7302/state y adn/7302/voice_event; el client_id del servidor solo necesita publish en esos dos topics (sin subscribe en el servidor).

Recarga (systemctl reload / SIGHUP): si cambia REPORTS.MQTT (activar/desactivar, URL, credenciales, TLS, TOPIC_PREFIX, QOS), el servidor desconecta el cliente MQTT anterior y conecta con la nueva config, o se queda sin MQTT si ENABLED pasa a false.

QoS: configurable con MQTT.QOS (por defecto 0).

Los timers usan deltas cuando solo cambia parte de BRIDGES; conexión, REPORT_INTERVAL, reload y CONFIG_REQ / BRIDGE_REQ envían instantáneas completas.

Acoplamiento de versiones (combinaciones soportadas)

Servidor Monitor Wire de informes Notas
1.0.x 1.0.x v1 (pickle/CSV) Par congelado
2.0.0-alpha.* 2.x (dev) solo v2 Línea develop actual
2.0.0 2.0.x solo v2 Par GA; monitor 1.0.x no soportado

No usar monitor 1.0.x con servidor 2.0.0 ni monitor 2.x con servidor 1.0.x en producción.

Ver también Monitor e informes.

Powered by TurnKey Linux.