跳到主要内容

Data Query API Reference

Available since: v1.3.1

The Data Query API provides read-only HTTP access to the OpenSynaptic SQL storage layer (os_packets and os_sensors tables).

All endpoints are served by the web_user service (default http://127.0.0.1:8765).


Authentication

When auth_enabled = true in the web_user service configuration, all data query endpoints require the X-Admin-Token header.

X-Admin-Token: <your-admin-token>

If the token is missing or incorrect the server returns 401 Unauthorized.


Prerequisites

SQL storage must be enabled in Config.json:

{
"storage": {
"sql": {
"enabled": true,
"dialect": "sqlite",
"driver": { "path": "data/opensynaptic.db" }
}
}
}

Supported dialects: sqlite, mysql, postgresql.

If storage is not configured, all data query endpoints return:

{ "ok": false, "error": "database not configured" }

with HTTP status 503.


Endpoints

GET /api/data/devices

List distinct devices recorded in the database with their last-seen timestamp and total packet count.

Query Parameters

ParameterTypeDefaultDescription
limitinteger100Maximum number of devices to return (1–500)
offsetinteger0Pagination offset

Response

{
"ok": true,
"devices": [
{
"device_id": "SENSOR_NODE_01",
"last_seen": 1712000500,
"packet_count": 120
}
],
"total": 1,
"limit": 100,
"offset": 0
}
FieldTypeDescription
device_idstringDevice identifier
last_seenintegerUnix epoch of the most recent packet
packet_countintegerTotal packets from this device
totalintegerTotal distinct devices (for pagination)

GET /api/data/packets

Return a paginated list of packets, ordered by timestamp_raw descending.

Query Parameters

ParameterTypeDefaultDescription
device_idstringFilter by device ID (exact match)
statusstringFilter by device_status (e.g. ONLINE, WARN)
sinceintegerUnix epoch lower bound (inclusive)
untilintegerUnix epoch upper bound (inclusive)
limitinteger50Max rows (1–500)
offsetinteger0Pagination offset

Response

{
"ok": true,
"packets": [
{
"packet_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"device_id": "SENSOR_NODE_01",
"device_status": "ONLINE",
"timestamp_raw": 1712000500,
"payload_json": { "id": "SENSOR_NODE_01", "s": "ONLINE", "t": 1712000500 },
"created_at": 1712000501
}
],
"total": 120,
"limit": 50,
"offset": 0
}
FieldTypeDescription
packet_uuidstringUUID primary key
device_idstringSource device ID
device_statusstringDevice status at time of packet
timestamp_rawintegerUnix epoch from the original packet
payload_jsonobjectDecoded packet payload
created_atintegerUnix epoch when the row was inserted
totalintegerTotal matching rows (for pagination)

GET /api/data/packets/{uuid}

Retrieve a single packet by its UUID, along with all associated sensor readings.

Path Parameters

ParameterDescription
uuidPacket UUID (from packet_uuid field)

Response — Found (200)

{
"ok": true,
"packet": {
"packet_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"device_id": "SENSOR_NODE_01",
"device_status": "ONLINE",
"timestamp_raw": 1712000500,
"payload_json": { "id": "SENSOR_NODE_01", "s": "ONLINE", "t": 1712000500 },
"created_at": 1712000501
},
"sensors": [
{
"sensor_index": 1,
"sensor_id": "TEMP",
"sensor_status": "OK",
"normalized_value": 22.5,
"normalized_unit": "Cel"
},
{
"sensor_index": 2,
"sensor_id": "HUM",
"sensor_status": "OK",
"normalized_value": 55.0,
"normalized_unit": "%"
}
]
}

Response — Not Found (404)

{
"ok": false,
"error": "packet not found",
"packet_uuid": "00000000-0000-0000-0000-000000000000"
}

GET /api/data/sensors

Return a paginated list of sensor readings, joined with packet metadata. Results are ordered by timestamp_raw descending, then sensor_index ascending.

Query Parameters

ParameterTypeDefaultDescription
device_idstringFilter by device ID
sensor_idstringFilter by sensor identifier (e.g. TEMP, HUM)
sinceintegerUnix epoch lower bound
untilintegerUnix epoch upper bound
limitinteger50Max rows (1–500)
offsetinteger0Pagination offset

Response

{
"ok": true,
"sensors": [
{
"packet_uuid": "a1b2c3d4-...",
"sensor_index": 1,
"sensor_id": "TEMP",
"sensor_status": "OK",
"normalized_value": 22.5,
"normalized_unit": "Cel",
"device_id": "SENSOR_NODE_01",
"timestamp_raw": 1712000500
}
],
"total": 240,
"limit": 50,
"offset": 0
}
FieldTypeDescription
packet_uuidstringParent packet UUID
sensor_indexinteger1-based position within the packet
sensor_idstringSensor identifier
sensor_statusstringSensor status at time of reading
normalized_valuefloat | nullUCUM-normalized numeric value
normalized_unitstring | nullUCUM unit string
device_idstringSource device ID (from parent packet)
timestamp_rawintegerUnix epoch (from parent packet)
totalintegerTotal matching rows

Python API

You can call the query methods directly on a DatabaseManager instance:

from opensynaptic.services.db_engine import DatabaseManager

db = DatabaseManager.from_opensynaptic_config(config)
db.connect()

# List devices
result = db.query_devices(limit=50, offset=0)

# List packets
result = db.query_packets(device_id='SENSOR_NODE_01', since=1710000000, limit=20)

# Single packet
result = db.query_packet('a1b2c3d4-e5f6-7890-abcd-ef1234567890')
# Returns None if not found

# Sensor readings
result = db.query_sensors(sensor_id='TEMP', since=1710000000)

All methods return plain dict objects matching the JSON response structure above.


Error Codes

HTTP StatusMeaning
200Success
400Bad request (e.g. missing required path segment)
401Unauthorized — missing or invalid X-Admin-Token
404Resource not found
503Database not configured