Device Response Schema¶
JSON Schema definitions for the v2 unified device response protocol (JSONL format).
Files¶
| File | Purpose |
|---|---|
device-response.json |
Strict validation — recommended for client code generation |
device-response-flexible.json |
Permissive validation — for protocol evolution and testing |
Strict Schema (device-response.json)¶
- Validates
type/statuscombinations (e.g.,event+erroris invalid) - Requires
error_codeanderror_messagewhenstatus="error" - Best for client libraries, type checking, code generation
Flexible Schema (device-response-flexible.json)¶
- Only validates required fields (
type,status,sent_us) - Allows any
type/statuscombination - Best for early development, integration testing, logging
Message Structure¶
All messages share a common envelope:
{
"type": "response|event",
"status": "ok|error",
"sent_us": 1748012345678901
}
sent_us is a Unix timestamp in microseconds (µs) from the ESP32 RTC.
Error Fields (when status="error")¶
{
"error_code": 1,
"error_message": "Invalid argument"
}
Error Codes¶
| Code | Name | Description |
|---|---|---|
0 |
SUCCESS |
Command executed successfully |
1 |
INVALID_ARG |
Invalid command or argument format |
2 |
OUT_OF_RANGE |
Argument value exceeds valid range |
3 |
HARDWARE_ERROR |
SPI/I2C/sensor communication failure |
4 |
NOT_SUPPORTED |
Feature not enabled in firmware build |
5 |
UNKNOWN |
General error |
Event Fields (type="event")¶
Always Present¶
| Field | Type | Description |
|---|---|---|
hit1 |
int | Detection count, channel 1 (GPIO12) |
hit2 |
int | Detection count, channel 2 (GPIO19) |
hit3 |
int | Detection count, channel 3 (GPIO27) |
adc |
int | ADC value (0–4095); 0 if dependent channel has no detection |
Conditional Fields¶
| Field | Condition | Description |
|---|---|---|
hit_type |
ENABLE_HITTYPE=1 |
8-bit bitmask of active channels (bit0=ch1, bit1=ch2, bit2=ch3) |
adc_raw |
ENABLE_ADC_MV=1 |
Raw ADC value (0–4095) |
adc_mv |
ENABLE_ADC_MV=1 |
ADC value converted to millivolts (0–3300) |
tmp_c |
ENABLE_BME280=1 |
Temperature (°C) |
atm_pa |
ENABLE_BME280=1 |
Atmospheric pressure (Pa) |
hmd_pct |
ENABLE_BME280=1 |
Relative humidity (%) |
uptime_ms |
ENABLE_TIMESTAMP=1 |
Device uptime at detection (ms) |
timedelta_us |
ENABLE_TIMESTAMP=1 |
Time since previous event (µs) |
detected_us |
ENABLE_RTC=1 |
Detection moment unix timestamp (µs) |
gnss_time_us |
ENABLE_GNSS=1 |
GNSS time (µs) |
gnss_latitude |
ENABLE_GNSS=1 |
Latitude (decimal degrees) |
gnss_longitude |
ENABLE_GNSS=1 |
Longitude (decimal degrees) |
gnss_altitude |
ENABLE_GNSS=1 |
Altitude (m) |
gnss_satellites |
ENABLE_GNSS=1 |
Number of satellites tracked |
gnss_fix_quality |
ENABLE_GNSS=1 |
Fix quality indicator |
gnss_hdop |
ENABLE_GNSS=1 |
Horizontal dilution of precision |
gnss_fix_valid |
ENABLE_GNSS=1 |
Fix valid flag |
Examples¶
Minimal event (v2 defaults):
{"type":"event","status":"ok","sent_us":1748012345678901,"hit1":85,"hit2":72,"hit3":91,"adc":2048,"hit_type":7,"detected_us":1748012345678456}
Full event (all optional fields enabled):
{
"type": "event",
"status": "ok",
"sent_us": 1748012345678901,
"hit1": 85,
"hit2": 72,
"hit3": 91,
"adc": 2048,
"hit_type": 7,
"adc_raw": 2048,
"adc_mv": 1960,
"tmp_c": 25.35,
"atm_pa": 101325.0,
"hmd_pct": 45.67,
"uptime_ms": 123456,
"timedelta_us": 1000000,
"detected_us": 1748012345678456,
"gnss_time_us": 1748012345000000,
"gnss_latitude": 34.6937,
"gnss_longitude": 135.5023,
"gnss_altitude": 45.9,
"gnss_satellites": 8,
"gnss_fix_quality": 1,
"gnss_hdop": 1.04,
"gnss_fix_valid": true
}
Response Fields (type="response")¶
Response payload fields vary by command. Examples:
{"type":"response","status":"ok","sent_us":1748012345678901,"version":"2.6.0"}
{"type":"response","status":"error","sent_us":1748012345678901,"error_code":1,"error_message":"Invalid argument"}
See Commands Reference for per-command response formats.
Validation¶
Python¶
pip install jsonschema
python3 -m jsonschema -i message.json device-response.json
JavaScript¶
npm install ajv
npx ajv validate -s device-response.json -d message.json