Skip to content

Unified Device Response Protocol - Implementation Checklist

Project: kurikintons (OSECHI Firmware) Target Versions: v1.11.3 - v1.12.0 Owner: qumasan Status: Ready for Phase 1 Implementation Last Updated: 2025-12-08

See Also:


Phase 1: Protocol Layer Definition (v1.12.0) - Estimated: 1-2 days

1.1 Create src/device_response.h

Estimated Lines: 80-100

Tasks:

  • File creation with license header
  • Include guards and dependency includes
  • device_response_t struct definition
    typedef struct {
      JsonDocument payload;  // Contains: type, status, sent_at, data fields
    } device_response_t;
    
  • Inline builder functions (at least these)
  • device_response_ok(const char* key, int32_t value)
  • device_response_ok(const char* key, const char* value)
  • device_response_error(int error_code, const char* message)
  • Overloaded versions for other types (float, bool, etc.)
  • device_get_timestamp() helper function with RTC conditional logic
  • Doxygen comments for all public APIs
  • Verify no compilation warnings

Validation:

  • #include "device_response.h" compiles without errors
  • Function overloading resolves correctly
  • std::move() semantics verified

1.2 Create src/device_response.cpp

Estimated Lines: 40-60

Tasks:

  • File creation with license header
  • Include device_response.h and <ArduinoJson.h>
  • Implement send_device_response(const device_response_t& resp)
    void send_device_response(const device_response_t& resp) {
      serializeJson(resp.payload, Serial);
      Serial.println();
    }
    
  • Verify JSONL output format with examples
  • Handle edge cases (empty payload, large JSON, etc.)

Validation:

  • Compilation succeeds
  • No linker errors
  • Output format matches unified schema

1.3 Modify include/config.h

Tasks:

  • Add ENABLE_DEVICE_RESPONSE flag (default: 1)
    #ifndef ENABLE_DEVICE_RESPONSE
    #define ENABLE_DEVICE_RESPONSE 1  // Phase 1+: opt-in enabled
    #endif
    
  • Add configuration comment explaining the flag
  • Verify no conflicts with existing flags

Validation:

  • Build succeeds with ENABLE_DEVICE_RESPONSE=0
    RAM:   [=         ]   8.8% (used 28764 bytes from 327680 bytes)
    Flash: [===       ]  26.6% (used 348301 bytes from 1310720 bytes)
    
  • Build succeeds with ENABLE_DEVICE_RESPONSE=1
    RAM:   [=         ]   8.8% (used 28764 bytes from 327680 bytes)
    Flash: [===       ]  26.6% (used 348389 bytes from 1310720 bytes)
    
  • Binary size difference logged

1.4 Integration Testing

Tasks:

  • Create simple test in text_command_manager.cpp
    #if ENABLE_DEVICE_RESPONSE
    // Test with GET_VERSION
    auto resp = device_response_ok("version", config_get_version());
    send_device_response(resp);
    #endif
    
  • Capture serial output to file
  • Verify JSON structure matches unified schema
  • type field present and correct
  • status field present and correct
  • sent_at field present and reasonable value
  • Response data fields present

Sample Output Verification:

{"type":"response","status":"ok","sent_at":123456,"version":"1.10.0"}
  • Test with error response

    {"type":"response","status":"error","sent_at":123456,"error_code":1,"error_message":"Invalid argument"}
    

  • Test with nested object

    {"type":"response","status":"ok","sent_at":123456,"gnss":{"latitude":37.3874,"longitude":121.9724}}
    

Validation:

  • All 3 output formats match unified schema
  • JSON is valid (use jq or online validator)
  • No truncation or malformed output

1.5 Documentation Updates

Tasks:

  • Add section to CLAUDE.md explaining device_response_t
  • API documentation (device_response_ok, device_response_error)
  • Usage examples (simple, nested, error cases)
  • ENABLE_DEVICE_RESPONSE flag explanation
  • Create docs/architecture/unified-device-response-schema.md (already prepared)
  • Update README.md with note about unified schema initiative

