From 06891e8d8245ea2791fcffa6a8e8c9ce5f60eadb Mon Sep 17 00:00:00 2001 From: bonamin Date: Sun, 26 Oct 2025 11:08:19 +0200 Subject: [PATCH] Fixed issue with Bell Assignments --- vesper/src/BellEngine/BellEngine.cpp | 2 +- .../CommandHandler/CommandHandler.cpp | 12 +++- vesper/src/ConfigManager/ConfigManager.cpp | 66 +++++++++++++++++++ vesper/src/ConfigManager/ConfigManager.hpp | 2 + vesper/src/Player/Player.cpp | 8 ++- 5 files changed, 85 insertions(+), 5 deletions(-) diff --git a/vesper/src/BellEngine/BellEngine.cpp b/vesper/src/BellEngine/BellEngine.cpp index ca37c4a..276ea1f 100644 --- a/vesper/src/BellEngine/BellEngine.cpp +++ b/vesper/src/BellEngine/BellEngine.cpp @@ -293,7 +293,7 @@ void BellEngine::activateNote(uint16_t note) { uint16_t durationMs = _configManager.getBellDuration(bellIndex); // Add to batch firing list - bellDurations.push_back({bellIndex, durationMs}); + bellDurations.push_back({physicalOutput, durationMs}); // Add to notification list (convert to 1-indexed for display) firedBellIndices.push_back(bellIndex + 1); diff --git a/vesper/src/Communication/CommandHandler/CommandHandler.cpp b/vesper/src/Communication/CommandHandler/CommandHandler.cpp index 5920223..1e8e835 100644 --- a/vesper/src/Communication/CommandHandler/CommandHandler.cpp +++ b/vesper/src/Communication/CommandHandler/CommandHandler.cpp @@ -358,9 +358,15 @@ void CommandHandler::handleSetRelayTimersCommand(JsonVariant contents, const Mes void CommandHandler::handleSetRelayOutputsCommand(JsonVariant contents, const MessageContext& context) { try { _configManager.updateBellOutputs(contents); - // Note: Bell outputs are typically not persisted to SD card as they're more of a mapping configuration - sendSuccessResponse("set_relay_outputs", "Relay outputs updated", context); - LOG_INFO("Relay outputs updated successfully"); + // Save bell outputs configuration to SD card for persistence + bool saved = _configManager.saveBellOutputs(); + if (saved) { + sendSuccessResponse("set_relay_outputs", "Relay outputs updated and saved", context); + LOG_INFO("Relay outputs updated and saved successfully"); + } else { + sendErrorResponse("set_relay_outputs", "Failed to save relay outputs to SD card", context); + LOG_ERROR("Failed to save relay outputs configuration"); + } } catch (...) { sendErrorResponse("set_relay_outputs", "Failed to update relay outputs", context); LOG_ERROR("Exception occurred while updating relay outputs"); diff --git a/vesper/src/ConfigManager/ConfigManager.cpp b/vesper/src/ConfigManager/ConfigManager.cpp index 2c029ad..af77a86 100644 --- a/vesper/src/ConfigManager/ConfigManager.cpp +++ b/vesper/src/ConfigManager/ConfigManager.cpp @@ -87,6 +87,12 @@ bool ConfigManager::begin() { LOG_INFO("ConfigManager: Creating default bell durations file"); saveBellDurations(); } + + // Load bell outputs, save defaults if not found + if (!loadBellOutputs()) { + LOG_INFO("ConfigManager: Creating default bell outputs file"); + saveBellOutputs(); + } // Load clock config, save defaults if not found if (!loadClockConfig()) { @@ -373,6 +379,60 @@ bool ConfigManager::saveBellDurations() { return true; } +bool ConfigManager::loadBellOutputs() { + if (!ensureSDCard()) { + LOG_ERROR("ConfigManager: SD Card not initialized. Using default bell outputs (1:1 mapping)."); + return false; + } + + File file = SD.open("/settings/bellOutputs.json", FILE_READ); + if (!file) { + LOG_WARNING("ConfigManager: Bell outputs file not found on SD. Using default 1:1 mapping."); + return false; + } + + StaticJsonDocument<512> doc; + DeserializationError error = deserializeJson(doc, file); + file.close(); + + if (error) { + LOG_ERROR("ConfigManager: Failed to parse bell outputs from SD. Using defaults."); + return false; + } + + for (uint8_t i = 0; i < 16; i++) { + String key = String("b") + (i + 1); + if (doc.containsKey(key)) { + bellConfig.outputs[i] = doc[key].as(); // Already 0-indexed in file + } + } + + LOG_INFO("ConfigManager: Bell outputs loaded from SD"); + return true; +} + +bool ConfigManager::saveBellOutputs() { + if (!ensureSDCard()) return false; + + StaticJsonDocument<512> doc; + for (uint8_t i = 0; i < 16; i++) { + String key = String("b") + (i + 1); + doc[key] = bellConfig.outputs[i]; // Save 0-indexed outputs + } + + char buffer[512]; + size_t len = serializeJson(doc, buffer, sizeof(buffer)); + + if (len == 0 || len >= sizeof(buffer)) { + LOG_ERROR("ConfigManager: Failed to serialize bell outputs JSON"); + return false; + } + + saveFileToSD("/settings", "bellOutputs.json", buffer); + LOG_INFO("ConfigManager: Bell outputs saved to SD"); + return true; +} + void ConfigManager::updateBellDurations(JsonVariant doc) { for (uint8_t i = 0; i < 16; i++) { String key = String("b") + (i + 1); @@ -388,11 +448,16 @@ void ConfigManager::updateBellOutputs(JsonVariant doc) { String key = String("b") + (i + 1); if (doc.containsKey(key)) { bellConfig.outputs[i] = doc[key].as() - 1; + LOG_VERBOSE("ConfigManager: Bell %d output set to %d", i + 1, bellConfig.outputs[i]); } } LOG_INFO("ConfigManager: Updated bell outputs"); } + + + + uint16_t ConfigManager::getBellDuration(uint8_t bellIndex) const { if (bellIndex >= 16) return 90; return bellConfig.durations[bellIndex]; @@ -829,6 +894,7 @@ bool ConfigManager::resetAllToDefaults() { "/settings/deviceConfig.json", "/settings/networkConfig.json", "/settings/relayTimings.json", + "/settings/bellOutputs.json", // <-- ADD THIS LINE "/settings/clockConfig.json", "/settings/clockState.json", "/settings/updateServers.json" diff --git a/vesper/src/ConfigManager/ConfigManager.hpp b/vesper/src/ConfigManager/ConfigManager.hpp index 0adba47..3a8bdfb 100644 --- a/vesper/src/ConfigManager/ConfigManager.hpp +++ b/vesper/src/ConfigManager/ConfigManager.hpp @@ -324,6 +324,8 @@ public: // Bell and clock configuration methods (unchanged) bool loadBellDurations(); bool saveBellDurations(); + bool loadBellOutputs(); + bool saveBellOutputs(); void updateBellDurations(JsonVariant doc); void updateBellOutputs(JsonVariant doc); uint16_t getBellDuration(uint8_t bellIndex) const; diff --git a/vesper/src/Player/Player.cpp b/vesper/src/Player/Player.cpp index b1be311..e7ad096 100644 --- a/vesper/src/Player/Player.cpp +++ b/vesper/src/Player/Player.cpp @@ -294,7 +294,13 @@ void Player::durationTimerCallback(TimerHandle_t xTimer) { // Check if it's time to stop playback bool Player::timeToStop(unsigned long now) { - if (isPlaying && !infinite_play) { + if (isPlaying && !infinite_play && total_duration == 0) { + if (now > startTime){} + LOG_DEBUG("(Single Loop Run Seelected) Soft Stopping."); + return true; + } + } + else if (isPlaying && !infinite_play) { uint64_t stopTime = startTime + total_duration; if (now >= stopTime) { LOG_DEBUG("(TimerFunction) Total Run Duration Reached. Soft Stopping.");