
// // cli.c
// //******************************************** Включаемые файлы *********************************************
// #include "cli.h"
// #include "lmcal.h"
// #include "string.h"
// #include "ring_buffer.h"
// #include <stdio.h>
// #include <stdlib.h>
// #include <stdint.h>
// #include "tcp.h"
// #include "fpga_cmn.h"
// #include "submodule.h"
// #include "submodule_cfg.h"
// #include "lta_private.h"
 
// //******************************************* Локальные константы *******************************************
// #define CLI_PROMPT               "> "
// #define CLI_MSG_UNKNOWN_CMD      "\r\nERROR: Unknown command\r\n"
// #define CLI_MSG_OK               "OK\r\n"
// #define CLI_MSG_ERROR            "ERROR: %s (code: %d)\r\n"
// #define CLI_MSG_BUFFER_OVERFLOW  "\r\nERROR: Buffer overflow\r\n"
// //************************************* Локальные (приватные) переменные ************************************
 
// static ringbuf_t  fifo_rx;                          // Кольцевой буфер приема
// static u8 fifo_rx_buf[CLI_MAX_CMD_LENGTH];          // Буфер данных приема
 
// static char cli_cmd_buffer[CLI_MAX_CMD_LENGTH];     // Буфер для приема команды
// static u16 cli_cmd_index = 0;                       // Индекс в буфере команды
 
// static const cli_command_t* cli_commands[CLI_MAX_COMMANDS];     // Массив зарегистрированных команд
// static u8 cli_cmd_count = 0;                        // Количество зарегистрированных команд
 
// static cli_state_t cli_current_state = CLI_STATE_DISABLED;  // Текущее состояние CLI
// static char* cli_args[CLI_MAX_ARGS];                // Массив аргументов команды
// static int cli_argc = 0;                            // Количество аргументов команды
 
// // Флаг для разрешения отправки в выключенном состоянии (только для инициализации)
// static bool cli_allow_send_in_disabled = true;
 
// //************************************* Локальные (приватные) функции ***************************************
 
// // Объявления функций для устранения ошибок компиляции
// static fun_res_t cli_cmd_help_handler(int argc, char** argv);
// static fun_res_t cli_cmd_cli_on_handler(int argc, char** argv);
// static fun_res_t cli_cmd_cli_off_handler(int argc, char** argv);
// static fun_res_t cli_cmd_mem_read_handler(int argc, char** argv);
// static fun_res_t cli_cmd_lta_search_handler(int argc, char** argv);
// static void cli_process_command(void);
// static void cli_process_disabled_mode(void);
// static void cli_process_normal_mode(void);
 
// /**
//  * @brief Безопасное копирование строки с ограничением длины
//  */
// static void cli_strncpy_safe(char* dest, const char* src, size_t dest_size) {
//     if (dest == NULL || src == NULL || dest_size == 0) return;
    
//     size_t i;
//     for (i = 0; i < dest_size - 1 && src[i] != '\0'; i++) {
//         dest[i] = src[i];
//     }
//     dest[i] = '\0';
// }
 
// /**
//  * @brief Разбор команды на аргументы (без модификации исходной строки)
//  */
// static void cli_parse_command(const char* cmd) {
//     cli_argc = 0;
    
//     if (cmd == NULL) return;
    
//     // Статическое хранилище для копий аргументов, чтобы указатели были валидны после выхода из функции
//     static char token_storage[CLI_MAX_ARGS][CLI_MAX_CMD_LENGTH];
 
//     // Обнуляем предыдущее содержимое (необязательно, но полезно для отладки)
//     for (int i = 0; i < CLI_MAX_ARGS; i++) {
//         token_storage[i][0] = '\0';
//         cli_args[i] = NULL;
//     }
 
//     // Создаем копию строки для безопасного парсинга
//     char cmd_copy[CLI_MAX_CMD_LENGTH];
//     cli_strncpy_safe(cmd_copy, cmd, sizeof(cmd_copy));
    
//     char* token = strtok(cmd_copy, " \t\n\r");
    
