Skip to content

sergefriendly/CommandProcessor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CommandProcessor

Поддержка токенизации, цветного вывода и автодополнения для embedded-систем и не только.

Мощный и легковесный процессор команд для встроенных систем (Embedded C++) с поддержкой токенизации, цветного вывода и автодополнения.

Этот проект представляет собой шаблонный класс на C++ для обработки текстовых команд в интерфейсах командной строки (CLI). Он разработан с учетом работы на микроконтроллерах (AVR) и на ПК, поддерживает динамическую токенизацию, цветной вывод, обработку escape-последовательностей и поиск команд.

Внимание: В примерах показан лишь интерфейс использования и концепция работы библиотеки. Реализация некоторых методов и внутренняя логика намеренно скрыты, так как являются:

  • 🧠 Интеллектуальной собственностью автора.
  • 🔧 Оптимизированными алгоритмами для embedded-систем.
  • 🛡️ Ноу-хау в области обработки текстовых команд на микроконтроллерах.
  • ⚡ Уникальными решениями по эффективности использования памяти.

✨ Особенности

  • Кросс-платформенность: Работает как на AVR (Arduino), так и на PC (Linux/Windows/MacOS).
  • Шаблонный дизайн: Размеры буферов и индексов задаются на этапе компиляции для контроля потребления памяти.
  • Динамическая токенизация: Гибкое разбиение входной строки на аргументы с различными режимами.
  • Цветной вывод: Поддержка ANSI-цветов для удобства отладки и пользовательского интерфейса.
  • Система команд: Простая регистрация и поиск команд с указанием количества ожидаемых аргументов.
  • Автодополнение: Функция для показа похожих команд по подстроке.
  • Экранирование символов: Встроенная обработка escape-последовательностей (\n, \t, \r и др.).

Быстрый старт

Пример 1. Базовая настройка на Arduino

#include "CommandProcessor.h"
#include "io.h"
#include "utils.h"

using utils::i; // char* to int
using utils::d; // char* to double

// Создаем экземпляр процессора (буфер 64 байта, индекс на 16 токенов)
CommandProcessor<64, 16> cli;

// Создаём простую функцию
void sayHello() {
  // cli[1] содержит первый аргумент
  io::println(io::YELLOW, "!!! ", cli[1], " !!!", io::NO);
}

// Создаём вспомогательную функцию по выислению квадратного корня методом Ньютона-Рафсона 
double NewtonRaphsonSqrt(double x, double initial_guess, double iterations, bool verbose = false) {
  // Метод Ньютона-Рафсона
  double result = initial_guess;
  for (int i = 0; i < iterations; ++i) {
    result = 0.5 * (result + x / result);
    if (verbose)
      io::cout << i << ": " << result << io::endl;
  }
  return result;
}

// Оборачиваем метод для подачи в массив комманд
void sqrt() {
  int result = NewtonRaphsonSqrt( d(cli[1]), d(cli[2]), i(cli[3]), i(cli[4]) );
  io::println(io::ORANGE, result, io::NO);
}

// Объявляем массив команд: {Имя, Функция-обработчик, Кол-во аргументов}
Command cmd[] = {
  {"say", sayHello, 1}, // Ожидает 1 аргумент
  {"sqrt", sqrt, -1}, // Ожидает бесконечного много аргументов, но необходимо всего 3
};

void setup() {
  io::init(115200); // Инициализируем Serial
  cli.setPrompt(">> ")
     .showWelcome()
     .setDebugMode(false); // Включаем по необходимости
  cli.setCommands(cmd);
}

void loop() {
  cli.readInput(); // Неблокирующее чтение из Serial
}

Пример 2. Базовая настройка на ПК

#include "CommandProcessor.h"
#include "io.h"
#include "utils.h"

using utils::d; // char* to double

CommandProcessor<64, 16> cli;

void half_sum() {
  double a = d( cli[1] );
  double b = d( cli[2] );
  double result = (a + b) / 2;
  io::println("The half-sum of ", a, " and ", b, " is ", io::BLUE, result, io::NO);
}

Command cmd[] = {
  {"hsum", half_sum, -1},
};

int main() {
  cli.run(cmd, false, ">>> "); // режим дебага выключен, приглашение осуществляется символами ">>> "
  return 0;
}

Логика отделения аргументов

В строке

{"cmd", cmd, -1},
  • "cmd" — это имя (или псевдоним) к функции-обработчику, по которому к этой функции можно обращаться интерактивно;
  • cmd — сама функция-обработчик;
  • -1 — ожидаемое количество аргументов.

В зависимости от ожидаемого количества аргументов на выходе получается разная интерпретация:

"cmd arg1 arg2 arg3 arg4" → ["cmd", "arg1 arg2 arg3 arg4"]           при  1;
"cmd arg1 arg2 arg3 arg4" → ["cmd", "arg1", "arg2 arg3 arg4"]        при  2;
"cmd arg1 arg2 arg3 arg4" → ["cmd", "arg1", "arg2", "arg3 arg4"]     при  3;
И т.д.
"cmd arg1 arg2 arg3 arg4" → ["cmd arg1 arg2 arg3 arg4"]              при  0;
"cmd arg1 arg2 arg3 arg4" → ["cmd", "arg1", "arg2", "arg3", "arg4"]  при -1;

Для аргументов, которые подаются в комлексе, может быть использован специальный парсер, разработанный пользователем.

Структура проекта

.
├── CommandProcessor.h  # Основной класс процессора команд
├── index.h             # Класс для работы с индексами (статический/динамический буфер)
├── io.h                # Абстракция ввода/вывода с поддержкой цветов (ANSI)
├── internal.h          # Внутренние платформо-зависимые функции (AVR/PC)
├── utils.h             # Вспомогательные утилиты (строки, математика)
└── examples/           # Папка с примерами использования (рекомендуется создать)

Сетевые интерфейсы

Библиотека может быть адаптирована для работы поверх любых сетевых интерфейсов, что делает её идеальным решением для IoT-устройств и систем удаленного управления.

Интерфейс Готовность Сценарии использования
UART/Serial ✅ Полная поддержка Локальное управление устройством
WiFi (TCP/IP) 🔄 Готова к адаптации Удаленное управление по сети
Ethernet 🔄 Готова к адаптации Промышленные системы, стационарные устройства
Bluetooth SPP 🔄 Готова к адаптации Мобильное управление с smartphones

Производительность и использование памяти

Библиотека оптимизирована для работы с ограниченными ресурсами микроконтроллеров:

Параметр Значение Примечания
Память кода 2-5 KB Зависит от компилятора и оптимизаций
Память данных Настраивается Зависит от BUFFER_SIZE и INDEX_SIZE
Время обработки < 1 ms На AVR @ 16MHz
Стек вызовов < 512 B Безопасно для RTOS
// Примеры конфигураций для разных устройств
CommandProcessor<64, 8> cli;    // ATtiny85, очень мало памяти
CommandProcessor<128, 16> cli;  // ATmega328P (Arduino Uno)  
CommandProcessor<256, 32> cli;  // ESP8266/32, больше ресурсов
CommandProcessor<1024, 64> cli; // STM32, сетевые приложения

Возможные расширения

Архитектура библиотеки позволяет легко добавить:

  • Историю команд (вверх/вниз для повтора)
  • Выполнение скриптов из последовательности команд
  • Поддержку JSON для структурированного вывода
  • Авто-документацию команд через help
  • Бинарный протокол для передачи по сети