Files
433_STM32/Core/Src/cmd_router.c

569 lines
18 KiB
C
Raw Normal View History

/**
******************************************************************************
* @file cmd_router.c
* @brief
* @author Application Layer
* @version 1.0
******************************************************************************
* @attention
*
* 3.2
*
*
* - UART端口读取数据并喂入解析器
* -
* -
*
*
* 1.
* 2. CmdRouter_Task轮询各端口缓冲区
* 3. CmdParser解析器
* 4.
******************************************************************************
*/
#include "cmd_router.h"
#include "multi_uart_router.h"
#include "cmd_parser.h"
#include "uart2_print.h"
#include "debug_log.h"
#include "uart3_protocol_discriminator.h"
#include "uart3_passthrough.h"
#include "uart3_smart_router_config.h"
#include <string.h>
/*==============================================================================
*
*============================================================================*/
/* DEBUG_CMD_ROUTER: 调试日志开关置1时启用路由过程日志输出 */
#define DEBUG_CMD_ROUTER 1
#if DEBUG_CMD_ROUTER
/* 路由模块日志宏,带模块前缀"[ROUTER]"方便过滤 */
#define ROUTER_LOG(fmt, ...) UART2_Print_Printf("[ROUTER] " fmt "\r\n", ##__VA_ARGS__)
#else
#define ROUTER_LOG(fmt, ...)
#endif
/*==============================================================================
*
*============================================================================*/
/**
* @brief
* @note 便
*
*/
#define RX_LOG_BUFFER_SIZE 128
/*==============================================================================
*
*============================================================================*/
/**
* @brief
* @note UART端口的解析状态和统计信息
*
*
* UART端口都可能接收到指令
*
*
*
* - source_port: ID编号
* - last_feed_tick: ()
* - rx_count:
* - active: ()
*/
typedef struct {
uint8_t source_port; /**< 源端口ID编号 */
uint32_t last_feed_tick; /**< 上次喂入数据的时间戳 */
uint32_t rx_count; /**< 累计接收字节数 */
bool active; /**< 端口活跃状态标志 */
} port_parser_state_t;
/*==============================================================================
*
*============================================================================*/
/**
* @brief
* @note PORT_COUNT个端口各自维护解析状态
*/
static port_parser_state_t g_port_states[PORT_COUNT];
/**
* @brief
* @note
* ()
*/
static cmd_response_handler_t g_response_handler = NULL;
/**
* @brief
* @note
*/
static uint32_t g_processed_count = 0;
/**
* @brief
* @note
*/
static uint32_t g_routed_count = 0;
/**
* @brief ID
* @note
*/
static uint8_t g_current_parsing_port = PORT_UART2;
/**
* @brief
* @note
* 便
*/
static uint8_t g_rx_log_buffer[PORT_COUNT][RX_LOG_BUFFER_SIZE];
/**
* @brief
*/
static uint16_t g_rx_log_len[PORT_COUNT];
/**
* @brief
* @note
*/
static uint32_t g_rx_log_last_tick[PORT_COUNT];
/**
* @brief ()
* @note
*/
#define RX_LOG_TIMEOUT_MS 50
/*==============================================================================
*
*============================================================================*/
static void flush_rx_log(port_id_t port_id);
static void append_rx_log(port_id_t port_id, uint8_t byte);
static void cmd_parser_response_callback(uint8_t source_port, const char *response);
/*==============================================================================
*
*============================================================================*/
/**
* @brief
* @note
*
* @param port_id: ID()
* @return
*
*
* - ASCII字符(0x20-0x7E)
* - '\r'"\\r"
* - '\n'"\\n"
* - "\\xXX"
*
*
* -
* - (RX_LOG_TIMEOUT_MS)
*/
static void flush_rx_log(port_id_t port_id)
{
/* 无日志数据时直接返回 */
if (g_rx_log_len[port_id] == 0) {
return;
}
/* 打印日志头部,包含端口名称 */
UART2_Print_Printf("[ROUTER] %s RX: \"", MultiUART_GetPortName(port_id));
/*----------------------------------------------------------
*
*----------------------------------------------------------*/
for (uint16_t i = 0; i < g_rx_log_len[port_id]; i++) {
uint8_t c = g_rx_log_buffer[port_id][i];
if (c >= 0x20 && c < 0x7F) {
/* 可打印ASCII字符直接输出 */
UART2_Print_Send(&c, 1);
} else if (c == '\r') {
/* 回车符:显示为转义序列 */
UART2_Print_Send((const uint8_t *)"\\r", 2);
} else if (c == '\n') {
/* 换行符:显示为转义序列 */
UART2_Print_Send((const uint8_t *)"\\n", 2);
} else {
/* 其他字符:显示为十六进制格式 */
char hex[4];
snprintf(hex, sizeof(hex), "\\x%02X", c);
UART2_Print_Send((const uint8_t *)hex, 4);
}
}
/* 打印日志尾部并换行 */
UART2_Print_String("\"\r\n");
/* 清空日志缓冲区 */
g_rx_log_len[port_id] = 0;
}
/**
* @brief
* @note
*
* @param port_id: ID()
* @param byte: ()
* @return
*
*
* (RX_LOG_BUFFER_SIZE)
*
*/
static void append_rx_log(port_id_t port_id, uint8_t byte)
{
/* 缓冲区未满时写入,否则丢弃(溢出处理) */
if (g_rx_log_len[port_id] < RX_LOG_BUFFER_SIZE) {
g_rx_log_buffer[port_id][g_rx_log_len[port_id]++] = byte;
}
/* 更新最后写入时间戳 */
g_rx_log_last_tick[port_id] = HAL_GetTick();
}
/**
* @brief
* @note CmdParser的响应回调
*
* @param source_port: ID()
* @param response: ()
* @return
*
*
* 1. (g_response_handler)
* 2. MultiUART_Send发送到源端口
* 3. routed_count计数
*
*
* 使LOG_INFO输出TX路由详情便
*/
static void cmd_parser_response_callback(uint8_t source_port, const char *response)
{
if (g_response_handler != NULL) {
/* 使用自定义响应处理器 */
g_response_handler((port_id_t)source_port, response, strlen(response));
g_routed_count++;
} else {
/* 直接发送到源端口 */
MultiUART_SendString((port_id_t)source_port, response);
g_routed_count++;
}
/* 输出TX路由调试日志 */
LOG_INFO("ROUTER", "TX[%s]: %s",
MultiUART_GetPortName((port_id_t)source_port), response);
}
/*==============================================================================
*
*============================================================================*/
/**
* @brief
* @note
*
* @param
* @return
*
*
* 1.
* 2.
* 3.
* 4. PORT_UART2
* 5.
*/
void CmdRouter_Init(void)
{
/*----------------------------------------------------------
*
*----------------------------------------------------------*/
for (port_id_t i = 0; i < PORT_COUNT; i++) {
g_port_states[i].source_port = i;
g_port_states[i].last_feed_tick = 0;
g_port_states[i].rx_count = 0;
g_port_states[i].active = false;
g_rx_log_len[i] = 0;
g_rx_log_last_tick[i] = 0;
}
/*----------------------------------------------------------
*
*----------------------------------------------------------*/
g_response_handler = NULL;
g_processed_count = 0;
g_routed_count = 0;
g_current_parsing_port = PORT_UART2;
/*----------------------------------------------------------
*
* cmd_parser的响应路由到正确的源端口
*----------------------------------------------------------*/
CmdParser_SetResponseCallback(cmd_parser_response_callback);
/*----------------------------------------------------------
* UART3智能路由模块
*----------------------------------------------------------*/
#if UART3_SMART_ROUTING_ENABLED
UART3_Protocol_Init();
Passthrough_Init();
ROUTER_LOG("UART3 Smart Router enabled");
#endif
ROUTER_LOG("Init OK, %d ports registered", PORT_COUNT);
}
/**
* @brief
* @note
*
* @param
* @return
*
*
* 1. UART1:
* 2. UART3: (+)
* 3.
* 4.
*
* UART3智能路由(UART3_SMART_ROUTING_ENABLED=1)
* 1. UART3接收缓冲区字节
* 2. CMD还是透传
* 3. CMD CmdParser_FeedByte()
* 4. PASSTHROUGH Passthrough_PushByte()
* 5. SCAN超时
* 6.
*/
void CmdRouter_Task(void)
{
uint32_t current_tick = HAL_GetTick();
/*----------------------------------------------------------
* UART1处理()
*----------------------------------------------------------*/
{
port_id_t port_id = PORT_UART1;
uint16_t rx_count = MultiUART_GetRxCount(port_id);
if (rx_count > 0) {
g_current_parsing_port = port_id;
CmdParser_SetSourcePort(port_id);
uint8_t byte;
while (MultiUART_ReadByte(port_id, &byte) > 0) {
append_rx_log(port_id, byte);
CmdParser_FeedByte(byte, current_tick);
g_port_states[port_id].rx_count++;
}
if (CmdParser_HasCompleteFrame(NULL)) {
flush_rx_log(port_id);
g_processed_count++;
g_port_states[port_id].active = true;
}
}
}
/*----------------------------------------------------------
* UART3智能路由处理
* 3.3.1 CmdRouter_Task
*----------------------------------------------------------*/
#if UART3_SMART_ROUTING_ENABLED
{
uint8_t byte;
while (MultiUART_ReadByte(PORT_UART3, &byte) > 0) {
route_result_t route = UART3_Protocol_FeedByte(byte, current_tick);
switch (route) {
case ROUTE_CMD:
CmdParser_SetSourcePort(PORT_UART3);
CmdParser_FeedByte(byte, current_tick);
LOG_DEBUG("UART3", "CMD byte: 0x%02X", byte);
break;
case ROUTE_PASSTHROUGH:
Passthrough_PushByte(byte);
LOG_DEBUG("UART3", "PTX byte: 0x%02X", byte);
break;
case ROUTE_NONE:
break;
}
}
if (UART3_Protocol_CheckTimeout(current_tick)) {
uint8_t buffer[128];
uint16_t length;
if (UART3_Protocol_GetPassthroughData(buffer, &length)) {
Passthrough_PushBuffer(buffer, length);
LOG_INFO("UART3", "PASSTHROUGH: %d bytes queued", (int)length);
}
}
Passthrough_Task();
}
#else
{
port_id_t port_id = PORT_UART3;
uint16_t rx_count = MultiUART_GetRxCount(port_id);
if (rx_count > 0) {
g_current_parsing_port = port_id;
CmdParser_SetSourcePort(port_id);
uint8_t byte;
while (MultiUART_ReadByte(port_id, &byte) > 0) {
append_rx_log(port_id, byte);
CmdParser_FeedByte(byte, current_tick);
g_port_states[port_id].rx_count++;
}
if (CmdParser_HasCompleteFrame(NULL)) {
flush_rx_log(port_id);
g_processed_count++;
g_port_states[port_id].active = true;
}
}
}
#endif
/*----------------------------------------------------------
*
*----------------------------------------------------------*/
for (port_id_t port_id = 0; port_id < PORT_COUNT; port_id++) {
if (port_id == PORT_UART2) {
continue;
}
if (g_rx_log_len[port_id] > 0 &&
(current_tick - g_rx_log_last_tick[port_id]) >= RX_LOG_TIMEOUT_MS) {
flush_rx_log(port_id);
}
}
/*----------------------------------------------------------
*
*----------------------------------------------------------*/
CmdParser_Task();
}
/**
* @brief
* @note ()
*
* @param handler: NULL则使用默认行为()
* @return
*
*
* void handler(port_id_t port, const char *response, uint16_t len)
*
* 使
* -
* - /
* -
*/
void CmdRouter_SetResponseHandler(cmd_response_handler_t handler)
{
g_response_handler = handler;
ROUTER_LOG("Response handler %s", handler ? "set" : "cleared");
}
/**
* @brief
* @note MultiUART_Send
*
* @param port: ID()
* @param response: ()
* @param len: ()
* @return
*
*
* - port超出范围response为NULL或len为0时直接返回
*
*
* g_routed_count计数
*/
void CmdRouter_SendResponse(port_id_t port, const char *response, uint16_t len)
{
/* 参数合法性检查 */
if (port >= PORT_COUNT || response == NULL || len == 0) {
return;
}
/* 通过多UART模块发送数据 */
MultiUART_Send(port, (const uint8_t *)response, len);
g_routed_count++;
LOG_INFO("ROUTER", "SendResponse[%s]: %.*s",
MultiUART_GetPortName(port), len, response);
}
/**
* @brief 广
* @note UART端口
*
* @param response: ()
* @param len: ()
* @return
*
* 使
* - 广
* -
*
*
* UART2()广
*/
void CmdRouter_BroadcastResponse(const char *response, uint16_t len)
{
/* 参数合法性检查 */
if (response == NULL || len == 0) {
return;
}
/* 遍历所有端口发送 */
for (port_id_t port = 0; port < PORT_COUNT; port++) {
MultiUART_Send(port, (const uint8_t *)response, len);
g_routed_count++;
}
LOG_INFO("ROUTER", "Broadcast: %.*s", len, response);
}
/**
* @brief
* @note
*
* @param
* @return uint32_t:
*
*
* -
* -
*/
uint32_t CmdRouter_GetProcessedCount(void)
{
return g_processed_count;
}
/**
* @brief
* @note
*
* @param
* @return uint32_t:
*
*
* -
* -
*/
uint32_t CmdRouter_GetRoutedCount(void)
{
return g_routed_count;
}