//     while (token != NULL && cli_argc < CLI_MAX_ARGS) {
//         // Копируем токен в постоянное хранилище и сохраняем указатель
//         cli_strncpy_safe(token_storage[cli_argc], token, sizeof(token_storage[cli_argc]));
//         cli_args[cli_argc] = token_storage[cli_argc];
//         cli_argc++;
//         token = strtok(NULL, " \t\n\r");
//     }
// }
 
// /**
//  * @brief Поиск команды по имени
//  */
// static const cli_command_t* cli_find_command(const char* name) {
//     if (name == NULL) return NULL;
    
//     for (u8 i = 0; i < cli_cmd_count; i++) {
//         if (strcmp(cli_commands[i]->name, name) == 0) {
//             return cli_commands[i];
//         }
//     }
//     return NULL;
// }
 
// /**
//  * @brief Получение строкового описания кода ошибки
//  */
// static const char* cli_get_error_string(fun_res_t error_code) {
//     switch (error_code) {
//         case ERR_OK: return "Success";
//         case ERR_ASSERT_ERROR: return "Assertion failed";
//         case ERR_RUNTIME_ERROR: return "Runtime error";
//         case ERR_INVALID_ARGUMENT: return "Invalid argument";
//         case ERR_NOT_IMPLEMENTED: return "Not implemented";
//         case ERR_TIMEOUT_EXPIRED: return "Timeout expired";
//         default: return "Unknown error";
//     }
// }
 
// /**
//  * @brief Включение модуля
//  */
// static void cli_enable(){
//     // Поностью чистим буферы
//     rb_clear(&fifo_rx);
//     cli_cmd_index = 0;
//     memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
 
//     // Вкдючаем cli
//     cli_current_state = CLI_STATE_IDLE;
 
//     cli_send_string("\r\n------------------------------------------------\r\n");
//     cli_send_string("            ==== CLI Enabled ====\r\n");
//     cli_send_string("------------------------------------------------\r\n");
//     cli_send_string("   Type 'help' for available commands");
//     cli_send_string("\r\n------------------------------------------------\r\n");
//     cli_send_string(CLI_PROMPT);
// }
 
// /**
//  * @brief Обработка полученной команды
//  */
// static void cli_process_command(void) {
//     if (cli_argc == 0) {
//         return;
//     }
 
//     const cli_command_t* cmd = cli_find_command(cli_args[0]);
//     if (cmd == NULL) {
//         cli_send_string(CLI_MSG_UNKNOWN_CMD);
//         return;
//     }
 
//     // Выполнение команды
//     fun_res_t result = cmd->handler(cli_argc, cli_args);
//     if (result == ERR_OK) {
//         cli_send_string(CLI_MSG_OK);
//     } else {
//         char error_msg[64];
//         snprintf(error_msg, sizeof(error_msg), CLI_MSG_ERROR, 
//                  cli_get_error_string(result), result);
//         cli_send_string(error_msg);
//     }
// }
 
// /**
//  * @brief Обработка выключенного состояния CLI
//  */
// static void cli_process_disabled_mode(void) {
//     static char temp_buffer[CLI_MAX_CMD_LENGTH] = {0};
//     static u16 temp_index = 0;
//     static bool promt_shown = false;
 
//     if(!promt_shown) {
//         cli_send_string(CLI_PROMPT);
//         promt_shown = true;
//     }
 
//     while (rb_get_items_qty(&fifo_rx) > 0) {
//         u8 received_char;
//         if (rb_get_item(&fifo_rx, &received_char) != RB_RES_OK) {
//             continue;
//         }
 
//         // Добавляем символ во временный буфер
//         if (temp_index < (CLI_MAX_CMD_LENGTH - 1) && 
//             received_char != '\r' && received_char != '\n') {
//             temp_buffer[temp_index++] = received_char;
//         }
        
//         // Enter - проверяем команду
//         if (received_char == '\r' || received_char == '\n') {
//             if (temp_index > 0) {
//                 temp_buffer[temp_index] = '\0';
                
