Files
ESP32C3-0.42OLED-OS/components/sys_cli/sys_cli.c
T

307 lines
9.2 KiB
C

#include "os_cli.h"
#include "os_app.h"
#include "os_input.h"
#include "os_gfx.h"
#include "os_oled.h"
#include "os_status.h"
#include "sys_uart.h"
#include "sys_time.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "esp_console.h"
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static const char *TAG = "SYS_CLI";
static int cmd_time(int argc, char **argv)
{
if (argc >= 2 && strcmp(argv[1], "sync") == 0) {
printf("Triggering SNTP network time sync...\n");
sys_time_start_sntp();
return 0;
} else if (argc >= 3 && strcmp(argv[1], "set") == 0) {
time_t epoch = (time_t)strtoull(argv[2], NULL, 10);
if (sys_time_set_epoch(epoch) == ESP_OK) {
printf("System time successfully set to epoch: %lld\n", (long long)epoch);
return 0;
} else {
printf("Failed to set time. Usage: time set <epoch_seconds>\n");
return 1;
}
}
struct tm tm_info;
bool synced = sys_time_get_local(&tm_info);
time_t now = sys_time_get_epoch();
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d %H:%M:%S (%A)", &tm_info);
printf("\n=== System Wall Clock ===\n");
printf("Status: %s\n", synced ? "SYNCHRONIZED" : "UNSYNCHRONIZED (Uptime only)");
printf("Local: %s\n", strftime_buf);
printf("Epoch: %lld\n", (long long)now);
printf("Timezone: %s\n", sys_time_get_timezone());
printf("\nCommands: time sync | time set <epoch>\n");
return 0;
}
static int cmd_tz(int argc, char **argv)
{
if (argc >= 2) {
if (sys_time_set_timezone(argv[1]) == ESP_OK) {
printf("Timezone set to '%s'\n", argv[1]);
return 0;
} else {
printf("Failed to set timezone\n");
return 1;
}
}
printf("Current Timezone: %s\n", sys_time_get_timezone());
printf("Examples: tz \"GMT0BST,M3.5.0/1,M10.5.0\" (UK)\n");
printf(" tz \"EST5EDT,M3.2.0,M11.1.0\" (US Eastern)\n");
printf(" tz \"CST-8\" (China / Asia)\n");
printf(" tz \"UTC0\" (UTC)\n");
return 0;
}
static int cmd_uart(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: uart <send <msg> | baud <rate> | stats | clear>\n");
return 1;
}
if (strcmp(argv[1], "send") == 0 && argc >= 3) {
sys_uart_write_str(argv[2]);
sys_uart_write_str("\r\n");
printf("Sent over UART TX: %s\n", argv[2]);
return 0;
} else if (strcmp(argv[1], "baud") == 0 && argc >= 3) {
uint32_t baud = (uint32_t)strtoul(argv[2], NULL, 10);
if (baud > 0 && sys_uart_set_baud_rate(baud) == ESP_OK) {
printf("UART baud rate changed to %lu\n", (unsigned long)baud);
return 0;
} else {
printf("Failed to set baud rate\n");
return 1;
}
} else if (strcmp(argv[1], "stats") == 0) {
uint32_t rx = 0, tx = 0;
sys_uart_get_stats(&rx, &tx);
printf("\n=== UART Status (TX: GPIO 21, RX: GPIO 20) ===\n");
printf("Active Baud Rate: %lu\n", (unsigned long)sys_uart_get_baud_rate());
printf("Total RX Bytes: %lu\n", (unsigned long)rx);
printf("Total TX Bytes: %lu\n", (unsigned long)tx);
return 0;
} else if (strcmp(argv[1], "clear") == 0) {
sys_uart_clear_rx_buffer();
printf("UART RX buffer cleared\n");
return 0;
}
printf("Unknown uart sub-command\n");
return 1;
}
static int cmd_ps(int argc, char **argv)
{
printf("\n=== Running FreeRTOS Tasks ===\n");
char task_buf[512];
vTaskList(task_buf);
printf("TaskName\tStatus\tPrio\tStack\tNum\n");
printf("%s\n", task_buf);
return 0;
}
static int cmd_free(int argc, char **argv)
{
printf("\n=== Memory Allocation ===\n");
printf("Current Free Heap: %lu bytes\n", (unsigned long)esp_get_free_heap_size());
printf("Minimum Free Heap: %lu bytes\n", (unsigned long)esp_get_minimum_free_heap_size());
return 0;
}
static int cmd_app(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: app <list | launch <id> | home>\n");
return 1;
}
if (strcmp(argv[1], "list") == 0) {
size_t count = sys_app_get_count();
printf("\n=== Registered Apps (%u) ===\n", (unsigned int)count);
for (size_t i = 0; i < count; i++) {
const sys_app_t *app = sys_app_get_by_index(i);
printf(" [%u] %-12s (ID: %s)\n", (unsigned int)i, app->name, app->id);
}
return 0;
} else if (strcmp(argv[1], "launch") == 0 && argc >= 3) {
esp_err_t err = sys_app_launch_by_id(argv[2]);
if (err == ESP_OK) {
printf("Launched app: %s\n", argv[2]);
} else {
printf("Failed to launch app: %s\n", argv[2]);
}
return 0;
} else if (strcmp(argv[1], "home") == 0) {
sys_app_launch_launcher();
printf("Switched to Home Launcher\n");
return 0;
}
printf("Unknown app sub-command\n");
return 1;
}
static int cmd_input(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: input <click | double | long | home>\n");
return 1;
}
if (strcmp(argv[1], "click") == 0) {
sys_input_inject(INPUT_ACTION_CLICK);
} else if (strcmp(argv[1], "double") == 0) {
sys_input_inject(INPUT_ACTION_DOUBLE_CLICK);
} else if (strcmp(argv[1], "long") == 0) {
sys_input_inject(INPUT_ACTION_LONG_PRESS);
} else if (strcmp(argv[1], "home") == 0) {
sys_input_inject(INPUT_ACTION_HOLD_HOME);
} else {
printf("Invalid action\n");
return 1;
}
printf("Injected action: %s\n", argv[1]);
return 0;
}
static int cmd_reboot(int argc, char **argv)
{
printf("Restarting system...\n");
esp_restart();
return 0;
}
static int cmd_contrast(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: contrast <0-255>\n");
return 1;
}
int val = atoi(argv[1]);
if (val < 0 || val > 255) {
printf("Value must be 0 to 255\n");
return 1;
}
oled_driver_set_contrast((uint8_t)val);
printf("Contrast set to %d\n", val);
return 0;
}
esp_err_t sys_cli_init(void)
{
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
repl_config.prompt = "esp32c3-os> ";
repl_config.max_cmdline_args = 8;
repl_config.max_cmdline_length = 256;
esp_console_dev_usb_serial_jtag_config_t hw_config =
ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
esp_console_repl_t *repl = NULL;
esp_err_t err = esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to create USB Serial/JTAG REPL: %s", esp_err_to_name(err));
return err;
}
esp_console_register_help_command();
const esp_console_cmd_t time_cmd = {
.command = "time",
.help = "View or configure real-time clock (time | time sync | time set <epoch>)",
.hint = "<sync|set <epoch>>",
.func = &cmd_time,
};
esp_console_cmd_register(&time_cmd);
const esp_console_cmd_t tz_cmd = {
.command = "tz",
.help = "View or configure timezone string",
.hint = "<tz_string>",
.func = &cmd_tz,
};
esp_console_cmd_register(&tz_cmd);
const esp_console_cmd_t ps_cmd = {
.command = "ps",
.help = "List active FreeRTOS tasks and memory",
.hint = NULL,
.func = &cmd_ps,
};
esp_console_cmd_register(&ps_cmd);
const esp_console_cmd_t free_cmd = {
.command = "free",
.help = "Display system heap status",
.hint = NULL,
.func = &cmd_free,
};
esp_console_cmd_register(&free_cmd);
const esp_console_cmd_t app_cmd = {
.command = "app",
.help = "App management (list, launch <id>, home)",
.hint = "<list|launch|home>",
.func = &cmd_app,
};
esp_console_cmd_register(&app_cmd);
const esp_console_cmd_t input_cmd = {
.command = "input",
.help = "Simulate button input (click, double, long, home)",
.hint = "<click|double|long|home>",
.func = &cmd_input,
};
esp_console_cmd_register(&input_cmd);
const esp_console_cmd_t contrast_cmd = {
.command = "contrast",
.help = "Set OLED contrast (0-255)",
.hint = "<value>",
.func = &cmd_contrast,
};
esp_console_cmd_register(&contrast_cmd);
const esp_console_cmd_t reboot_cmd = {
.command = "reboot",
.help = "Reboot the MCU",
.hint = NULL,
.func = &cmd_reboot,
};
esp_console_cmd_register(&reboot_cmd);
const esp_console_cmd_t uart_cmd = {
.command = "uart",
.help = "Hardware UART control (send, baud, stats, clear)",
.hint = "<send|baud|stats|clear>",
.func = &cmd_uart,
};
esp_console_cmd_register(&uart_cmd);
err = esp_console_start_repl(repl);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to start USB Serial/JTAG REPL: %s", esp_err_to_name(err));
return err;
}
ESP_LOGI(TAG, "CLI shell initialized");
return ESP_OK;
}