Přeskočit na hlavní obsah

Nahrání firmware ESPHome přes USB: první instalace i záchrana zamčeného zařízení

ESPHome umí aktualizovat zařízení bezdrátově a v běžném životě to je jediná věc, kterou potřebujete. Jsou ale situace, kdy se bez kabelu neobejdete: první instalace na čistý čip, výměna bootloaderu, čtení logů ze zařízení, které není na síti, a hlavně záchrana zařízení, které po aktualizaci vůbec nenaběhne.

Tenhle článek je referenční příručka právě na tyhle případy. Ukážeme si dva odlišné světy - desku, která má USB port a stačí jí kabel, a zařízení, které port nemá a musíte se k jeho sériové lince prodrat sami. A pak si projdeme diagnostiku, protože sériová linka je jediné místo, odkud se dá zaseknuté ESP32 spolehlivě rozmluvit.

Na co se tady nedozvíte odpověď

Tohle není úvod do ESPHome. Pokud ho ještě nemáte nainstalovaný, nebo neznáte YAML konfiguraci, začněte mým článkem ESPHome - Chytré zařízení z ESP32 za pár minut. Sem se vraťte ve chvíli, kdy máte co nahrát.

Kdy potřebujete USB a kdy stačí OTA

OTA (bezdrátová) aktualizace přepisuje jen aplikační oddíl. Všechno ostatní ve flash paměti zůstává, jak bylo - a přesně z toho vyplývá seznam situací, kdy vám OTA nepomůže:

SituaceŘešení
První nahrání na nový čipMusí být přes USB. ESPHome do zařízení, které nikdy nic nemělo, bezdrátově nahrát neumí - není tam s čím se spojit
Zařízení není na Wi-Fi (špatné heslo, změněné SSID, mrtvý AP)USB. Wi-Fi údaje jsou zakompilované ve firmwaru, takže je nejde opravit jinak než novým firmwarem
Zařízení je zamčené v safe mode, displej černýUSB plus erase-flash - rozebírám níž
Potřebujete vyměnit bootloader (například kvůli volbě, která chce ESP-IDF v5.1+)USB. OTA bootloader nemění
Chcete přečíst logy nebo backtrace ze zařízení, které se nepřipojíUSB - viz níž
Zařízení běží a je na sítiOTA, klidně z Device Builderu. Kabel nechte v šuplíku
OTA je bezpečnější než sériový flash

Zní to protiintuitivně, ale je to tak. ESP-IDF nově nahraný firmware po startu sleduje, a když se zařízení resetuje dřív, než ho ESPHome označí za funkční, vrátí předchozí verzi. Sériový flash tuhle záchrannou síť nemá - přepíše vám aplikaci bez ptaní a když nová verze nenaběhne, musíte k zařízení znovu. Jak tenhle rollback vypadá v praxi, popisuju v post-mortemu jednoho výpadku.

Má to ale jednu podmínku, kterou je dobré znát: ESPHome tenhle rollback váže na komponentu safe_mode. Když ji v konfiguraci nemáte, ESPHome ochranu vypne a do logu to napíše. Je v tom pěkná symetrie - ta samá komponenta, která vám umí zařízení zamknout v safe mode, je zároveň to, co dělá OTA bezpečnou.

Dva případy, které se od sebe hodně liší

Tohle je osa celého článku. Fyzická část práce se totiž mezi těmi dvěma případy nedá srovnávat.

Deska s USB portem

Sem patří všechny běžné vývojové desky - ESP32 devkit, ESP32-S3, D1 mini, NodeMCU, Lolin32 a desítky klonů. Mají na sobě převodník USB na sériovou linku (nejčastěji CP2102 nebo CH340) nebo přímo nativní USB, a ten se hlásí v počítači jako sériový port.

Co budete potřebovat:

  • Datový USB kabel - a tohle je ten nejčastější problém. Kabel od powerbanky nebo od nabíječky často vede jen napájení a data v něm nejsou. Vypadá to pak jako mrtvá deska.
  • Nic dalšího. Žádný adaptér, žádné dráty, žádné pájení.

Často nemusíte mačkat vůbec nic. Ty desky mají mezi převodníkem a čipem zapojenou automatickou resetovací logiku: signál RTS sériového portu je připojený na EN (reset) a DTR na GPIO0. esptool (a stejně tak webový flasher, který ho má v sobě) si těmito dvěma signály zařízení sám přehodí do bootloader režimu a po nahrání ho zase restartuje. Tohle propojení popisuje dokumentace esptool v tabulce doporučeného zapojení převodníku k ESP - EN na RTS, GPIO0 na DTR.

Kdy to nestačí a musíte na tlačítka:

  • Deska automatickou resetovací logiku vůbec nemá (levné klony, holé moduly na nosné desce)
  • Máte na GPIO0 nebo EN připojenou vlastní periferii, která signál přebíjí
  • Dostáváte Wrong boot mode detected - komunikace funguje, ale automatický reset ne
  • Napájíte desku odjinud a USB slouží jen na data

Ruční vstup do bootloader režimu na desce s tlačítky:

  1. Podržte tlačítko BOOT (na některých deskách označené IO0 nebo FLASH)
  2. Krátce stiskněte a pusťte RESET (nebo EN)
  3. Pusťte BOOT
  4. Spusťte nahrávání
Proč právě GPIO0

Dokumentace esptool to říká na rovinu: "The ESP32 will enter the serial bootloader when GPIO0 is held low on reset. Otherwise it will run the program in flash." Tlačítko BOOT nedělá nic jiného, než že GPIO0 stahuje na zem. GPIO2 k tomu musí být nezapojený nebo taky nízko - u hotových desek to je vždycky splněné, u vlastních plošňáků na to pozor.

Nativní USB u ESP32-S2, S3 a C3

Novější čipy mají USB řadič v sobě a deska může mít dva USB porty - jeden vedený přes převodník (UART) a druhý přímo do čipu. Ten druhý ale existuje ve dvou různých podobách a vyplatí se je nepomíchat, protože se chovají opačně:

  • USB-OTG (ESP32-S2 a S3) je konfigurovatelný řadič, takže se jako sériový port hlásí jen tehdy, když to firmware zapne. Když vám zařízení po nahrání firmwaru ze seznamu portů zmizí, není rozbité - nová konfigurace jen nezapnula USB CDC.
  • USB-Serial-JTAG (ESP32-C3, na S3 vedle OTG) je naopak fixní hardware. Existuje bez ohledu na to, co je ve flash, takže přes něj jde flashovat i zařízení s prázdným nebo rozbitým firmwarem.