//                 // Временно парсим команду
//                 char temp_args[CLI_MAX_ARGS][CLI_MAX_CMD_LENGTH];
//                 int temp_argc = 0;
//                 char temp_copy[CLI_MAX_CMD_LENGTH];
//                 cli_strncpy_safe(temp_copy, temp_buffer, sizeof(temp_copy));
                
//                 char* token = strtok(temp_copy, " \t\n\r");
//                 while (token != NULL && temp_argc < CLI_MAX_ARGS) {
//                     cli_strncpy_safe(temp_args[temp_argc], token, sizeof(temp_args[temp_argc]));
//                     temp_argc++;
//                     token = strtok(NULL, " \t\n\r");
//                 }
                
//                 // Если это команда cli_on - обрабатываем
//                 if (temp_argc > 0 && strcmp(temp_args[0], "cli_on") == 0) {
//                     cli_enable();
//                 }
//             }
            
//             // Сбрасываем временный буфер
//             temp_index = 0;
//             memset(temp_buffer, 0, sizeof(temp_buffer));
//         }
//     }
// }
 
// /**
//  * @brief Обработка нормального режима (CLI включен)
//  */
// static void cli_process_normal_mode(void) {
//     while (rb_get_items_qty(&fifo_rx) > 0) {
//         u8 received_char;
//         if (rb_get_item(&fifo_rx, &received_char) != RB_RES_OK) {
//             continue;
//         }
        
//         // Если мы в состоянии IDLE и получаем первый символ - переходим в RECEIVING
//         if (cli_current_state == CLI_STATE_IDLE && cli_cmd_index == 0) {
//             cli_current_state = CLI_STATE_RECEIVING;
//         }
        
//         // Пропускаем пустые строки в начале
//         if (cli_cmd_index == 0 && (received_char == '\n' || received_char == '\r')) {
//             cli_current_state = CLI_STATE_IDLE;
//             continue;
//         }
        
//         // Enter - обработка команды
//         if (received_char == '\r' || received_char == '\n') {
//             if (cli_cmd_index > 0) {
//                 cli_cmd_buffer[cli_cmd_index] = '\0';
                
//                 // Разбираем команду на аргументы
//                 cli_parse_command(cli_cmd_buffer);
                
//                 // Обрабатываем команду
//                 cli_current_state = CLI_STATE_PROCESSING;
//                 cli_process_command();
                
//                 // После обработки команды проверяем, не была ли это команда cli_off
//                 // Если да, то сразу выходим из нормального режима
//                 if (cli_current_state == CLI_STATE_DISABLED) {
//                     return;
//                 }
//             }
            
//             // Возвращаемся в состояние IDLE и выводим приглашение
//             cli_current_state = CLI_STATE_IDLE;
//             cli_cmd_index = 0;
//             memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
//             cli_send_string(CLI_PROMPT);
//         } 
//         // Backspace - удаление символа
//         else if (received_char == 8 || received_char == 127) {
//             if (cli_cmd_index > 0) {
//                 // Уменьшаем индекс и явно очищаем удаленный символ в буфере
//                 cli_cmd_index--;
//                 cli_cmd_buffer[cli_cmd_index] = '\0';
//                 // Эхо: сдвинуть курсор назад, стереть символ, снова сдвинуть
//                 cli_send_string("\b \b");
//             }
//             // если индекс == 0 — ничего не делаем
//         }
//         // Обычный символ - добавление в буфер
//         else if (cli_cmd_index < (CLI_MAX_CMD_LENGTH - 1)) {
//             cli_cmd_buffer[cli_cmd_index++] = received_char;
//             // Эхо символа
//             u8 echo_char[2] = {received_char, 0};
//             cli_send_string((char*)echo_char);
//         }
//         // Переполнение буфера команды
//         else {
//             cli_send_string(CLI_MSG_BUFFER_OVERFLOW);
//             cli_current_state = CLI_STATE_IDLE;
//             cli_cmd_index = 0;
//             memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
//             rb_clear(&fifo_rx);
//             cli_send_string(CLI_PROMPT);
//         }
//     }
// }
 
