{"id":785,"date":"2025-04-22T23:48:28","date_gmt":"2025-04-22T21:48:28","guid":{"rendered":"https:\/\/paxo.fr\/?page_id=785"},"modified":"2025-08-27T23:35:55","modified_gmt":"2025-08-27T21:35:55","slug":"flash","status":"publish","type":"page","link":"https:\/\/paxo.fr\/en\/flash","title":{"rendered":"Flasher"},"content":{"rendered":"<style>\n        #status { margin-top: 15px; font-weight: bold; padding: 10px; border-radius: 4px; font-size: 20px; width: 100%; box-sizing: border-box;}\n        button { padding:10px 15px; cursor: pointer; font-size: 18px; background-color:#38B99B; color:white; border: none; border-radius: 20px; }\n        progress { width: 100%; margin-top: 5px; height: 20px;}\n        .error { color: #D8000C; background-color: #FFD2D2; border: 1px solid #D8000C; }\n        .success { color: #4F8A10; background-color: #DFF2BF; border: 1px solid #4F8A10;}\n        .info { color: white; background-color: rgb(84, 199, 236); border: 1px solid rgb(84, 199, 236);}\n        .file-info { margin-top: 20px; padding: 15px; background-color: #f8f8f8;  font-size: 0.9em; width: 100%; box-sizing: border-box; }\n        .file-info code { background-color: #eee; padding: 2px 5px; border-radius: 3px; font-family: monospace; }\n        .warning { color: white; background-color: #161616; border: 1px solid #161616; padding: 10px; margin-bottom: 10px; border-radius: 4px; width: 100%; box-sizing: border-box;}\n        h1, h2 { border-bottom: 1px solid #ccc; padding-bottom: 5px; font-size: 20px; margin-top: 0; }\n        li {font-size: 15px;}\n         esp-web-install-button {\n             display: flex;\n             justify-content: center;\n             margin-top: 20px;\n             width: 100%;\n         }\n         .warning ol li {\n             margin-bottom: 8px;\n         }\n    <\/style>\n<p>    <script type=\"module\" src=\"https:\/\/unpkg.com\/esp-web-tools@9.4.3\/dist\/web\/install-button.js?module\"><\/script><\/p>\n<h1>Outil de Flashage Web PaxOS-9(2) pour ESP32<\/h1>\n<p><\/br><\/p>\n<p>Flashez la version &lsquo;alpha&rsquo; de PaxOS-9 sur un ESP32 connect\u00e9 directement depuis votre navigateur gr\u00e2ce \u00e0 <strong>Web Serial<\/strong>.<\/p>\n<p>N\u00e9cessite <strong>Google Chrome<\/strong> ou <strong>Microsoft Edge<\/strong> (version 79 ou ult\u00e9rieure) sur ordinateur de bureau.<\/p>\n<p>    <\/br><br \/>\n    <\/br><\/p>\n<div class=\"warning\">\n<h2 style=\"color:white;\">\u00c9tapes Importantes :<\/h2>\n<ol>\n<li>Connectez votre appareil ESP32 \u00e0 votre ordinateur via USB.<\/li>\n<li>Cliquez sur le bouton \u00ab\u00a0Connecter &#038; Installer PaxOS-9\u00a0\u00bb ci-dessous.<\/li>\n<li>Lorsque le navigateur vous le demande, s\u00e9lectionnez le Port S\u00e9rie correct pour votre ESP32 et cliquez sur \u00ab\u00a0Connecter\u00a0\u00bb.<\/li>\n<\/ol><\/div>\n<p>    <\/br><br \/>\n    <\/br>  <\/p>\n<p>    <esp-web-install-button id=\"installButton\" manifest=\"https:\/\/paxo.fr\/wp-content\/uploads\/2025\/08\/manifest.json\"><br \/>\n        <button slot=\"activate\">Connecter &#038; Installer PaxOS-9<\/button><br \/>\n        <span slot=\"unsupported\">Votre navigateur ne prend pas en charge Web Serial. Veuillez utiliser Chrome ou Edge.<\/span><br \/>\n        <span slot=\"not-allowed\">Permission refus\u00e9e. Assurez-vous que l&rsquo;appareil est connect\u00e9 et que vous avez s\u00e9lectionn\u00e9 le bon port.<\/span><br \/>\n    <\/esp-web-install-button><\/p>\n<p>    <\/br><br \/>\n    <\/br> <\/p>\n<div id=\"status\" class=\"info\">Statut : En attente de connexion&#8230;<\/div>\n<progress id=\"progressBar\" value=\"0\" max=\"100\" style=\"display: none;\"><\/progress>\n<p>    <script>\n        const installButton = document.getElementById('installButton');\n        const statusElement = document.getElementById('status');\n        const progressBar = document.getElementById('progressBar');\n        const fileInfoDiv = document.getElementById('fileInfoDiv'); \/\/ Get reference to the div<\/p>\n<p>        \/\/ Informational display elements (inside fileInfoDiv)\n        const bootloaderUrlElement = document.getElementById('bootloader-url');\n        const bootloaderOffsetElement = document.getElementById('bootloader-offset');\n        const partitionsUrlElement = document.getElementById('partitions-url');\n        const partitionsOffsetElement = document.getElementById('partitions-offset');\n        const appUrlElement = document.getElementById('app-url');\n        const appOffsetElement = document.getElementById('app-offset');\n        const chipFamilyElement = document.getElementById('chip-family');<\/p>\n<p>        \/\/ Function to fetch and display manifest info\n        async function displayManifestInfo(manifestUrl) {\n            try {\n                 if (!manifestUrl) {\n                     throw new Error(\"L'URL du manifest n'est pas sp\u00e9cifi\u00e9e dans le HTML.\");\n                 }\n                const response = await fetch(manifestUrl);\n                if (!response.ok) throw new Error(`Erreur HTTP lors du chargement du manifest ! Statut : ${response.status}`);\n                const manifest = await response.json();<\/p>\n<p>                statusElement.textContent = `Statut : Manifest \"${manifest.name} v${manifest.version}\" charg\u00e9. Pr\u00eat \u00e0 connecter.`;\n                statusElement.className = 'info';\n                fileInfoDiv.style.display = 'block'; \/\/ Ensure div is visible on success<\/p>\n<p>                if (manifest.builds && manifest.builds.length > 0) {\n                    const build = manifest.builds[0];\n                    chipFamilyElement.textContent = build.chipFamily || 'Non sp\u00e9cifi\u00e9';<\/p>\n<p>                    const bootloader = build.parts.find(p => p.path.includes('bootloader.bin'));\n                    const partitions = build.parts.find(p => p.path.includes('partitions.bin'));\n                    const app = build.parts.find(p => p.path.includes('firmware.bin'));<\/p>\n<p>                     if (bootloader) {\n                        bootloaderUrlElement.textContent = bootloader.path.split('\/').pop();\n                        bootloaderOffsetElement.textContent = `0x${bootloader.offset.toString(16)}`;\n                    } else {\n                         bootloaderUrlElement.textContent = 'Non sp\u00e9cifi\u00e9'; bootloaderOffsetElement.textContent = 'N\/A';\n                    }\n                    if (partitions) {\n                        partitionsUrlElement.textContent = partitions.path.split('\/').pop();\n                        partitionsOffsetElement.textContent = `0x${partitions.offset.toString(16)}`;\n                    } else {\n                         partitionsUrlElement.textContent = 'Non sp\u00e9cifi\u00e9'; partitionsOffsetElement.textContent = 'N\/A';\n                    }\n                     if (app) {\n                        appUrlElement.textContent = app.path.split('\/').pop();\n                        appOffsetElement.textContent = `0x${app.offset.toString(16)}`;\n                    } else {\n                         appUrlElement.textContent = 'Non sp\u00e9cifi\u00e9'; appOffsetElement.textContent = 'N\/A';\n                    }\n                } else {\n                     chipFamilyElement.textContent = 'Erreur : Aucune build trouv\u00e9e dans le manifest';\n                     \/\/ Optionally keep the error text inside, but the main status shows the issue\n                }<\/p>\n<p>            } catch (error) {\n                statusElement.textContent = `Erreur lors du chargement du manifest : ${error.message}`;\n                statusElement.className = 'error';\n                fileInfoDiv.style.display = 'none'; \/\/ Hide the file info div on error\n                console.error(\"Manifest load error:\", error);\n                \/\/ No need to update inner elements to 'Erreur' if the div is hidden\n            }\n        }<\/p>\n<p>        \/\/ Display manifest info on load by reading the attribute\n        if (installButton) {\n             const manifestAttr = installButton.getAttribute('manifest'); \/\/ Safer way to read attribute\n             if (manifestAttr) {\n                displayManifestInfo(manifestAttr);\n             } else {\n                 statusElement.textContent = \"Erreur : Attribut 'manifest' non trouv\u00e9 sur le bouton d'installation.\";\n                 statusElement.className = 'error';\n                 fileInfoDiv.style.display = 'none'; \/\/ Hide div if attribute is missing\n                 console.error(\"Install button manifest attribute not found.\");\n             }\n        } else {\n             statusElement.textContent = \"Erreur : Composant du bouton d'installation introuvable.\";\n             statusElement.className = 'error';\n             if (fileInfoDiv) { \/\/ Check if fileInfoDiv exists before trying to hide\n                fileInfoDiv.style.display = 'none'; \/\/ Hide div if button component fails\n             }\n             console.error(\"Could not find #installButton element.\");\n        }<\/p>\n<p>        \/\/ Event listeners remain the same as the previous French version...\n        installButton.addEventListener('state-changed', (e) => {\n            let statusText;\n            if (typeof e.detail === 'string') {\n                 switch (e.detail) {\n                    case 'prompt': statusText = 'Demande de connexion...'; break;\n                    case 'connecting': statusText = 'Connexion en cours...'; break;\n                    case 'connected': statusText = 'Connect\u00e9.'; break;\n                    case 'initializing': statusText = 'Initialisation en cours...'; break;\n                    case 'erasing': statusText = 'Effacement en cours...'; break;\n                    case 'writing': statusText = '\u00c9criture en cours...'; break;\n                    case 'finished': statusText = 'Termin\u00e9.'; break;\n                    default: statusText = e.detail;\n                 }\n            } else if (e.detail && e.detail.newState) {\n                 switch (e.detail.newState) {\n                     case 'prompt': statusText = 'Demande de connexion...'; break;\n                     case 'connecting': statusText = 'Connexion en cours...'; break;\n                     case 'connected': statusText = 'Connect\u00e9.'; break;\n                     case 'initializing': statusText = 'Initialisation en cours...'; break;\n                     case 'erasing': statusText = 'Effacement en cours...'; break;\n                     case 'writing': statusText = '\u00c9criture en cours...'; break;\n                     case 'finished': statusText = 'Termin\u00e9.'; break;\n                     default: statusText = e.detail.newState;\n                 }\n            } else {\n                 statusText = JSON.stringify(e.detail);\n            }\n            statusElement.textContent = `Statut : ${statusText}`;\n            statusElement.className = 'info';\n            progressBar.style.display = 'none';\n            progressBar.value = 0;\n            console.log(\"State changed:\", e.detail);\n        });<\/p>\n<p>        installButton.addEventListener('error', (e) => {\n            let errorText;\n             if (typeof e.detail === 'string') {\n                 if (e.detail.includes(\"Failed to get firmware file URL\")) { errorText = `Impossible d'obtenir l'URL du fichier firmware. V\u00e9rifiez la configuration du manifest. (${e.detail})`; }\n                 else if (e.detail.includes(\"already open\")) { errorText = `Le port s\u00e9rie est d\u00e9j\u00e0 utilis\u00e9. Fermez les autres applications utilisant le port et r\u00e9essayez. (${e.detail})`;}\n                 else if (e.detail.includes(\"network\")) { errorText = `Erreur r\u00e9seau. V\u00e9rifiez votre connexion internet et l'URL du manifest. (${e.detail})`;}\n                 else { errorText = e.detail; }\n             } else if (e.detail && e.detail.message) {\n                 if (e.detail.message.includes(\"Failed to get firmware file URL\")) { errorText = `Impossible d'obtenir l'URL du fichier firmware. V\u00e9rifiez la configuration du manifest. (${e.detail.message})`; }\n                 else if (e.detail.message.includes(\"already open\")) { errorText = `Le port s\u00e9rie est d\u00e9j\u00e0 utilis\u00e9. Fermez les autres applications utilisant le port et r\u00e9essayez. (${e.detail.message})`; }\n                 else if (e.detail.message.includes(\"network\")) { errorText = `Erreur r\u00e9seau. V\u00e9rifiez votre connexion internet et l'URL du manifest. (${e.detail.message})`; }\n                 else { errorText = e.detail.message; }\n             } else { errorText = JSON.stringify(e.detail); }\n            statusElement.textContent = `Erreur : ${errorText}`;\n            statusElement.className = 'error';\n            progressBar.style.display = 'none';\n            console.error(\"Flashing error:\", e.detail);\n        });<\/p>\n<p>         installButton.addEventListener('flash-progress', (e) => {\n            const state = (e.detail.state === 'writing' ? '\u00c9criture' : e.detail.state) || 'Flashage';\n            const percent = Math.round((e.detail.bytesWritten \/ e.detail.totalBytes) * 100);\n            statusElement.textContent = `${state} : ${percent}% (${e.detail.bytesWritten} \/ ${e.detail.totalBytes} octets)`;\n            statusElement.className = 'info';\n            progressBar.style.display = 'block';\n            progressBar.value = percent;\n         });<\/p>\n<p>         installButton.addEventListener('installation-finished', (e) => {\n            statusElement.textContent = \"Flashage r\u00e9ussi ! L'appareil devrait red\u00e9marrer avec PaxOS-9.\";\n            statusElement.className = 'success';\n            progressBar.style.display = 'none';\n            console.log(\"Installation finished\");\n         });<\/p>\n<p>    <\/script><\/p>","protected":false},"excerpt":{"rendered":"<p>Outil de Flashage Web PaxOS-9(2) pour ESP32 Flashez la version &lsquo;alpha&rsquo; de PaxOS-9 sur un ESP32 connect\u00e9 directement depuis votre navigateur gr\u00e2ce \u00e0 Web Serial. N\u00e9cessite Google Chrome ou Microsoft Edge (version 79 ou ult\u00e9rieure) sur ordinateur de bureau. \u00c9tapes Importantes : Connectez votre appareil ESP32 \u00e0 votre ordinateur via USB. Cliquez sur le bouton [&hellip;]<\/p>","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-785","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/pages\/785","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/comments?post=785"}],"version-history":[{"count":0,"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/pages\/785\/revisions"}],"wp:attachment":[{"href":"https:\/\/paxo.fr\/en\/wp-json\/wp\/v2\/media?parent=785"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}