Na flashování je pořád jistota port označený UART - Espressif ho v uživatelských příručkách svých desek uvádí jako výchozí. Pokud ho deska nemá, funguje i nativní port, ale do bootloader režimu ho budete občas muset dostat tlačítky.

Zařízení bez USB portu

Sem patří hotová komerční zařízení - Sonoff NSPanel, Shelly, Sonoff Basic, žárovky, zásuvky. Uvnitř mají ESP32 nebo ESP8266, ale výrobce ho nikam nevyvedl, protože se počítalo s tím, že firmware nikdy nikdo měnit nebude.

Co budete potřebovat:

  • USB-TTL adaptér s čipem CP2102 nebo CH340
  • Propojovací kabely Female-to-Female, alespoň pět
  • Šroubovák na otevření zařízení
  • ⚠️ Adaptér přepnutý na 3,3 V, pokud má přepínač
  • ⚠️ Někdy pájku, když zařízení nemá vyvedený header
  • ⚠️ U zařízení na 230 V odpojené napájení

CP2102 USB 2.0 to TTL UART Module

  • USB
Momentálně není k dispozici nákup v této zemi

Dupont kabely 10cm / 20cm / 30cm - male / female

Momentálně není k dispozici nákup v této zemi
3,3 V, nikdy 5 V na datové piny

Datové piny RX a TX musí být na 3,3 V logice. Adaptér přepnutý na 5 V vám čip nezničí vždycky, ale zničí ho dost často - a je to nevratné. Dokumentace ESPHome je v tom kategorická: "You MUST make sure the data (RX and TX) and VCC pins are set for 3.3V."

U zařízení napájených ze sítě navíc před jakoukoli manipulací odpojte 230 V. Pracujeme sice s 3,3V logikou, ale na desce jsou i části, které s ní nemají nic společného.

Zapojení je vždycky stejné čtveřice, jen jinak pojmenovaná:

ZařízeníUSB-TTL adaptérPoznámka
TXRXProhozené!
RXTXProhozené!
GNDGNDBez společné země nefunguje nic
5V, pokud ho zařízení má+5VZařízení si 5 V převede vlastním stabilizátorem. Viz varování níž
3V3, když 5V pin není3V3Na pin 3V3 nikdy nedávejte +5V - to čip zničí. Počítejte s tím, že stabilizátor adaptéru nemusí stačit, a připravte si externí 3,3V zdroj

Schéma zapojení USB-TTL adaptéru k zařízení s ESP32

A takhle ten header vypadá ve skutečnosti, na příkladu NSPanelu:

Sériový header uvnitř Sonoff NSPanelu

Napájení berte z +5V, ne z pinu 3V3 převodníku

Tohle je past, která vyrobí dokonale zavádějící diagnózu. Pin 3V3 na USB-TTL adaptéru jde z drobného stabilizátoru na jeho desce, který dá tak 50–100 mA. Na samotné flashování to stačí bez problémů - firmware se nahraje a všechno vypadá dobře. Jenže při startu si Wi-Fi řekne o mnohonásobek, napájení se složí a zařízení se restartuje. V logu pak vidíte rst:0x1 a hledáte chybu ve firmwaru, který je úplně v pořádku. Rozebírám to níž.

Použijte pin +5V převodníku, ten jde prakticky přímo z USB VBUS. Zařízení si těch 5 V převede vlastním stabilizátorem, který na to dimenzovaný je. Externí zdroj obvykle není potřeba, u portu s limitem 500 mA ale může být těsno - pomůže port USB 3.0.

Ruční vstup do bootloader režimu je tady nutnost, protože automatická resetovací logika na desce není:

  1. Odpojte zařízení od veškerého napájení
  2. Spojte pin GPIO0 (často označený IO0) s GND - drátkem, propojkou, nebo prostě přidržte
  3. Připojte napájení (adaptér do USB počítače)
  4. Počkejte pár sekund a zkratku můžete rozpojit
  5. Že jste uspěl, poznáte tak, že se k zařízení flashovací nástroj připojí

Pořadí je tady zásadní: GPIO0 musí být na zemi ve chvíli, kdy čip startuje. Spojit ho až potom nemá žádný efekt.

Nikdy zařízení nenapájejte z obojího zároveň

Zařízení připojené na 230 V a současně na USB-TTL adaptér v počítači je kombinace, po které přijdete o adaptér, o USB port, nebo o víc. Vždy jen jedno.

Konkrétní postup pro Sonoff NSPanel - jak ho otevřít, kde je header a co má který pin - mám v samostatném článku o NSPanelu.

Tři způsoby, jak firmware dostat do zařízení

Když máte zařízení fyzicky připojené a v bootloader režimu, zbývá vybrat nástroj. Všechny tři pod kapotou používají esptool, takže výsledek je identický - liší se pohodlím a tím, co všechno umí.

ZpůsobKdy ho použít
Device Builder → Install → Plug into this computerStandardní volba, když máte ESPHome v Home Assistantovi. Nemusíte nic stahovat
web.esphome.io samostatněNemáte ESPHome v HA, flashujete z cizího počítače, nebo máte .factory.bin stažený a jen ho chcete nahrát
esptool z příkazové řádkyKdyž potřebujete erase-flash, konkrétní adresy, jiný baud rate, nebo to chcete zaskriptovat

Device Builder: Plug into this computer

Dialog Install dnes rovnou pozná, že zařízení ještě nikdy nahrané nebylo, a napíše vám to:

Dialog pro instalaci firmware v ESPHome Device Builderu

Máte v něm tři zjevné volby a čtvrtou - pro nás nejdůležitější - schovanou pod rozbalovacím Advanced options:

