BMS Connectors

The BMS Application uses a modular connector architecture to integrate with various real-time data sources. Each connector implements a common interface for receiving position updates, video feeds, geofences, and bullseye references.

Connector Architecture

flowchart TB subgraph External["External Data Sources"] RADAR["🛰️ RADAR
Cambridge Pixel"] TAK["📡 TAK Server
ATAK/WinTAK"] AI["🤖 AI Sensor
Autonomous Detection"] GPS["📍 GPS Receiver
NMEA 0183"] ADSB["✈️ ADS-B
OpenSky Network"] AIS["🚢 AIS
Marine Traffic"] GTFS["🚌 GTFS-RT
Transit Feeds"] JSON["📄 JSON Files
Static Data"] DDS["⚙️ DDS Bus
LDM v10"] end subgraph Connectors["BMS Connectors"] SPX["SPX Connector
UDP Multicast"] SAPIENT["SAPIENT Connector
TCP Protobuf"] COT["CoT Connector
TCP/Multicast"] NMEA["NMEA Connector
Serial/Network"] ADSBC["ADS-B Connector
REST API"] AISC["AIS Connector
WebSocket"] GTFSC["GTFS Connector
Protobuf"] JSONC["JSON Connector
File Watch"] LDMC["LDM Connector
DDS Topics"] end subgraph BMS["BMS Application"] CM["Connector Manager"] MAP["Map Widget"] TRACK["Track Display"] end %% RADAR feeds RADAR --> SPX RADAR --> SAPIENT %% AI Sensor feeds AI --> SAPIENT %% TAK feeds TAK --> COT %% Other feeds GPS --> NMEA ADSB --> ADSBC AIS --> AISC GTFS --> GTFSC JSON --> JSONC DDS --> LDMC %% Connectors to BMS SPX --> CM SAPIENT --> CM COT --> CM NMEA --> CM ADSBC --> CM AISC --> CM GTFSC --> CM JSONC --> CM LDMC --> CM CM --> MAP CM --> TRACK style RADAR fill:#e74c3c,color:#fff style AI fill:#9b59b6,color:#fff style TAK fill:#3498db,color:#fff style GPS fill:#27ae60,color:#fff style ADSB fill:#f39c12,color:#fff style AIS fill:#1abc9c,color:#fff style BMS fill:#2c3e50,color:#fff

Available Connectors

Connector Protocol Transport Description
SPX RADAR Cambridge Pixel Binary UDP Multicast RADAR track reports from Cambridge Pixel systems
SAPIENT BSI Flex 335 v2.0 TCP Protobuf Autonomous sensor integration (AI, RADAR)
CoT Cursor on Target XML TCP/Multicast TAK ecosystem integration (ATAK, WinTAK)
NMEA NMEA 0183 Serial/TCP GPS position data
ADS-B OpenSky REST HTTP/JSON Real-time aircraft positions
AIS AIS Messages WebSocket Maritime vessel tracking
GTFS GTFS Realtime HTTP/Protobuf Public transit vehicle positions
JSON File Custom JSON File System Static position data with live monitoring
LDM Land Data Model v10 DDS GVA vehicle/unit positions

SPX RADAR Connector

The SPX connector receives track reports from Cambridge Pixel RADAR systems over UDP multicast.

Protocol Details

  • Magic Number: 0x4342 (Cambridge Pixel)
  • Default Multicast: 239.192.50.79:5079
  • Encoding: Big-endian binary

Message Types

Type Code Size Description
Tracker Status 0x0115 80 bytes Sensor position, track counts
Plot Status 0x0116 48 bytes Sector status updates
Track Minimal 0x0110 72 bytes Basic track info (ID, range, azimuth, speed)
Track Normal 0x0111 128 bytes Includes Cartesian position
Track Extended 0x0112 Variable Includes lat/lon from bitmap

Track Status Values

Status Value Symbol
Deleted 0 Track removed
Provisional 1 Pending confirmation
Established 2 Confirmed track
Lost 3 Coasting (no updates)
Plot 4 Raw detection

Configuration

{
    "connectorId": "spx",
    "enabled": true,
    "settings": {
        "multicastAddress": "239.192.50.79",
        "port": 5079,
        "interface": "",
        "staleTimeoutSec": 30,
        "calculateLatLon": true
    }
}

SAPIENT Connector

The SAPIENT connector implements BSI Flex 335 v2.0 for autonomous sensor integration. It receives detection reports from AI sensors, RADAR, and LIDAR systems and converts them to map tracks with MIL-STD-2525D symbology.

Protocol Details

Property Value
Standard BSI Flex 335 v2.0 (Dstl / Crown Copyright 2024)
Encoding Protocol Buffers (sapient_msg.bsi_flex_335_v2_0)
Transport TCP with 4-byte big-endian length prefix
Default port 8080

Full protobuf parsing requires building with the SAPIENT proto files (HAS_SAPIENT_PROTO). Without them the connector operates in simplified parsing mode.

Operating Modes

Mode Description
client Connects outward to a SAPIENT Data Fusion Node (DFN)
server Binds and accepts inbound connections from autonomous sensor modules (ASMs)

Message Types

flowchart LR subgraph SapientMessage R[Registration] RA[RegistrationAck] DR[DetectionReport] SR[StatusReport] T[Task] TA[TaskAck] AL[Alert] AA[AlertAck] ER[Error] end ASM -->|TCP stream| SapientMessage SapientMessage -->|parsed| BMS
Message Direction Description
Registration ASM → DFN/BMS Sensor capabilities, ICD version, node type, mode definitions
RegistrationAck DFN/BMS → ASM Accept or reject registration with reason strings
DetectionReport ASM → DFN/BMS Object detections with position, classification, velocity
StatusReport ASM → DFN/BMS Sensor health (OK, WARNING, ERROR, GOODBYE), coverage, power
Task DFN/BMS → ASM Sensor tasking commands
TaskAck ASM → DFN/BMS Task acknowledgement
Alert / AlertAck bidirectional Alert events

Detection Reports

A DetectionReport carries:

  • object_id — ULID uniquely identifying the detected object across reports
  • task_id — ULID of the active task
  • state — e.g. "Active", "Lost"
  • Location (one of):
    • Location — absolute WGS-84 x (longitude), y (latitude), z (altitude) with coordinate system flag (LAT_LNG_DEG_M, LAT_LNG_RAD_M, UTM_M)
    • RangeBearing — azimuth, elevation, range relative to the sensor node
  • ENUVelocity — east, north, up velocity in m/s
  • detection_confidence — 0–1 confidence the detection is real
  • classification — repeated DetectionReportClassification with type strings and confidence levels

Detection Classifications

SAPIENT provides AI-based object classification. Classification strings are mapped to APP-6D SIDC:

Classification SIDC Battle Dimension Notes
Vehicle Ground (G) Tank, APC, truck, car
Person Ground (G) Individual or group
Aircraft Air (A) Fixed-wing or rotary
Maritime Surface (S) Boat or ship
Unknown Unknown (U) Fallback

The APP-6D affiliation is derived from the connector's defaultAffiliation setting.

Node Types (Registration)

NodeType Description
RADAR Radar-based system
LIDAR Light-based ranging sensor
CAMERA Optical / thermal camera
ACOUSTIC Acoustic sensor
SEISMIC Seismic sensor
GPS_JAMMING GPS jamming detector
COMMS_INTELLIGENCE COMINT sensor
HUMAN Human reporter
FUSION Data fusion node
OTHER Unclassified type

Stale Track Removal

Tracks not updated within staleTimeout seconds are automatically removed and a trackLost(objectId) signal is emitted. The stale check runs every 30 seconds.

Reconnection

In client mode, if the TCP connection is lost the connector schedules an automatic reconnect after reconnectInterval seconds (default 5 s). The reconnect cycle continues until stop() is called.

Configuration

{
    "connectorId": "sapient",
    "enabled": true,
    "settings": {
        "mode": "client",
        "host": "192.168.1.100",
        "port": 8080,
        "nodeId": "",
        "defaultAffiliation": "unknown",
        "staleTimeout": 300,
        "reconnectInterval": 5
    }
}
Key Type Default Description
mode string client client or server
host string 127.0.0.1 DFN host (client) or bind address (server)
port integer 8080 TCP port
nodeId string (auto-generated UUID) Node UUID sent in Registration messages
defaultAffiliation string unknown Affiliation applied to all detections: unknown, pending, friend, neutral, hostile, suspect
staleTimeout integer 300 Seconds before an unseen track is removed
reconnectInterval integer 5 Seconds between reconnect attempts (client mode)

Server Mode Example

{
    "connectorId": "sapient",
    "enabled": true,
    "settings": {
        "mode": "server",
        "host": "0.0.0.0",
        "port": 8080,
        "defaultAffiliation": "unknown",
        "staleTimeout": 300
    }
}

Cursor on Target (CoT) Connector

The CoT connector provides full integration with the TAK ecosystem (ATAK, WinTAK, TAK Server). It supports both receiving and transmitting SA (situational awareness) data, Self-SA broadcasting, mesh peer unicast, and authenticated TAK server connections.

Protocol Details

Property Value
Format CoT XML (legacy) or TAK Protocol Buffer v2 (binary)
SA multicast group 239.2.3.1:6969
Default TCP port 8087 (plain) / 8089 (TAK server streaming)
TAK Protocol magic byte 0xBF

Receive Modes (source)

Mode Description
multicast Join UDP multicast group — receives all SA broadcasts on the local network
tcp Connect to a single TCP host (e.g. a TAK server relay or ATAK device)
takserver Authenticated connection to a TAK Server with protocol version negotiation and optional TLS

TAK Server Connection

When source is takserver, the connector:

  1. Opens a TCP (or TLS) connection to takServerHost:takServerPort.
  2. Sends a protocol negotiation frame requesting CoT XML (version=0) or TAK Protobuf v1 (version=1).
  3. Receives the server's <version> response and confirms the agreed version.
  4. Enters Authenticated state and begins receiving SA tracks.

Connection state transitions:

stateDiagram-v2 [*] --> Disconnected Disconnected --> Connecting : start() Connecting --> Connected : TCP connected Connected --> Negotiating : send protocol negotiation Negotiating --> Authenticated : version confirmed Authenticated --> Disconnected : TCP lost / stop() Connecting --> Error : timeout Connecting --> Disconnected : auto-reconnect timer Error --> Connecting : auto-reconnect

TLS / Certificate Support

For secure TAK server connections (tlsEnabled: true):

  • PEM client certificate + private key (clientCertPath / clientKeyPath)
  • CA certificate for server verification (caCertPath)
  • PKCS#12 bundle (.p12 / .pfx) via loadPkcs12Certificate() — requires HAS_OPENSSL
  • Certificate password protected keys are supported (keyPassword)

Transmit — Self-SA Broadcasting

When transmitEnabled is true, the connector periodically broadcasts the platform's own position as a CoT Situational Awareness event (a-f-G-U-C by default).

Setting Default Description
transmitEnabled false Enable Self-SA broadcast
selfSaInterval 3 s Broadcast interval
txMulticastGroup same as receive Multicast group to transmit on
txMulticastPort same as receive Port to transmit on
transmitProtocol 0 (XML) 0 = CoT XML, 1 = TAK Protobuf v2
callsign GVA-BMS Own callsign
uid (auto-generated) Own UID (stable across restarts if set)
team Cyan TAK team colour
role Team Member TAK role
cotType a-f-G-U-C Own CoT type string

Mesh Peer Unicast

In addition to multicast, the connector can send CoT events directly to named peers:

"meshPeers": [
    { "address": "192.168.1.50", "port": 6969 },
    { "address": "192.168.1.51", "port": 6969 }
]

sendToAllPeers() transmits to every configured peer. Individual peers can be addressed with sendToPeer().

GeoChat

Incoming CoT events of type b-t-f (GeoChat) are parsed and emitted as chatMessageReceived(uid, senderCallsign, chatroom, message, timestamp) so the BMS chat widget can display them alongside positional tracks.

Track Filtering

Setting Description
filterCotTypePrefix Only accept tracks whose CoT type starts with this string (e.g. "a-h" for hostile only). Empty = accept all.
filterTeamColor Only accept tracks from the specified TAK team colour (e.g. "Red"). Empty = accept all.
maxTracks Maximum concurrent tracks. Oldest entry is evicted when the limit is exceeded. 0 = unlimited.
filterFriendly true = suppress friendly (a-f-*) tracks from the map.

CoT Type → SIDC Mapping

CoT Type Pattern Affiliation APP-6D Battle Dimension
a-f-G-* Friendly Ground
a-f-A-* Friendly Air
a-f-S-* Friendly Surface (maritime)
a-h-G-* Hostile Ground
a-h-A-* Hostile Air
a-n-G-* Neutral Ground
a-s-G-* Suspect Ground
a-u-* Unknown (any)
a-p-* Pending (any)
b-m-p-* Map point / marker
b-t-f GeoChat message

Stale Track Removal

Tracks not updated within staleTimeout seconds (default 300 s) are removed. The stale check runs every 30 seconds.

Configuration Reference

{
    "connectorId": "cot",
    "enabled": true,
    "settings": {
        "source": "multicast",
        "multicastGroup": "239.2.3.1",
        "multicastPort": 6969,
        "networkInterface": "",
        "staleTimeout": 300,
        "filterFriendly": false,
        "filterCotTypePrefix": "",
        "filterTeamColor": "",
        "maxTracks": 0,

        "transmitEnabled": true,
        "selfSaInterval": 3,
        "transmitProtocol": 0,
        "callsign": "GVA-BMS",
        "team": "Cyan",
        "role": "Team Member",
        "cotType": "a-f-G-U-C"
    }
}

TAK Server (TCP / TLS) Example

{
    "connectorId": "cot",
    "enabled": true,
    "settings": {
        "source": "takserver",
        "takServerHost": "tak.example.mil",
        "takServerPort": 8089,
        "tlsEnabled": true,
        "clientCertPath": "/etc/tak/client.pem",
        "clientKeyPath": "/etc/tak/client.key",
        "caCertPath": "/etc/tak/ca.pem",
        "autoReconnect": true,
        "reconnectIntervalMs": 5000,
        "transmitEnabled": true,
        "callsign": "CALLSIGN-1"
    }
}
Key Type Default Description
source string multicast multicast, tcp, or takserver
multicastGroup string 239.2.3.1 Receive multicast group
multicastPort integer 6969 Receive multicast port
tcpHost string localhost Remote host for tcp mode
tcpPort integer 8087 Remote port for tcp mode
takServerHost string TAK server hostname/IP
takServerPort integer 8089 TAK server streaming port
tlsEnabled bool false Use TLS for TAK server
clientCertPath string PEM client certificate
clientKeyPath string PEM private key
caCertPath string CA certificate for server verification
keyPassword string Private key password (if encrypted)
autoReconnect bool true Reconnect on TAK server disconnect
reconnectIntervalMs integer 5000 Reconnect interval in ms
networkInterface string Bind interface for multicast (empty = default)
filterFriendly bool false Suppress friendly tracks
filterCotTypePrefix string Accept only tracks with this CoT type prefix
filterTeamColor string Accept only tracks from this TAK team
maxTracks integer 0 Max concurrent tracks (0 = unlimited)
staleTimeout integer 300 Seconds before a track is removed
transmitEnabled bool false Enable Self-SA broadcast
selfSaInterval integer 3 Self-SA interval in seconds
txMulticastGroup string (same as receive) Transmit multicast group
txMulticastPort integer (same as receive) Transmit multicast port
transmitProtocol integer 0 0 = XML, 1 = TAK Protobuf v2
callsign string GVA-BMS Own callsign
uid string (auto-generated) Own UID
team string Cyan TAK team colour
role string Team Member TAK role
cotType string a-f-G-U-C Own CoT type
meshPeers array [] Unicast mesh peers [{"address":"…","port":6969}]

Data Flow

sequenceDiagram participant Sensor as Data Source participant Conn as Connector participant CM as Connector Manager participant Map as Map Widget Sensor->>Conn: Raw Data (Binary/XML/JSON) Conn->>Conn: Parse & Validate Conn->>Conn: Convert to PositionUpdate Conn->>CM: emit positionUpdated() CM->>Map: Forward Update Map->>Map: Render Symbol

Connector Manager

The Connector Manager handles:

  • Registration: Built-in and plugin connectors
  • Lifecycle: Start, stop, configure connectors
  • Routing: Forward updates to map and track displays
  • Status: Monitor connector health and statistics

Loading Connectors

// Get connector manager instance
auto* manager = ConnectorManager::instance();

// Create and configure a connector
auto* spx = manager->createInstance("spx", "radar-1");
spx->configure({
    {"multicastAddress", "239.192.50.79"},
    {"port", 5079}
});

// Connect signals
connect(spx, &ConnectorInterface::positionUpdated,
        this, &BmsWindow::onPositionUpdate);

// Start receiving data
spx->start();

Symbol Mapping

Connectors convert source-specific data to APP-6D military symbols (SIDC):

Source Default Symbol Notes
SPX Track Air/Surface Unknown Based on track status and flags
SAPIENT Detection Based on classification AI confidence affects display
CoT Event Derived from CoT type Direct mapping from a-X-Y-Z
ADS-B Aircraft Neutral Air Based on aircraft category
AIS Vessel Neutral Surface Based on vessel type

Adding Custom Connectors

Implement the ConnectorInterface to create custom connectors:

class MyConnector : public ConnectorInterface
{
    Q_OBJECT
public:
    QString connectorId() const override { return "my-connector"; }
    QString displayName() const override { return "My Custom Connector"; }

    bool configure(const QVariantMap& settings) override;
    bool start() override;
    void stop() override;

    // Emit positionUpdated() when data arrives
};

See ConnectorInterface.h for the full interface definition.