// /**
//  * @brief Колбек прерывания по приему байта через UART
//  * @note Добавляет принятый байт в буфер приема
//  */
// static void f_uart_read_byte(void) {
//     // Исправлено: правильный вызов функции согласно LMCAL API (один аргумент)
//     u16 rx_data = lmcal_uart_read(CLI_UART_CHANNEL);
//     u8 byte_data = (u8)(rx_data & 0xFF);
//     rb_add_item(&fifo_rx, &byte_data);
// }
 
// /**
//  * @brief Отправка строки через UART с буферизацией
//  * @param str Указатель на строку для отправки
//  */
// void cli_send_string(const char* str) {
//     if (str == NULL) return;
    
//     // Разрешаем отправку в следующих случаях:
//     // 1. CLI включен (INIT, IDLE, RECEIVING, PROCESSING)
//     // 2. Разрешена отправка в выключенном состоянии (только для инициализации)
//     if (cli_current_state != CLI_STATE_DISABLED || cli_allow_send_in_disabled) {
//         // Отправка каждого символа синхронно
//         while (*str != '\0') {
//             lmcal_uart_write(CLI_UART_CHANNEL, (u16)*str);
//             str++;
//         }
//     }
// }
 
// /**
//  * @brief Обработчик встроенной команды help
//  */
// static fun_res_t cli_cmd_help_handler(int argc, char** argv) {
//     L_UNUSED(argc);
//     L_UNUSED(argv);
 
//     // В выключенном состоянии команда не должна работать
//     if (cli_current_state == CLI_STATE_DISABLED) {
//         return ERR_RUNTIME_ERROR;
//     }
 
//     cli_send_string("\r\n------------------------------------------------\r\n");
//     cli_send_string("============ CLI Help ============\r\n");
//     cli_send_string("------------------------------------------------\r\n");
//     cli_send_string("Command Line Interface for system control\r\n");
//     cli_send_string("------------------------------------------------\r\n");
 
//     for (u8 i = 0; i < cli_cmd_count; i++) {
//         // Формируем строку с именем команды и ее описанием
//         char help_line[96];
//         snprintf(help_line, sizeof(help_line), "%-12s - %s\r\n",
//                  cli_commands[i]->name,
//                  cli_commands[i]->description ? cli_commands[i]->description : "No description");
//         cli_send_string(help_line);
//     }
 
//     cli_send_string("------------------------------------------------\r\n");
//     cli_send_string("Type '<command> --help' for more information\r\n");
//     cli_send_string("------------------------------------------------\r\n");
//     return ERR_OK;
// }
 
// /**
//  * @brief Обработчик встроенной команды cli_on
//  */
// static fun_res_t cli_cmd_cli_on_handler(int argc, char** argv) {
//     L_UNUSED(argc);
//     L_UNUSED(argv);
    
//     // Если уже в режиме пароля или включен, ничего не делаем
//     if (cli_current_state != CLI_STATE_DISABLED) {
//         cli_send_string("CLI is already enabled\r\n");
//         return ERR_OK;
//     }
    
//     // Очищаем буфер
//     rb_clear(&fifo_rx);
 
//     // Включаем cli
//     cli_enable();
//     return ERR_OK;
// }
 
// /**
//  * @brief Обработчик встроенной команды cli_off
//  */
// static fun_res_t cli_cmd_cli_off_handler(int argc, char** argv) {
//     L_UNUSED(argc);
//     L_UNUSED(argv);
    
//     if (cli_current_state == CLI_STATE_DISABLED) {
//         return ERR_OK; // Уже выключен
//     }
    
//     // Временно разрешаем отправку для завершающих сообщений команды cli_off
//     bool temp_allow_send = cli_allow_send_in_disabled;
//     cli_allow_send_in_disabled = true;
    
//     // Очищаем буферы
//     rb_clear(&fifo_rx);
 
//     // Сбрасываем состояние командного буфера
//     cli_cmd_index = 0;
//     memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
    
//     // Выводим сообщение о выключении (только если CLI был включен)
//     cli_send_string("\r\nCLI disabled\r\n");
    
//     // Выключаем CLI
//     cli_current_state = CLI_STATE_DISABLED;
    
