Progress Log: Text Command Module Refactoring Planning¶
Task Description¶
Planning and design for consolidating text protocol layer (4 files, 1321 lines) into a unified text_command module with similar structure to binary command but accounting for higher complexity:
Current Structure (Text Protocol - Problem)¶
include/
├── text_protocol.h (114 lines)
└── text_protocol_handler.h (101 lines)
src/
├── text_protocol.cpp (241 lines)
└── text_protocol_handler.cpp (865 lines)
Identified Issues¶
- Type Definitions Scattered:
text_command_t,command_response_t,command_handler_t, etc. split across files - Unclear Boundaries: Protocol layer vs handler layer responsibility unclear
- Large Handler File: 865 lines of command handlers in single file
- Dependency Chain: Include dependencies: text_protocol.h → text_protocol_handler.h → multiple subsystems
Proposed Solution: Hybrid Consolidation¶
include/
└── text_command.h (225 lines estimated)
├── All type definitions
├── Protocol layer declarations
└── Handler declarations
src/
├── text_command.cpp (241 lines)
│ ├── Reception & availability functions
│ ├── Queue management
│ ├── Flow control (text_receive, text_execute)
│ └── Parsing & dispatching
│
└── text_command_handlers.cpp (865 lines)
├── Command dispatch table
├── Command alias table
├── Response utilities
├── Helper functions
└── All command handlers (10+ functions)
Analysis & Design Decisions¶
Why Hybrid Approach (not full consolidation)?¶
Comparison with Binary Command:
- Binary: 1 command type, 3 files → consolidated to 1 file ✅
- Text: 10+ command types, 4 files → split to 2 implementation files ✅
Rationale:
- File Size Management: 241 + 865 = 1106 lines, split maintains ~500-600 line modules (editor friendly)
- Separation of Concerns:
text_command.cpp: Protocol mechanics (serial I/O, parsing, queuing)text_command_handlers.cpp: Command logic (SET_THRESHOLD, LED, WIFI, etc.)- Scalability: Adding new command only requires editing
text_command_handlers.cpp - Header Simplification: Single
text_command.h(unified API despite dual implementation)
8-Section Organization for text_command.h¶
Section 1: Configuration Constants
- TEXT_COMMAND_QUEUE_SIZE = 10
- TEXT_COMMAND_TIMEOUT_MS = 500
- MAX_COMMAND_LENGTH = 64
- MAX_COMMAND_ARGS = 2
Section 2: Type Definitions
- text_command_t (command structure)
- command_response_t (response structure)
- command_handler_t (function pointer type)
- command_entry_t (dispatch table entry)
- command_alias_t (alias mapping)
Section 3: Initialization
- text_command_init(void)
Section 4: Reception & Availability
- text_available(void)
- text_receive_line(char* buffer, int buffer_size)
Section 5: Queue Management
- text_queue(text_command_t cmd)
- text_queued(void)
- text_dequeue(void) → command_response_t
Section 6: Flow Control
- text_receive(void)
- text_execute(void)
Section 7: Parsing & Dispatching
- text_parse(const char* line) → text_command_t
- text_dispatch(text_command_t cmd) → command_response_t
Section 8: Response Utilities (internal)
- (Internal functions - not in public header for this version)
Definitions¶
text_command.h¶
// ============================================================================
// SECTION 1: CONFIGURATION CONSTANTS
// ============================================================================
#define TEXT_COMMAND_QUEUE_SIZE 10
#define TEXT_COMMAND_TIMEOUT_MS 500
#define MAX_COMMAND_LENGTH 64
#define MAX_COMMAND_ARGS 2
// ============================================================================
// SECTION 2: TYPE DEFINITIONS
// ============================================================================
typedef struct {
char command_name[32];
uint8_t arg_count;
char args[MAX_COMMAND_ARGS][16];
char raw_buffer[MAX_COMMAND_LENGTH];
} text_command_t;
typedef struct {
bool is_ok;
char message[512];
} command_response_t;
typedef command_response_t (*command_handler_t)(text_command_t cmd);
typedef struct {
const char* name;
command_handler_t handler;
} command_entry_t;
typedef struct {
const char* alias;
const char* full_name;
} command_alias_t;
// ============================================================================
// SECTION 3: INITIALIZATION
// ============================================================================
void text_command_init(void);
// ============================================================================
// SECTION 4: RECEPTION & AVAILABILITY
// ============================================================================
bool text_available(void);
bool text_receive_line(char* buffer, int buffer_size);
// ============================================================================
// SECTION 5: QUEUE MANAGEMENT
// ============================================================================
bool text_queue(text_command_t cmd);
bool text_queued(void);
command_response_t text_dequeue(void);
// ============================================================================
// SECTION 6: FLOW CONTROL
// ============================================================================
bool text_receive(void);
bool text_execute(void);
// ============================================================================
// SECTION 7: PARSING & DISPATCHING
// ============================================================================
text_command_t text_parse(const char* line);
command_response_t text_dispatch(text_command_t cmd);
text_command.cpp¶
// text_command.cpp は Section 4-7 のみ実装
// Section 1-3 は定義のみ(ヘッダーにある)
// ============================================================================
// SECTION 4: RECEPTION & AVAILABILITY
// ============================================================================
bool text_available(void) { ... }
bool text_receive_line(char* buffer, int buffer_size) { ... }
// ============================================================================
// SECTION 5: QUEUE MANAGEMENT
// ============================================================================
static text_command_t text_command_queue[TEXT_COMMAND_QUEUE_SIZE];
// ... queue variables ...
bool text_queue(text_command_t cmd) { ... }
bool text_queued(void) { ... }
command_response_t text_dequeue(void) { ... }
// ============================================================================
// SECTION 6: FLOW CONTROL
// ============================================================================
bool text_receive(void) { ... }
bool text_execute(void) { ... }
// ============================================================================
// SECTION 7: PARSING & DISPATCHING
// ============================================================================
text_command_t text_parse(const char* line) { ... }
command_response_t text_dispatch(text_command_t cmd) { ... }
text_command_handlers.cpp¶
// text_command_handlers.cpp はハンドラーのみ実装
#include "text_command.h"
#include "cosmic_detector.h"
#include "runtime_config.h"
#include "dac_manager.h"
#include "wifi_manager.h"
#include <ArduinoJson.h>
// ============================================================================
// COMMAND TABLES & CONFIGURATION
// ============================================================================
static const command_alias_t alias_table[] = { ... };
static const command_entry_t command_table[] = { ... };
// ============================================================================
// RESPONSE UTILITIES
// ============================================================================
static void text_response_ok(const __FlashStringHelper* message) { ... }
static void text_response_error(const __FlashStringHelper* command, ...) { ... }
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================
static void to_uppercase(char* str) { ... }
static void resolve_command_alias(char* command_name) { ... }
static bool is_valid_char(char c) { ... }
// ============================================================================
// COMMAND HANDLERS
// ============================================================================
static command_response_t handle_set_poll_count(text_command_t cmd) { ... }
static command_response_t handle_set_threshold(text_command_t cmd) { ... }
// ... 10+ more handlers ...
#if ENABLE_WIFI
static command_response_t handle_wifi_enable(text_command_t cmd) { ... }
// ... WiFi handlers ...
#endif
Implementation Split Plan¶
text_command.cpp (241 lines - Protocol Layer):
- Section 4: text_available(), text_receive_line()
- Section 5: text_queue(), text_queued(), text_dequeue()
- Section 6: text_receive(), text_execute()
- Section 7: text_parse(), text_dispatch()
- Static variables: FIFO queue management
text_command_handlers.cpp (865 lines - Command Processing):
- Command dispatch table (maps command names to handlers)
- Command alias table (single-letter shortcuts)
- Response utilities: text_response_ok(), text_response_error()
- Helper functions: to_uppercase(), resolve_command_alias(), is_valid_char()
- 10+ command handlers:
- handle_set_poll_count()
- handle_set_threshold()
- handle_get_threshold()
- handle_get_version()
- handle_status()
- handle_led()
- handle_uptime()
- handle_reset()
- handle_set_interval()
- handle_help()
- handle_wifi_* (3 functions, ENABLE_WIFI conditional)
Benefits of This Approach¶
| Aspect | Current | Proposed |
|---|---|---|
| Header Files | 2 | 1 |
| Implementation Files | 2 | 2 |
| Type Definition Location | Scattered | Unified (text_command.h) |
| API Clarity | Unclear | Clear (single header) |
| Protocol/Handler Separation | Via filenames | Via file contents |
| Handler Maintenance | Slow (find across files) | Fast (single file) |
| New Command Addition | 3+ files to touch | 1 file (handlers) |
Outcome (So Far)¶
Design Status: ✅ Complete Implementation Status: 🔄 Ready to begin
Finalized Architecture Pattern¶
This approach unifies the "protocol vs command" naming confusion from binary refactoring:
- Single Header (
text_command.h): Presents unified API regardless of implementation - Dual Implementation (
text_command.cpp+text_command_handlers.cpp): - Separates protocol mechanics from command logic
- Allows independent scaling of each layer
- Consistent with Binary Command: Both use
commandin naming (notprotocol)
Files to Create¶
include/text_command.h(new, unified types + declarations)src/text_command.cpp(new, from text_protocol.cpp)src/text_command_handlers.cpp(new, from text_protocol_handler.cpp)- Update
include/serial_protocol.h(change includes) - Delete old files (text_protocol.h, text_protocol_handler.h, text_protocol.cpp, text_protocol_handler.cpp)
Learnings¶
Architecture Insights (from Binary Command refactoring)¶
- New-First Strategy: Works well - create new files, verify build, delete old files
- Section Numbering: Consistent 8-section pattern improves readability across modules
- Hybrid Consolidation: Not all consolidations are 1:1 - complex modules may benefit from 1 header + 2 implementations
- Dependency Removal: Implementing utilities locally (e.g., binary_discard) improves encapsulation
Text Protocol Specific Insights¶
- Handler Complexity: 865 lines of command handlers suggests handler separation is justified
- Type Proliferation: 5 typedef declarations better co-located than scattered
- Table-Driven Dispatch: Command/alias tables are reference-heavy (benefit from dedicated section)
Next Steps¶
Implementation Plan (v1.8.10)¶
- Create
text_command.h: - Copy structure from
binary_command.h - Add 5 typedef definitions
-
Declare all text-specific functions (sections 3-7)
-
Create
text_command.cpp: - Copy implementation from
text_protocol.cpp - Adjust section numbers to match header
-
Keep queue management static variables
-
Create
text_command_handlers.cpp: - Copy implementation from
text_protocol_handler.cpp - Update include from text_protocol_handler.h → text_command.h
-
No functional changes (just file reorganization)
-
Update
serial_protocol.h: - Change:
#include "text_protocol.h"→#include "text_command.h" -
Change:
#include "text_protocol_handler.h"(delete, merged into text_command.h) -
Build & Verify:
task dev:buildtask prod:build-
Verify no new errors
-
Delete Old Files:
include/text_protocol.hinclude/text_protocol_handler.hsrc/text_protocol.cpp-
src/text_protocol_handler.cpp -
Version & Release:
- Bump to v1.8.10
- Create release notes
- Update CHANGELOG
Estimated Changes¶
- Files: 4 → 3 (reduction by 1 file)
- Code Lines: No change (1321 lines → 1321 lines, just reorganized)
- Headers: 2 → 1 (type definition consolidation)
- Build Time: Slightly faster (fewer header includes)
- Compile Dependencies: Simplified (single header reference)