VolbaCo dělá
Plug into this computerESP je v USB tohoto počítače. Otevře se webový flasher v novém tabu, firmware zůstane v prohlížeči a flashuje se 100 % lokálně
Plug into your Home Assistant serverESP je v USB portu serveru s Home Assistantem. Užitečné, když máte HA na Raspberry Pi na dosah ruky
On the networkFirmware zkompiluje, ale nahrát ho půjde až po první instalaci přes USB
Download firmware binaryCompile here and download the binary, then flash it manually with your preferred tool. Zkompiluje a nabídne soubor ke stažení na disk. Tuhle volbu chcete, když budete flashovat přes web.esphome.io, esptool, nebo z úplně jiného počítače
Download firmware binary je schovaný pod Advanced options

Na screenshotu výš ho nevidíte a není to chyba - dialog ho schovává pod rozbalovací Advanced options dole. Po rozbalení se objeví dvě položky:

Dialog Install v ESPHome Device Builderu s rozbalenými Advanced options

  • Device IP or hostname - nahrání na konkrétní adresu místo automaticky zjištěné
  • Download firmware binary - tohle je ta volba, kterou hledáte

Všimněte si formulace „Compile here". Kompilace proběhne tam, kde běží Device Builder - tedy typicky na serveru s Home Assistantem, ne na počítači, kam si soubor stahujete. Samotné stažení tedy práci nezrychlí, jen ji přenese jinam; rozebírám to dál.

Chcete Factory image, ne OTA update

Po kliknutí na Download firmware binary se ESPHome nejdřív zkompiluje a pak se zeptá „Choose what to download". Na výběr jsou tři položky - vyberete jednu a potvrdíte tlačítkem Download:

Dialog s výběrem, co stáhnout: Factory image, OTA update a ELF

Volba v dialoguStažený souborK čemu je
Factory image<nazev>-firmware.factory.binFull image for ESPHome Web and other flashing tools. Tohle chcete pro sériový flash
OTA update<nazev>-firmware.ota.binFor updating a device over the network. Jen pro bezdrátovou aktualizaci
ELF (debug symbols)soubor .elfFor decoding crash backtraces with the ESP stack trace decoder. Firmware to není - hodí se, když luštíte pád, viz dál

Rozdíl mezi prvními dvěma je zásadní. OTA update je jen aplikace - sériově nahraná na adresu 0x0 nenaběhne, protože tam chybí bootloader i tabulka oddílů. Factory image je slepenec všeho potřebného od adresy nula. Pro první instalaci a po každém erase-flash musíte mít factory image, nic jiného nenaskočí.

Starší návody a nápověda uvnitř samotného web.esphome.io mluví o Modern Format a Manual Download - rozhraní se od té doby přejmenovalo, ale jde o tu samou věc.

web.esphome.io samostatně

Stejný nástroj, jen bez Home Assistantu okolo. Hodí se na záchranu a na situace, kdy ESPHome nikde nainstalované nemáte.

  1. Otevřete web.esphome.io v Chrome nebo Edge
  2. Connect → v dialogu prohlížeče vyberte svůj sériový port
  3. Objeví se karta ESP Device s odznakem Connected a řádkou akcí
  4. Klikněte na ikonu nahrávání (druhá v řadě) → otevře se dialog „Install your existing ESPHome project" s výběrem souboru
  5. Vyberte stažený .factory.bin a potvrďte Install
  6. Nechte to nahrát, u ESP32 to trvá přibližně minutu

Za pozornost stojí bod 4: web.esphome.io nahrává ze souboru na vašem disku, ne z nějakého připojeného ESPHome. Nepotřebuje vidět váš Home Assistant, nepotřebuje být s ním na stejné síti a nepotřebuje vůbec nic vědět o vaší instalaci. Stačí mu binárka a zařízení v USB. Přímo v tom dialogu si to ESPHome ověřuje samo - je v něm návod, jak soubor získat: Open your ESPHome Device Builder → device card menu → Install → Manual Download → Modern Format.

Karta ESP Device na web.esphome.io po připojení zařízení

Jediné pojmenované tlačítko je to nesprávné

Tohle je na tom rozhraní nejzrádnější. Prepare for first use je jediná akce s textovým popiskem a ještě je zvýrazněná modře, takže na ni ruka jde sama. Přitom je to ta, kterou nechcete: nahraje obecný ESPHome firmware určený k pozdější adopci, ne vaši binárku.

Akce, kterou hledáte, je ikona nahrávání hned vedle - bez popisku. Zbylé dvě ikony jsou logy a nastavení Wi-Fi, vpravo je odpojení. Popisek se u nich objeví, když na ně chvíli podržíte kurzor.

Web Serial API: proč vám Connect nic nenabídne

Webové flashery stojí na Web Serial API a to má dvě podmínky, o které se dá snadno zakopnout:

  • Nefunguje ve všech prohlížečích - spolehlivě jde o ty na jádře Chromium (Chrome, Edge, Opera, Brave), od verze Firefox 151 už i o Firefox. V Safari ne, a to ani na iOS. MDN to řadí mezi funkce s omezenou dostupností, protože "it does not work in some of the most widely-used browsers".
  • Vyžaduje zabezpečený kontext - tedy https:// nebo localhost. Citace z MDN: "This feature is available only in secure contexts (HTTPS), in some or all supporting browsers."

A tady je ta opakovaná past: pokud na Home Assistant chodíte po http://192.168.1.x:8123, volba Plug into this computer vám nebude fungovat. Není to chyba ESPHome ani vašeho počítače, prohlížeč prostě přístup k sériovému portu z nezabezpečené stránky odmítne. Máte tři východiska: použít volbu s USB portem serveru, dát si Home Assistant za HTTPS (mám na to článek o certifikátu od Let's Encrypt), nebo stáhnout .factory.bin a nahrát ho přes web.esphome.io, které na HTTPS běží.

esptool z příkazové řádky

esptool je oficiální nástroj Espressifu a jediná ze tří cest, která vám dá plnou kontrolu. Nainstalujete ho přes pip install esptool; když máte ESPHome nainstalované lokálně, už ho tam máte s ním.

Základní nahrání:

esptool --port /dev/cu.usbserial-0001 --baud 460800 \
write-flash 0x0 muj-firmware.factory.bin

Kompletní smazání flash paměti - tohle je ta věc, kterou žádný webový flasher neumí:

esptool --port /dev/cu.usbserial-0001 erase-flash

Přečtení kusu flash do souboru, například když si chcete zachránit starší firmware z druhého OTA oddílu:

