Прошивальщик: данные прошивки передаются строкой в esptool-js (ошибка charCodeAt)
This commit is contained in:
1 parent
83f70c2241
commit
9937f26631
3 files changed
+30
-3
No files matched your search
@@ -85,6 +85,16 @@ nginx -t && systemctl reload nginx
|
||||
- определение чипа при подключении, журнал операций, прогресс, кнопка перезагрузки;
|
||||
- для nRF52 (`.uf2`, `.zip`) — скачивание и инструкция: копирование на UF2-диск или DFU через nRF Connect.
|
||||
|
||||
## Грабли
|
||||
|
||||
- **`A.charCodeAt is not a function` при прошивке ESP32.** esptool-js 0.5.x ожидает содержимое
|
||||
файла как «двоичную строку»: внутри `writeFlash` вызывается `bstrToUi8(data)`, то есть
|
||||
`data.charCodeAt(i)`. Если передать `Uint8Array`, запись падает. В `app.js` байты приводит
|
||||
`bytesToBinaryString()` (кусками по 32 КБ, чтобы не упереться в лимит аргументов).
|
||||
- **Браузер держит старый `app.js`.** Для `location /flasher/` в nginx стоит
|
||||
`Cache-Control: no-cache`, а подключение в `index.html` идёт с версией (`app.js?v=...`).
|
||||
При правке скрипта версию нужно поднять, иначе браузер возьмёт старый файл из кэша.
|
||||
|
||||
## Ограничения
|
||||
|
||||
- прошивка из браузера возможна только для ESP32: nRF52 требует UF2-диска или DFU;
|
||||
|
||||
@@ -213,13 +213,30 @@ async function connect() {
|
||||
}
|
||||
}
|
||||
|
||||
// esptool-js (0.5.x) ожидает содержимое прошивки как «двоичную строку» (binary string):
|
||||
// внутри writeFlash вызывается bstrToUi8(data), то есть data.charCodeAt(i). Если передать
|
||||
// Uint8Array, падает с "data.charCodeAt is not a function" — поэтому конвертируем сами.
|
||||
function bytesToBinaryString(bytes) {
|
||||
let out = '';
|
||||
const CHUNK = 0x8000; // чтобы String.fromCharCode.apply не упёрся в лимит аргументов
|
||||
for (let i = 0; i < bytes.length; i += CHUNK) {
|
||||
out += String.fromCharCode.apply(null, bytes.subarray(i, i + CHUNK));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
async function fetchFirmware(file) {
|
||||
log('Загрузка ' + file.name + ' (' + human(file.size) + ')…');
|
||||
const res = await fetch(file.url, { cache: 'no-store' });
|
||||
if (!res.ok) throw new Error('не удалось скачать файл: HTTP ' + res.status);
|
||||
const buf = await res.arrayBuffer();
|
||||
log('Получено ' + human(buf.byteLength));
|
||||
return new Uint8Array(buf);
|
||||
const bytes = new Uint8Array(buf);
|
||||
log('Получено ' + human(bytes.length) + ', подготовка данных…');
|
||||
const data = bytesToBinaryString(bytes);
|
||||
if (data.length !== bytes.length) {
|
||||
throw new Error(`данные повреждены при подготовке: ${data.length} вместо ${bytes.length} байт`);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function flash() {
|
||||
|
||||
@@ -112,6 +112,6 @@
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script type="module" src="app.js"></script>
|
||||
<script type="module" src="app.js?v=20261012"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user