WIP: Debug-level logs.

This commit is contained in:
Joe Kearney 2026-01-08 21:41:40 -06:00
parent a25627232c
commit e47fdd38d4
3 changed files with 233 additions and 152 deletions

View file

@ -1,3 +1,25 @@
/*
* This program source code file is part of the KTag project, a DIY laser tag
* game with customizable features and wide interoperability.
*
* 🛡 <https://ktag.clubk.club> 🃞
*
* Copyright © 2026 Joseph P. Kearney and the KTag developers.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* There should be a copy of the GNU Affero General Public License in the LICENSE
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
*/
#include "esp_console.h" #include "esp_console.h"
#include "esp_log.h" #include "esp_log.h"
#include "nvs.h" #include "nvs.h"
@ -8,8 +30,10 @@
#include "esp_vfs_dev.h" #include "esp_vfs_dev.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
#define LOG_NVS_NS "logcfg" #define LOG_NVS_NS "logcfg"
#define LOGCFG_VERSION 1
#define MAX_TAGS 16 #define MAX_TAGS 16
#define MAX_TAGLEN 16 #define MAX_TAGLEN 16
@ -65,44 +89,57 @@ static const char *level_str(esp_log_level_t lvl)
} }
} }
static void normalize_tag(char *dst, const char *src)
{
size_t i;
for (i = 0; i < MAX_TAGLEN - 1 && src[i]; i++)
{
//dst[i] = toupper((unsigned char)src[i]);
dst[i] = src[i];
}
dst[i] = 0;
}
/* ---------------- NVS ---------------- */ /* ---------------- NVS ---------------- */
static void nvs_save(void) static void nvs_save(void)
{ {
nvs_handle_t h; nvs_handle_t h;
esp_err_t err = nvs_open(LOG_NVS_NS, NVS_READWRITE, &h); esp_err_t err = nvs_open(LOG_NVS_NS, NVS_READWRITE, &h);
if (err != ESP_OK)
if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
ESP_LOGW("Console", "NVS not initialized, cannot save");
return; return;
}
else if (err != ESP_OK) {
ESP_LOGE("Console", "Failed to open NVS: %s", esp_err_to_name(err));
return;
}
uint8_t lvl = esp_log_get_default_level();
nvs_set_u8(h, "global", lvl);
nvs_set_u8(h, "ver", LOGCFG_VERSION);
nvs_set_u8(h, "global", esp_log_get_default_level());
nvs_set_u8(h, "tagcnt", Tag_Count); nvs_set_u8(h, "tagcnt", Tag_Count);
nvs_set_blob(h, "tags", Tag_Table, nvs_set_blob(h, "tags", Tag_Table, Tag_Count * sizeof(tag_entry_t));
Tag_Count * sizeof(tag_entry_t));
nvs_commit(h); nvs_commit(h);
nvs_close(h); nvs_close(h);
} }
static void nvs_clear_tags(void)
{
nvs_handle_t h;
if (nvs_open(LOG_NVS_NS, NVS_READWRITE, &h) != ESP_OK)
return;
nvs_erase_key(h, "tagcnt");
nvs_erase_key(h, "tags");
nvs_commit(h);
nvs_close(h);
}
static void log_config_load(void) static void log_config_load(void)
{ {
nvs_handle_t h; nvs_handle_t h;
esp_err_t err = nvs_open(LOG_NVS_NS, NVS_READONLY, &h); if (nvs_open(LOG_NVS_NS, NVS_READONLY, &h) != ESP_OK)
if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
ESP_LOGW("Console", "NVS not initialized, cannot load");
return; return;
}
else if (err != ESP_OK) { uint8_t ver;
ESP_LOGE("Console", "Failed to open NVS: %s", esp_err_to_name(err)); if (nvs_get_u8(h, "ver", &ver) != ESP_OK || ver != LOGCFG_VERSION)
{
nvs_close(h);
nvs_clear_tags();
return; return;
} }
@ -113,7 +150,7 @@ static void log_config_load(void)
Saved_Global_Level = lvl; Saved_Global_Level = lvl;
} }
uint8_t cnt = 0; uint8_t cnt;
if (nvs_get_u8(h, "tagcnt", &cnt) == ESP_OK && cnt <= MAX_TAGS) if (nvs_get_u8(h, "tagcnt", &cnt) == ESP_OK && cnt <= MAX_TAGS)
{ {
size_t sz = cnt * sizeof(tag_entry_t); size_t sz = cnt * sizeof(tag_entry_t);
@ -122,8 +159,7 @@ static void log_config_load(void)
Tag_Count = cnt; Tag_Count = cnt;
for (size_t i = 0; i < Tag_Count; i++) for (size_t i = 0; i < Tag_Count; i++)
{ {
esp_log_level_set(Tag_Table[i].tag, esp_log_level_set(Tag_Table[i].tag, Tag_Table[i].level);
Tag_Table[i].level);
} }
} }
} }
@ -131,60 +167,40 @@ static void log_config_load(void)
nvs_close(h); nvs_close(h);
} }
static void nvs_clear_tags(void) /* ---------------- Tag table ---------------- */
{
nvs_handle_t h;
esp_err_t err = nvs_open(LOG_NVS_NS, NVS_READWRITE, &h);
if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
ESP_LOGW("Console", "NVS not initialized, cannot clear tags");
return;
}
else if (err != ESP_OK) {
ESP_LOGE("Console", "Failed to open NVS: %s", esp_err_to_name(err));
return;
}
nvs_erase_key(h, "tagcnt");
nvs_erase_key(h, "tags");
nvs_commit(h);
nvs_close(h);
}
static void clear_tag_levels(void) static void clear_tag_levels(void)
{ {
esp_log_level_t default_level = esp_log_get_default_level(); esp_log_level_t def = esp_log_get_default_level();
for (size_t i = 0; i < Tag_Count; i++) for (size_t i = 0; i < Tag_Count; i++)
{ {
esp_log_level_set(Tag_Table[i].tag, default_level); esp_log_level_set(Tag_Table[i].tag, def);
} }
Tag_Count = 0; Tag_Count = 0;
} }
/* ---------------- Tag table ---------------- */ static bool set_tag_level(const char *tag, esp_log_level_t level)
static void set_tag_level(const char *tag, esp_log_level_t level)
{ {
for (size_t i = 0; i < Tag_Count; i++) for (size_t i = 0; i < Tag_Count; i++)
{ {
if (!strcmp(Tag_Table[i].tag, tag)) if (!strcmp(Tag_Table[i].tag, tag))
{ {
Tag_Table[i].level = level; Tag_Table[i].level = level;
return; return true;
} }
} }
if (Tag_Count < MAX_TAGS) if (Tag_Count >= MAX_TAGS)
{ return false;
strncpy(Tag_Table[Tag_Count].tag, tag, MAX_TAGLEN - 1);
Tag_Table[Tag_Count].tag[MAX_TAGLEN - 1] = 0; strncpy(Tag_Table[Tag_Count].tag, tag, MAX_TAGLEN - 1);
Tag_Table[Tag_Count].level = level; Tag_Table[Tag_Count].tag[MAX_TAGLEN - 1] = 0;
Tag_Count++; Tag_Table[Tag_Count].level = level;
} Tag_Count++;
return true;
} }
/* ---------------- Console command ---------------- */ /* ---------------- Command helpers ---------------- */
static void print_usage(void) static void print_usage(void)
{ {
@ -192,16 +208,127 @@ static void print_usage(void)
"Usage:\n" "Usage:\n"
" log show\n" " log show\n"
" log clear\n" " log clear\n"
" log reset\n"
" log off | on\n" " log off | on\n"
" log <level>\n" " log <level>\n"
" log tag <tag|*> <level|off>\n" " log tag <tag> [level|off]\n"
"Levels: none error warn info debug verbose\n"); "Levels: none error warn info debug verbose\n");
} }
static int cmd_log(int argc, char **argv) static int log_cmd_show(void)
{
printf("Global level: %s\n",
level_str(esp_log_get_default_level()));
if (Tag_Count == 0)
{
printf("No tag overrides\n");
}
else
{
printf("Tag overrides:\n");
for (size_t i = 0; i < Tag_Count; i++)
{
printf(" %-10s : %s\n",
Tag_Table[i].tag,
level_str(Tag_Table[i].level));
}
}
return 0;
}
static int log_cmd_clear(void)
{
clear_tag_levels();
nvs_clear_tags();
printf("All tag overrides cleared\n");
return 0;
}
static int log_cmd_reset(void)
{
esp_log_level_set("*", ESP_LOG_INFO);
Saved_Global_Level = ESP_LOG_INFO;
clear_tag_levels();
nvs_clear_tags();
nvs_save();
printf("Logging reset to defaults\n");
return 0;
}
static int log_cmd_off(void)
{
Saved_Global_Level = esp_log_get_default_level();
esp_log_level_set("*", ESP_LOG_NONE);
nvs_save();
printf("Global logging disabled\n");
return 0;
}
static int log_cmd_on(void)
{
esp_log_level_set("*", Saved_Global_Level);
nvs_save();
printf("Global logging restored\n");
return 0;
}
static int log_cmd_tag(int argc, char **argv)
{
char tag[MAX_TAGLEN];
normalize_tag(tag, argv[2]);
if (argc == 3)
{
printf("Tag '%s' is %s\n",
tag,
level_str(esp_log_level_get(tag)));
return 0;
}
esp_log_level_t level;
if (!strcmp(argv[3], "off"))
{
level = ESP_LOG_NONE;
}
else if (!parse_level(argv[3], &level))
{
printf("Invalid level\n");
return 0;
}
if (!set_tag_level(tag, level))
{
printf("Tag table full (%d max)\n", MAX_TAGS);
return 0;
}
esp_log_level_set(tag, level);
nvs_save();
printf("Tag '%s' set to %s\n", tag, argv[3]);
return 0;
}
static int log_cmd_set_global(const char *lvl)
{ {
esp_log_level_t level; esp_log_level_t level;
if (!parse_level(lvl, &level))
{
print_usage();
return 0;
}
esp_log_level_set("*", level);
Saved_Global_Level = level;
nvs_save();
printf("Global level set to %s\n", lvl);
return 0;
}
/* ---------------- Dispatcher ---------------- */
static int cmd_log(int argc, char **argv)
{
if (argc < 2) if (argc < 2)
{ {
print_usage(); print_usage();
@ -209,96 +336,42 @@ static int cmd_log(int argc, char **argv)
} }
if (!strcmp(argv[1], "show")) if (!strcmp(argv[1], "show"))
{ return log_cmd_show();
printf("Global level: %s\n",
level_str(esp_log_get_default_level()));
if (Tag_Count == 0)
{
printf("No tag overrides\n");
}
else
{
printf("Tag overrides:\n");
for (size_t i = 0; i < Tag_Count; i++)
{
printf(" %-10s : %s\n",
Tag_Table[i].tag,
level_str(Tag_Table[i].level));
}
}
return 0;
}
if (!strcmp(argv[1], "clear")) if (!strcmp(argv[1], "clear"))
{ return log_cmd_clear();
clear_tag_levels(); if (!strcmp(argv[1], "reset"))
nvs_clear_tags(); return log_cmd_reset();
printf("All tag overrides cleared\n");
return 0;
}
if (!strcmp(argv[1], "off")) if (!strcmp(argv[1], "off"))
{ return log_cmd_off();
Saved_Global_Level = esp_log_get_default_level();
esp_log_level_set("*", ESP_LOG_NONE);
nvs_save();
printf("Global logging disabled\n");
return 0;
}
if (!strcmp(argv[1], "on")) if (!strcmp(argv[1], "on"))
{ return log_cmd_on();
esp_log_level_set("*", Saved_Global_Level);
printf("Global logging restored\n");
return 0;
}
if (!strcmp(argv[1], "tag")) if (!strcmp(argv[1], "tag"))
{ return log_cmd_tag(argc, argv);
if (argc != 4)
{
print_usage();
return 0;
}
const char *tag = argv[2]; return log_cmd_set_global(argv[1]);
const char *lvl = argv[3];
if (!strcmp(lvl, "off"))
{
level = ESP_LOG_NONE;
}
else if (!parse_level(lvl, &level))
{
printf("Invalid level\n");
return 0;
}
esp_log_level_set(tag, level);
set_tag_level(tag, level);
nvs_save();
printf("Tag '%s' set to %s\n", tag, lvl);
return 0;
}
if (!parse_level(argv[1], &level))
{
print_usage();
return 0;
}
esp_log_level_set("*", level);
nvs_save();
printf("Global level set to %s\n", argv[1]);
return 0;
} }
/* ---------------- Registration ---------------- */ /* ---------------- Registration ---------------- */
static void log_completion(const char *buf, linenoiseCompletions *lc)
{
if (!strncmp(buf, "log", 3))
{
linenoiseAddCompletion(lc, "log show");
linenoiseAddCompletion(lc, "log clear");
linenoiseAddCompletion(lc, "log reset");
linenoiseAddCompletion(lc, "log off");
linenoiseAddCompletion(lc, "log on");
linenoiseAddCompletion(lc, "log info");
linenoiseAddCompletion(lc, "log debug");
linenoiseAddCompletion(lc, "log warn");
}
}
static void register_log_command(void) static void register_log_command(void)
{ {
linenoiseSetCompletionCallback(log_completion);
const esp_console_cmd_t cmd = { const esp_console_cmd_t cmd = {
.command = "log", .command = "log",
.help = "Control logging levels", .help = "Control logging levels",
@ -311,15 +384,18 @@ static void register_log_command(void)
void Initialize_Console(void) void Initialize_Console(void)
{ {
esp_console_repl_t *repl = NULL; esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_cfg = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
repl_config.prompt = "KTag>"; repl_cfg.prompt = "KTag>";
repl_config.max_cmdline_length = 1024; repl_cfg.max_cmdline_length = 1024;
log_config_load(); log_config_load();
register_log_command(); register_log_command();
esp_console_register_help_command(); esp_console_register_help_command();
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); esp_console_dev_uart_config_t hw_cfg =
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(
esp_console_new_repl_uart(&hw_cfg, &repl_cfg, &repl));
ESP_ERROR_CHECK(esp_console_start_repl(repl)); ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }

@ -1 +1 @@
Subproject commit 3b2718e6f41070de1db08f9d173de94e90cc372a Subproject commit e62f243e86ab0636121ded3f8197da2a8be40976

View file

@ -1952,13 +1952,11 @@ CONFIG_LOG_VERSION=1
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set # CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set # CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
CONFIG_LOG_DEFAULT_LEVEL_INFO=y # CONFIG_LOG_DEFAULT_LEVEL_INFO is not set
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y
CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_LOG_DEFAULT_LEVEL=5
# CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT is not set CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set
CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE=y
CONFIG_LOG_MAXIMUM_LEVEL=5 CONFIG_LOG_MAXIMUM_LEVEL=5
# #
@ -1978,7 +1976,7 @@ CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31
# #
# Format # Format
# #
CONFIG_LOG_COLORS=y # CONFIG_LOG_COLORS is not set
CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y
# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set
# end of Format # end of Format
@ -2638,6 +2636,13 @@ CONFIG_KTAG_ANIMATION_STEP_TIME_IN_ms=10
CONFIG_KTAG_T_DEFAULT_START_GAME_in_ms=30000 CONFIG_KTAG_T_DEFAULT_START_GAME_in_ms=30000
CONFIG_KTAG_MAX_AUDIO_VOLUME=100 CONFIG_KTAG_MAX_AUDIO_VOLUME=100
CONFIG_KTAG_MIN_AUDIO_VOLUME=0 CONFIG_KTAG_MIN_AUDIO_VOLUME=0
CONFIG_SYSTEMK_LOG_LEVEL=5
# CONFIG_SYSTEMK_LOG_LEVEL_NONE is not set
# CONFIG_SYSTEMK_LOG_LEVEL_ERROR is not set
# CONFIG_SYSTEMK_LOG_LEVEL_WARN is not set
# CONFIG_SYSTEMK_LOG_LEVEL_INFO is not set
# CONFIG_SYSTEMK_LOG_LEVEL_DEBUG is not set
CONFIG_SYSTEMK_LOG_LEVEL_VERBOSE=y
# end of KTag SystemK # end of KTag SystemK
# #