Complete Rebuild, with Subsystems for each component. RTOS Tasks. (help by Claude)

This commit is contained in:
2025-10-01 12:42:00 +03:00
parent 104c1d04d4
commit f696984cd1
57 changed files with 11757 additions and 2290 deletions

View File

@@ -0,0 +1,227 @@
#include "Telemetry.hpp"
#include "../Communication/Communication.hpp"
void Telemetry::begin() {
// Initialize arrays
for (uint8_t i = 0; i < 16; i++) {
strikeCounters[i] = 0;
bellLoad[i] = 0;
bellMaxLoad[i] = 60; // Default max load
}
coolingActive = false;
// Create the telemetry task
xTaskCreatePinnedToCore(telemetryTask, "TelemetryTask", 4096, this, 2, &telemetryTaskHandle, 1);
LOG_INFO("Telemetry initialized");
}
void Telemetry::setPlayerReference(bool* isPlayingPtr) {
playerIsPlayingPtr = isPlayingPtr;
LOG_DEBUG("Player reference set");
}
void Telemetry::setForceStopCallback(void (*callback)()) {
forceStopCallback = callback;
LOG_DEBUG("Force stop callback set");
}
void Telemetry::recordBellStrike(uint8_t bellIndex) {
if (bellIndex >= 16) {
LOG_ERROR("Invalid bell index: %d", bellIndex);
return;
}
// Critical section - matches your original code
portENTER_CRITICAL(&telemetrySpinlock);
strikeCounters[bellIndex]++; // Count strikes per bell (warranty)
bellLoad[bellIndex]++; // Load per bell (heat simulation)
coolingActive = true; // System needs cooling
portEXIT_CRITICAL(&telemetrySpinlock);
}
uint32_t Telemetry::getStrikeCount(uint8_t bellIndex) {
if (bellIndex >= 16) {
LOG_ERROR("Invalid bell index: %d", bellIndex);
return 0;
}
return strikeCounters[bellIndex];
}
void Telemetry::resetStrikeCounters() {
portENTER_CRITICAL(&telemetrySpinlock);
for (uint8_t i = 0; i < 16; i++) {
strikeCounters[i] = 0;
}
portEXIT_CRITICAL(&telemetrySpinlock);
LOG_WARNING("Strike counters reset by user");
}
uint16_t Telemetry::getBellLoad(uint8_t bellIndex) {
if (bellIndex >= 16) {
LOG_ERROR("Invalid bell index: %d", bellIndex);
return 0;
}
return bellLoad[bellIndex];
}
void Telemetry::setBellMaxLoad(uint8_t bellIndex, uint16_t maxLoad) {
if (bellIndex >= 16) {
LOG_ERROR("Invalid bell index: %d", bellIndex);
return;
}
bellMaxLoad[bellIndex] = maxLoad;
LOG_INFO("Bell %d max load set to %d", bellIndex, maxLoad);
}
bool Telemetry::isOverloaded(uint8_t bellIndex) {
if (bellIndex >= 16) {
LOG_ERROR("Invalid bell index: %d", bellIndex);
return false;
}
return bellLoad[bellIndex] > bellMaxLoad[bellIndex];
}
bool Telemetry::isCoolingActive() {
return coolingActive;
}
void Telemetry::logTemperature(float temperature) {
// Future implementation for temperature logging
LOG_INFO("Temperature: %.2f°C", temperature);
}
void Telemetry::logVibration(float vibration) {
// Future implementation for vibration logging
LOG_INFO("Vibration: %.2f", vibration);
}
void Telemetry::checkBellLoads() {
coolingActive = false; // Reset cooling flag
// Collect overloaded bells for batch notification
std::vector<uint8_t> criticalBells;
std::vector<uint16_t> criticalLoads;
std::vector<uint8_t> warningBells;
std::vector<uint16_t> warningLoads;
bool anyOverload = false;
for (uint8_t i = 0; i < 16; i++) {
if (bellLoad[i] > 0) {
bellLoad[i]--;
coolingActive = true; // Still has heat left
}
// Check for critical overload (90% of max load)
uint16_t criticalThreshold = (bellMaxLoad[i] * 90) / 100;
// Check for warning overload (60% of max load)
uint16_t warningThreshold = (bellMaxLoad[i] * 60) / 100;
// Critical overload - protection kicks in
if (bellLoad[i] > bellMaxLoad[i]) {
LOG_ERROR("Bell %d OVERLOADED! load=%d max=%d",
i, bellLoad[i], bellMaxLoad[i]);
criticalBells.push_back(i);
criticalLoads.push_back(bellLoad[i]);
anyOverload = true;
} else if (bellLoad[i] > criticalThreshold) {
// Critical warning - approaching overload
LOG_WARNING("Bell %d approaching overload! load=%d (critical threshold=%d)",
i, bellLoad[i], criticalThreshold);
criticalBells.push_back(i);
criticalLoads.push_back(bellLoad[i]);
} else if (bellLoad[i] > warningThreshold) {
// Warning - moderate load
LOG_INFO("Bell %d moderate load warning! load=%d (warning threshold=%d)",
i, bellLoad[i], warningThreshold);
warningBells.push_back(i);
warningLoads.push_back(bellLoad[i]);
}
}
// Send batch notifications if any bells are overloaded
if (!criticalBells.empty()) {
String severity = anyOverload ? "critical" : "warning";
if (Communication::_instance) {
Communication::_instance->sendBellOverloadNotification(criticalBells, criticalLoads, severity);
}
} else if (!warningBells.empty()) {
if (Communication::_instance) {
Communication::_instance->sendBellOverloadNotification(warningBells, warningLoads, "warning");
}
}
// Trigger force stop if any bell is actually overloaded
if (anyOverload && forceStopCallback != nullptr) {
forceStopCallback();
}
}
void Telemetry::telemetryTask(void* parameter) {
Telemetry* telemetry = static_cast<Telemetry*>(parameter);
LOG_INFO("Telemetry task started");
while(1) {
// Only run if player is playing OR we're still cooling
bool isPlaying = (telemetry->playerIsPlayingPtr != nullptr) ?
*(telemetry->playerIsPlayingPtr) : false;
if (isPlaying || telemetry->coolingActive) {
telemetry->checkBellLoads();
}
vTaskDelay(pdMS_TO_TICKS(1000)); // Run every 1s
}
}
// ════════════════════════════════════════════════════════════════════════════
// HEALTH CHECK IMPLEMENTATION
// ════════════════════════════════════════════════════════════════════════════
bool Telemetry::isHealthy() const {
// Check if telemetry task is created and running
if (telemetryTaskHandle == NULL) {
LOG_DEBUG("Telemetry: Unhealthy - Task not created");
return false;
}
// Check if task is still alive
eTaskState taskState = eTaskGetState(telemetryTaskHandle);
if (taskState == eDeleted || taskState == eInvalid) {
LOG_DEBUG("Telemetry: Unhealthy - Task deleted or invalid");
return false;
}
// Check if player reference is set
if (playerIsPlayingPtr == nullptr) {
LOG_DEBUG("Telemetry: Unhealthy - Player reference not set");
return false;
}
// Check for any critical overloads that would indicate system stress
bool hasCriticalOverload = false;
for (uint8_t i = 0; i < 16; i++) {
if (bellLoad[i] > bellMaxLoad[i]) {
hasCriticalOverload = true;
break;
}
}
if (hasCriticalOverload) {
LOG_DEBUG("Telemetry: Unhealthy - Critical bell overload detected");
return false;
}
return true;
}