Unified Device Response Schema - Detailed Specification¶
Date: 2025-12-08 Version: 1.0 (Design) Status: 決定済み Target: v1.11.3+
Quick Links:
- Executive Summary: 2025-12-08-device-response-1-executive-summary.md - 1-page overview
- Architecture Overview: 2025-12-08-device-response-2-architecture-overview.md - Design principles and rationale
- Implementation Checklist: 2025-12-08-device-response-4-implementation-checklist.md - Task breakdown by phase
Overview¶
OSECHI(検出器)が送信するすべてのデータ(イベント・レスポンス)を単一の統一スキーマに従わせ、クライアント(kazunoko等)が統一されたパーサーで処理できる状態を実現する。
終状態:
- OSECHI: event/response → unified schema (JSONL) → Serial
- Client: unified schema (JSONL) → single parser → application logic
Unified Schema Definition¶
Top-level Structure¶
すべての出力は以下の統一フォーマットに従う:
{
"type": "response" | "event",
"status": "ok" | "error",
"sent_at": 1732046789,
"<field_name>": <value>,
"<nested_object>": { ... }
}
Field Specifications¶
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
type |
string | ✅ | "response" = コマンド応答 / "event" = 検出イベント |
status |
string | ✅ | "ok" = 成功 / "error" = エラー |
sent_at |
uint32 | ✅ | Unix timestamp (RTC利用時) または device uptime (秒単位) |
error_code |
int | ❌ | エラーコード(status="error" 時のみ) |
error_message |
string | ❌ | エラーメッセージ(status="error" 時のみ) |
| 他すべてのフィールド | * | ❌ | type/status に応じた動的フィールド |
Response Schema¶
type="response" かつ status="ok"
{
"type": "response",
"status": "ok",
"sent_at": 1732046789,
"<command_specific_field>": <value>
}
Examples:
// GET_VERSION
{"type":"response","status":"ok","sent_at":1732046789,"version":"1.10.0"}
// SET_THRESHOLD (channel=1, value=1234)
{"type":"response","status":"ok","sent_at":1732046789,"threshold":{"channel":1,"value":1234}}
// GET_STATUS (nested structure)
{"type":"response","status":"ok","sent_at":1732046789,"system":{"version":"1.10.0","uptime_ms":123456},"detection":{"poll_count":100,"deadtime_ms":50}}
// GET_GNSS_POSITION
{"type":"response","status":"ok","sent_at":1732046789,"gnss":{"latitude":37.3874,"longitude":121.9724,"altitude":45.9}}
type="response" かつ status="error"
{
"type": "response",
"status": "error",
"sent_at": 1732046789,
"error_code": <code>,
"error_message": "<message>"
}
Examples:
{"type":"response","status":"error","sent_at":1732046789,"error_code":1,"error_message":"Invalid argument"}
{"type":"response","status":"error","sent_at":1732046789,"error_code":2,"error_message":"Value out of range"}
Event Schema¶
type="event" かつ status="ok"
{
"type": "event",
"status": "ok",
"sent_at": 1732046789,
"hit1": <uint16>,
"hit2": <uint16>,
"hit3": <uint16>,
"adc": <int>,
"hit_type": <uint8> (optional, ENABLE_HITTYPE=1),
"adc_raw": <uint16> (optional, ENABLE_ADCMV=1),
"adc_mv": <uint16> (optional, ENABLE_ADCMV=1),
"tmp_c": <float> (optional, ENABLE_BME280=1),
"atm_pa": <float> (optional, ENABLE_BME280=1),
"hmd_pct": <float> (optional, ENABLE_BME280=1),
"uptime_ms": <uint32> (optional, ENABLE_TIMESTAMP=1),
"timedelta_us": <uint64> (optional, ENABLE_TIMESTAMP=1),
"unix_timestamp": <uint32> (optional, ENABLE_RTC=1),
"gnss": { ... } (optional, ENABLE_GNSS=1)
}
Examples:
// Minimal event (core fields only)
{"type":"event","status":"ok","sent_at":1732046789,"hit1":95,"hit2":87,"hit3":91,"adc":2048}
// Full event with environmental + timing
{"type":"event","status":"ok","sent_at":1732046789,"hit1":95,"hit2":87,"hit3":91,"adc":2048,"tmp_c":25.35,"atm_pa":101325,"hmd_pct":45.67,"uptime_ms":123456,"timedelta_us":1000000}
// Event with GNSS data
{"type":"event","status":"ok","sent_at":1732046789,"hit1":100,"hit2":100,"hit3":100,"adc":2000,"gnss":{"latitude":37.3874,"longitude":121.9724,"altitude":45.9,"satellites":8,"hdop":1.04}}
See Also: For detailed implementation steps and task breakdown, refer to unified-device-response-protocol-design.md
Client-side Integration (kazunoko 対応)¶
kazunoko Parser 統一化¶
# kazunoko/parser.py
class DeviceResponse(BaseModel):
"""統一スキーマに従うデバイスレスポンス"""
type: Literal["response", "event"]
status: Literal["ok", "error"]
sent_at: int
# Dynamic fields (Pydantic's extra="allow")
model_config = ConfigDict(extra="allow")
# Optional error fields
error_code: Optional[int] = None
error_message: Optional[str] = None
# パーサーは既存の parse_jsonl() で対応可能
response = DeviceResponse(**json.loads(line))
クライアント実装例¶
# Any client language can follow the schema
def handle_osechi_output(jsonl_line):
msg = parse_json(jsonl_line)
if msg.type == "response":
if msg.status == "ok":
handle_command_response(msg)
else:
handle_error(msg.error_code, msg.error_message)
elif msg.type == "event":
if msg.status == "ok":
handle_detection_event(msg)
Key Design Decisions¶
1. Single Schema for All Output¶
決定: response と event を同一スキーマで表現
メリット: - ✅ クライアント実装がシンプル(単一パーサーで全対応) - ✅ スキーマ仕様がシンプル(扱う型が統一) - ✅ 将来の拡張が容易(新フィールド追加も スキーマ内で完結)
2. Dynamic Fields via JSON¶
決定: response/event 固有フィールドは JSON 内に格納
メリット: - ✅ スキーマは固定だが、ペイロード内は可変 - ✅ nested object/array にも対応 - ✅ Optional fields(ENABLE_* フラグ)も自然に対応
3. sent_at = Common Timestamp¶
決定: すべての出力に sent_at フィールドを含める
メリット: - ✅ イベント/レスポンスのタイムスタンプが一貫 - ✅ ENABLE_RTC 時は Unix time、なければ device uptime で自動フォールバック - ✅ クライアント側で時系列ソートが容易
4. Zero-cost Adoption via Conditional Compilation¶
決定: ENABLE_DEVICE_RESPONSE フラグで段階的採用
メリット: - ✅ Phase 1 段階では response のみ、binary size 影響最小 - ✅ phase 2-3 で完全移行後、response.h を削除 - ✅ リスク最小化(既存機能温存)
Note: Testing details and strategies are provided in unified-device-response-protocol-design.md (Implementation Checklist section).
Future Extensions¶
Multi-language Client Libraries¶
スキーマが固定なので、以下の客動言語で同一パーサーを実装可能:
- Python: kazunoko (現在開発中)
- JavaScript/TypeScript: osechi-client
- Rust: osechi-rs
- Go: osechi-go
各言語とも、JSON スキーマバリデーター自動生成が可能:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["type", "status", "sent_at"],
"properties": {
"type": {"enum": ["response", "event"]},
"status": {"enum": ["ok", "error"]},
"sent_at": {"type": "integer"}
},
"additionalProperties": true
}
Summary¶
統一スキーマにより実現される開発体験:
OSECHI (firmware) kazunoko (Python) custom client (Any language)
| | |
+---> unified JSON -------> single parser <------- single schema
| (JSONL) (auto-generated) definition
|
+---> JSON Schema validation (multi-language)
|
+---> Client library code generation (OpenAPI-like)
最終状態: - ✅ OSECHI: unified schema に従った出力のみ - ✅ Client: schema definition から自動生成可能なパーサー - ✅ Documentation: 単一の schema spec (JSON Schema)
Design approved by: qumasan Target implementation: v1.11.3 Phase 1 (Protocol Layer)