Refactor to split .h into .h and .cpp pair

This commit is contained in:
2026-03-27 12:38:31 +01:00
parent c6bcd3a9d7
commit 06495a089f
16 changed files with 1029 additions and 694 deletions

200
src/modules/cmd/cmd.cpp Normal file
View File

@@ -0,0 +1,200 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "cmd.h"
#include <string.h>
char *cmd::trim_arg(char *input) {
if (input == nullptr) {
return nullptr;
}
while (*input == ' ' || *input == '\t' || *input == '\r' || *input == '\n') {
input++;
}
if (*input == '\0') {
return input;
}
char *end = input + strlen(input) - 1;
while (end >= input &&
(*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) {
*end = '\0';
end--;
}
return input;
}
unsigned short cmd::split_args(char *input, char *argv[], unsigned short max_args) {
unsigned short argc = 0;
char *p = input;
char *token_start = input;
if (input == nullptr || argv == nullptr || max_args == 0) {
return 0;
}
if (*input == '\0') {
return 0;
}
while (argc < max_args) {
if (*p == ',' || *p == '\0') {
char separator = *p;
*p = '\0';
argv[argc] = trim_arg(token_start);
argc++;
if (separator == '\0') {
break;
}
token_start = p + 1;
}
p++;
}
return argc;
}
cmd::command_id cmd::parse_command_name(const char *input) {
if (input == nullptr) {
return CMD_UNKNOWN;
}
if (strcmp(input, "REBOOT") == 0) {
return CMD_REBOOT;
}
if (strcmp(input, "DUMPCFG") == 0) {
return CMD_DUMPCFG;
}
return CMD_UNKNOWN;
}
int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[]) {
switch (command) {
case CMD_REBOOT:
#ifdef INFO
if (_logger != nullptr) {
_logger->info("Rebooting");
}
#endif
delay(200);
wdt_enable(WDTO_15MS);
while (true) {
}
case CMD_DUMPCFG:
#ifdef INFO
if (_logger != nullptr) {
_logger->dump_config();
}
#endif
return 0;
case CMD_UNKNOWN:
default:
#ifdef ERROR
if (_logger != nullptr) {
if (argc > 0 && argv != nullptr && argv[0] != nullptr && argv[0][0] != '\0') {
_logger->error(String("Unknown command: ") + String(argv[0]));
} else {
_logger->error("Unknown command");
}
}
#endif
return 1;
}
}
int cmd::try_parse() {
#ifdef DEBUG
if (_logger != nullptr) {
_logger->debug("Attempting to parse command");
}
#endif
char *argvp[_max_args];
unsigned short argc = split_args(_buffer, argvp, _max_args);
if (argc == 0 || argvp[0] == nullptr || argvp[0][0] == '\0') {
#ifdef ERROR
if (_logger != nullptr) {
_logger->error("Empty command");
}
#endif
return 1;
}
command_id command = parse_command_name(argvp[0]);
return dispatch_command(command, argc, argvp);
}
int cmd::push(const Task &task) {
return _queue.push(task);
}
cmd::cmd(HardwareSerial *data_stream)
: _data_stream(data_stream), _logger(nullptr) {}
cmd::cmd(HardwareSerial *data_stream, system_logger *logger)
: _data_stream(data_stream), _logger(logger) {}
cmd::~cmd() {}
int cmd::init() {
_data_stream->begin(_baud_rate);
return 0;
}
int cmd::parse_task(unsigned long timeout_ms) {
unsigned long start = millis();
while (_data_stream->available()) {
if ((unsigned long)(millis() - start) >= timeout_ms) {
return 1;
}
char c = _data_stream->read();
if (c == '<') {
_buf_open = true;
_idx = 0;
continue;
}
if (!_buf_open) {
continue;
}
if (c == '>') {
_buffer[_idx] = '\0';
_buf_open = false;
return this->try_parse();
}
if (_idx >= sizeof(_buffer) - 1) {
_buf_open = false;
_idx = 0;
#ifdef ERROR
if (_logger != nullptr) {
_logger->error("Command parser buffer overflow");
}
#endif
return 1;
}
_buffer[_idx] = c;
_idx++;
}
return 0;
}

View File

@@ -2,101 +2,45 @@
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <Arduino.h>
#include <avr/wdt.h>
#include "custom_types.h"
#include "modules/logger/system_logger.h"
#include "base/task.h"
#include "base/ring_buffer.h"
#include "base/module_base.h"
#include <avr/wdt.h>
class cmd: public module_base{
class cmd : public module_base {
private:
enum command_id {
CMD_UNKNOWN = 0,
CMD_REBOOT,
CMD_DUMPCFG
};
HardwareSerial *_data_stream;
unsigned long _baud_rate = 115200;
system_logger *_logger;
char _buffer[256];
unsigned int _idx = 0;
bool _buf_open = false;
int try_parse();
ring_buffer<Task, 16> _queue;
static const unsigned short _max_args = 10;
int try_parse();
unsigned short split_args(char *input, char *argv[], unsigned short max_args);
char *trim_arg(char *input);
command_id parse_command_name(const char *input);
int dispatch_command(command_id command, unsigned short argc, char *argv[]);
public:
int push(const Task& task) override;
int push(const Task &task) override;
cmd(HardwareSerial *data_stream);
cmd(HardwareSerial *data_stream, system_logger *logger);
~cmd();
int init();
int parse_task(unsigned long timeout_ms = 500);
};
int cmd::try_parse() {
#ifdef DEBUG
if (_logger != nullptr) {
_logger->debug("Attempting to parse command");
}
#endif
if (strcmp(_buffer, "REBOOT") == 0) {
#ifdef INFO
if (_logger != nullptr) {
_logger->info("Rebooting");
}
#endif
delay(200);
wdt_enable(WDTO_15MS);
while (true) {
}
}
return 0;
}
int cmd::push(const Task& task) {
return _queue.push(task);
}
cmd::cmd(HardwareSerial *data_stream)
: _data_stream(data_stream), _logger(nullptr) {}
cmd::cmd(HardwareSerial *data_stream, system_logger *logger)
: _data_stream(data_stream), _logger(logger) {}
cmd::~cmd() {}
int cmd::init() {
_data_stream->begin(_baud_rate);
return 0;
}
int cmd::parse_task(unsigned long timeout_ms) {
unsigned long timeout = millis() + timeout_ms;
while (_data_stream->available()) {
char c = _data_stream->read();
if (c == '<') {
_buf_open = true;
_idx = 0;
continue;
}
if (_idx >= sizeof(_buffer) - 1) {
_buf_open = false;
_idx = 0;
#ifdef ERROR
if (_logger != nullptr) {
_logger->error("Command parser buffer overflow");
}
#endif
return 1;
}
if (c == '>') {
_buffer[_idx] = '\0';
_buf_open = false;
return this->try_parse();
}
if (_buf_open) {
_buffer[_idx] = c;
_idx++;
}
if (millis() > timeout) {
return 1;
}
}
return 0;
}
};