Install The Library

We recomend you to install our library component from espressif registery here.

You can find the library and example here. You can also download it.

Important note

Please be aware that you must choose the correct partition and flash size to get the library to work correctly. see here.

IDF Library Reference

Below is the list of OTAdrive library methods.

Method Description
setInfo Sets general information about your firmware. You should call this method first.
updateFirmwareInfo Returns data about new firmware on the OTAdrive if available. It's useful to show users some data before starting the update progress.
updateFirmware Updates firmware from the OTAdrive server, if a newer version is available.
Events Events of the library
downloadConfigValues Downloads all config paramerters of the device
getConfigValue Gets device configuration by a key-value mechanism
timeTick A helper for periodical syncing
getChipId Get the chip serial number, if it has been overwriting, then returns a new value
setChipId Overwrites the chip serial number

setInfo

void otadrive_setInfo(char *apiKey, char *current_version)

You have to call setInfo once and before any usage of OTAdrive library. This method gives the APIkey and the version of the application (your code).

void app_main(void)
{
  ...
  // Set ApiKey and firmware version of your device
  // Remember, You have to change the version field before
  //   upload the firmware.bin to the OTAdrive
  otadrive_setInfo("c0af643b-4f90-4905-9807-db8be5164cde", "v@2.5.5");
}

updateFirmwareInfo

otadrive_result otadrive_updateFirmwareInfo()

This method calls to update firmware API and gets the status of the new firmware if a newer(different) version is available on the OTAdrive server. You can show the information to the user.

otadrive_result uinf = otadrive_updateFirmwareInfo();
if (uinf.available)
{
  ESP_LOGI("A new version %s with size %dBytes available.\n", uinf.version, uinf.size);
  // wait user to click OK button to start download
  for (uint8_t time = 0; time < 30; time++)
  {
    if (digitalRead(BTN_ON))
    {
      otadrive_updateFirmware(true);
    }
  }
}

updateFirmware

otadrive_result otadrive_updateFirmware(bool reboot)

This method calls update firmware API and updates your ESP8266/ESP32 firmware if a newer(different) version available on the OTAdrive server. You can show the update progress to users by registering to the Events event.
After successfull firmware update, the device should reset. If you want to do something before restart (for exampl save some value), you should pass reboot parameter as false, then you have to call esp_restart() yourself.

// The device will reboot here on success update
otadrive_result r = otadrive_updateFirmware(true);
ESP_LOGI("Update result is: %d\n", r.code);

Events

The OTADRIVE_EVENTS event class is defined in essoerssif event system to notify the background progresses to you.
Here is regular event process method you can use in your application:

static void otadrive_event_handler(void *arg, esp_event_base_t event_base,
                                   int32_t event_id, void *event_data)
{
    if (event_base == ESP_HTTPS_OTA_EVENT)
    {
        switch (event_id)
        {
        case ESP_HTTPS_OTA_START:
            ESP_LOGI(TAG, "OTA started");
            break;
        case ESP_HTTPS_OTA_CONNECTED:
            ESP_LOGI(TAG, "Connected to server");
            break;
        case ESP_HTTPS_OTA_GET_IMG_DESC:
            ESP_LOGI(TAG, "Reading Image Description");
            break;
        case ESP_HTTPS_OTA_VERIFY_CHIP_ID:
            ESP_LOGI(TAG, "Verifying chip id of new image: %d", *(esp_chip_id_t *)event_data);
            break;
        case ESP_HTTPS_OTA_DECRYPT_CB:
            ESP_LOGI(TAG, "Callback to decrypt function");
            break;
        case ESP_HTTPS_OTA_WRITE_FLASH:
            ESP_LOGD(TAG, "Writing to flash: %d written", *(int *)event_data);
            break;
        case ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION:
            ESP_LOGI(TAG, "Boot partition updated. Next Partition: %d", *(esp_partition_subtype_t *)event_data);
            break;
        case ESP_HTTPS_OTA_FINISH:
            ESP_LOGI(TAG, "OTA finish");
            break;
        case ESP_HTTPS_OTA_ABORT:
            ESP_LOGI(TAG, "OTA abort");
            break;
        }
    }
}

downloadConfigValues

bool otadrive_downloadConfigValues()

This method calls configuration API and gets the device's configuration from the server. It returns true on success.

if(otadrive_downloadConfigValues())
{
    ESP_LOGI("Configs downloaded");
    // lets decode and save config values
}

getConfigValues

bool otadrive_getConfigValue(char *key, char *o_value, int o_maxlen)

you should use this after a successful call of the downloadConfigValues. The method searchs for the given key in the downloaded data and fills the o_value buffer. The o_maxlen is the maximum length of the o_value.

For example we defined following confing in the server.

{
    "speed":180,
    "alarm":{
        "number":"+188554436",
        "msg1":"Fire, please help",
        "msg2":"Emergency, please help"
    }
}

Then your code to load configuration should be something like this.

// define key-value object in global
int speed = 100;
char n_buf[10];
char alarm_num[64];
char alarm_msg1[64];
char alarm_msg2[64];
...
// download configs
if(otadrive_downloadConfigValues())
{
    ESP_LOGI("Configs downloaded");
    // lets decode and save config values
    if(otadrive_getConfigValue("speed", n_buf, sizeof(n_buf)))
    {
        ESP_LOGI("configuration parameter [speed]: %s\n", n_buf);
        speed = atoi(n_buf);
    }
    if(otadrive_getConfigValue("alarm.number", alarm_num, sizeof(alarm_num)))
        ESP_LOGI("configuration parameter [alarm.number]: %s\n", alarm_num);
    if(otadrive_getConfigValue("alarm.msg1", alarm_msg1, sizeof(alarm_msg1)))
        ESP_LOGI("configuration parameter [alarm.msg1]: %s\n", alarm_msg1);
    if(otadrive_getConfigValue("alarm.msg2", alarm_msg2, sizeof(alarm_msg2)))
        ESP_LOGI("configuration parameter [alarm.msg2]: %s\n", alarm_msg2);
}

setChipId

void otadrive_setChipId(char *serial)

The library uses the chip's MAC address as the device serial number. If you want to use something else as the serial number, you have to call this method after setInfo on the setup procedure.

void app_main()
{
    ...
    otadrive_setInfo(APIKEY, FW_VER);
    // change the serial number to something else
    // for example obtain it from gsm modem IMEI, external EEPROM uid, etc.
    char* myNewSerial = some_method();
    otadrive_setChipId(myNewSerial);
}

getChipId

char *otadrive_getChipId()

Return the serial number of the chip, using in the library and server. The library uses the chip's MAC address as the device serial number. If you want to use something else as the serial number, you have to call setInfo on the setup procedure.

void app_main()
{
    ...
    otadrive_setInfo(APIKEY, FW_VER);
    // print chip serial to monitor
    ESP_LOGI(TAG, "Chip Id = %s", otadrive_getChipId());
}

timeTick

bool otadrive_timeTick(uint16_t seconds)

This method helps you to manage intervals between each update/sync operation between your device and the OTAdrive.
The following example shows how to check and update firmware every 5 minutes (300 seconds).

void loop()
{
  ...
  // every 5 minutes
  if (otadrive_timeTick(300))
  {
    otadrive_result r = otadrive_updateFirmware(true);
    ESP_LOGI("Update result is: %d\n", r.code);
  }
}