Validation:

  • CLAUDE.md builds without errors (if markdown validation available)
  • All code examples in docs are valid C++
  • Links to schema spec are correct

1.6 Commit and Version

Tasks:

  • Create feature branch: feature/device-response-protocol
  • Git commit: feat(device_response): add unified protocol layer
  • Message should reference unified schema doc
  • Include scope: (protocol) or (core)
  • Push to repository
  • Verify CI/CD pipeline passes (if available)

Phase 2: Command Handler Unification (v1.11.3 - v1.11.4) - Estimated: 2-3 weeks

2.1 Group A: Simple Commands (Day 1-2)

Priority Order (simplest first):

  1. GET_VERSION (1 minute)
  2. Before: send_response(response_string("version", config_get_version()));
  3. After: send_device_response(device_response_ok("version", config_get_version()));
  4. Test: Verify output format

  5. GET_UPTIME (1 minute)

  6. Before: send_response(response_int("uptime_ms", millis()));
  7. After: send_device_response(device_response_ok("uptime_ms", (int32_t)millis()));
  8. Test: Verify output format

  9. GET_MAC_ADDRESS (1 minute)

  10. Modify response call
  11. Test

  12. SET_POLL_COUNT (2 minutes)

  13. Modify success response
  14. Keep error response (error path unchanged for now)
  15. Test

  16. SET_DEADTIME (2 minutes)

  17. Similar to SET_POLL_COUNT

  18. Repeat pattern for: GET_STREAM, SET_STREAM, GET_QUEUE_STATS, TEST_LED, etc.

Validation for Each Command: - [ ] Command still receives arguments correctly - [ ] Success response matches schema - [ ] Error response matches schema - [ ] No compiler warnings/errors - [ ] Serial output validated manually or with automated JSON parser

Estimated Duration: 15-20 commands × 2-3 minutes = 30-60 minutes


2.2 Group B: Medium Commands with Nested Objects (Day 3-5)

Priority Order:

  1. GET_THRESHOLD (5 minutes)
    // Before: send_response(response_pairs("channel", ch, "threshold", val));
    // After:
    JsonDocument payload;
    payload["type"] = "response";
    payload["status"] = "ok";
    payload["sent_at"] = device_get_timestamp();
    JsonObject threshold = payload["threshold"].to<JsonObject>();
    threshold["channel"] = ch;
    threshold["value"] = val;
    send_device_response({std::move(payload)});
    
  2. Create helper: device_response_threshold(ch, val) (optional)
  3. Test: Verify nested structure

  4. SET_THRESHOLD (5 minutes)

  5. Success response with nested object
  6. Error response path

  7. GET_RTC_TIME / SET_RTC_TIME (5 minutes each)

  8. GET_GNSS_STATUS (10 minutes)

    {"type":"response","status":"ok","sent_at":...,"gnss":{"satellites":8,"hdop":1.04,...}}
    

  9. GET_GNSS_POSITION (10 minutes)

  10. GET_GNSS_TIME (5 minutes)

  11. GET_BME280 (5 minutes)

Validation for Each Command: - [ ] Nested JSON structure correct - [ ] All fields present - [ ] No JSON serialization errors - [ ] Output can be parsed by kazunoko DeviceResponse model

Estimated Duration: 7 commands × 8-10 minutes avg = 60-90 minutes


2.3 Group C: Complex Commands (Day 6-10)

Priority Order:

  1. GET_STATUS (30 minutes) - Most complex
    {
      "type":"response",
      "status":"ok",
      "sent_at":...,
      "system":{"version":"...","uptime_ms":...},
      "detection":{"poll_count":...,"threshold1":...},
      "features":{...}
    }
    
  2. Multiple nested objects
  3. Conditional fields (if ENABLE_*)
  4. Test: Full feature flag coverage

  5. GET_HELP (20 minutes)

  6. Array of commands (if applicable)
  7. Test: Large JSON output handling

  8. Error Response Standardization (10 minutes)

  9. All error paths use device_response_error()
  10. Consistent error_code and error_message format
  11. Test: Verify all error codes