esptool --port /dev/cu.usbserial-0001 read-flash 0x1d0000 0x200 app1.bin
Podtržítka, nebo pomlčky?

esptool v páté generaci přešel na pomlčky: write-flash, erase-flash, read-flash, merge-bin. Starší instalace používaly esptool.py s podtržítky (write_flash, erase_flash). Pokud vám příkaz z tohoto článku hlásí neznámý parametr, máte starší verzi - podtržítka pomůžou. --chip uvádět nemusíte, dokumentace říká, že "esptool will detect the type of chip when it connects to the serial port."

ESPHome má na sériovou práci taky vlastní příkazy, které se vyplatí znát, protože si samy poradí s kompilací:

# zkompilovat, nahrat pres USB a hned pustit logy
esphome run muj-device.yaml --device /dev/cu.usbserial-0001

# jen nahrat posledni build
esphome upload muj-device.yaml --device /dev/cu.usbserial-0001

# jen se koukat do logu pres seriovku
esphome logs muj-device.yaml --device /dev/cu.usbserial-0001

Parametr --device je podle dokumentace CLI určený k tomu, aby "manually specify the port/IP to use for upload and logging" - přijme jak sériový port, tak IP adresu pro OTA.

Ovladače a názvy portů podle systému

Nejčastější hlášení, které o flashování slyším, je „port není v seznamu". V devíti z deseti případů je to ovladač nebo kabel, ne zařízení.

SystémJak se port jmenujeNa co si dát pozor
WindowsCOM3, COM4... (najdete ve Správci zařízení)Windows často nabídne obecný ovladač, který nefunguje. Nainstalujte ten od výrobce čipu
macOS/dev/cu.usbserial-0001, /dev/cu.SLAB_USBtoUART, /dev/cu.wchusbserial*Vždycky cu., nikdy tty. - viz níž
Linux/dev/ttyUSB0 (CP2102, CH340), /dev/ttyACM0 (nativní USB)Váš uživatel musí být ve skupině dialout

Ovladače podle čipu na adaptéru. Dokumentace ESPHome uvádí všechny tři stejně: podle čipu a operačního systému může být potřeba ovladač doinstalovat, takže než začnete hledat chybu jinde, ověřte si to.

  • CP2102 / CP2104 (Silicon Labs) - CP210x USB to UART Bridge VCP Driver. Ovladač cp210x je součástí linuxového jádra už dlouho, na Windows ho většinou doinstalovat musíte
  • CH340 / CH341 (WCH) - ovladač CH34x. Z mé zkušenosti je tohle ten, který chybí nejčastěji
  • PL2303 (Prolific) - ovladač PL2303. U klonů se opakovaně hlásí problémy s novějšími oficiálními ovladači, takže když máte volbu, sáhněte radši po CP2102 nebo CH340
macOS: cu. ano, tty. ne

Na macOS se každý sériový port objeví dvakrát - jako /dev/tty.neco a /dev/cu.neco. Rozdíl je v tom, že varianta tty. umí při otevření čekat na signál DCD, který na USB-TTL adaptéru nikdo nedrží. esptool se na ní pak jednoduše zasekne bez chybové zprávy a vy hledáte problém v zapojení. Používejte cu.

Aktuální seznam portů si vypíšete takhle:

ls /dev/cu.*
Linux: skupina dialout

Bez oprávnění k portu dostanete Permission denied nebo port vůbec neuvidíte. Dokumentace esptool doporučuje přidat účet do skupiny dialout (na některých distribucích uucp):

sudo usermod -aG dialout $USER

Po přidání se musíte odhlásit a přihlásit, jinak se změna neprojeví.

A jedna specialita: pokud ESPHome běží v Docker kontejneru, musíte mu port prostrčit přes --device /dev/ttyUSB0, jinak ho uvnitř nenajde.

Kompilace a flashování z jiného stroje

Kompilace je zdaleka nejnáročnější věc na celém ESPHome workflow a odehrává se tam, kde běží Device Builder - tedy typicky na tom samém serveru, kde máte Home Assistanta. Na Raspberry Pi, Home Assistant Greenu nebo na NASu z toho bývají minuty čekání u každého zařízení.

Dobrá zpráva je, že se s tím dá něco dělat, a že to není obcházení: Device Builder umí kompilaci po síti odklonit na výkonnější stroj, přičemž konfigurace zůstane jen v Home Assistantovi. Protože je to na samostatné téma - párování, shoda verzí i pasti se sítí - vyčlenil jsem ho do vlastního článku.

Vzdálený build má samostatný článek

Proč je kompilace tak pomalá, o kolik to reálně zrychlí, jak spárovat dva Device Buildery a kdy to naopak nefunguje, rozebírám v článku ESPHome kompiluje minuty? Odkloňte build na výkonnější stroj.

Zbytek téhle sekce je o dvou věcech, které s tím souvisí, ale řeší jiný problém - jak se firmware dostane do zařízení, které není u serveru, a co dělat, když desktopovou aplikaci ESPHome použít nemůžete.

Stažení image a nahrání z jiného počítače

Když je firmware zkompilovaný, zbývá ho dostat do zařízení. A tady přichází druhé rozpojení: image si můžete stáhnout jako soubor a nahrát ji odkudkoli. Klikací postup i to, proč chcete Factory image a ne OTA update, rozebírám výš - tady je podstatné jen to, že vám na disku skončí jeden soubor.

A ten soubor je přenosný artefakt. Nezáleží na tom, jestli je zařízení v USB toho stroje, kde běží Home Assistant, jestli je vůbec na stejné síti, ani jestli ten počítač o vaší instalaci něco ví. Stačí mu ta binárka a zařízení na kabelu. Flashovat tedy můžete z Macu na stole, z notebooku, který jste vzal k panelu na chodbě, nebo z počítače kolegy.

Pro zařízení bez USB portu je tohle často jediná praktická cesta. Rozebraný NSPanel s USB-TTL adaptérem prostě nepřenesete k serveru ve sklepě.

Samotné stažení image kompilaci nezrychlí

Tohle si přiznejme, protože se v tom dá snadno utěšit. Download firmware binary rozpojuje kde je zařízení od kde je konfigurace. Nerozpojuje kde se kompiluje.

