esp32-serial-commands

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ESP32 Serial Command Emulation

ESP32串口命令模拟

Overview

概述

Send commands directly to the serial port to emulate button presses and user actions. Works over USB serial.
直接向串口发送命令,模拟按键操作与用户行为。支持USB串口连接。

ESP32 Setup (Device Side)

ESP32设备端设置

ESP-IDF Framework

ESP-IDF Framework

cpp
#include "esp_log.h"
#include <string.h>

static const char* TAG = "SerialCmd";

void serial_command_task(void* arg) {
    char buf[64];
    int idx = 0;

    while (1) {
        int c = getchar();
        if (c == EOF) {
            vTaskDelay(pdMS_TO_TICKS(10));
            continue;
        }

        if (c == '\n' || c == '\r') {
            buf[idx] = '\0';
            if (idx > 0) {
                ESP_LOGI(TAG, "Command: %s", buf);

                if (strcmp(buf, "PRESS") == 0) {
                    button_callback();
                } else if (strncmp(buf, "SCREEN:", 7) == 0) {
                    int screen = atoi(buf + 7);
                    go_to_screen(screen);
                }
            }
            idx = 0;
        } else if (idx < sizeof(buf) - 1) {
            buf[idx++] = c;
        }
    }
}

// In app_main():
// xTaskCreate(serial_command_task, "serial_cmd", 2048, NULL, 5, NULL);
cpp
#include "esp_log.h"
#include <string.h>

static const char* TAG = "SerialCmd";

void serial_command_task(void* arg) {
    char buf[64];
    int idx = 0;

    while (1) {
        int c = getchar();
        if (c == EOF) {
            vTaskDelay(pdMS_TO_TICKS(10));
            continue;
        }

        if (c == '\n' || c == '\r') {
            buf[idx] = '\0';
            if (idx > 0) {
                ESP_LOGI(TAG, "Command: %s", buf);

                if (strcmp(buf, "PRESS") == 0) {
                    button_callback();
                } else if (strncmp(buf, "SCREEN:", 7) == 0) {
                    int screen = atoi(buf + 7);
                    go_to_screen(screen);
                }
            }
            idx = 0;
        } else if (idx < sizeof(buf) - 1) {
            buf[idx++] = c;
        }
    }
}

// In app_main():
// xTaskCreate(serial_command_task, "serial_cmd", 2048, NULL, 5, NULL);

Arduino Framework

Arduino Framework

cpp
void setup() {
    Serial.begin(115200);
}

void loop() {
    if (Serial.available()) {
        String cmd = Serial.readStringUntil('\n');
        cmd.trim();

        Serial.printf("Command: %s\n", cmd.c_str());

        if (cmd == "PRESS") {
            button_callback();
        } else if (cmd.startsWith("SCREEN:")) {
            int screen = cmd.substring(7).toInt();
            go_to_screen(screen);
        } else if (cmd == "STATUS") {
            Serial.println("OK");
        }
    }
}
cpp
void setup() {
    Serial.begin(115200);
}

void loop() {
    if (Serial.available()) {
        String cmd = Serial.readStringUntil('\n');
        cmd.trim();

        Serial.printf("Command: %s\n", cmd.c_str());

        if (cmd == "PRESS") {
            button_callback();
        } else if (cmd.startsWith("SCREEN:")) {
            int screen = cmd.substring(7).toInt();
            go_to_screen(screen);
        } else if (cmd == "STATUS") {
            Serial.println("OK");
        }
    }
}

Host Side - Send Commands

主机端 - 发送命令

bash
undefined
bash
undefined

Find serial port

查找串口

PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* /dev/ttyACM* 2>/dev/null | head -1)
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* /dev/ttyACM* 2>/dev/null | head -1)

Send a command

发送命令

echo "PRESS" > "$PORT"
undefined
echo "PRESS" > "$PORT"
undefined

Common Command Patterns

常见命令模式

bash
undefined
bash
undefined

Simple command

简单命令

echo "PRESS" > "$PORT"
echo "PRESS" > "$PORT"

Command with parameter

带参数的命令

echo "PRESS:3" > "$PORT" # Press 3 times echo "SCREEN:2" > "$PORT" # Go to screen 2 echo "MODE:debug" > "$PORT" # Set debug mode
undefined
echo "PRESS:3" > "$PORT" # 按压3次 echo "SCREEN:2" > "$PORT" # 切换到屏幕2 echo "MODE:debug" > "$PORT" # 设置调试模式
undefined

Automated Testing

自动化测试

Stress Test

压力测试

bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
for i in {1..100}; do
  echo "PRESS" > "$PORT"
  echo "Sent press $i"
  sleep 2
done
bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
for i in {1..100}; do
  echo "PRESS" > "$PORT"
  echo "已发送第$i次按压命令"
  sleep 2
done

Long-Duration Stability Test

长期稳定性测试

bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
END=$(($(date +%s) + 3600))  # 1 hour
count=0

while [ $(date +%s) -lt $END ]; do
  count=$((count + 1))
  echo "PRESS" > "$PORT"
  echo "[$(date +%H:%M:%S)] Press $count"
  sleep 30
done

echo "Total: $count presses"
bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
END=$(($(date +%s) + 3600))  # 1小时
count=0

while [ $(date +%s) -lt $END ]; do
  count=$((count + 1))
  echo "PRESS" > "$PORT"
  echo "[$(date +%H:%M:%S)] 第$count次按压"
  sleep 30
done

echo "总计: $count次按压"

Test with Log Monitoring

结合日志监控的测试

Terminal 1 - Monitor logs:
bash
tail -f /tmp/device.log
Terminal 2 - Send commands:
bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
echo "PRESS" > "$PORT"
终端1 - 监控日志:
bash
tail -f /tmp/device.log
终端2 - 发送命令:
bash
PORT=$(ls /dev/cu.usbmodem* /dev/ttyUSB* 2>/dev/null | head -1)
echo "PRESS" > "$PORT"

Tips

注意事项

  • Timing: Add delays between commands to let device process
  • Feedback: Check serial logs to confirm command was received
  • Error handling: Device should echo back status (OK/ERROR)
  • Combine with logging: Always monitor logs while testing
  • 时序控制: 在命令之间添加延迟,以便设备处理
  • 反馈验证: 查看串口日志确认命令已接收
  • 错误处理: 设备应返回状态信息(OK/ERROR)
  • 日志结合: 测试过程中持续监控日志