Validation for Complex Commands: - [ ] Large JSON output doesn't truncate - [ ] Nested objects serialize correctly - [ ] Conditional compilation respected (#if ENABLE_*) - [ ] Memory usage acceptable (ArduinoJson dynamic allocation)

Estimated Duration: 10 handlers × 15-20 minutes avg = 150-200 minutes


2.4 Comprehensive Testing

Tasks: - [ ] Create test harness: send each command via serial, capture output - [ ] Validate each output against unified schema (JSON Schema validator) - [ ] Verify response_t references are removed from handlers - [ ] Grep for remaining send_response() calls (should be < 5, error paths) - [ ] Memory profiling: ensure no stack overflow with nested JsonDocument - [ ] Regression testing: all commands produce output within 100ms

Tools to Use:

# Validate JSON against schema
python3 -m jsonschema unified-device-response-schema.json < output.jsonl

# Verify no remaining response_t calls
grep -r "response_t" src/text_command* --exclude="*.orig"

# Check response_string, response_int removals
grep -r "send_response(" src/text_command* | grep -v "send_device_response"


2.5 Documentation & Migration Guide

Tasks: - [ ] Update CLAUDE.md with migration examples - [ ] Before/After code snippets for each group - [ ] Common patterns (simple, nested, error) - [ ] Document builder helper functions created during migration - [ ] If multiple handlers share same structure, create helper - [ ] Example: device_response_threshold(ch, val) - [ ] Add section to REFACTORING_ROADMAP summarizing completed work


2.6 Commits (Incremental)

Tasks: - [ ] Group A commit: refactor(text_commands): migrate simple commands to device_response_t - [ ] Group B commit: refactor(text_commands): migrate nested response commands - [ ] Group C commit: refactor(text_commands): migrate complex commands (GET_STATUS) - [ ] Error path commit: refactor(text_commands): standardize error responses


Phase 3: Event Output Unification (v1.12.0) - Estimated: 1-2 days

3.1 Modify stream_formatter.cpp

Focus: send_jsonl() function (only when STREAM_FORMAT=3)

Tasks: - [ ] Replace manual JsonDocument creation with device_response_t builder pattern

// Before:
void send_jsonl(const event_t *data) {
  JsonDocument doc;
  doc["hit1"] = data->hit1;
  // ...
  serializeJson(doc, Serial);
  Serial.println();
}

// After:
void send_jsonl(const event_t *data) {
  JsonDocument payload;
  payload["type"] = "event";
  payload["status"] = "ok";
  payload["sent_at"] = device_get_timestamp();
  payload["hit1"] = data->hit1;
  // ...
  send_device_response({std::move(payload)});
}

  • Verify all ENABLE_* conditional fields included
  • Test with different ENABLE flag combinations:
  • ENABLE_BME280=0, ENABLE_GNSS=0
  • ENABLE_BME280=1, ENABLE_GNSS=0
  • ENABLE_BME280=0, ENABLE_GNSS=1
  • ENABLE_BME280=1, ENABLE_GNSS=1 (all features)

Validation: - [ ] Event output matches unified schema - [ ] Sample event output:

{"type":"event","status":"ok","sent_at":123456,"hit1":95,"hit2":87,"hit3":91,"adc":2048}
- [ ] With ENABLE_BME280:
{"type":"event","status":"ok","sent_at":123456,"hit1":95,"hit2":87,"hit3":91,"adc":2048,"tmp_c":25.35,"atm_pa":101325}


3.2 Verify Format Consistency

