{"id":20341941,"url":"https://github.com/douglaszuqueto/esp32-ota","last_synced_at":"2025-04-11T23:34:19.505Z","repository":{"id":91302762,"uuid":"181249663","full_name":"douglaszuqueto/esp32-ota","owner":"douglaszuqueto","description":"ESP32 OTA Server","archived":false,"fork":false,"pushed_at":"2020-02-27T22:30:12.000Z","size":123,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T19:21:20.141Z","etag":null,"topics":["esp32","iot","ota"],"latest_commit_sha":null,"homepage":"https://github.com/douglaszuqueto/esp32-ota","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/douglaszuqueto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-14T02:12:43.000Z","updated_at":"2024-03-24T04:07:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"7c8450c9-7b73-4bb9-957d-7f3ca96105e0","html_url":"https://github.com/douglaszuqueto/esp32-ota","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/douglaszuqueto%2Fesp32-ota","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/douglaszuqueto%2Fesp32-ota/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/douglaszuqueto%2Fesp32-ota/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/douglaszuqueto%2Fesp32-ota/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/douglaszuqueto","download_url":"https://codeload.github.com/douglaszuqueto/esp32-ota/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248495182,"owners_count":21113581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32","iot","ota"],"created_at":"2024-11-14T21:29:49.480Z","updated_at":"2025-04-11T23:34:19.493Z","avatar_url":"https://github.com/douglaszuqueto.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# ESP32 - OTA\n\n## Índice\n\n## Esquema de partições (em testes)\n\nDentre algumas discussões com o José(Zé) envolvendo **OTA**, foi 'descoberto' que os esquemas de partição disponíveis para o ESP32 na IDE do Arduino(integração [arduino-esp32](https://github.com/espressif/arduino-esp32)) não tinha disponível uma partição valiosa denominada *factory*!\n\nEssa partição podemos dizer que pode ser considerada como *'padrão de fábrica'*, ou seja, é o último firmware gravado via cabo em seu esp32. Toda atualização utilizando OTA será gravado nas partições *app0* e *app1*.\n\nEntão no lugar de termos 2 partições ota0 e ota1 que o esquema padrão(default) nos trás, nos teremos 3 partições. Cada uma terá 1MB de armazenamento para seu firmware - é claro que com essa opção, se terá um custo! Você terá um espaço de armazenamento menor para seu firmware como consequência.\n\nEntão imagine um cenário onde você utilize OTA e por algum motivo seu firmware bugou ou algo equivalente, portanto talvez sua última chance seria voltar para a partição factory! Nessa partição o Zé deu a ideia de deixar um firmare bem cru contendo apenas uma camada de OTA para aceitar novos updades.\n\nCaso você fique sem comunicação alguma, pode-se adicionar até um push button para realizar esse rollback para factory - um caso bem real por sinal :)\n\nBem, chega de enrolação, abaixo seguem alguns passos e informações para poder ser adicionado essa nova partição ao seu ambiente.\n\n* Esquema default\n\nEsse é o schema que geralmente é utilizado durante as gravações de firmware. Portanto todas gravações serão feitas e alternadas entre app0 e app1.\n\n**Name**|**Type**|**SubType**|**Offset**|**Size**|**Flags**\n:-----:|:-----:|:-----:|:-----:|:-----:|:-----:\nnvs|      data| nvs|     0x9000|  0x5000| \notadata|  data| ota|     0xe000|  0x2000| \napp0|     app|  ota_0|   0x10000| 0x140000| \napp1|     app|  ota_1|   0x150000|0x140000| \neeprom|   data| 0x99|    0x290000|0x1000| \nspiffs|   data| spiffs|  0x291000|0x16F000|\n\n### Diagrama de funcionamento(referência em anexo)\n\nPara ficar mais claro o fluxo de atualizações, acabei achando o diagrama(sem querer rsrs) onde esse fluxo é ilustrado.\n\n![img](https://cdn-images-1.medium.com/max/800/1*s320_ezWr_0EUvkg5Y9Edg.png)\n\n### Criando um novo schema de partição - Factory\n\n* Passo 1\n\nCrie o arquivo CSV no diretório conforme modelo descrito abaixo: **/home/dzuqueto/Arduino/hardware/espressif/esp32/tools/partitions/factory.csv**\n\n**Name**|**Type**|**SubType**|**Offset**|**Size**|**Flags**\n:-----:|:-----:|:-----:|:-----:|:-----:|:-----:\nnvs|      data| nvs|     0x9000|  0x5000| \notadata|  data| ota|     0xe000|  0x2000| \nfactory|app|factory|0x10000|1M| \napp0|     app|  ota_0|0x110000|1M| \napp1|     app|  ota_1|0x210000|1M| \n\nCaso deseje fazer o download do arquivo, segue o link: **[factory.csv](https://raw.githubusercontent.com/douglaszuqueto/esp32-ota/master/.github/factory.csv)**\n\nPara mais detalhes sobre partições e particionamento, segue link da documentação: [Link](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html)\n\n**Obs:** O caminho do arquivo irá variar dependendo do seu sistema operacional!\n\n* Passo 2\n\nPara incluir a opção do novo schema criado(Factory), se faz necessário a edição do seguinte arquivo:  **/home/dzuqueto/Arduino/hardware/espressif/esp32/boards.txt**\n\nLevando-se em consideração que a placa alvo seja o modelo **ESP32 Dev Module**, o que você verá no arquivo será algo como:\n\n```\nesp32.menu.PartitionScheme.default=Default\nesp32.menu.PartitionScheme.default.build.partitions=default\nesp32.menu.PartitionScheme.minimal=Minimal (2MB FLASH)\nesp32.menu.PartitionScheme.minimal.build.partitions=minimal\nesp32.menu.PartitionScheme.no_ota=No OTA (Large APP)\nesp32.menu.PartitionScheme.no_ota.build.partitions=no_ota\nesp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152\nesp32.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA)\nesp32.menu.PartitionScheme.huge_app.build.partitions=huge_app\nesp32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728\nesp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)\nesp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs\nesp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080\nesp32.menu.PartitionScheme.fatflash=16M Fat\nesp32.menu.PartitionScheme.fatflash.build.partitions=ffat\n```\n\nAdicione as seguintes linhas:\n\n```\nesp32.menu.PartitionScheme.factory=Factory\nesp32.menu.PartitionScheme.factory.build.partitions=factory\nesp32.menu.PartitionScheme.factory.upload.maximum_size=1024000\n```\n\n* Resultado final na IDE\n\n![img](https://raw.githubusercontent.com/douglaszuqueto/esp32-ota/master/.github/arduino-ide-v1.png)\n\n* Passo 3: Alteração do arquivo *boot_app0.bin* (update)\n\nDepois de ter feito vários testes, foi observado que o comportamento que o fluxo de atualização deveria seguir não estava correto. Foi ao que recorri ao Zé para saber um pouco mais sobre - se realmente o comportamento que estava acontecendo era de fato um problema!\n\nDesde então começamos a fazer uma rotina de muitos testes para tentar encontrar o real problema que estava acontecendo.\n\nObserve novamente o diagrama de fluxo abaixo: \n![img](https://cdn-images-1.medium.com/max/800/1*s320_ezWr_0EUvkg5Y9Edg.png)\n\nO que eu havia mencionado la no inicio não estava 'acontecendo': \"é o último firmware gravado via cabo em seu esp32.\". O que deu para se entender é que, como a IDE não estava preparada para ter uma partição factory, alguns binários essenciais para o funcionamento do ESP32 também não estavam.\n\nEntão o que de fato acontecia? Com os partições geradas o upload era feito normalmente, ficando hospedado e rodando na partição factory. Quando era feita uma atualização OTA por meio de HTTP, o fluxo ia para app0 e dava boot na partição app0, tudo correto! O problema estava em fazer upload novamente via IDE do Arduino... o firmware era gravado normalmente, porém o boot iniciava em qual partição? app0 ou app1 kkk.\n\nSó depois de inúmeros testes comecei a entender os problemas e as peças começaram a se encaixar. No processo de build/upload 4 arquivos binários são gerados/utilizados e os mesmos são enviados para o ESP32, cada um no seu respectivo endereço de memória.\n\n* Bootloader\n* Otadata ( boot_app0.bin )\n* Partitions\n* App\n\nApenas 2 da lista acima eram gerados a cada build do firmware: Partitions e App - ambos ficam armazenados na pasta temporária do sistema juntamente com outros arquivos.\n\nBootloader e otadata sempre eram os mesmos. Foi ai que surgiu uma grande curiosidade e possível causa do problema, pois utilizando ESP-IDF, em todo build os 4 arquivos sempre eram gerados.\n\nEntão na rotina de testes, eu peguei os 2 arquivos(os fixos) gerados e realizei a substituição na pasta onde estavam armazenados, então ai eu consegui desmistificar o grande mistério. O grande vilão da jogada era o **boot_app0.bin**, como ele era fixo e não existia partição factory, certamente algo dentro dele se fazia essencial para o correto fluxo de atualizações.\n\nMas e agora, como resolver esse 'pequeno' problema?\n\nVamos la, os 2 arquivos mencionados ficam dentro da pasta onde suas ferramentas para usar esp32 estão instaladas.\n\n* Bootloader - /home/dzuqueto/Arduino/hardware/espressif/esp32/tools/sdk/bin\n* boot_app0 - /home/dzuqueto/Arduino/hardware/espressif/esp32/tools/partitions\n\nO que precisa ser alterado é apenas o boot_app0. Segue um gabarito da pasta *partitions* para você se localizar melhor:\n\n```\n.\n├── boot_app0.bin\n├── boot_app0 (cópia).bin\n├── boot_app0 (outra cópia).bin\n├── default_16MB.csv\n├── default_8MB.csv\n├── default.bin\n├── default.csv\n├── factory.csv\n├── ffat.csv\n├── huge_app.csv\n├── large_spiffs_16MB.csv\n├── minimal.csv\n├── min_spiffs.csv\n├── no_ota.csv\n└── partitions.bin\n```\n\nPode ver que eu fiz algumas cópias de segurança para não perder o arquivo original. Caso você deseja efetuar todo esse processo segue o link de download do binário: [boot_app0.bin](https://raw.githubusercontent.com/douglaszuqueto/esp32-ota/master/.github/boot_app0.bin)\n\nDepois de todas essas modificações, eu refiz todos os testes, inclusive com a partição padrão, e mesmo com a alteração do arquivo, tudo funcionou perfeitamente! Recomendo que teste o exemplo que deixei abaixo - [Blink OTA](https://github.com/douglaszuqueto/esp32-ota#blink---ota)\n\nEu acredito que, caso você faça todo esse processo tudo irá funcionar corretamente. Mas caso não ocorra, pode me chamar no telegram ou no [Grupo do FernandoK(Telegram)](https://t.me/fernandok_oficial) onde toda essa discussão se desenrolou.\n\n## Blink\n\n```c\n#include \"freertos/FreeRTOS.h\"\n#include \"esp_ota_ops.h\"\n\n#define LED_BUILTIN 2\n\nvoid setup() {\n  pinMode(LED_BUILTIN, OUTPUT);\n  Serial.begin(115200);\n}\n\nString getRunningPartition() {\n  const esp_partition_t* partition = esp_ota_get_running_partition();\n  Serial.printf(\"Partition: %s\\n\", partition-\u003elabel);\n\n  return partition-\u003elabel;\n}\n\nvoid loop() {\n  digitalWrite(LED_BUILTIN, HIGH);\n  delay(1000);\n  digitalWrite(LED_BUILTIN, LOW);\n  delay(1000);\n\n  getRunningPartition();\n}\n```\n\nCom a função *esp_ota_get_running_partition()* você sempre saberá em que partição seu firmware estará rodando!\n\n```c\nString getRunningPartition() {\n  const esp_partition_t* partition = esp_ota_get_running_partition();\n  Serial.printf(\"Partition: %s\\n\", partition-\u003elabel);\n\n  return partition-\u003elabel;\n}\n```\n\n## Blink - OTA\n\nAbaixo segue um exemplo de OTA utilizando a biblioteca que o [Zé](https://www.facebook.com/JoseMorais69) desenvolveu. Para mais detalhes acesse: [link](https://github.com/urbanze/esp32_gota)\n\nFica também uma referéncia ao post que ele fez no Grupo Arduino Brasil falando um pouco sobre sua biblioteca: [link](https://www.facebook.com/groups/arduino.br/permalink/2285458301493259/)\n\n```c\n#include \u003chttp.h\u003e\n#include \u003cWiFi.h\u003e\n#include \"esp_ota_ops.h\"\n\n#define LED_BUILTIN 2\n#define WIFI_SSID \"\"\n#define WIFI_PASSWORD \"\"\n\nString getRunningPartition() {\n  const esp_partition_t* partition = esp_ota_get_running_partition();\n  Serial.printf(\"Partition: %s\\n\", partition-\u003elabel);\n\n  return partition-\u003elabel;\n}\n\nvoid setup()\n{\n  Serial.begin(115200);\n  pinMode(LED_BUILTIN, OUTPUT);\n\n  WiFi.mode(WIFI_STA);\n  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);\n\n  OTA_HTTP ota;\n  ota.init();\n}\n\nvoid loop()\n{\n  digitalWrite(LED_BUILTIN, HIGH);\n  delay(1000);\n  digitalWrite(LED_BUILTIN, LOW);\n  delay(1000);\n\n  getRunningPartition();\n}\n```\n\n## Referências\n\nhttps://blog.classycode.com/over-the-air-updating-an-esp32-29f83ebbcca2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdouglaszuqueto%2Fesp32-ota","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdouglaszuqueto%2Fesp32-ota","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdouglaszuqueto%2Fesp32-ota/lists"}