v1.8.0: Refonte UX update firmware (progress bar live + streaming logs)
L'ancien flow etait un AJAX bloquant qui attendait ~90s sans aucun retour visuel autre qu'un spinner. Nouveau flow: - Backend: launcher.php lance update_firmware.sh en background (route update_firmware_start) et expose une route de polling incremental (update_firmware_progress) avec offset. - Frontend: progress bar Bootstrap animee + label de l'etape en cours + timer mm:ss / estimation, plus streaming des logs toutes les 700ms. - Sous-etape Step 3c (la plus longue): interpolation fine de la progression en comptant les 'Started X' (services demarres). - Logs techniques masques par defaut dans <details>, ouverts automatiquement en cas d'echec pour faciliter le debug. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -418,7 +418,7 @@ if ($type == "update_firmware") {
|
||||
// Execute the comprehensive update script
|
||||
$command = 'sudo /var/www/nebuleair_pro_4g/update_firmware.sh 2>&1';
|
||||
$output = shell_exec($command);
|
||||
|
||||
|
||||
// Return the output as JSON for better web display
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
@@ -428,6 +428,71 @@ if ($type == "update_firmware") {
|
||||
]);
|
||||
}
|
||||
|
||||
// Start firmware update in background, returns immediately so the UI can poll progress.
|
||||
// Output is written to a temp log file. A 'done' marker file is created when finished.
|
||||
if ($type == "update_firmware_start") {
|
||||
$logFile = '/tmp/nebuleair_firmware_update.log';
|
||||
$doneFile = '/tmp/nebuleair_firmware_update.done';
|
||||
|
||||
// Reset previous run markers
|
||||
@file_put_contents($logFile, '');
|
||||
@unlink($doneFile);
|
||||
|
||||
// Launch in background:
|
||||
// - run the update script, capture stdout/stderr into log
|
||||
// - append "EXIT_CODE=N" so the UI can detect success/failure
|
||||
// - touch the done file so the UI knows the run finished
|
||||
// - detach all stdio from PHP so this call returns immediately
|
||||
$cmd = '(sudo /var/www/nebuleair_pro_4g/update_firmware.sh > '
|
||||
. escapeshellarg($logFile) . ' 2>&1; '
|
||||
. 'echo "EXIT_CODE=$?" >> ' . escapeshellarg($logFile) . '; '
|
||||
. 'touch ' . escapeshellarg($doneFile) . ') > /dev/null 2>&1 &';
|
||||
shell_exec($cmd);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'started_at' => time(),
|
||||
'log_file' => $logFile
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Poll firmware update progress. The UI sends the byte offset it has already read,
|
||||
// we return any new content since that offset and whether the run has finished.
|
||||
if ($type == "update_firmware_progress") {
|
||||
$logFile = '/tmp/nebuleair_firmware_update.log';
|
||||
$doneFile = '/tmp/nebuleair_firmware_update.done';
|
||||
|
||||
$offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
|
||||
|
||||
$content = '';
|
||||
$newOffset = $offset;
|
||||
if (file_exists($logFile)) {
|
||||
$size = filesize($logFile);
|
||||
if ($size > $offset) {
|
||||
$fp = fopen($logFile, 'r');
|
||||
if ($fp) {
|
||||
fseek($fp, $offset);
|
||||
$content = fread($fp, $size - $offset);
|
||||
fclose($fp);
|
||||
}
|
||||
$newOffset = $size;
|
||||
}
|
||||
}
|
||||
|
||||
$done = file_exists($doneFile);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'content' => $content,
|
||||
'offset' => $newOffset,
|
||||
'done' => $done
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($type == "upload_firmware") {
|
||||
// Firmware update via ZIP file upload (offline mode)
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
|
||||
Reference in New Issue
Block a user