Když tedy kliknete na Install a nemáte spárovaný vzdálený build, kompilace proběhne na tom stroji, kde Device Builder běží - tedy na tom slabém serveru. Tlačítko je v prohlížeči na vašem rychlém Macu, ale výpočet je na NASu a čekáte ty svoje minuty. Ty dvě věci se doplňují: vzdálený build řeší rychlost, stažení image řeší dosah.

Alternativa: celé ESPHome na výkonném stroji

Vzdálený build potřebuje na obou stranách Device Builder, takže existují případy, kdy ho použít nemůžete - headless Linux server, platforma bez desktopové aplikace, nebo prostě když radši pracujete v terminálu. Pak je cesta mít na tom rychlém stroji plnou instalaci ESPHome a pracovat rovnou tam.

Berte to jako alternativu, ne jako doporučení. Vrací vám totiž zpátky problém se dvěma kopiemi konfigurací, který vzdálený build ruší.

Jedna věc pro klid v duši: ESPHome na tom druhém stroji nenahrazuje to v Home Assistantovi, je to jen překladač. Zařízení dál patří pod integraci ESPHome v Home Assistantovi a entity zůstávají tam, kde byly.

Jak ho tam rozjet. Dvě cesty, které nepotřebují desktopovou aplikaci:

Docker je jeden příkaz, který dokumentace uvádí takto:

docker run --rm --net=host -v "${PWD}":/config -it ghcr.io/esphome/esphome

Rozhraní najdete na http://localhost:6052. Přepínač --net=host je tam kvůli mDNS - bez něj vám kontejner zařízení na síti nenajde. Na Docker Desktopu (macOS, Windows) --net=host nefunguje, tam ho nahraďte za -p 6052:6052. Adresář, ze kterého příkaz spustíte, se stane konfiguračním adresářem.

pip vyžaduje Python 3.12 nebo novější a dokumentace doporučuje instalovat ho do virtuálního prostředí:

# jen prikazova radka
pip install esphome

# prikazova radka plus webove rozhrani Device Builder
pip install "esphome-device-builder[esphome]"
esphome dashboard už neexistuje

Dokumentace CLI to píše natvrdo: "the built-in dashboard command has been removed". Ze pip install esphome tedy dostanete výhradně příkazovou řádku - a tím i žádný vzdálený build, protože ten je funkce Device Builderu, ne CLI. Chcete-li rozhraní, potřebujete desktopovou aplikaci, Docker obraz, nebo balíček esphome-device-builder.

A ještě poznámka k poctivosti: dokumentace dnes u ruční instalace uvádí jen pip. pipx ani uv v ní nenajdete. Nejspíš by fungovaly, ale oficiálně podporovaný postup to není, takže je tady nedoporučuju.

Jak tam dostat konfigurace. Tady je ta otravná část, protože jakmile máte ESPHome na dvou místech, máte i dvě kopie konfigurací - a nic vám samo neřekne, která je ta správná.

VariantaJak fungujeSlabina
Síťové sdílení /config/esphomePřes Sambu si adresář z Home Assistanta připojíte na rychlý stroj a pracujete přímo v němJeden zdroj pravdy, žádná synchronizace. Ale build přes síťový disk je pomalejší a sdílíte i adresář .esphome - viz past níž
Git repozitářKonfigurace v gitu, obě instance z něj tahajíMusíte si pamatovat commit a pull. Zato máte historii
Primární editace na rychlém strojiPíšete a kompilujete jen tadyNejjednodušší na hlavu, ale s vypnutým strojem nemáte čím nahrát
Device Builder si dnes konfigurace verzuje sám

Než si na git sednete, vězte, že Device Builder už udržuje vlastní historii verzí postavenou na gitu. Podle README commituje každou změnu YAML v konfiguračním adresáři "whether the edit came from the dashboard, an external editor, a script, or an AI agent working in the directory", umí je porovnávat a vracet, a secrets.yaml do historie nikdy nezařadí. Když už adresář v gitovém repozitáři je, adoptuje ho a váš .gitignore nepřepisuje.

Pokud si repozitář vedete sám a nechcete v něm cizí commity, vypnete to v Nastavení → Expert mode → Save version history.

secrets.yaml do vlastního repozitáře nedávejte

Jsou v něm Wi-Fi heslo, šifrovací klíč k API a OTA heslo. I do privátního repozitáře to nepatří - z historie gitu se to pak dostává hodně nepříjemně.

# .gitignore
secrets.yaml
.esphome/

Místo toho si vedle nechte secrets.yaml.example s těmi samými klíči, ale prázdnými hodnotami. Ten do gitu klidně dejte - je z něj vidět, co konfigurace potřebuje, a při rozjíždění nového stroje ho jen zkopírujete a doplníte.

U sdílení přes Sambu tenhle problém nemáte, protože secrets.yaml je automaticky společný. Je to výhoda i riziko zároveň.

Vlastní build. Když máte konfiguraci na místě, kompilace je jeden příkaz:

esphome compile nspanel-obyvak.yaml

Dokumentace CLI o něm říká přesně to, co byste čekal - "validates the configuration and compiles the firmware", tedy nic nikam nenahraje. Výsledek najdete v adresáři .esphome, který ESPHome zakládá vedle vaší konfigurace. Konkrétní cesta záleží na toolchainu:

ToolchainFirmware (pro OTA)Factory image (pro USB)
Nativní ESP-IDF (výchozí od 2026.7).esphome/build/<nazev>/build/<nazev>.bin.esphome/build/<nazev>/build/firmware.factory.bin
PlatformIO (--toolchain platformio).esphome/build/<nazev>/.pioenvs/<nazev>/firmware.binfirmware.factory.bin ve stejném adresáři

Ten firmware.factory.bin je přesně ten soubor, který chcete pro sériový flash - proč, rozebírám výš. Nahrajete ho podle esptool nebo přes web.esphome.io. Anebo, a to je pohodlnější, necháte nahrání na ESPHome samotném:

# OTA po siti - zarizeni uz jednou naflashovane bezi
esphome upload nspanel-obyvak.yaml

# pres USB - prvni instalace nebo zachrana
esphome run nspanel-obyvak.yaml --device /dev/cu.usbserial-0001

# jen se koukat do logu, po siti nebo pres seriovku
esphome logs nspanel-obyvak.yaml --device /dev/cu.usbserial-0001