//     // Восстанавливаем исходное значение флага
//     cli_allow_send_in_disabled = temp_allow_send;
    
//     return ERR_OK;
// }

// /**
//  * @brief Обработчик команды lta_search
//  * Выводит информацию о модуле: имя, серийный номер, версия, board_id
//  */
// static fun_res_t cli_cmd_lta_search_handler(int argc, char** argv)
// {
//     L_UNUSED(argc);
//     L_UNUSED(argv);
    
//     cli_send_string("\r\n========== LTA MODULE INFO ==========\r\n");
    
//     cli_send_string("Module Name: ");
//     cli_send_string(tsp_dev_info.name);
//     cli_send_string("\r\n");
    
//     cli_send_string("Serial Number: ");
//     cli_send_string(tsp_dev_info.serial_dev);
//     cli_send_string("\r\n");
    
//     cli_send_string("Board Revision: ");
//     cli_send_string(tsp_dev_info.brd_rev);
//     cli_send_string("\r\n");
    
//     cli_send_string("Slot Number: ");
//     cli_send_string(tsp_dev_info.pos_num);
//     cli_send_string("\r\n");
    
//     char ver_str[32];
//     snprintf(ver_str, sizeof(ver_str), "MCU Version: %lu\r\n", tsp_dev_info.mcu_ver);
//     cli_send_string(ver_str);
    
//     char fpga_ver_str[32];
//     snprintf(fpga_ver_str, sizeof(fpga_ver_str), "FPGA Version: %u\r\n", tsp_dev_info.fpga_ver);
//     cli_send_string(fpga_ver_str);
    
//     cli_send_string("\r\n========== SUBMODULES ==========\r\n");
//     for (u8 i = 0; i < SU_SUBUNITS_MAX_QTY; i++) {
//         u8 sub_data[4];
//         if (subm_read(i, 0, sub_data, 4) == ERR_OK) {
//             char sub_str[64];
//             snprintf(sub_str, sizeof(sub_str), "Submodule %d: ID=0x%02X%02X%02X%02X\r\n",
//                      i, sub_data[0], sub_data[1], sub_data[2], sub_data[3]);
//             cli_send_string(sub_str);
//         } else {
//             char sub_str[32];
//             snprintf(sub_str, sizeof(sub_str), "Submodule %d: not present\r\n", i);
//             cli_send_string(sub_str);
//         }
//     }
    
//     cli_send_string("====================================\r\n");
    
//     return ERR_OK;
// }
 
// /**
//  * @brief Проверка адреса/диапазона на принадлежность допустимым диапазонам памяти (Flash или SRAM)
//  */
// static bool cli_check_mem_range(u32 addr, u32 size)
// {
//     if (size == 0) return false;
 
//     u32 end = addr + size - 1;
 
//     // Flash: 0x0800_0000 - 0x080F_FFFF
//     const u32 FLASH_START = 0x08000000UL;
//     const u32 FLASH_END   = 0x080FFFFFUL;
 
//     // SRAM: 0x2000_0000 - 0x20FF_FFFF
//     const u32 SRAM_START  = 0x20000000UL;
//     const u32 SRAM_END    = 0x20FFFFFFUL;
 
//     // Проверяем переполнение при вычислении end
//     if (end < addr) return false;
 
//     if ((addr >= FLASH_START && end <= FLASH_END) ||
//         (addr >= SRAM_START  && end <= SRAM_END)) {
//         return true;
//     }
 
//     return false;
// }
 
// /**
//  * @brief Обработчик встроенной команды mem_read
//  * Формат: mem_read <address> <size>
//  * address может быть в 0xHEX или в десятичном виде
//  */
// static fun_res_t cli_cmd_mem_read_handler(int argc, char** argv)
// {
//     if (cli_current_state == CLI_STATE_DISABLED) {
//         return ERR_RUNTIME_ERROR;
//     }
 
//     if (argc < 3 || argv == NULL) {
//         cli_send_string("\r\nUsage: mem_read <address> <size>\r\n");
//         return ERR_INVALID_ARGUMENT;
//     }
 
