Added Set Log Level Commands
This commit is contained in:
@@ -259,7 +259,7 @@ void BellEngine::activateNote(uint16_t note) {
|
|||||||
if (bellConfig == 0) continue;
|
if (bellConfig == 0) continue;
|
||||||
|
|
||||||
// Convert 1-indexed config to 0-indexed bellIndex
|
// Convert 1-indexed config to 0-indexed bellIndex
|
||||||
uint8_t bellIndex = bellConfig-1;
|
uint8_t bellIndex = bellConfig - 1;
|
||||||
|
|
||||||
// Additional safety check to prevent underflow crashes
|
// Additional safety check to prevent underflow crashes
|
||||||
if (bellIndex >= 255) {
|
if (bellIndex >= 255) {
|
||||||
@@ -311,7 +311,8 @@ void BellEngine::activateNote(uint16_t note) {
|
|||||||
LOG_VERBOSE("🔥🔥 BATCH FIRED %d bells SIMULTANEOUSLY!", bellDurations.size());
|
LOG_VERBOSE("🔥🔥 BATCH FIRED %d bells SIMULTANEOUSLY!", bellDurations.size());
|
||||||
|
|
||||||
// 🔔 NOTIFY WEBSOCKET CLIENTS OF BELL DINGS!
|
// 🔔 NOTIFY WEBSOCKET CLIENTS OF BELL DINGS!
|
||||||
notifyBellsFired(firedBellIndices);
|
// * deactivated currently, since unstable and causes performance issues *
|
||||||
|
// notifyBellsFired(firedBellIndices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1005,9 +1005,76 @@ void CommandHandler::handleSystemCommand(JsonVariant contents, const MessageCont
|
|||||||
handleGetFirmwareStatusCommand(context);
|
handleGetFirmwareStatusCommand(context);
|
||||||
} else if (action == "set_network_config") {
|
} else if (action == "set_network_config") {
|
||||||
handleSetNetworkConfigCommand(contents, context);
|
handleSetNetworkConfigCommand(contents, context);
|
||||||
|
} else if (action == "set_serial_log_level") {
|
||||||
|
handleSetSerialLogLevelCommand(contents, context);
|
||||||
|
} else if (action == "set_sd_log_level") {
|
||||||
|
handleSetSdLogLevelCommand(contents, context);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING("Unknown system action: %s", action.c_str());
|
LOG_WARNING("Unknown system action: %s", action.c_str());
|
||||||
sendErrorResponse("system", "Unknown action: " + action, context);
|
sendErrorResponse("system", "Unknown action: " + action, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
// LOG LEVEL COMMANDS
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
void CommandHandler::handleSetSerialLogLevelCommand(JsonVariant contents, const MessageContext& context) {
|
||||||
|
if (!contents.containsKey("level")) {
|
||||||
|
sendErrorResponse("set_serial_log_level", "Missing level parameter", context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t level = contents["level"].as<uint8_t>();
|
||||||
|
|
||||||
|
// Set the level in ConfigManager
|
||||||
|
if (_configManager.setSerialLogLevel(level)) {
|
||||||
|
// Apply the level to Logging immediately
|
||||||
|
Logging::setLevel((Logging::LogLevel)level);
|
||||||
|
|
||||||
|
// Save to SD card
|
||||||
|
bool saved = _configManager.saveGeneralConfig();
|
||||||
|
|
||||||
|
if (saved) {
|
||||||
|
sendSuccessResponse("set_serial_log_level",
|
||||||
|
"Serial log level set to " + String(level) + " and saved", context);
|
||||||
|
LOG_INFO("Serial log level updated to %d", level);
|
||||||
|
} else {
|
||||||
|
sendErrorResponse("set_serial_log_level",
|
||||||
|
"Log level set but failed to save to SD card", context);
|
||||||
|
LOG_ERROR("Failed to save serial log level to SD card");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendErrorResponse("set_serial_log_level",
|
||||||
|
"Invalid log level (must be 0-5)", context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandHandler::handleSetSdLogLevelCommand(JsonVariant contents, const MessageContext& context) {
|
||||||
|
if (!contents.containsKey("level")) {
|
||||||
|
sendErrorResponse("set_sd_log_level", "Missing level parameter", context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t level = contents["level"].as<uint8_t>();
|
||||||
|
|
||||||
|
// Set the level in ConfigManager
|
||||||
|
if (_configManager.setSdLogLevel(level)) {
|
||||||
|
// Save to SD card
|
||||||
|
bool saved = _configManager.saveGeneralConfig();
|
||||||
|
|
||||||
|
if (saved) {
|
||||||
|
sendSuccessResponse("set_sd_log_level",
|
||||||
|
"SD log level set to " + String(level) + " and saved", context);
|
||||||
|
LOG_INFO("SD log level updated to %d (not yet implemented)", level);
|
||||||
|
} else {
|
||||||
|
sendErrorResponse("set_sd_log_level",
|
||||||
|
"Log level set but failed to save to SD card", context);
|
||||||
|
LOG_ERROR("Failed to save SD log level to SD card");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendErrorResponse("set_sd_log_level",
|
||||||
|
"Invalid log level (must be 0-5)", context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,4 +139,8 @@ private:
|
|||||||
|
|
||||||
// System Config
|
// System Config
|
||||||
void handleResetDefaultsCommand(const MessageContext& context);
|
void handleResetDefaultsCommand(const MessageContext& context);
|
||||||
|
|
||||||
|
// Log Level Commands
|
||||||
|
void handleSetSerialLogLevelCommand(JsonVariant contents, const MessageContext& context);
|
||||||
|
void handleSetSdLogLevelCommand(JsonVariant contents, const MessageContext& context);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ bool ConfigManager::begin() {
|
|||||||
LOG_INFO("ConfigManager: Creating default clock state file");
|
LOG_INFO("ConfigManager: Creating default clock state file");
|
||||||
saveClockState();
|
saveClockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!loadGeneralConfig()) {
|
||||||
|
LOG_INFO("ConfigManager: Creating default general config file");
|
||||||
|
saveGeneralConfig();
|
||||||
|
}
|
||||||
|
|
||||||
LOG_INFO("ConfigManager: Initialization complete - UID: %s, Hostname: %s",
|
LOG_INFO("ConfigManager: Initialization complete - UID: %s, Hostname: %s",
|
||||||
deviceConfig.deviceUID.c_str(), networkConfig.hostname.c_str());
|
deviceConfig.deviceUID.c_str(), networkConfig.hostname.c_str());
|
||||||
@@ -1000,3 +1005,77 @@ String ConfigManager::getAllSettingsAsJson() const {
|
|||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
// GENERAL CONFIGURATION - LOG LEVELS
|
||||||
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
bool ConfigManager::setSerialLogLevel(uint8_t level) {
|
||||||
|
if (level > 5) { // Max level is VERBOSE (5)
|
||||||
|
LOG_WARNING("ConfigManager: Invalid serial log level %d, valid range is 0-5", level);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
generalConfig.serialLogLevel = level;
|
||||||
|
LOG_INFO("ConfigManager: Serial log level set to %d", level);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::setSdLogLevel(uint8_t level) {
|
||||||
|
if (level > 5) { // Max level is VERBOSE (5)
|
||||||
|
LOG_WARNING("ConfigManager: Invalid SD log level %d, valid range is 0-5", level);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
generalConfig.sdLogLevel = level;
|
||||||
|
LOG_INFO("ConfigManager: SD log level set to %d", level);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::loadGeneralConfig() {
|
||||||
|
if (!ensureSDCard()) return false;
|
||||||
|
|
||||||
|
File file = SD.open("/settings/generalConfig.json", FILE_READ);
|
||||||
|
if (!file) {
|
||||||
|
LOG_WARNING("ConfigManager: General config file not found - using defaults");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticJsonDocument<256> doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, file);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
LOG_ERROR("ConfigManager: Failed to parse general config from SD: %s", error.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.containsKey("serialLogLevel")) {
|
||||||
|
generalConfig.serialLogLevel = doc["serialLogLevel"].as<uint8_t>();
|
||||||
|
}
|
||||||
|
if (doc.containsKey("sdLogLevel")) {
|
||||||
|
generalConfig.sdLogLevel = doc["sdLogLevel"].as<uint8_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("ConfigManager: General config loaded - Serial log level: %d, SD log level: %d",
|
||||||
|
generalConfig.serialLogLevel, generalConfig.sdLogLevel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigManager::saveGeneralConfig() {
|
||||||
|
if (!ensureSDCard()) return false;
|
||||||
|
|
||||||
|
StaticJsonDocument<256> doc;
|
||||||
|
doc["serialLogLevel"] = generalConfig.serialLogLevel;
|
||||||
|
doc["sdLogLevel"] = generalConfig.sdLogLevel;
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
size_t len = serializeJson(doc, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
if (len == 0 || len >= sizeof(buffer)) {
|
||||||
|
LOG_ERROR("ConfigManager: Failed to serialize general config JSON");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFileToSD("/settings", "generalConfig.json", buffer);
|
||||||
|
LOG_INFO("ConfigManager: General config saved");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -203,6 +203,18 @@ public:
|
|||||||
String nighttimeSilenceOffTime = "07:00"; // 🌙 End of nighttime silence
|
String nighttimeSilenceOffTime = "07:00"; // 🌙 End of nighttime silence
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct General Config
|
||||||
|
* @brief General configuration (loaded from SD)
|
||||||
|
*
|
||||||
|
* All clock settings are loaded from SD card at startup.
|
||||||
|
*/
|
||||||
|
struct GeneralConfig {
|
||||||
|
uint8_t serialLogLevel = 0;
|
||||||
|
uint8_t sdLogLevel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ═══════════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
// MEMBER VARIABLES - Clean deployment-ready storage
|
// MEMBER VARIABLES - Clean deployment-ready storage
|
||||||
@@ -215,6 +227,7 @@ private:
|
|||||||
UpdateConfig updateConfig;
|
UpdateConfig updateConfig;
|
||||||
BellConfig bellConfig;
|
BellConfig bellConfig;
|
||||||
ClockConfig clockConfig;
|
ClockConfig clockConfig;
|
||||||
|
GeneralConfig generalConfig;
|
||||||
|
|
||||||
bool sdInitialized = false;
|
bool sdInitialized = false;
|
||||||
std::vector<String> updateServers;
|
std::vector<String> updateServers;
|
||||||
@@ -286,6 +299,7 @@ public:
|
|||||||
const UpdateConfig& getUpdateConfig() const { return updateConfig; }
|
const UpdateConfig& getUpdateConfig() const { return updateConfig; }
|
||||||
const BellConfig& getBellConfig() const { return bellConfig; }
|
const BellConfig& getBellConfig() const { return bellConfig; }
|
||||||
const ClockConfig& getClockConfig() const { return clockConfig; }
|
const ClockConfig& getClockConfig() const { return clockConfig; }
|
||||||
|
const GeneralConfig& getGeneralConfig() const { return generalConfig; }
|
||||||
|
|
||||||
// Device identity methods (READ-ONLY - factory set via separate factory firmware)
|
// Device identity methods (READ-ONLY - factory set via separate factory firmware)
|
||||||
// These values are loaded ONCE at boot from NVS and kept in RAM
|
// These values are loaded ONCE at boot from NVS and kept in RAM
|
||||||
@@ -376,6 +390,12 @@ public:
|
|||||||
void setNighttimeSilenceOnTime(const String& time) { clockConfig.nighttimeSilenceOnTime = time; }
|
void setNighttimeSilenceOnTime(const String& time) { clockConfig.nighttimeSilenceOnTime = time; }
|
||||||
void setNighttimeSilenceOffTime(const String& time) { clockConfig.nighttimeSilenceOffTime = time; }
|
void setNighttimeSilenceOffTime(const String& time) { clockConfig.nighttimeSilenceOffTime = time; }
|
||||||
|
|
||||||
|
// General Config methods
|
||||||
|
bool setSerialLogLevel(uint8_t level);
|
||||||
|
bool setSdLogLevel(uint8_t level);
|
||||||
|
bool loadGeneralConfig();
|
||||||
|
bool saveGeneralConfig();
|
||||||
|
|
||||||
// Other methods (unchanged)
|
// Other methods (unchanged)
|
||||||
void updateClockAlerts(JsonVariant doc);
|
void updateClockAlerts(JsonVariant doc);
|
||||||
void updateClockBacklight(JsonVariant doc);
|
void updateClockBacklight(JsonVariant doc);
|
||||||
@@ -395,6 +415,7 @@ public:
|
|||||||
String getAPSSID() const { return networkConfig.apSsid; }
|
String getAPSSID() const { return networkConfig.apSsid; }
|
||||||
bool isHealthy() const;
|
bool isHealthy() const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get all configuration settings as a JSON string
|
* @brief Get all configuration settings as a JSON string
|
||||||
* @return JSON string containing all current settings
|
* @return JSON string containing all current settings
|
||||||
|
|||||||
@@ -368,12 +368,23 @@ void Player::onMelodyLoopCompleted() {
|
|||||||
// Check if it's time to pause playback
|
// Check if it's time to pause playback
|
||||||
bool Player::timeToPause(unsigned long now) {
|
bool Player::timeToPause(unsigned long now) {
|
||||||
if (isPlaying && continuous_loop) {
|
if (isPlaying && continuous_loop) {
|
||||||
uint64_t timeToPause = segmentStartTime + segment_duration;
|
// Special case: segment_duration = 0 means "one loop only"
|
||||||
LOG_DEBUG("PTL: %llu // NOW: %lu", timeToPause, now);
|
if (segment_duration == 0) {
|
||||||
if (now >= timeToPause && !isPaused) {
|
// Only pause after first loop completes (segmentCmpltTime updated)
|
||||||
LOG_DEBUG("(TimerFunction) Segment Duration Reached. Pausing.");
|
if (segmentCmpltTime > segmentStartTime && !isPaused) {
|
||||||
pauseTime = now;
|
LOG_DEBUG("(TimerFunction) One-loop segment completed. Pausing.");
|
||||||
return true;
|
pauseTime = now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal duration-based pausing
|
||||||
|
uint64_t timeToPause = segmentStartTime + segment_duration;
|
||||||
|
LOG_DEBUG("PTL: %llu // NOW: %lu", timeToPause, now);
|
||||||
|
if (now >= timeToPause && !isPaused) {
|
||||||
|
LOG_DEBUG("(TimerFunction) Segment Duration Reached. Pausing.");
|
||||||
|
pauseTime = now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -385,6 +396,7 @@ bool Player::timeToResume(unsigned long now) {
|
|||||||
uint64_t timeToResume = segmentCmpltTime + pause_duration;
|
uint64_t timeToResume = segmentCmpltTime + pause_duration;
|
||||||
if (now >= timeToResume) {
|
if (now >= timeToResume) {
|
||||||
LOG_DEBUG("(TimerFunction) Pause Duration Reached. Resuming");
|
LOG_DEBUG("(TimerFunction) Pause Duration Reached. Resuming");
|
||||||
|
segmentStartTime = now; // Reset segment start time for next cycle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
* 👨💻 AUTHOR: BellSystems bonamin
|
* 👨💻 AUTHOR: BellSystems bonamin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FW_VERSION "1.0"
|
#define FW_VERSION "1.2"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -70,6 +70,7 @@
|
|||||||
* 📅 VERSION HISTORY:
|
* 📅 VERSION HISTORY:
|
||||||
* ═══════════════════════════════════════════════════════════════════════════════
|
* ═══════════════════════════════════════════════════════════════════════════════
|
||||||
* v0.1 - Vesper Launch Beta
|
* v0.1 - Vesper Launch Beta
|
||||||
|
* v1.2 - Added Log Level Configuration via App/MQTT
|
||||||
* ═══════════════════════════════════════════════════════════════════════════════
|
* ═══════════════════════════════════════════════════════════════════════════════
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -201,6 +202,11 @@ void setup()
|
|||||||
// Initialize Configuration (loads factory identity from NVS + user settings from SD)
|
// Initialize Configuration (loads factory identity from NVS + user settings from SD)
|
||||||
configManager.begin();
|
configManager.begin();
|
||||||
|
|
||||||
|
// Apply log level from config (loaded from SD)
|
||||||
|
uint8_t logLevel = configManager.getGeneralConfig().serialLogLevel;
|
||||||
|
Logging::setLevel((Logging::LogLevel)logLevel);
|
||||||
|
LOG_INFO("Log level set to %d from configuration", logLevel);
|
||||||
|
|
||||||
inputManager.begin();
|
inputManager.begin();
|
||||||
inputManager.setFactoryResetLongPressCallback(handleFactoryReset);
|
inputManager.setFactoryResetLongPressCallback(handleFactoryReset);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user