Rozdíl mezi upload a run je v tom, že upload podle dokumentace "uploads the most recent firmware build" - nahraje to, co už je zkompilované, kdežto run zkompiluje, nahraje a hned pustí logy. Po esphome compile vám stačí upload.

Na hromadné aktualizace má CLI příkaz esphome update-all, který podle dokumentace "compiles and uploads firmware to all devices via OTA". Na rychlém stroji je to úplně jiná zkušenost než na slabém serveru, kde se kompilace deseti zařízení protáhne na celé odpoledne.

Na co si dát pozor

Verze ESPHome se na dvou strojích shodovat nemusí. Při rozdílu si ESPHome build adresář sám vyčistí, takže přijdete jen o inkrementální build. Co přesně se přitom děje a jak si u vzdáleného buildu shodu verzí vynutit, rozebírám v článku o vzdáleném buildu.

Jedna věc, kde verze naopak vadí, a je to OTA

Nahrávání je jiná disciplína než kompilace. ESPHome starší než 2025.10, které se autentizuje heslem, nedostane firmware do zařízení, které už běží na 2026.1 nebo novějším. Rozebírám to v článku o ESPHome a týká se to přesně tohohle scénáře: stačí, aby vám na druhém stroji zamrzla loňská verze, a nahrávání přestane fungovat, aniž byste chápal proč. Držte obě instance aktualizované.

Toolchain na tom rychlém stroji zabere gigabajty. Adresář s cache ESP-IDF u mě na Macu narostl na necelých 5 GB a je to úplně normální - je v něm kompletní kompilátor pro Xtensa i RISC-V. Když si na to nedáte pozor u malého SSD, přijde to jako nepříjemné překvapení. Uklízí se dvěma příkazy: esphome clean smaže build soubory daného zařízení, kdežto esphome clean-all podle dokumentace "cleans all build files, PlatformIO platform and package files, and the PlatformIO core directory" - tedy i toolchain, který se pak stahuje znovu. Na rychlém stroji to nechte být, na slabém serveru s malým diskem je to naopak první místo, kde hledat volné místo.

Nesdílejte .esphome mezi stroji s různými verzemi. Past přesně u varianty se Sambou: dva stroje s odlišnou verzí ESPHome, které tlučou do jednoho build adresáře, si budou navzájem shazovat cache. Každý build tam bude plný, protože ten druhý stroj adresář mezitím vyčistil. Buď držte verze stejné, nebo build adresáře oddělte proměnnými ESPHOME_BUILD_PATH a ESPHOME_DATA_DIR. U vzdáleného buildu tenhle problém nemáte - každá strana má svůj vlastní.

Architektura hostitele nehraje roli. ESPHome vždycky cross-kompiluje - cílem je Xtensa nebo RISC-V, tedy něco úplně jiného než procesor, na kterém build běží. Že je Apple Silicon plnohodnotný build stroj, je vidět už na tom, že ESPHome pro něj vydává samostatný nativní balíček (arm64). Nemusíte tedy hledat emulaci ani se bát, že vám ARM Mac postaví jiný firmware než x86 server.

Záchrana a diagnostika

Tady začíná ta část, kvůli které tenhle článek existuje. Následující čtyři situace mají společné to, že vypadají jako mrtvý hardware, ale nejsou - a všechny se řeší jedině přes sériovou linku.

Zamčené safe mode: factory.bin ho nepřepíše

Příznaky: zařízení po aktualizaci nenaskočí, displej zůstává černý, na Wi-Fi se nehlásí. Přeflashujete ho a nic se nezmění. Přeflashujete znovu a je to pořád stejné.

V sériovém logu je pak tohle:

[C][safe_mode:189]: Unsuccessful boot attempts: 10
[E][safe_mode:201]: Boot loop detected

Zařízení se zakouslo v safe mode. To je ochranná funkce ESPHome: po deseti neúspěšných startech nabootuje minimální firmware bez vaší konfigurace, aby zbyla možnost nahrát OTA. Černá obrazovka je v tomhle stavu naprosto očekávaná - safe mode displej vůbec nespustí.

A teď ta zákeřná část ve dvou vrstvách.

Počítadlo neúspěšných startů přežije odpojení od proudu. Výchozí nastavení safe_mode na ESP32 je storage: flash a dokumentace ESPHome k tomu říká, že se počítadlo ukládá do flash a odpojení od proudu ho nesmaže - za cenu drobného opotřebení flash při každém startu. Každé vypnutí a zapnutí je tedy k ničemu, počítadlo zůstává na desítce.

A factory.bin ho nesmaže. Tohle chce vysvětlení, protože z názvu „factory image" by člověk čekal opak. Podívejte se, jak ESPHome rozvrhne 4 MB flash pro ESP-IDF:

OddílAdresaVelikostJe ve factory.bin?
bootloader0x032 kB✅ ano
tabulka oddílů0x80004 kB✅ ano
otadata0x90008 kB✅ ano
phy_init0xb0004 kB
app0 (aplikace)0x100001 792 kB✅ ano
app1 (druhý OTA slot)0x1d00001 792 kB
nvs (tady je počítadlo)0x390000448 kBne

Vidíte to? ESPHome dává oddíl nvs na konec flash paměti, až za oba aplikační sloty. factory.bin je slepenec bootloaderu, tabulky oddílů, otadata a aplikace - tedy věcí od nuly do necelých 2 MB. Na 0x390000 vůbec nedosáhne. Můžete zařízení přeflashovat, kolikrát chcete, počítadlo tam bude sedět dál.

Řešení je smazat celý flash a teprve pak nahrát firmware:

# smazat CELY flash vcetne NVS - tohle je ten podstatny krok
esptool --port /dev/cu.usbserial-0001 erase-flash

# a az potom nahrat firmware
esptool --port /dev/cu.usbserial-0001 --baud 460800 \
write-flash 0x0 muj-firmware.factory.bin

Wi-Fi údaje jsou zakompilované ve firmwaru, takže smazáním NVS o nic důležitého nepřijdete. Ztratíte jen věci uložené za běhu - stavy globals s restore_value: true a podobné maličkosti.

Prevence: přesuňte počítadlo do RTC paměti

Do konfigurace každého zařízení, ke kterému se nechcete plazit s kabelem, si dejte tohle:

