From 268a132283077a28fca5676a829326a5c0faf508 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Wed, 4 Feb 2026 13:45:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- User/device/mrobot.c | 120 ++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/User/device/mrobot.c b/User/device/mrobot.c index 8e924d5..76210f2 100644 --- a/User/device/mrobot.c +++ b/User/device/mrobot.c @@ -229,29 +229,45 @@ static int print_imu_device(const void *device_data, char *buffer, size_t buffer char gx[16], gy[16], gz[16]; char temp[16]; char roll[16], pitch[16], yaw[16]; + char q0[16], q1[16], q2[16], q3[16]; + /* 格式化加速度 */ format_float(ax, sizeof(ax), imu->accl.x, 3); format_float(ay, sizeof(ay), imu->accl.y, 3); format_float(az, sizeof(az), imu->accl.z, 3); + + /* 格式化陀螺仪 */ format_float(gx, sizeof(gx), imu->gyro.x, 3); format_float(gy, sizeof(gy), imu->gyro.y, 3); format_float(gz, sizeof(gz), imu->gyro.z, 3); + + /* 格式化温度 */ format_float(temp, sizeof(temp), imu->temp, 2); + + /* 格式化欧拉角(转换为角度) */ format_float(roll, sizeof(roll), imu->euler.rol * RAD_TO_DEG, 2); format_float(pitch, sizeof(pitch), imu->euler.pit * RAD_TO_DEG, 2); format_float(yaw, sizeof(yaw), imu->euler.yaw * RAD_TO_DEG, 2); + /* 格式化四元数 */ + format_float(q0, sizeof(q0), imu->quat.q0, 4); + format_float(q1, sizeof(q1), imu->quat.q1, 4); + format_float(q2, sizeof(q2), imu->quat.q2, 4); + format_float(q3, sizeof(q3), imu->quat.q3, 4); + return snprintf(buffer, buffer_size, - "状态: %s\r\n" - "加速度计: X=%s Y=%s Z=%s m/s²\r\n" - "陀螺仪: X=%s Y=%s Z=%s rad/s\r\n" - "温度: %s °C\r\n" - "欧拉角: Roll=%s Pitch=%s Yaw=%s °\r\n", - imu->header.online ? "在线" : "离线", + " Status : %s\r\n" + " Accel : X=%-10s Y=%-10s Z=%-10s (m/s^2)\r\n" + " Gyro : X=%-10s Y=%-10s Z=%-10s (rad/s)\r\n" + " Euler : Roll=%-8s Pitch=%-8s Yaw=%-8s (deg)\r\n" + " Quaternion: q0=%-10s q1=%-10s q2=%-10s q3=%-10s\r\n" + " Temp : %-10s C\r\n", + imu->header.online ? "Online" : "Offline", ax, ay, az, gx, gy, gz, - temp, - roll, pitch, yaw); + roll, pitch, yaw, + q0, q1, q2, q3, + temp); } /** @@ -270,14 +286,14 @@ static int print_motor_device(const void *device_data, char *buffer, size_t buff format_float(temp, sizeof(temp), motor->feedback.temp, 1); return snprintf(buffer, buffer_size, - "状态: %s\r\n" - "反装: %s\r\n" - "角度: %s °\r\n" - "转速: %s RPM\r\n" - "电流: %s A\r\n" - "温度: %s °C\r\n", - motor->header.online ? "在线" : "离线", - motor->reverse ? "是" : "否", + " Status : %s\r\n" + " Reverse : %s\r\n" + " Angle : %-15s deg\r\n" + " Speed : %-15s RPM\r\n" + " Current : %-15s A\r\n" + " Temp : %-15s C\r\n", + motor->header.online ? "Online" : "Offline", + motor->reverse ? "Yes" : "No", angle, speed, current, temp); } @@ -294,7 +310,7 @@ static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const ch int offset = snprintf(pcWriteBuffer, xWriteBufferLen, "MRobot CLI v2.0\r\n" "================\r\n" - "内置命令:\r\n"); + "Built-in Commands:\r\n"); for (size_t i = 0; i < BUILTIN_CMD_COUNT && offset < (int)xWriteBufferLen - 50; i++) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, @@ -303,7 +319,7 @@ static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const ch if (ctx.custom_cmd_count > 0) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "\r\n自定义命令:\r\n"); + "\r\nCustom Commands:\r\n"); for (uint8_t i = 0; i < ctx.custom_cmd_count && offset < (int)xWriteBufferLen - 50; i++) { if (ctx.custom_cmds[i] != NULL) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, @@ -347,7 +363,7 @@ static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char if (param == NULL) { /* 无参数时切换到根目录 */ strcpy(ctx.current_path, "/"); - snprintf(pcWriteBuffer, xWriteBufferLen, "切换到: %s\r\n", ctx.current_path); + snprintf(pcWriteBuffer, xWriteBufferLen, "Changed to: %s\r\n", ctx.current_path); return pdFALSE; } @@ -365,11 +381,11 @@ static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char } else if (strcmp(path, "modules") == 0 || strcmp(path, "/modules") == 0) { strcpy(ctx.current_path, "/modules"); } else { - snprintf(pcWriteBuffer, xWriteBufferLen, "错误: 目录 '%s' 不存在\r\n", path); + snprintf(pcWriteBuffer, xWriteBufferLen, "Error: Directory '%s' not found\r\n", path); return pdFALSE; } - snprintf(pcWriteBuffer, xWriteBufferLen, "切换到: %s\r\n", ctx.current_path); + snprintf(pcWriteBuffer, xWriteBufferLen, "Changed to: %s\r\n", ctx.current_path); return pdFALSE; } @@ -385,30 +401,35 @@ static BaseType_t cmd_ls(char *pcWriteBuffer, size_t xWriteBufferLen, const char "dev/\r\n" "modules/\r\n"); } else if (strcmp(ctx.current_path, "/dev") == 0) { - offset = snprintf(pcWriteBuffer, xWriteBufferLen, "设备列表 (%d 个):\r\n", ctx.device_count); + offset = snprintf(pcWriteBuffer, xWriteBufferLen, + "Device List (%d devices)\r\n\r\n", + ctx.device_count); if (ctx.device_count == 0) { - snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, " (无设备)\r\n"); + offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, + " (No devices)\r\n"); } else { /* 按类型分组显示 */ - static const char *type_names[] = { "IMU", "电机", "传感器", "自定义" }; + static const char *type_names[] = { "IMU", "Motor", "Sensor", "Custom" }; + for (uint8_t t = 0; t < MROBOT_DEVICE_TYPE_NUM && offset < (int)xWriteBufferLen - 50; t++) { bool has_type = false; for (uint8_t i = 0; i < ctx.device_count; i++) { if (ctx.devices[i].type == t) { if (!has_type) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - " [%s]\r\n", type_names[t]); + "\r\n[%s]\r\n", type_names[t]); has_type = true; } offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - " %s\r\n", ctx.devices[i].name); + " - %s\r\n", ctx.devices[i].name); } } } } } else if (strcmp(ctx.current_path, "/modules") == 0) { - snprintf(pcWriteBuffer, xWriteBufferLen, "(模块功能暂未实现)\r\n"); + snprintf(pcWriteBuffer, xWriteBufferLen, + "Module functions not yet implemented\r\n"); } return pdFALSE; @@ -432,8 +453,8 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch /* 检查是否在 /dev 目录 */ if (strcmp(ctx.current_path, "/dev") != 0) { snprintf(pcWriteBuffer, xWriteBufferLen, - "错误: show 命令仅在 /dev 目录下可用\r\n" - "提示: 使用 'cd /dev' 切换到设备目录\r\n"); + "Error: 'show' command only works in /dev directory\r\n" + "Hint: Use 'cd /dev' to switch to device directory\r\n"); return pdFALSE; } @@ -477,8 +498,8 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch if (target_device[0] == '\0') { /* 显示所有设备 */ - offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "=== 所有设备 ===\r\n\r\n"); + offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, + "=== All Devices ===\r\n\r\n"); for (uint8_t i = 0; i < ctx.device_count && offset < (int)xWriteBufferLen - 100; i++) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, @@ -491,14 +512,13 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch offset += (written > 0) ? written : 0; } else { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "(无打印函数)\r\n"); + " (No print function)\r\n"); } - offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, "\r\n"); } if (ctx.device_count == 0) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "(无已注册设备)\r\n"); + " (No devices registered)\r\n"); } } else { /* 显示指定设备 */ @@ -506,7 +526,8 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch if (dev == NULL) { snprintf(pcWriteBuffer, xWriteBufferLen, - "错误: 设备 '%s' 未找到\r\n", target_device); + "Error: Device '%s' not found\r\n", + target_device); current_iter = 0; return pdFALSE; } @@ -518,7 +539,7 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch dev->print_cb(dev->data, pcWriteBuffer + offset, xWriteBufferLen - offset); } else { snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "(无打印函数)\r\n"); + " (No print function)\r\n"); } } @@ -533,23 +554,12 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch } } -/* ========================================================================== */ -/* htop 模式实现 */ -/* ========================================================================== */ - -/** - * @brief 处理 htop 模式显示 - */ +/* ============================================================================ + * htop 模式处理 + * ========================================================================== */ static void handle_htop_mode(void) { - /* 清屏 */ send_string(ANSI_CLEAR_SCREEN); - - /* 显示头部 */ - send_string( - "MRobot Task Monitor (按 'q' 退出)\r\n" - "================================================================================\r\n" - "Task Name State Prio Stack Num\r\n" - "--------------------------------------------------------------------------------\r\n"); + send_string("=== MRobot Task Monitor (Press 'q' to exit) ===\r\n\r\n"); /* 获取任务列表 */ char task_buffer[1024]; @@ -557,6 +567,10 @@ static void handle_htop_mode(void) { vTaskList(task_buffer); + /* 表头 */ + send_string("Task Name State Prio Stack Num\r\n"); + send_string("------------------------------------------------\r\n"); + /* 解析并格式化任务列表 */ char *line = strtok(task_buffer, "\r\n"); while (line != NULL) { @@ -571,7 +585,7 @@ static void handle_htop_mode(void) { case 'B': state_str = "Blocked"; break; case 'S': state_str = "Suspend"; break; case 'D': state_str = "Deleted"; break; - case 'X': state_str = "Ready"; break; + case 'X': state_str = "Ready "; break; default: state_str = "Unknown"; break; } @@ -585,7 +599,7 @@ static void handle_htop_mode(void) { /* 显示系统信息 */ snprintf(display_line, sizeof(display_line), - "--------------------------------------------------------------------------------\r\n" + "------------------------------------------------\r\n" "System Tick: %lu | Free Heap: %lu bytes\r\n", (unsigned long)xTaskGetTickCount(), (unsigned long)xPortGetFreeHeapSize());