Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: unified Over-The-Air (OTA) upgrades #2332

Merged
merged 16 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 15 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Table of Contents
* [Connect to WiFi](#connect-to-wifi)
* [Read DHT22 sensor](#read-dht22-sensor)
* [HTTP Client](#http-client)
* [OTA Application Update Based on rBoot](#ota-application-update-based-on-rboot)
* [OTA Application Update](#ota-application-update)
* [HTTP Server](#http-server)
* [Email Client](#email-client)
* [Live Debugging](#live-debugging)
Expand Down Expand Up @@ -161,7 +161,7 @@ And check some of the examples.
- [Connect to WiFi](#connect-to-wifi)
- [Read DHT22 sensor](#read-dht22-sensor)
- [HTTP Client](#http-client)
- [OTA Application Update Based on rBoot](#ota-application-update-based-on-rboot)
- [OTA Application Update](#ota-application-update)
- [HTTP Server](#http-server)
- [Email Client](#email-client)

Expand Down Expand Up @@ -236,44 +236,31 @@ void onDataSent(HttpClient& client, bool successful)

For more examples take a look at the [HttpClient](samples/HttpClient/app/application.cpp), [HttpClient_Instapush](samples/HttpClient_Instapush/app/application.cpp) and [HttpClient_ThingSpeak](samples/HttpClient_ThingSpeak/app/application.cpp) samples.

### OTA Application Update Based on rBoot
### OTA Application Update
```c++
void OtaUpdate()
void doUpgrade()
{
  uint8 slot;
  rboot_config bootconf;
// need a clean object, otherwise if run before and failed will not run again
if(otaUpdater) {
delete otaUpdater;
}
otaUpdater = new Ota::Network::HttpUpgrader();

  Serial.println("Updating...");
// select rom partition to flash
auto part = ota.getNextBootPartition();

  // need a clean object, otherwise if run before and failed will not run again
  if (otaUpdater) {
    delete otaUpdater;
  }

  otaUpdater = new RbootHttpUpdater();

  // select rom slot to flash
  bootconf = rboot_get_config();
  slot = bootconf.current_rom;
  if (slot == 0) {
    slot = 1;
  }
  else {
    slot = 0;
  }

  // flash rom to position indicated in the rBoot config rom table
  otaUpdater->addItem(bootconf.roms[slot], ROM_0_URL);
  // The content located on ROM_0_URL will be stored to the new partition
  otaUpdater->addItem(ROM_0_URL, part);

  // and/or set a callback (called on failure or success without switching requested)
  otaUpdater->setCallback(OtaUpdate_CallBack);
  otaUpdater->setCallback(upgradeCallback);

  // start update
  otaUpdater->start();
}
```

For a complete example take a look at the [Basic_rBoot](samples/Basic_rBoot/app/application.cpp) sample.
For a complete example take a look at the [Basic_Ota](samples/Basic_Ota/app/application.cpp) sample.

### HTTP Server
```c++
Expand Down
33 changes: 33 additions & 0 deletions Sming/Arch/Esp32/spiffs-two-roms.hw
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "Two ROM slots with single SPIFFS",
"base_config": "spiffs",
"partitions": {
"factory": {
"size": "1M"
},
"rom0": {
"address": "0x110000",
"size": "960K",
"type": "app",
"subtype": "ota_0",
"filename": "$(TARGET_BIN)"
},
"ota": {
"address": "0x00200000",
"size": "8K",
"type": "data",
"subtype": "ota"
},
"rom1": {
"address": "0x210000",
"size": "960K",
"type": "app",
"subtype": "ota_1",
"filename": ""
},
"spiffs0": {
"address": "0x300000",
"size": "1M"
}
}
}
4 changes: 2 additions & 2 deletions Sming/Arch/Esp8266/spiffs-two-roms.hw
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"subtype": "ota_0"
},
"rom1": {
"address": "0x108000",
"address": "0x102000",
"size": "992K",
"type": "app",
"subtype": "ota_1",
"filename": "$(RBOOT_ROM_1_BIN)"
"filename": "$(RBOOT_ROM_0_BIN)"
}
}
}
61 changes: 61 additions & 0 deletions Sming/Components/Ota/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Over-The-Air(OTA) Upgrader
==========================

.. highlight:: c++

Introduction
------------

This architecture-agnostic component adds support for Over-The-Air upgrades.

Usage
-----
1. Add ``COMPONENT_DEPENDS += Ota`` to your application componenent.mk file.
2. Add these lines to your application::

#include <Ota/Manager.h>

After that you will have access to a global ``OtaManager`` instance that can be used to manage your OTA upgrade process.

3. You can use ``OtaManager`` to get information about the bootable partitions and update them.
The code below will display the current bootable and running partition::

void init()
{

// ...
auto partition = OtaManager.getRunningPartition();

Serial.printf("\r\nCurrently running %s @ 0x%08x.\r\n", partition.name().c_str(), partition.address());

}

4. If needed you can also create your own instance of the of OtaUpgrader as shown below::


// Call when IP address has been obtained
void onIp(IpAddress ip, IpAddress mask, IpAddress gateway)
{
// ...

OtaUpgrader ota;

auto part = ota.getNextBootPartition();

ota.begin(part);

// ... write all the data to the partition

ota.end();

// ...
}

See the :sample:`Upgrade` sample application.

API Documentation
-----------------

.. doxygennamespace:: Ota
:members:

16 changes: 16 additions & 0 deletions Sming/Components/Ota/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
COMPONENT_ARCH := $(SMING_ARCH)
ifeq ($(COMPONENT_ARCH),Host)
COMPONENT_ARCH := Esp8266
endif

COMPONENT_SRCDIRS := \
src \
src/Arch/$(COMPONENT_ARCH)

COMPONENT_INCDIRS := \
src/include \
src/Arch/$(COMPONENT_ARCH)/include

ifeq ($(COMPONENT_ARCH),Esp8266)
COMPONENT_DEPENDS += rboot
endif
Empty file added Sming/Components/Ota/src/.cs
Empty file.
47 changes: 47 additions & 0 deletions Sming/Components/Ota/src/Arch/Esp32/IdfUpgrader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* IdfUpgrader.cpp
*
****/

#include "include/Ota/IdfUpgrader.h"

namespace Ota
{
bool IdfUpgrader::begin(Partition partition, size_t size)
{
if(partition.size() < size) {
return false; // the requested size is too big...
}

writtenSoFar = 0;
maxSize = size ?: partition.size();

esp_err_t result = esp_ota_begin(convertToIdfPartition(partition), maxSize, &handle);

return result == ESP_OK;
}

size_t IdfUpgrader::write(const uint8_t* buffer, size_t size)
{
if(writtenSoFar + size > maxSize) {
// cannot write more bytes than allowed
return 0;
}

esp_err_t result = esp_ota_write(handle, buffer, size);
if(result != ESP_OK) {
// write failed
return 0;
}

writtenSoFar += size;

return size;
}

} // namespace Ota
slaff marked this conversation as resolved.
Show resolved Hide resolved
77 changes: 77 additions & 0 deletions Sming/Components/Ota/src/Arch/Esp32/include/Ota/IdfUpgrader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* IdfUpgrader.h
*
* This header includes all unified Over-The-Air functions.
*
*/

#pragma once
#include <Ota/UpgraderBase.h>
#include <esp_ota_ops.h>

namespace Ota
{
class IdfUpgrader : public UpgraderBase
{
public:
slaff marked this conversation as resolved.
Show resolved Hide resolved
bool begin(Partition partition, size_t size = 0) override;
size_t write(const uint8_t* buffer, size_t size) override;

bool end() override
{
return esp_ota_end(handle) == ESP_OK;
}

bool abort() override
{
return true;
}

bool setBootPartition(Partition partition, bool save = true) override
{
if(!save) {
return false;
}

return esp_ota_set_boot_partition(convertToIdfPartition(partition)) == ESP_OK;
}

Partition getBootPartition() override
{
return convertFromIdfPartition(esp_ota_get_boot_partition());
}

Partition getRunningPartition() override
{
return convertFromIdfPartition(esp_ota_get_running_partition());
}

Partition getNextBootPartition(Partition startFrom = {}) override
{
const esp_partition_t* idfFrom = startFrom ? convertToIdfPartition(startFrom) : nullptr;
return convertFromIdfPartition(esp_ota_get_next_update_partition(idfFrom));
}

static const esp_partition_t* convertToIdfPartition(Partition partition)
{
return esp_partition_find_first(esp_partition_type_t(partition.type()),
esp_partition_subtype_t(partition.subType()), partition.name().c_str());
}

static Partition convertFromIdfPartition(const esp_partition_t* partition)
{
return partition ? Storage::findPartition(String(partition->label)) : Partition{};
}

private:
size_t maxSize{0};
size_t writtenSoFar{0};
esp_ota_handle_t handle{};
};

} // namespace Ota
16 changes: 16 additions & 0 deletions Sming/Components/Ota/src/Arch/Esp32/include/Ota/Upgrader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* Upgrader.h
*
* This header includes all unified Over-The-Air functions.
*
*/

#pragma once
#include "IdfUpgrader.h"

using OtaUpgrader = Ota::IdfUpgrader;
Loading