project_alpha/lib/SerialCmd/SerialCmd.h
2026-02-28 17:03:14 -05:00

87 lines
1.9 KiB
C++

#ifndef SERIAL_CMD_H
#define SERIAL_CMD_H
#include <Arduino.h>
#include <functional>
#ifndef SERIAL_CMD_MAX_LINE
#define SERIAL_CMD_MAX_LINE 128
#endif
#ifndef SERIAL_CMD_MAX_ARGS
#define SERIAL_CMD_MAX_ARGS 16
#endif
#ifndef SERIAL_CMD_MAX_COMMANDS
#define SERIAL_CMD_MAX_COMMANDS 16
#endif
class CmdArgs {
public:
void parse(char* line);
const char* command() const { return _command; }
// Positional args (skips flags)
const char* arg(int index) const;
int intArg(int index, int fallback = 0) const;
float floatArg(int index, float fallback = 0.0f) const;
int count() const { return _posCount; }
// Flag check
bool has(const char* flag) const;
// Raw token access (includes flags)
const char* raw(int index) const;
int rawCount() const { return _rawCount; }
private:
const char* _command = nullptr;
const char* _tokens[SERIAL_CMD_MAX_ARGS];
int _rawCount = 0;
const char* _positional[SERIAL_CMD_MAX_ARGS];
int _posCount = 0;
};
class SerialCmd {
public:
using Handler = std::function<void(CmdArgs&)>;
explicit SerialCmd(Stream& stream);
bool on(const char* name, Handler handler);
bool on(const char* name, const char* usage, Handler handler);
void onDefault(Handler handler);
bool poll();
void wait();
bool sync(unsigned long timeout_ms = 5000);
void setEcho(bool enabled) { _echo = enabled; }
private:
void feedChar(char c);
void dispatch();
void sendSyncList();
Stream& _stream;
bool _echo = false;
char _line[SERIAL_CMD_MAX_LINE];
int _linePos = 0;
bool _lineReady = false;
bool _prevCR = false;
struct Command {
const char* name;
const char* usage;
Handler handler;
};
Command _commands[SERIAL_CMD_MAX_COMMANDS];
int _commandCount = 0;
Handler _defaultHandler;
};
#endif