feat: Add per-subsystem log tags to all firmware modules

Refactored logging system to require a TAG as first argument on all
LOG_* macros, enabling per-subsystem log filtering and cleaner output.
Each subsystem now defines its own TAG (e.g. "BellEngine", "Player").
Also overhauled Logging.hpp/cpp with improved level control and output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 17:31:28 +02:00
parent c656835d8e
commit fe6b1d871a
26 changed files with 1334 additions and 1074 deletions

View File

@@ -1,4 +1,6 @@
#include "Player.hpp"
#define TAG "Player"
#include "../Communication/CommunicationRouter/CommunicationRouter.hpp"
#include "../BellEngine/BellEngine.hpp"
#include "../Telemetry/Telemetry.hpp"
@@ -85,7 +87,7 @@ Player::~Player() {
}
void Player::begin() {
LOG_INFO("Initializing Player with FreeRTOS Timer (saves 4KB RAM!)");
LOG_INFO(TAG, "Initializing Player with FreeRTOS Timer (saves 4KB RAM!)");
// Create a periodic timer that fires every 500ms
_durationTimerHandle = xTimerCreate(
@@ -98,22 +100,22 @@ void Player::begin() {
if (_durationTimerHandle != NULL) {
xTimerStart(_durationTimerHandle, 0);
LOG_INFO("Player initialized successfully with timer");
LOG_INFO(TAG, "Player initialized successfully with timer");
} else {
LOG_ERROR("Failed to create Player timer!");
LOG_ERROR(TAG, "Failed to create Player timer!");
}
}
void Player::play() {
if (_melodySteps.empty()) {
LOG_ERROR("Cannot play: No melody loaded");
LOG_ERROR(TAG, "Cannot play: No melody loaded");
return;
}
// 🔥 CRITICAL: Interrupt any active clock alerts - user playback has priority!
if (_timekeeper) {
_timekeeper->interruptActiveAlert();
LOG_DEBUG("Player: Interrupted any active clock alerts");
LOG_DEBUG(TAG, "Player: Interrupted any active clock alerts");
}
if (_bellEngine) {
@@ -125,7 +127,7 @@ void Player::play() {
hardStop = false;
startTime = segmentStartTime = millis();
setStatus(PlayerStatus::PLAYING); // Update status and notify clients
LOG_DEBUG("Plbck: PLAY");
LOG_DEBUG(TAG, "Plbck: PLAY");
}
void Player::forceStop() {
@@ -142,7 +144,7 @@ void Player::forceStop() {
_telemetry->saveStrikeCounters();
}
LOG_DEBUG("Plbck: FORCE STOP");
LOG_DEBUG(TAG, "Plbck: FORCE STOP");
}
void Player::stop() {
@@ -162,10 +164,10 @@ void Player::stop() {
_telemetry->saveStrikeCounters();
}
LOG_DEBUG("Plbck: STOP from PAUSED state");
LOG_DEBUG(TAG, "Plbck: STOP from PAUSED state");
} else {
setStatus(PlayerStatus::STOPPING);
LOG_DEBUG("Plbck: SOFT STOP (waiting for melody to complete)");
LOG_DEBUG(TAG, "Plbck: SOFT STOP (waiting for melody to complete)");
}
// NOTE: The actual "stop" message is now sent in onMelodyLoopCompleted()
// when the BellEngine actually finishes the current loop
@@ -174,14 +176,14 @@ void Player::stop() {
void Player::pause() {
isPaused = true;
setStatus(PlayerStatus::PAUSED);
LOG_DEBUG("Plbck: PAUSE");
LOG_DEBUG(TAG, "Plbck: PAUSE");
}
void Player::unpause() {
isPaused = false;
segmentStartTime = millis();
setStatus(PlayerStatus::PLAYING);
LOG_DEBUG("Plbck: RESUME");
LOG_DEBUG(TAG, "Plbck: RESUME");
}
bool Player::command(JsonVariant data) {
@@ -189,7 +191,7 @@ bool Player::command(JsonVariant data) {
loadMelodyInRAM(); // Removed parameter - use internal storage
String action = data["action"];
LOG_DEBUG("Incoming Command: %s", action.c_str());
LOG_DEBUG(TAG, "Incoming Command: %s", action.c_str());
// Play or Stop Logic
if (action == "play") {
@@ -199,7 +201,7 @@ bool Player::command(JsonVariant data) {
forceStop();
return true;
} else {
LOG_WARNING("Unknown playback action: %s", action.c_str());
LOG_WARNING(TAG, "Unknown playback action: %s", action.c_str());
return false;
}
}
@@ -245,10 +247,10 @@ void Player::setMelodyAttributes(JsonVariant doc) {
}
// Print Just for Debugging Purposes
LOG_DEBUG("Set Melody Vars / Name: %s, UID: %s",
LOG_DEBUG(TAG, "Set Melody Vars / Name: %s, UID: %s",
name.c_str(), uid.c_str());
LOG_DEBUG("URL: %s", url.c_str());
LOG_DEBUG("Speed: %d, Per Segment Duration: %lu, Pause Duration: %lu, Total Duration: %d, Continuous: %s, Infinite: %s",
LOG_DEBUG(TAG, "URL: %s", url.c_str());
LOG_DEBUG(TAG, "Speed: %d, Per Segment Duration: %lu, Pause Duration: %lu, Total Duration: %d, Continuous: %s, Infinite: %s",
speed, segment_duration, pause_duration, total_duration,
continuous_loop ? "true" : "false", infinite_play ? "true" : "false");
}
@@ -258,13 +260,13 @@ void Player::loadMelodyInRAM() {
// 🎵 PRIORITY 1: Check if this is a built-in melody
if (BuiltInMelodies::isBuiltInMelody(uidStr)) {
LOG_INFO("Loading built-in melody: %s", uidStr.c_str());
LOG_INFO(TAG, "Loading built-in melody: %s", uidStr.c_str());
if (BuiltInMelodies::loadBuiltInMelody(uidStr, _melodySteps)) {
LOG_INFO("✅ Built-in melody loaded successfully: %d steps", _melodySteps.size());
LOG_INFO(TAG, "✅ Built-in melody loaded successfully: %d steps", _melodySteps.size());
return;
} else {
LOG_ERROR("Failed to load built-in melody: %s", uidStr.c_str());
LOG_ERROR(TAG, "Failed to load built-in melody: %s", uidStr.c_str());
return;
}
}
@@ -274,8 +276,8 @@ void Player::loadMelodyInRAM() {
File bin_file = SD.open(filePath.c_str(), FILE_READ);
if (!bin_file) {
LOG_ERROR("Failed to open file: %s", filePath.c_str());
LOG_ERROR("Check Servers for the File...");
LOG_ERROR(TAG, "Failed to open file: %s", filePath.c_str());
LOG_ERROR(TAG, "Check Servers for the File...");
// Try to download the file using FileManager
if (_fileManager) {
@@ -284,20 +286,20 @@ void Player::loadMelodyInRAM() {
doc["melodys_uid"] = uid;
if (!_fileManager->addMelody(doc)) {
LOG_ERROR("Failed to Download File. Check Internet Connection");
LOG_ERROR(TAG, "Failed to Download File. Check Internet Connection");
return;
} else {
bin_file = SD.open(filePath.c_str(), FILE_READ);
}
} else {
LOG_ERROR("FileManager not available for download");
LOG_ERROR(TAG, "FileManager not available for download");
return;
}
}
size_t fileSize = bin_file.size();
if (fileSize % 2 != 0) {
LOG_ERROR("Invalid file size: %u (not a multiple of 2)", fileSize);
LOG_ERROR(TAG, "Invalid file size: %u (not a multiple of 2)", fileSize);
bin_file.close();
return;
}
@@ -311,7 +313,7 @@ void Player::loadMelodyInRAM() {
_melodySteps[i] = (high << 8) | low;
}
LOG_INFO("Melody loaded successfully from SD: %d steps", _melodySteps.size());
LOG_INFO(TAG, "Melody loaded successfully from SD: %d steps", _melodySteps.size());
bin_file.close();
}
@@ -341,7 +343,7 @@ bool Player::timeToStop(unsigned long now) {
if (isPlaying && !infinite_play) {
uint64_t stopTime = startTime + total_duration;
if (now >= stopTime) {
LOG_DEBUG("(TimerFunction) Total Run Duration Reached. Soft Stopping.");
LOG_DEBUG(TAG, "(TimerFunction) Total Run Duration Reached. Soft Stopping.");
return true;
}
}
@@ -392,7 +394,7 @@ void Player::setStatus(PlayerStatus newStatus) {
// 🔥 Use broadcastStatus() to send to BOTH WebSocket AND MQTT clients!
_commManager->broadcastStatus(doc);
LOG_DEBUG("Status changed: %d → %d, broadcast sent with runTime: %llu",
LOG_DEBUG(TAG, "Status changed: %d → %d, broadcast sent with runTime: %llu",
(int)oldStatus, (int)newStatus, projectedRunTime);
}
}
@@ -402,7 +404,7 @@ void Player::onMelodyLoopCompleted() {
if (_status == PlayerStatus::STOPPING) {
// We were in soft stop mode, now actually stop
setStatus(PlayerStatus::STOPPED);
LOG_DEBUG("Plbck: ACTUAL STOP (melody loop completed)");
LOG_DEBUG(TAG, "Plbck: ACTUAL STOP (melody loop completed)");
}
// Mark segment completion time
@@ -413,9 +415,9 @@ void Player::onMelodyLoopCompleted() {
bool Player::timeToPause(unsigned long now) {
if (isPlaying && continuous_loop) {
uint64_t timeToPause = segmentStartTime + segment_duration;
LOG_DEBUG("PTL: %llu // NOW: %lu", timeToPause, now);
LOG_DEBUG(TAG, "PTL: %llu // NOW: %lu", timeToPause, now);
if (now >= timeToPause && !isPaused) {
LOG_DEBUG("(TimerFunction) Segment Duration Reached. Pausing.");
LOG_DEBUG(TAG, "(TimerFunction) Segment Duration Reached. Pausing.");
pauseTime = now;
return true;
}
@@ -428,7 +430,7 @@ bool Player::timeToResume(unsigned long now) {
if (isPaused) {
uint64_t timeToResume = segmentCmpltTime + pause_duration;
if (now >= timeToResume) {
LOG_DEBUG("(TimerFunction) Pause Duration Reached. Resuming");
LOG_DEBUG(TAG, "(TimerFunction) Pause Duration Reached. Resuming");
segmentStartTime = now; // Reset segment start time for next cycle
return true;
}
@@ -466,35 +468,35 @@ uint64_t Player::calculateProjectedRunTime() const {
bool Player::isHealthy() const {
// Check if dependencies are properly set
if (!_commManager) {
LOG_DEBUG("Player: Unhealthy - Communication manager not set");
LOG_DEBUG(TAG, "Player: Unhealthy - Communication manager not set");
return false;
}
if (!_fileManager) {
LOG_DEBUG("Player: Unhealthy - File manager not set");
LOG_DEBUG(TAG, "Player: Unhealthy - File manager not set");
return false;
}
if (!_bellEngine) {
LOG_DEBUG("Player: Unhealthy - BellEngine not set");
LOG_DEBUG(TAG, "Player: Unhealthy - BellEngine not set");
return false;
}
// Check if timer is properly created
if (_durationTimerHandle == NULL) {
LOG_DEBUG("Player: Unhealthy - Duration timer not created");
LOG_DEBUG(TAG, "Player: Unhealthy - Duration timer not created");
return false;
}
// Check if timer is actually running
if (xTimerIsTimerActive(_durationTimerHandle) == pdFALSE) {
LOG_DEBUG("Player: Unhealthy - Duration timer not active");
LOG_DEBUG(TAG, "Player: Unhealthy - Duration timer not active");
return false;
}
// Check for consistent playback state
if (isPlaying && (_status == PlayerStatus::STOPPED)) {
LOG_DEBUG("Player: Unhealthy - Inconsistent playback state");
LOG_DEBUG(TAG, "Player: Unhealthy - Inconsistent playback state");
return false;
}