//     // Парсим адрес и размер (поддерживается 0x...)
//     char* addr_str = argv[1];
//     char* size_str = argv[2];
 
//     unsigned long addr_ul = strtoul(addr_str, NULL, 0);
//     unsigned long size_ul = strtoul(size_str, NULL, 0);
 
//     if (size_ul == 0) {
//         cli_send_string("ERROR: size must be > 0\r\n");
//         return ERR_INVALID_ARGUMENT;
//     }
 
//     u32 addr = (u32)addr_ul;
//     u32 size = (u32)size_ul;
 
//     if (!cli_check_mem_range(addr, size)) {
//         cli_send_string("ERROR: address out of permitted memory ranges (Flash or SRAM)\r\n");
//         return ERR_INVALID_ARGUMENT;
//     }
 
//     // Переходим на новую строку, чтобы вывод дампа не оказался на той же строке, где была введена команда
//     cli_send_string("\r\n");
    
//     // Выводим побайтово. Формат: 0xAAAAAAAA: XX
//     char out_line[256];
//     for (u32 i = 0; i < size; i++) {
//         // Безопасное чтение: приводим к указателю на volatile u8
//         volatile u8* ptr = (volatile u8*)(uintptr_t)(addr + i);
//         u8 value = *ptr;
//         snprintf(out_line, sizeof(out_line), "0x%08lX: %02X\r\n", (unsigned long)(addr + i), (unsigned int)value);
//         cli_send_string(out_line);
//     }
 
//     return ERR_OK;
// }
 
// // Структуры встроенных команд
// static const cli_command_t cli_help_cmd = {
//     .name = "help",
//     .handler = cli_cmd_help_handler,
//     .description = "Display available commands and their descriptions"
// };
 
// static const cli_command_t cli_on_cmd = {
//     .name = "cli_on", 
//     .handler = cli_cmd_cli_on_handler,
//     .description = "Enable the Command Line Interface module"
// };
 
// static const cli_command_t cli_off_cmd = {
//     .name = "cli_off",
//     .handler = cli_cmd_cli_off_handler, 
//     .description = "Disable the Command Line Interface module"
// };
 
// static const cli_command_t cli_mem_cmd = {
//     .name = "mem_read",
//     .handler = cli_cmd_mem_read_handler,
//     .description = "Read memory: mem_read <address> <size> (address supports 0x... or decimal)"
// };

// static const cli_command_t cli_lta_search_cmd = {
//     .name = "lta_search",
//     .handler = cli_cmd_lta_search_handler,
//     .description = "Search and display LTA module info (name, SN, versions, submodules)"
// };

// //*********************************** Глобальные (публичные) функции ***************************************
 
// bool cli_is_active(void) {
//     return (cli_current_state != CLI_STATE_DISABLED);
// }
 
// cli_state_t cli_get_state(void) {
//     return cli_current_state;
// }
 
// u8 cli_get_command_count(void) {
//     return cli_cmd_count;
// }
 
// /**
//  * @brief Инициализация модуля CLI
//  * @return ERR_OK - успех, код ошибки - failure
//  */
// fun_res_t cli_init(void) {
//     if (cli_current_state != CLI_STATE_DISABLED) {
//         return ERR_OK;  // Уже инициализирован
//     }
 
//     // Разрешаем отправку для инициализационных сообщений
//     cli_allow_send_in_disabled = true;
 
//     // Проверка инициализации UART канала
//     lmcal_ch_sts_t uart_status = lmcal_uart_get_status(CLI_UART_CHANNEL);
//     if (uart_status == CH_STS_NOT_INIT) {
//         cli_send_string("ERROR: UART channel not initialized\r\n");
//         cli_allow_send_in_disabled = false;
//         return ERR_RUNTIME_ERROR;
//     }
 
//     // Инициализация FIFO
//     fifo_rx.item_size = sizeof(u8);
//     if (rb_init(&fifo_rx, fifo_rx_buf, sizeof(fifo_rx_buf)/sizeof(u8)) != RB_RES_OK) {
//         cli_send_string("ERROR: RX FIFO initialization failed\r\n");
//         cli_allow_send_in_disabled = false;
//         return ERR_RUNTIME_ERROR;
//     }
//     rb_clear(&fifo_rx);
 