Tasks: - [ ] Compare response format with event format - Both use "type", "status", "sent_at" - Verify consistency across all output

  • Test with stream enabled/disabled:
  • SET_STREAM on: events should appear in log
  • SET_STREAM off: no event output
  • Response still appears regardless

3.3 Memory & Performance Testing

Tasks: - [ ] Event generation rate test: 100 events generated, measure serial output time - [ ] Baseline (before): X seconds - [ ] After unification: Y seconds - [ ] Acceptable if Y ≤ 1.1 × X (≤10% overhead)

  • Stack usage test: Measure free heap during 1000 events
  • Verify no memory leak (heap should stabilize)

3.4 Backward Compatibility Check

Tasks: - [ ] Verify event_t struct unchanged (still used by detection loop) - [ ] stream_formatter.cpp only modifies output, not input pipeline - [ ] Existing SSV/TSV/CSV paths unchanged (only JSONL modified)


3.5 Commit

Tasks: - [ ] Git commit: refactor(stream_formatter): unify event output with device_response_t


Phase 4: Legacy Code Cleanup (v1.12.0+) - Estimated: 1 day

4.1 Remove response.h

Tasks: - [ ] Verify no remaining #include "response.h" (except archived/docs)

grep -r "include.*response\.h" src/ --exclude="*.orig"
- [ ] Delete include/response.h - [ ] Confirm no build errors


4.2 Remove response.cpp

Tasks: - [ ] Verify no references to send_response() function

grep -r "send_response" src/ | grep -v "send_device_response"
- [ ] Delete src/response.cpp - [ ] Confirm no linker errors


4.3 Remove response_t Type

Tasks: - [ ] Verify all response_t variables replaced - [ ] Check no response_status_t enum usage remaining - [ ] Confirm build succeeds


4.4 Disable Conditional Flag

Tasks: - [ ] Remove ENABLE_DEVICE_RESPONSE flag (or set to always 1) - [ ] Remove conditional compilation wrapper in handlers


4.5 Final Testing

Tasks: - [ ] Full integration test: all commands + events produce output - [ ] Binary size measurement: compare to v1.11.x - [ ] Measure reduction from response.h/cpp removal - [ ] Expected: 5-10KB smaller binary

  • Serial output validation: random sampling of commands
  • 20 commands: GET_VERSION, SET_POLL_COUNT, GET_STATUS, etc.
  • Verify each output matches unified schema

4.6 Documentation Finalization

Tasks: - [ ] Update CLAUDE.md: remove legacy response_t section - [ ] Finalize unified schema spec: docs/architecture/unified-device-response-schema.md - [ ] Create migration guide: docs/migration/response-unification-v1.12.md - [ ] Add JSON Schema file: docs/schemas/device-response.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
}


4.7 Commit

Tasks: - [ ] Git commit: chore(response): remove legacy response_t - [ ] Tag: v1.12.0 or appropriate version


Cross-Phase Validation

Code Quality

  • No compiler warnings (use PLATFORMIO_BUILD_FLAGS="-Werror")
  • No unused variables or imports
  • Consistent indentation and style (run formatter)
  • All Doxygen comments present and correct

Testing

  • Unit tests for device_response builders (if test framework available)
  • Integration tests: all commands produce valid JSON
  • Regression tests: compare output to baseline (v1.11.x)

Documentation

  • All APIs documented in CLAUDE.md
  • Unified schema spec complete and accurate
  • Examples match actual output
  • No broken links

Performance

  • Command response latency unchanged
  • Event generation not impacted
  • No memory leaks over 24-hour run

Sign-off

Implementation Owner: [To be assigned] Code Review: [To be assigned] QA: [To be assigned] Documentation: [To be assigned]

Target Completion: - Phase 1: Week of 2025-12-09 (v1.11.3) - Phase 2: Week of 2025-12-15 (v1.11.4) - Phase 3-4: Week of 2025-12-29 (v1.12.0)


Status: Ready for development ✅