Getting Started

From zero to CoT in minutes

Build the extension, load it into DuckDB, configure your TAK Server, and transmit your first Cursor-on-Target event β€” all from SQL.

Prerequisites

You need these tools installed before building tak-cot-sender.

DuckDB CLI
v0.10.0 or later

The runtime that hosts the extension. Download from duckdb.org/docs/installation/

CMake
v3.21+

Build system. Install via system package manager or cmake.org

C++ Compiler
MSVC 2022 (Win) / GCC 11+ / Clang 14+

C++17 required. Windows: Visual Studio Build Tools.

OpenSSL
1.1.x or 3.x

Required for TCP+TLS transport. Windows: use vcpkg or the OpenSSL installer.

vcpkg (Windows)
optional but recommended

Easiest way to install OpenSSL on Windows: vcpkg install openssl:x64-windows

Git
any recent version

Required to clone the repository and its CMake dependencies.

Build the Extension

Clone the repository and run the standard DuckDB extension CMake build.

PowerShell
# Clone
git clone --recurse-submodules https://github.com/your-org/tak-cot-sender.git
cd tak-cot-sender

# Configure (vcpkg provides OpenSSL)
cmake -B build -S . `
  -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
  -DVCPKG_TARGET_TRIPLET=x64-windows `
  -DCMAKE_BUILD_TYPE=Release

# Build
cmake --build build --config Release --parallel

# Output: build/Release/tak_cot_sender.duckdb_extension
Bash
# Install OpenSSL dev headers (Debian/Ubuntu)
sudo apt-get install -y libssl-dev

# Clone
git clone --recurse-submodules https://github.com/your-org/tak-cot-sender.git
cd tak-cot-sender

# Configure & Build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel $(nproc)

# Output: build/tak_cot_sender.duckdb_extension

Load into DuckDB

Use DuckDB's LOAD command with the path to the built .duckdb_extension file. For community extensions not yet in the official registry, use the unsigned load path.

SQL
-- Allow unsigned extensions (community build)
SET allow_unsigned_extensions = 'true';

-- Windows path example
LOAD 'C:/tak-cot-sender/build/Release/tak_cot_sender.duckdb_extension';

-- Linux path example
LOAD '/opt/tak-cot-sender/build/tak_cot_sender.duckdb_extension';

-- Verify load was successful
SELECT * FROM duckdb_extensions() WHERE extension_name LIKE '%tak%';
πŸ’‘

Add the LOAD and SET statements to a .duckdbrc file in your home directory to auto-load the extension on every DuckDB session.

Configure TAK Server

Store your TAK Server endpoint. Configuration is persisted to an in-memory table __tak_config for the lifetime of the DuckDB session.

SQL
-- Plain TCP (development / non-TLS environments)
SELECT tak_configure('192.168.1.100', 8087, 'tcp');

-- Verify the config was stored
SELECT * FROM tak_config_show();

Common TAK Server ports

8087 β€” TCP (plain)
8088 β€” TCP + TLS
8089 β€” TCP + mTLS (cert auth)
8080 β€” HTTP CoT ingest

Build Your First CoT Event

Construct and inspect a CoT event before sending it to verify the XML output.

Construct the event struct

SQL
SELECT cot_event(
  'UNIT-ALPHA-001',             -- uid
  cot_type('a', 'f', 'G-U-C'),  -- type: friendly ground combat unit
  34.0522,                       -- lat (Los Angeles)
  -118.2437,                     -- lon
  71.0,                          -- hae (m)
  10.0,                          -- ce (m)
  10.0,                          -- le (m)
  now(),                         -- time
  now(),                         -- start
  now() + INTERVAL '5 minutes'  -- stale
) AS event;

Add optional detail metadata

SQL
SELECT struct_pack(
  uid      := 'UNIT-ALPHA-001',
  type     := cot_type('a', 'f', 'G-U-C'),
  lat      := 34.0522,
  lon      := -118.2437,
  hae      := 71.0,
  ce       := 10.0,
  le       := 10.0,
  event_time := now(),
  start    := now(),
  stale    := now() + INTERVAL '5 minutes',
  detail   := cot_detail(
    'callsign', 'ALPHA-1',
    'battery',  '87',
    'group',    'Cyan',
    'role',     'Team Member'
  )
);

Preview the XML output

SQL
SELECT cot_to_xml(cot_event(
  'UNIT-ALPHA-001', cot_type('a','f','G-U-C'),
  34.0522, -118.2437, 71.0, 10.0, 10.0,
  now(), now(), now() + INTERVAL '5 minutes'
));

The output is a complete UTF-8 XML string you can paste into any CoT validator or send manually to verify the structure before wiring up the TAK connection.

Connect & Send

Establish the connection and transmit the event.

SQL
-- 1. Connect (uses the tak_configure settings)
SELECT tak_connect();

-- 2. Verify the connection
SELECT * FROM tak_connection_status();

-- 3. Send a single event β€” returns bytes written
SELECT tak_send(cot_event(
  'UNIT-ALPHA-001', cot_type('a','f','G-U-C'),
  34.0522, -118.2437, 71.0, 10.0, 10.0,
  now(), now(), now() + INTERVAL '5 minutes'
));

-- 4. Check the log for errors
SELECT * FROM tak_log();

-- 5. Disconnect when done
SELECT tak_disconnect();

Batch Transmission

Send many events at once β€” perfect for a query result set like a patrol route, asset registry, or geofence boundary.

SQL
-- Build events from a table of assets
CREATE TABLE assets AS (
  SELECT 'BRAVO-1' AS uid, 34.052 AS lat, -118.24 AS lon UNION ALL
  SELECT 'CHARLIE-1',         34.060,       -118.30          UNION ALL
  SELECT 'DELTA-1',           34.045,       -118.20
);

-- Send batch β€” returns per-event status rows
SELECT *
FROM tak_send_batch(
  SELECT list(cot_event(
    uid, cot_type('a','f','G-U-C'),
    lat, lon, NULL, NULL, NULL,
    now(), now(), now() + INTERVAL '5 min'
  )) FROM assets
);

TLS & mTLS Setup

Production TAK Servers require TLS, and most require mutual TLS with client certificates issued by the TAK Server CA.

SQL
-- Step 1: Configure the server endpoint with TLS
SELECT tak_configure('tak.mission.mil', 8089, 'tcp+tls');

-- Step 2: Load certificate material from PEM files
SELECT tak_configure_tls(
  read_text('/certs/client.pem'),   -- client certificate
  read_text('/certs/client.key'),   -- private key (PEM)
  read_text('/certs/ca-chain.pem')  -- CA certificate chain
);

-- Step 3: Connect β€” performs full mTLS handshake
SELECT tak_connect();
πŸ”

Key handling: Private key PEM content is held in memory only for the session and never written to disk by the extension. Treat the DuckDB process as a security boundary β€” don't share session state across untrusted processes.

Next Steps

πŸ”Œ
Connect Data Sources HTTP endpoints, databases, files, radio feeds, cloud storage and more via community extensions.
πŸ“–
SQL Reference All 24+ function signatures, parameter tables, return types, and copy-ready examples.
πŸ—ΊοΈ
GIS Integration Use the spatial extension to feed GeoJSON, shapefiles, and PostGIS queries directly to TAK.