//     // Колбек по приему байта через UART
//     lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, f_uart_read_byte);
//     // TX колбек не нужен в синхронном режиме
 
//     // Инициализация переменных
//     cli_cmd_index = 0;
//     cli_cmd_count = 0;
//     cli_current_state = CLI_STATE_DISABLED;
    
//     // Очистка буферов
//     memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
//     memset(cli_commands, 0, sizeof(cli_commands));
 
//     // Регистрация встроенных команд
//     cli_register_command(&cli_help_cmd);
//     cli_register_command(&cli_on_cmd);
//     cli_register_command(&cli_off_cmd);
//     cli_register_command(&cli_mem_cmd);
//     cli_register_command(&cli_lta_search_cmd);
    
//     // Выводим приветственное сообщение при инициализации
//     cli_send_string("\r\n------------------------------------------------\r\n");
//     cli_send_string("====== CLI Initialized (Disabled) ======\r\n");
//     cli_send_string("------------------------------------------------\r\n");
//     cli_send_string("             Type 'cli_on' to enable\r\n");
//     cli_send_string("------------------------------------------------\r\n");
    
//     // После инициализации запрещаем отправку в выключенном состоянии
//     //cli_allow_send_in_disabled = false;
 
//     return ERR_OK;
// }
 
// /**
//  * @brief Включение модуля CLI (с проверкой пароля)
//  * @return ERR_OK - успех, код ошибки - failure
//  */
// fun_res_t cli_on(void) {
//     return cli_cmd_cli_on_handler(0, NULL);
// }
 
// /**
//  * @brief Выключение модуля CLI
//  * @return ERR_OK - успех, код ошибки - failure
//  */
// fun_res_t cli_off(void) {
//     return cli_cmd_cli_off_handler(0, NULL);
// }
 
// /**
//  * @brief Регистрация новой команды в CLI
//  * @param cmd Указатель на структуру команды
//  * @return ERR_OK - успех, код ошибки - failure
//  */
// fun_res_t cli_register_command(const cli_command_t* cmd) {
//     if (cli_cmd_count >= CLI_MAX_COMMANDS) {
//         return ERR_RUNTIME_ERROR;
//     }
    
//     if (cmd == NULL || cmd->name == NULL || cmd->handler == NULL) {
//         return ERR_INVALID_ARGUMENT;
//     }
    
//     // Проверка длины имени команды
//     size_t name_len = strlen(cmd->name);
//     if (name_len == 0 || name_len > 16) {
//         return ERR_INVALID_ARGUMENT;
//     }
    
//     // Проверка на дубликаты
//     for (u8 i = 0; i < cli_cmd_count; i++) {
//         if (strcmp(cli_commands[i]->name, cmd->name) == 0) {
//             return ERR_RUNTIME_ERROR;
//         }
//     }
    
//     cli_commands[cli_cmd_count++] = cmd;
//     return ERR_OK;
// }
 
// /**
//  * @brief Деинициализация модуля CLI
//  * @return ERR_OK - успех, код ошибки - failure
//  */
// fun_res_t cli_deinit(void) {
//     if (cli_current_state == CLI_STATE_DISABLED) {
//         return ERR_OK;
//     }
 
//     // Отключаем колбеки
//     lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, NULL);
//     lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_TX_CALLBACK, NULL);
 
//     // Сбрасываем состояние
//     cli_current_state = CLI_STATE_DISABLED;
//     return ERR_OK;
// }
 
// /**
//  * @brief Основная функция обработки CLI
//  * @note Должна вызываться в основном цикле программы
//  */
// void cli_process(void) {   
//     // Если CLI выключен - только мониторим команду cli_on
//     if (cli_current_state == CLI_STATE_DISABLED) {
//         cli_process_disabled_mode();
//         return;
//     }
    
//     // CLI включен - нормальная обработка команд
//     cli_process_normal_mode();
// }
 