Added Reboot and Manual FW Update commands
This commit is contained in:
@@ -1035,6 +1035,12 @@ void CommandHandler::handleSystemCommand(JsonVariant contents, const MessageCont
|
|||||||
handleSetMqttLogLevelCommand(contents, context);
|
handleSetMqttLogLevelCommand(contents, context);
|
||||||
} else if (action == "set_mqtt_enabled") {
|
} else if (action == "set_mqtt_enabled") {
|
||||||
handleSetMqttEnabledCommand(contents, context);
|
handleSetMqttEnabledCommand(contents, context);
|
||||||
|
} else if (action == "restart" || action == "reboot") {
|
||||||
|
handleRestartCommand(context);
|
||||||
|
} else if (action == "force_update") {
|
||||||
|
handleForceUpdateCommand(contents, context);
|
||||||
|
} else if (action == "custom_update") {
|
||||||
|
handleCustomUpdateCommand(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);
|
||||||
@@ -1172,3 +1178,103 @@ void CommandHandler::handleSetMqttEnabledCommand(JsonVariant contents, const Mes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
// RESTART COMMAND
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
void CommandHandler::handleRestartCommand(const MessageContext& context) {
|
||||||
|
LOG_WARNING("🔄 Device restart requested via command");
|
||||||
|
sendSuccessResponse("restart", "Device will restart in 2 seconds", context);
|
||||||
|
|
||||||
|
// Small delay to ensure response is sent
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
// Restart the ESP32
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
// FORCE UPDATE COMMAND
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
void CommandHandler::handleForceUpdateCommand(JsonVariant contents, const MessageContext& context) {
|
||||||
|
LOG_WARNING("🔄 Force OTA update requested via command");
|
||||||
|
|
||||||
|
// Check if player is active
|
||||||
|
if (_player && _player->isPlaying()) {
|
||||||
|
sendErrorResponse("force_update", "Cannot update while playback is active", context);
|
||||||
|
LOG_WARNING("Force update rejected - player is active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get optional channel parameter (defaults to "stable")
|
||||||
|
String channel = "stable";
|
||||||
|
if (contents.containsKey("channel")) {
|
||||||
|
channel = contents["channel"].as<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSuccessResponse("force_update",
|
||||||
|
"Starting forced OTA update from channel: " + channel + ". Device may reboot.", context);
|
||||||
|
|
||||||
|
// Small delay to ensure response is sent
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Perform the update
|
||||||
|
bool result = _otaManager.performManualUpdate(channel);
|
||||||
|
|
||||||
|
// Note: If update succeeds, device will reboot and this won't be reached
|
||||||
|
if (!result) {
|
||||||
|
LOG_ERROR("Force update failed");
|
||||||
|
// Error response may not be received if we already restarted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
// CUSTOM UPDATE COMMAND
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
void CommandHandler::handleCustomUpdateCommand(JsonVariant contents, const MessageContext& context) {
|
||||||
|
LOG_WARNING("🔥 Custom OTA update requested via command");
|
||||||
|
|
||||||
|
// Validate required parameters
|
||||||
|
if (!contents.containsKey("firmware_url")) {
|
||||||
|
sendErrorResponse("custom_update", "Missing firmware_url parameter", context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String firmwareUrl = contents["firmware_url"].as<String>();
|
||||||
|
|
||||||
|
// Optional parameters
|
||||||
|
String checksum = contents.containsKey("checksum") ?
|
||||||
|
contents["checksum"].as<String>() : "";
|
||||||
|
size_t fileSize = contents.containsKey("file_size") ?
|
||||||
|
contents["file_size"].as<size_t>() : 0;
|
||||||
|
|
||||||
|
// Check if player is active
|
||||||
|
if (_player && _player->isPlaying()) {
|
||||||
|
sendErrorResponse("custom_update", "Cannot update while playback is active", context);
|
||||||
|
LOG_WARNING("Custom update rejected - player is active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Custom update: URL=%s, Checksum=%s, Size=%u",
|
||||||
|
firmwareUrl.c_str(),
|
||||||
|
checksum.isEmpty() ? "none" : checksum.c_str(),
|
||||||
|
fileSize);
|
||||||
|
|
||||||
|
sendSuccessResponse("custom_update",
|
||||||
|
"Starting custom OTA update. Device may reboot.", context);
|
||||||
|
|
||||||
|
// Small delay to ensure response is sent
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Perform the custom update
|
||||||
|
bool result = _otaManager.performCustomUpdate(firmwareUrl, checksum, fileSize);
|
||||||
|
|
||||||
|
// Note: If update succeeds, device will reboot and this won't be reached
|
||||||
|
if (!result) {
|
||||||
|
LOG_ERROR("Custom update failed");
|
||||||
|
// Error response may not be received if we already restarted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,4 +153,9 @@ private:
|
|||||||
|
|
||||||
// MQTT Control Commands
|
// MQTT Control Commands
|
||||||
void handleSetMqttEnabledCommand(JsonVariant contents, const MessageContext& context);
|
void handleSetMqttEnabledCommand(JsonVariant contents, const MessageContext& context);
|
||||||
|
|
||||||
|
// Device Control Commands
|
||||||
|
void handleRestartCommand(const MessageContext& context);
|
||||||
|
void handleForceUpdateCommand(JsonVariant contents, const MessageContext& context);
|
||||||
|
void handleCustomUpdateCommand(JsonVariant contents, const MessageContext& context);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -701,6 +701,54 @@ bool OTAManager::performManualUpdate(const String& channel) {
|
|||||||
return installFromSD("/firmware/staged_update.bin");
|
return installFromSD("/firmware/staged_update.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
// CUSTOM FIRMWARE UPDATE
|
||||||
|
// ════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
bool OTAManager::performCustomUpdate(const String& firmwareUrl, const String& checksum, size_t fileSize) {
|
||||||
|
if (_status != Status::IDLE) {
|
||||||
|
LOG_WARNING("OTA update already in progress");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if player is active
|
||||||
|
if (isPlayerActive()) {
|
||||||
|
LOG_ERROR("Cannot perform custom update: Player is active");
|
||||||
|
setStatus(Status::FAILED, ErrorCode::PLAYER_ACTIVE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("🔥 Starting CUSTOM firmware update...");
|
||||||
|
LOG_INFO(" URL: %s", firmwareUrl.c_str());
|
||||||
|
LOG_INFO(" Checksum: %s", checksum.isEmpty() ? "NOT PROVIDED" : checksum.c_str());
|
||||||
|
LOG_INFO(" File Size: %u bytes", fileSize);
|
||||||
|
|
||||||
|
if (checksum.isEmpty()) {
|
||||||
|
LOG_WARNING("⚠️ No checksum provided - update will proceed without verification!");
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(Status::DOWNLOADING);
|
||||||
|
|
||||||
|
// Download firmware from custom URL to SD
|
||||||
|
if (!downloadToSD(firmwareUrl, checksum, fileSize)) {
|
||||||
|
LOG_ERROR("Custom firmware download failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("✅ Custom firmware downloaded successfully");
|
||||||
|
|
||||||
|
// Install from SD
|
||||||
|
bool result = installFromSD("/firmware/staged_update.bin");
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
LOG_INFO("🚀 Custom firmware installed - device will reboot");
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("❌ Custom firmware installation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Hardware variant management
|
// Hardware variant management
|
||||||
String OTAManager::getHardwareVariant() const {
|
String OTAManager::getHardwareVariant() const {
|
||||||
return _configManager.getHardwareVariant();
|
return _configManager.getHardwareVariant();
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ public:
|
|||||||
void checkFirmwareUpdateFromSD(); // Check SD for firmware update
|
void checkFirmwareUpdateFromSD(); // Check SD for firmware update
|
||||||
bool performManualUpdate(); // Manual update triggered by app
|
bool performManualUpdate(); // Manual update triggered by app
|
||||||
bool performManualUpdate(const String& channel); // Manual update from specific channel
|
bool performManualUpdate(const String& channel); // Manual update from specific channel
|
||||||
|
bool performCustomUpdate(const String& firmwareUrl, const String& checksum = "", size_t fileSize = 0); // Custom firmware update
|
||||||
|
|
||||||
// Hardware identification
|
// Hardware identification
|
||||||
String getHardwareVariant() const;
|
String getHardwareVariant() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user