github_dfu

Example of the component matterizelabs/esp_gh_ota v1.1.1
# github_dfu example

Reference app for the [`matterizelabs/esp_gh_ota`](https://components.espressif.com/components/matterizelabs/esp_gh_ota) component. Connects to WiFi, starts the config HTTP API, and polls GitHub Releases for firmware updates; flashes a new release when one is detected.

## Build & flash this example

```bash
cp sdkconfig.secrets.example sdkconfig.secrets
# edit sdkconfig.secrets — fill in WiFi SSID and password
idf.py set-target esp32
idf.py build flash monitor
```

`sdkconfig.defaults` enables partial HTTP download, OTA resumption, and
anti-rollback. Anti-rollback burns eFuses one-way — comment out
`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK=y` for dev devices.

## Wire it into your own project

Start from the ESP-IDF `hello-world` (or any template) and add three things.

**1. Declare the dependency** — `main/idf_component.yml`:

```yaml
dependencies:
  matterizelabs/esp_gh_ota: "^1.0.1"
```

(plus your WiFi-connect helper if you use one; this example uses
`protocol_examples_common` from the IDF tree).

**2. Require the component** — `main/CMakeLists.txt`:

```cmake
idf_component_register(SRCS "app_main.c"
                    INCLUDE_DIRS "."
                    PRIV_REQUIRES esp_gh_ota
                                  nvs_flash
                                  esp_netif
                                  esp_event
                                  esp_wifi
                                  app_update
                                  esp_https_ota)
```

**3. Bootwire in `app_main`** — `main/app_main.c`:

```c
#include "esp_log.h"
#include "esp_event.h"
#include "esp_system.h"
#include "esp_ota_ops.h"
#include "esp_https_ota.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "github_ota.h"

static const char *TAG = "main";

static void ota_event_handler(void *arg, esp_event_base_t base,
                              int32_t id, void *data)
{
    if (base != ESP_HTTPS_OTA_EVENT) return;
    switch (id) {
    case ESP_HTTPS_OTA_START:    ESP_LOGI(TAG, "OTA started");      break;
    case ESP_HTTPS_OTA_CONNECTED:ESP_LOGI(TAG, "connected");       break;
    case ESP_HTTPS_OTA_FINISH:   ESP_LOGI(TAG, "OTA finish");       break;
    case ESP_HTTPS_OTA_ABORT:    ESP_LOGW(TAG, "OTA abort");        break;
    default: break;
    }
}

void app_main(void)
{
    /* 1. NVS (component stores config + resumption state here) */
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);

    /* 2. netif + default event loop + OTA event logging */
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTPS_OTA_EVENT, ESP_EVENT_ANY_ID,
                                               &ota_event_handler, NULL));

    /* 3. WiFi — use your own connect here; example_connect() is from
     *    protocol_examples_common. Max throughput for OTA. */
    ESP_ERROR_CHECK(example_connect());
    esp_wifi_set_ps(WIFI_PS_NONE);

    /* 4. (optional) cancel a pending rollback from a previous OTA */
#if defined(CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE)
    const esp_partition_t *running = esp_ota_get_running_partition();
    esp_ota_img_states_t ota_state;
    if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK &&
        ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
        esp_ota_mark_app_valid_cancel_rollback();
    }
#endif

    /* 5. Start the /api/config HTTP endpoint + the GitHub poller task */
    ESP_ERROR_CHECK(github_config_api_start());
    github_poller_start();
}
```

That's the whole integration: `github_config_api_start()` brings up the
runtime config endpoint; `github_poller_start()` spawns the task that polls
GitHub and flashes new releases.

## Runtime config

Defaults come from `CONFIG_ESP_GH_OTA_DEFAULT_OWNER` / `CONFIG_ESP_GH_OTA_DEFAULT_REPO`
(or NVS if previously saved). Override at runtime over HTTP:

```bash
# point the device at a repo + (optional) private-repo token
curl -X POST http://<esp-ip>/api/config -H 'Content-Type: application/json' \
  -d '{"owner":"matterizelabs","repo":"esp-github-dfu","token":"ghp_xxx"}'

# inspect current config + running firmware version
curl http://<esp-ip>/api/config
```

A config change wakes the poller immediately (no need to wait for the next
interval).

## Release workflow

Push a strict `vX.Y.Z` tag to the firmware repo to trigger its CI build +
GitHub Release with the `.bin` asset attached. The device polls every 5
minutes (default) and OTA-updates when a newer version is detected.

To create a project from this example, run:

idf.py create-project-from-example "matterizelabs/esp_gh_ota=1.1.1:github_dfu"

or download archive (~4.63 KB)