safe_mode:
storage: rtc

Počítadlo se přesune do RTC paměti, o které dokumentace píše, že přežije "software reboots (restarts, OTA updates, crashes) and deep sleep but not power loss." Přesně to chcete: safe mode vám zůstane jako záchranná síť pro softwarové pády, ale zamčené zařízení oživí obyčejné vypnutí a zapnutí místo sériové linky.

Bonusem to ubere zápisy do flash, protože počítadlo se při každém startu nezvyšuje ve flash paměti. storage: rtc je dostupné na všech platformách s RTC pamětí; nejde na RP2040, ESP32-C2 a ESP32-C61.

Celý rozbor toho, jak jsem se k téhle diagnóze dostal a kolika slepými uličkami jsem přitom prošel, mám v článku Když NSPanel po aktualizaci nenaběhne.

Boot loop s rst:0x1: nedostatečné napájení

Příznaky: flash proběhne bez chyby, ale zařízení se pak restartuje přibližně každou sekundu. V logu se opakuje:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)

Ten kód je celá diagnóza. rst:0x1 (POWERON_RESET) znamená, že čip skutečně ztratil napájení - nespadl software, prostě mu zmizely volty. Kdyby padal firmware, viděli byste rst:0xc (SW_CPU_RESET) a k tomu Guru Meditation Error s backtrace.

Nejčastější příčina je napájení z pinu 3V3 na USB-TTL převodníku, jak jsem popisoval výš: stabilizátor na desce převodníku dá 50–100 mA, flashování se do toho vejde, ale startující Wi-Fi si řekne o mnohonásobek a napájení se složí.

Co s tím:

  1. Přepojte napájení na pin +5V převodníku - jde prakticky z USB VBUS a zařízení si ho převede vlastním stabilizátorem
  2. Pokud to nepomůže, zkuste port USB 3.0 místo 2.0, dá vám vyšší proudový limit
  3. U žravějších zařízení použijte externí zdroj a od převodníku vezměte jen RX, TX a GND
  4. Zkontrolujte, že máte jen jednu společnou zem - dva zdroje bez propojené GND umí vyrobit úplně stejné příznaky
Tenhle omyl vyrobí falešnou diagnózu

Zrádnost té pasti není v tom, že by se dala přehlédnout, ale v tom, že ta data vypadají důvěryhodně. Sedíte nad sériovým logem, který věrně dokumentuje limity vašeho adaptéru, a hledáte podle něj chybu ve firmwaru, kde žádná není. Sám jsem takhle ztratil několik hodin - podrobně v post-mortemu. Než začnete věřit datům, ověřte sestavu, na které jste je naměřil.

Bootloader: OTA ho nikdy nezmění

Tenhle případ je vzácný, ale když na něj narazíte, je nepříjemný.

OTA aktualizace přepisuje jen aplikační oddíl. Bootloader, který leží na adrese 0x0, zůstává ten, který se do zařízení dostal při prvním sériovém flashi - a to klidně před dvěma roky, s tehdejší verzí ESP-IDF.

Praktický důsledek: některé pokročilé volby ESP-IDF vyžadují bootloader z konkrétní verze frameworku nebo novější. Když takovou volbu zapnete a nahrajete přes OTA, kompilace projde, upload projde, a zařízení vůbec nenaběhne - protože starý bootloader nový obraz neumí zavést. A protože nenaběhne, nemůžete ho zachránit dalším OTA. Zbývá jedině sériové přeflashování, po kterém se bootloader konečně přepíše taky.

Nezapínejte volby, které chtějí novější bootloader, naslepo

Zvlášť když je zařízení někde, kde se k němu nedostanete s kabelem. Postup, který tenhle problém obchází: nejdřív zařízení jednou sériově přeflashujte aktuální verzí ESPHome (tím dostanete i aktuální bootloader) a teprve potom tu volbu zapněte a pošlete OTA. Pořadí opačným směrem vám může zařízení sundat ze zdi.

Čtení logů a backtrace přes sériovou linku

Když zařízení není na síti, esphome logs přes OTA vám nepomůže a webové rozhraní taky ne. Sériová linka je jediná cesta, jak se dozvědět, co se děje.

Máte tři možnosti, jak se do logu dostat:

# 1. ESPHome CLI - nejlepsi varianta, dekoduje i nazvy komponent
esphome logs muj-device.yaml --device /dev/cu.usbserial-0001

# 2. Jakykoli seriovy monitor, kdyz konfiguraci nemate po ruce
screen /dev/cu.usbserial-0001 115200
# ukonceni: Ctrl+A, potom K, potom Y

Třetí možností je čtení logu přímo v web.esphome.io - připojíte se přes Connect a kliknete na ikonu logu na kartě ESP Device (třetí v řadě, bez popisku - viz výš). Je to nejrychlejší cesta, když jen chcete vidět, co zařízení říká, a nemáte nic nainstalované.

Zařízení musí být v normálním režimu, ne v bootloader módu

V bootloader režimu čip žádný log nevypisuje, čeká na příkazy flasheru. Pro čtení logu tedy GPIO0 nechte být a zařízení nechte nabootovat normálně.

Co v logu hledat. Sériový log má tu výhodu, že vidíte i to, co se děje před tím, než se ESPHome rozběhne. První řádky přijdou přímo od bootloaderu ROM:

Řádek v loguCo znamená
rst:0x1 (POWERON_RESET)Ztráta napájení - viz boot loop výš
rst:0xc (SW_CPU_RESET)Softwarový reset, obvykle po pádu firmwaru
rst:0x10 (RTCWDT_RTC_RESET)Zakousnutý watchdog
Guru Meditation ErrorPád firmwaru, hned pod tím je backtrace
waiting for downloadČip je v bootloader režimu, GPIO0 je pořád na zemi
invalid header: 0xffffffffVe flash není platná aplikace - nedokončený flash, nebo jste nahrál obyčejný .bin místo .factory.bin
Unsuccessful boot attempts: 10Zamčené safe mode - viz výš

Backtrace samotný je řada hexadecimálních adres a bez dekódování je nečitelný. Jak z něj dostat čísla řádků, popisuju v sekci Backtrace bez sériového kabelu - potřebujete k tomu stroj, na kterém jste firmware kompiloval.

