Skip to content
Free shipping on orders over $2,000.

Quickstart

Stand up the smallest server a QuickComm device is happy with, point a unit at it, and watch real 16 kHz audio arrive — in about thirty minutes, on your own infrastructure.

9 min read

This is the shortest path that proves every layer works: the device reaches your server, your server understands what it sent, and audio lands where you can act on it. Do it once, in order, before you write a line of your own business logic. Most integration pain is somebody debugging their intent extraction against a device that was never actually online.

1. Stand up the smallest server that works

A factory-flashed device needs exactly one endpoint to be happy — a heartbeat — plus a socket for whichever transport its mode selects. This file is both, in about forty lines. Run it on a machine the device can reach.

pythonquickcomm_min.py — heartbeat plus udp-v1 ingest
import asyncio, datetime as dt, json
from http.server import BaseHTTPRequestHandler, HTTPServer
from threading import Thread

SEEN = {}                       # mac -> last heartbeat, so you can watch presence

class Fleet(BaseHTTPRequestHandler):
    def _json(self, code, body):
        raw = json.dumps(body).encode()
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(raw)))
        self.end_headers()
        self.wfile.write(raw)

    def do_POST(self):
        if self.path != "/api/devices/heartbeat":
            return self._json(404, {"detail": "not found"})
        n = int(self.headers.get("Content-Length", 0))
        beat = json.loads(self.rfile.read(n) or b"{}")
        mac = beat.get("mac_address", "").upper()
        SEEN[mac] = dt.datetime.now(dt.timezone.utc)
        print("heartbeat", mac, beat.get("firmware_version"), beat.get("wifi_rssi"))
        # pending_commands 0 tells the device not to bother polling for commands.
        self._json(200, {"status": "ok",
                         "last_seen_at": SEEN[mac].isoformat(),
                         "pending_commands": 0})

    def do_GET(self):
        self._json(200, {"status": "ok"}) if self.path == "/health" \
            else self._json(404, {"detail": "not found"})

    def log_message(self, *a):
        pass                     # the prints above are the interesting output

class Ingest(asyncio.DatagramProtocol):
    def datagram_received(self, data, addr):
        nl = data.find(b"\x0a")
        if nl < 1:
            return                                   # not udp-v1; skip, never raise
        meta = data[:nl].decode("ascii", "ignore").split(",")
        pcm  = data[nl + 1:]
        if len(meta) < 9 or meta[0] != "v1" or not pcm:
            return
        print(f"audio seq={meta[1]} session={meta[2]} mac={meta[3]} "
              f"property={meta[5]} bytes={len(pcm)}")
        # ── everything below this line is YOUR product ──────────────────
        # recogniser(f"{meta[3]}|{meta[2]}").feed(pcm)

async def udp():
    loop = asyncio.get_running_loop()
    await loop.create_datagram_endpoint(Ingest, local_addr=("0.0.0.0", 12345))
    await asyncio.Event().wait()

Thread(target=HTTPServer(("0.0.0.0", 8000), Fleet).serve_forever, daemon=True).start()
print("fleet plane on :8000, udp-v1 ingest on :12345")
asyncio.run(udp())
bashRun it, and note the address the device will use
python3 quickcomm_min.py
# fleet plane on :8000, udp-v1 ingest on :12345

# In another shell — the LAN address the device must reach:
ipconfig getifaddr en0            # macOS
hostname -I | awk '{print $1}'    # Linux

2. Prove your server answers before you involve hardware

If these two commands do not behave, the device will not either — and you will spend the next hour blaming the device.

bashImpersonate a device from the network it will sit on
HOST=http://192.168.1.50:8000
MAC=AA:BB:CC:DD:EE:FF

curl -s -X POST $HOST/api/devices/heartbeat \
  -H "Content-Type: application/json" \
  -d "{\"mac_address\":\"$MAC\",\"firmware_version\":\"2.1.4\"}"
# → {"status":"ok","last_seen_at":"...","pending_commands":0}

printf 'v1,1,probe01,%s,2,4,7,19,\n0000000000' "$MAC" \
  | nc -u -w1 192.168.1.50 12345
# the server prints: audio seq=1 session=probe01 mac=AA:BB:... bytes=10

3. Point the device at your server

Every device ships with a QR provisioning card. The payload it carries is what the device writes into non-volatile storage and keeps across reboots — including the address of the server it will talk to.

textThe provisioning payload, pointed at you
http://192.168.4.1/?mac_address=AA:BB:CC:DD:EE:FF
                    &property_id=4
                    &organization_id=2
                    &team_id=7
                    &comm_mode=udp
                    &mode=local              ← your server, not a managed one
                    &local_ip=192.168.1.50
                    &local_port=8000
                    &ssid=YourWiFi
                    &password=...
  1. 1Power the device on. It boots into SoftAP mode and publishes a captive portal at 192.168.4.1.
  2. 2Join that access point with a phone and scan the QR card from the box.
  3. 3The phone opens the URL. The device writes the query string into non-volatile storage and reboots.
  4. 4It joins your Wi-Fi and starts heartbeating your server every 30 seconds.

4. Watch it arrive

Within thirty seconds of the reboot your terminal should print a heartbeat line. Hold the button and speak, and it should print audio lines as fast as the capture buffers fill.

textWhat a healthy bring-up looks like
heartbeat AA:BB:CC:DD:EE:FF 2.1.4 -58
audio seq=0 session=b7f3a1c2 mac=AA:BB:CC:DD:EE:FF property=4 bytes=640
audio seq=1 session=b7f3a1c2 mac=AA:BB:CC:DD:EE:FF property=4 bytes=640
audio seq=2 session=b7f3a1c2 mac=AA:BB:CC:DD:EE:FF property=4 bytes=640
heartbeat AA:BB:CC:DD:EE:FF 2.1.4 -57

5. Turn audio into something

The line marked YOUR product above is where your stack begins. Key a recognition session on mac and device_session so a reboot starts a new session rather than joining the last one, and feed it the PCM as it arrives.

pythonThe change that makes it a product
SESSIONS = {}

def datagram_received(self, data, addr):
    ...
    key = f"{meta[3]}|{meta[2]}"          # mac | device_session
    stream = SESSIONS.get(key)
    if stream is None:
        stream = SESSIONS[key] = my_stt.open(sample_rate=16000, encoding="s16le")
        stream.on_final = lambda text: my_logic(text, property_id=int(meta[5]))
    stream.feed(pcm)

Any provider that accepts a live 16 kHz signed 16-bit little-endian mono stream will work, hosted or local. The device has no opinion.

Where to go from here

  1. 1The minimum server — the full endpoint contract, including commands, incidents and OTA.
  2. 2The page for your mode: push-to-talk streaming, request and response, or full-duplex agent.
  3. 3Building your business logic — eight worked verticals on the same firmware.
  4. 4Acceptance tests — twenty-seven pass/fail tests that define integrated.

Something wrong or missing on this page? Tell us.