Skip to content

Latest commit

 

History

History
109 lines (89 loc) · 6.01 KB

File metadata and controls

109 lines (89 loc) · 6.01 KB

Local HTTP and native control API

The default server binds to 127.0.0.1:8000. These APIs control its physical station devices in normal mode. Use the silent demo server for experiments. Do not expose this control API to the public internet.

Session token and formats

GET / returns the page with a meta[name="station-token"] value. Every POST/PUT/PATCH/DELETE requires that value in X-Station-Token. JSON calls use Content-Type: application/json; file uploads use multipart form data. Origin, trusted-host and cross-site checks also apply. Reload/retrieve the page after a server restart, because the token changes. It is not an account password or a token to include in URLs, screenshots, Git commits or logs.

Example using the Python standard library against a silent demo on port 8001:

import json, re, urllib.request
base = 'http://127.0.0.1:8001'
page = urllib.request.urlopen(base + '/').read().decode()
token = re.search(r'name="station-token" content="([^"]+)"', page).group(1)
body = json.dumps({'sender': 'LAB-1', 'text': 'Research example'}).encode()
request = urllib.request.Request(base + '/api/transfers', data=body,
    headers={'Content-Type': 'application/json', 'X-Station-Token': token})
transfer = json.load(urllib.request.urlopen(request))
print(transfer['id'])  # Saved to outbox; this call does not play audio.

Errors are JSON { "error": "…" } with an HTTP status. Typical cases: 400 invalid input, 403 missing/expired token or cross-origin request, 409 busy/conflict, 413 oversized input, 503 unavailable native service. Avoid retrying TX blindly.

Messages and transfers

Method / route Body or result
GET /api/status General station information
GET /api/messages {messages: [...]}
DELETE /api/messages Clear displayed message history, retain transfers
DELETE /api/messages/<id> Delete one message
GET /api/transfers {items: [...]} with integrity, progress and missing indices
POST /api/transfers JSON {sender, text} or multipart sender + file; prepares, does not transmit
GET /api/transfers/<id>/packets {packets: [...]}; optional ?parts=0,2,3
GET /api/transfers/<id>/download Original outgoing or verified incoming payload
DELETE /api/transfers/<id> Delete transfer, blocked during its active TX
POST /api/transfers/<id>/sent Record local playback; does not acknowledge remote delivery
POST /api/rx One decoded packet object; validates and ingests it

Raw packet fields are id, kind, name, sender, index, total, size, sha256, data (base64). Indices are zero-based in the API and one-based in operator resend lists. See PROTOCOL.md for exact bounds. Do not pass the UI's one-based numbers directly to packet selection.

Native audio and calibration

Method / route Body or result
GET /api/modem/status Worker availability/PID, devices/settings, meters, preview, job, calibration and events
GET /api/modem/devices {devices: [{deviceId, label, kind}, ...]} on the server's computer
POST /api/modem/settings Partial input/output device, threshold, auto_rx, keep_awake settings
POST /api/modem/rx/start Optional {device}; opens RX and saves enabled intent
POST /api/modem/rx/stop Stops RX and clears enabled intent
POST /api/modem/tx {transfer_id, parts?: [0, ...], settings?: {...}}; starts audible TX
POST /api/modem/tx/stop Stops ordinary TX or calibration
POST /api/modem/calibration/start `{mode: "local"
POST /api/modem/calibration/stop Stops calibration and restores prior state
POST /api/modem/export-wav Transfer/parts/settings like TX; returns WAV without playing it
POST /api/modem/test-wav Optional {level}; fresh 100-baud microphone test WAV
POST /api/modem/decode-wav Multipart file; imports valid NM packets from a WAV

TX settings: baud 100/300, repeats 1–3, level 0.05–0.9, lead 0.1–3 seconds, tail 0–2 seconds, gap 500–5000 milliseconds. The UI TX slider displays percentages, so 18% is 0.18. Calibration caps max_level to 0.1–0.65; the UI offers 18%, 38%, 60%. RX threshold is -65 to -15 dBFS. The calibration profile and rx_enabled cannot be injected with the ordinary settings endpoint; they are managed by verified calibration and RX controls.

Only one TX/calibration runs at a time. Settings mutations and ordinary RX/TX controls are blocked while calibrating; Stop remains available. Calibration traffic is reserved and does not create chat/files. Status is polled by the UI about every 400 ms; long polling or a websocket is not required.

Legacy tools

POST /api/legacy/encode accepts {mode: "1"|"2", text} and returns a job/folder. POST /api/legacy/upload accepts multipart files (1–32 WAV parts). GET /api/library lists legacy folders; GET /api/job/<id> polls work. POST /api/decode/<folder_id> decodes a saved folder; POST /api/delete/<folder_id> deletes it; GET /files/<folder_id>/<filename> retrieves a job artifact. Folder IDs are server-issued, not arbitrary paths.

Native stdin/stdout protocol

The parent talks to nm_minimodem --service using bounded JSON lines containing an incrementing numeric id and op. Replies echo the ID with ok, optional data or error; asynchronous events include level, packet, tx_done and probe_done. See native/station.c and webapp/native_modem.py for the actual implementation. Do not bypass the supervisor while another station owns audio.

Native WAV CLI gap uses seconds, unlike the HTTP/GUI millisecond setting:

{"packets": ["<CRC-valid raw packet hex>"], "baud": 100, "lead": 0.6, "tail": 0.2, "level": 0.18, "gap": 1}

Pipe that JSON into ./nm_minimodem --encode-wav output.wav. ./nm_minimodem --decode-wav input.wav prints CRC-valid packets as JSON lines. These file operations do not open microphones or speakers.