Řešení problémů

Rychlý přehled hlášení a toho, co za nimi bývá.

Port se nezobrazuje v seznamu

Postupujte v tomhle pořadí, je zhruba podle pravděpodobnosti:

  1. Vyměňte kabel. Vážně. Dokumentace ESPHome to zdůrazňuje taky: "a power only USB cable that usually comes presupplied with powerbanks won't work." Potřebujete datový kabel
  2. Nainstalujte ovladač podle čipu na adaptéru - viz tabulka výš
  3. Zkuste jiný USB port, ideálně přímo v počítači, ne v hubu
  4. Na macOS ověřte, že koukáte na /dev/cu.*, ne na tty.
  5. Na Linuxu zkontrolujte skupinu dialout
  6. Zkuste jiný adaptér - CP2102 a CH340 klony různé kvality dělají různé věci

Failed to connect to ESP32 nebo Wrong boot mode detected

Tohle hlášení je vlastně dobrá zpráva: komunikace funguje, jen se čip nepřepnul do bootloader režimu.

  • U zařízení bez USB portu ověřte, že GPIO0 byl na GND před zapnutím napájení, ne až potom
  • U desky s tlačítky použijte ruční postup: držet BOOT, ťuknout RESET, pustit BOOT
  • Zkontrolujte, že port nedrží jiný program - otevřený sériový monitor nebo běžící esphome logs je klasika. Dokumentace esptool na to výslovně upozorňuje
  • Někdy pomůže ubrat baud rate

Flash začne a spadne někde v polovině

Dokumentace esptool je v tomhle jednoznačná: "If flashing fails with random errors part way through, retry with a lower baud rate."

esptool --port /dev/cu.usbserial-0001 --baud 115200 \
write-flash 0x0 muj-firmware.factory.bin

Dokumentovaný default je 115200 a esptool na tuhle rychlost shazuje i úvodní handshake - vyšší hodnoty se použijí až na samotný přenos dat. Já sám postupuju sestupně 460800 → 115200 → 57600, ale to je moje praktická zkušenost, ne doporučení dokumentace: 460800 funguje na dobrém adaptéru a krátkých drátech, u dlouhých propojek nebo levného CH340 klonu to bývá na hraně. Pokud potřebujete vyloučit rychlost jako příčinu úplně, dokumentace navrhuje jednorázově zkusit -b 9600 - je to pomalé jako mlýn, ale odpoví vám to na otázku.

Invalid head of packet nebo poškozený log

Tohle je téměř vždycky hardware:

  • Špatný kabel - esptool to uvádí jako typickou příčinu ("Using bad quality USB cable")
  • Prohozené TX a RX. Dokumentace ESPHome to zmiňuje jako běžnou věc: "RX and TX can be sometimes swapped." Když si nejste jistý, prostě je zkuste přehodit - nic tím nezničíte
  • Chybí společná GND. Bez ní má sériový signál nedefinovanou referenci a čtou se náhodné bajty. Nejčastěji se to stane, když zařízení napájíte z externího zdroje a zapomenete GND propojit s adaptérem
  • Zkrat o kovové části uvnitř zařízení - u NSPanelu je kovové stínění displeje přímo vedle headeru
  • Dlouhé nebo tenké propojovací drátky

Firmware se nahraje, ale zařízení se nespojí s Home Assistantem

Flash tedy nebyl problém. Podívejte se do sériového logu, jestli se zařízení vůbec připojilo k Wi-Fi. Pokud vidíte No networks found a máte skrytou SSID, je dokumentovaným řešením hidden: true - pozor, patří k položce uvnitř networks:, ne do top-level wifi:. Když vám to balíček nedovolí nastavit (typicky u NSPanel Easy), pomůže wifi: fast_connect: true, které scan přeskočí a připojí se rovnou na první nakonfigurovanou síť - proč to tak je, rozebírám u NSPanelu. Zbytek diagnostiky, včetně toho, když zařízení na Wi-Fi je a přesto se neobjeví, mám v sekci Řešení problémů u ESPHome.

Nahrál jsem .bin místo .factory.bin

Nic jste nezničil, zařízení jen nemá platný obraz a v logu hlásí invalid header. Stáhněte správný soubor a nahrajte znovu - klidně bez erase-flash.

Zhodnocení

Sériové flashování má reputaci nepříjemné práce a částečně si ji zaslouží: u zařízení bez USB portu se hrabete v plastech, přidržujete drátky a hlídáte, ať nic nezkratujete. Jenže je to jediná záchranná síť, která funguje vždycky. OTA je pohodlnější, rychlejší a v devadesáti devíti procentech případů to jediné, co potřebujete - ale ve zbývajícím procentu vás zachrání jen kabel.

Co bych si z toho odnesl jako čtenář:

  • Mít doma USB-TTL adaptér, i když ho roky nepoužijete
  • Napájet z +5V, ne z 3V3 převodníku
  • safe_mode: storage: rtc do každé konfigurace
  • Datový kabel, ne ten od powerbanky
  • Nevěřit factory.bin, že smaže všechno
  • Nezapínat volby chtějící nový bootloader přes OTA naslepo
  • Nehledat chybu ve firmwaru, dokud nemáte ověřené napájení
  • Nemít 5 V na datových pinech

A jednu věc bych si přál vědět dřív: vzdálený build. Roky jsem čekal na kompilaci na slabém serveru s tím, že se s tím nic dělat nedá, a přitom to ESPHome umí samo - konfigurace zůstane na jednom místě a počítá to stroj, který na to má. Jestli vám Home Assistant běží na Raspberry Pi nebo na NASu, začněte tady.

Ta jedna řádka safe_mode: storage: rtc je pak z celého článku nejlepší investice. Napsání zabere pět sekund a v den, kdy vám zařízení nenaskočí, vám ušetří celé odpoledne se šroubovákem.

Související články

Zdroje

Pomohl vám tenhle návod?

Návody tu píšu ve volném čase a udržuju je aktuální. Když vám některý ušetřil čas, můžete přispět.

Jednorázově, kartou nebo Apple Pay. Částku lze na další stránce změnit.

Nechcete posílat peníze? Kupujte podle návodů přes moje odkazy na produkty. Cena je pro vás stejná a pomůže to taky.

Komentáře