Skip to content

Commit

Permalink
[ESP32] CLI option to set delayed action time in OTA Provider app and…
Browse files Browse the repository at this point in the history
… restart OTA Requestor once ApplyUpdate is successful (#13620)

* [ESP32] CLI option to set delayedActionTime in OTA Provider app

Also, modify Linux OTA Provider help for delayedActionTime cli option

* [ESP32] Schedule the restart once OTA image apply is successful

Also, Apply suggestion from #13484 in lighting-app

* Review comments

* Fix a small typo

* Apply suggestions from code review

Co-authored-by: Carol Yang <[email protected]>

Co-authored-by: Carol Yang <[email protected]>
  • Loading branch information
shubhamdp and carol-apple authored Jan 21, 2022
1 parent 7e09d15 commit dd209ce
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 37 deletions.
1 change: 1 addition & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ OTA
OTADownloader
OTAImageProcessorDriver
OTAImageProcessorInterface
OTAProvider
OTAProviderIpAddress
OTAProviderNodeId
OTAProviderSerialPort
Expand Down
11 changes: 6 additions & 5 deletions examples/lighting-app/esp32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug c

hello-world.bin can be obtained from compiling the hello-world ESP-IDF example.

- Provision the Linux OTA Provider using chip-tool
- Commission the Linux OTA Provider using chip-tool

```
./out/debug/chip-tool pairing onnetwork 12345 20202021
./out/debug/chip-tool pairing onnetwork 12346 20202021
```

## Query for an OTA Image
Expand All @@ -154,10 +154,11 @@ After commissioning is successful, press Enter in requestor device console and
type below query.

```
>matter ota query 1 12345 0
>matter ota query 1 12346 0
```

## Apply update

Once transfer is complete, reboot the device manually to boot from upgraded OTA
image.
Once the transfer is complete, OTA requestor sends ApplyUpdateRequest command to
OTA provider for applying the image. Device will restart on successful
application of OTA image.
4 changes: 1 addition & 3 deletions examples/lighting-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,10 @@ static void InitOTARequestor(void)
{
#if CONFIG_ENABLE_OTA_REQUESTOR
SetRequestorInstance(&gRequestorCore);
gRequestorCore.SetServerInstance(&Server::GetInstance());
gRequestorCore.SetOtaRequestorDriver(&gRequestorUser);
gRequestorCore.Init(&Server::GetInstance(), &gRequestorUser, &gDownloader);
gImageProcessor.SetOTADownloader(&gDownloader);
gDownloader.SetImageProcessorDelegate(&gImageProcessor);
gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
gRequestorCore.SetBDXDownloader(&gDownloader);
#endif
}

Expand Down
9 changes: 9 additions & 0 deletions examples/ota-provider-app/esp32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ idf.py -p <OTAProviderSerialPort> flash
./out/debug/chip-tool pairing ble-wifi 12345 <ssid> <passphrase> 20202021 3841
```

## Set delayed action time (Optional)

- Set delayed action time in the Query Image Response and Apply Update
Response, default is zero.

```
> matter OTAProvider delay <delay seconds>
```

---

Once OTA provider is commissioned then head over to
Expand Down
1 change: 1 addition & 0 deletions examples/ota-provider-app/esp32/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ idf_component_register(PRIV_INCLUDE_DIRS
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-provider"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension"
EXCLUDE_SRCS
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp"
PRIV_REQUIRES chip QRCode bt console spiffs)
Expand Down
87 changes: 87 additions & 0 deletions examples/ota-provider-app/esp32/main/OTAProviderCommands.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <OTAProviderCommands.h>
#include <lib/shell/Commands.h>
#include <lib/shell/Engine.h>
#include <lib/shell/commands/Help.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace Shell {
namespace {

OTAProviderExample * exampleOTAProvider = nullptr;
Shell::Engine sSubShell;

CHIP_ERROR DelayedActionTimeHandler(int argc, char ** argv)
{
VerifyOrReturnError(argc == 1, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(exampleOTAProvider != nullptr, CHIP_ERROR_INCORRECT_STATE);

const uint32_t delay = strtoul(argv[0], nullptr, 10);
exampleOTAProvider->SetDelayedActionTimeSec(delay);
return CHIP_NO_ERROR;
}

CHIP_ERROR OTAProviderHandler(int argc, char ** argv)
{
if (argc == 0)
{
sSubShell.ForEachCommand(PrintCommandHelp, nullptr);
return CHIP_NO_ERROR;
}

CHIP_ERROR error = sSubShell.ExecCommand(argc, argv);

if (error != CHIP_NO_ERROR)
{
streamer_printf(streamer_get(), "Error: %" CHIP_ERROR_FORMAT "\r\n", error.Format());
}

return error;
}
} // namespace

void OTAProviderCommands::Register()
{
// These commands can be moved to src/lib/shell/commands/Ota.cpp along with the other OTA commands.
// But as of now only Linux and ESP32 platforms supports OTA provider

// Register subcommands of the `OTAProvider` commands.
static const shell_command_t subCommands[] = {
{ &DelayedActionTimeHandler, "delay",
"Set delayed action time for QueryImageResponse and ApplyUpdateResponse\n"
"Usage: OTAProvider delay <delay in seconds>" },
};

sSubShell.RegisterCommands(subCommands, ArraySize(subCommands));

// Register the root `OTA Provider` command in the top-level shell.
static const shell_command_t otaProviderCommand = { &OTAProviderHandler, "OTAProvider", "OTA Provider commands" };

Engine::Root().RegisterCommands(&otaProviderCommand, 1);
}

// Set Example OTA provider
void OTAProviderCommands::SetExampleOTAProvider(OTAProviderExample * otaProvider)
{
exampleOTAProvider = otaProvider;
}

} // namespace Shell
} // namespace chip
51 changes: 51 additions & 0 deletions examples/ota-provider-app/esp32/main/include/OTAProviderCommands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once
#include <ota-provider-common/OTAProviderExample.h>

namespace chip {
namespace Shell {

class OTAProviderCommands
{
public:
// delete the copy constructor
OTAProviderCommands(const OTAProviderCommands &) = delete;
// delete the move constructor
OTAProviderCommands(OTAProviderCommands &&) = delete;
// delete the assignment operator
OTAProviderCommands & operator=(const OTAProviderCommands &) = delete;

static OTAProviderCommands & GetInstance()
{
static OTAProviderCommands instance;
return instance;
}

// Register the OTA provider commands
void Register();

// Set Example OTA provider
void SetExampleOTAProvider(OTAProviderExample * otaProvider);

private:
OTAProviderCommands() {}
};

} // namespace Shell
} // namespace chip
36 changes: 10 additions & 26 deletions examples/ota-provider-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,25 @@

#include "CHIPDeviceManager.h"
#include "DeviceCallbacks.h"
#include "esp_heap_caps_init.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_spi_flash.h"
#include "esp_spiffs.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include <app-common/zap-generated/callback.h>
#include <app/server/Server.h>
#include <lib/support/logging/CHIPLogging.h>

#include <cmath>
#include <cstdio>
#include <string>
#include <vector>

#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>

#include <lib/support/ErrorStr.h>
#include <lib/support/logging/CHIPLogging.h>

#include <OTAProviderCommands.h>
#include <app/clusters/ota-provider/ota-provider.h>
#include <ota-provider-common/BdxOtaSender.h>
#include <ota-provider-common/OTAProviderExample.h>
#include <shell_extension/launch.h>

using chip::Callback::Callback;
using namespace ::chip;
using namespace ::chip::Shell;
using namespace ::chip::System;
using namespace ::chip::Credentials;
using namespace ::chip::DeviceManager;
Expand Down Expand Up @@ -130,17 +119,6 @@ extern "C" void app_main()
{
ESP_LOGI(TAG, "OTA Provider!");

/* Print chip information */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGI(TAG, "This is ESP32 chip with %d CPU cores, WiFi%s%s, ", chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

ESP_LOGI(TAG, "silicon revision %d, ", chip_info.revision);

ESP_LOGI(TAG, "%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

// Initialize the ESP NVS layer.
esp_err_t err = nvs_flash_init();
if (err != ESP_OK)
Expand Down Expand Up @@ -216,4 +194,10 @@ extern "C" void app_main()
}

chip::app::Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, &otaProvider);

// Launch a chip shell and register OTA Provider Commands
chip::LaunchShell();
OTAProviderCommands & otaProviderCommands = OTAProviderCommands::GetInstance();
otaProviderCommands.SetExampleOTAProvider(&otaProvider);
otaProviderCommands.Register();
}
3 changes: 3 additions & 0 deletions examples/ota-provider-app/esp32/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ CONFIG_ESPTOOLPY_FLASHSIZE="4MB"

# discriminator
CONFIG_USE_TEST_SETUP_DISCRIMINATOR=0xF01

# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
3 changes: 2 additions & 1 deletion examples/ota-provider-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS"
" -q/--QueryImageBehavior <UpdateAvailable | Busy | UpdateNotAvailable>\n"
" Status value in the Query Image Response\n"
" -d/--DelayedActionTimeSec <time>\n"
" Value in seconds for the DelayedActionTime in the Query Image Response\n" };
" Value in seconds for the DelayedActionTime in the Query Image Response\n"
" and Apply Update Response\n" };

HelpOptions helpOptions("ota-provider-app", "Usage: ota-provider-app [options]", "1.0");

Expand Down
5 changes: 3 additions & 2 deletions examples/ota-requestor-app/esp32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ chip-tool. On receiving this command OTA requestor will query for OTA image.

## Apply update

Once transfer is complete, reboot the device manually to boot from upgraded OTA
image.
Once the transfer is complete, OTA requestor sends ApplyUpdateRequest command to
OTA provider for applying the image. Device will restart on successful
application of OTA image.

## ESP32 OTA Requestor with Linux OTA Provider

Expand Down
11 changes: 11 additions & 0 deletions src/platform/ESP32/OTAImageProcessorImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,17 @@
#include "lib/core/CHIPError.h"

#define TAG "OTAImageProcessor"
using namespace chip::System;
using namespace ::chip::DeviceLayer::Internal;

namespace chip {
namespace {

void HandleRestart(Layer * systemLayer, void * appState)
{
esp_restart();
}
} // namespace

CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
{
Expand Down Expand Up @@ -168,6 +176,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context)
return;
}
ESP_LOGI(TAG, "Applying, Boot partition set offset:0x%x", imageProcessor->mOTAUpdatePartition->address);

// HandleApply is called after delayed action time seconds are elapsed, so it would be safe to schedule the restart
chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(2 * 1000), HandleRestart, nullptr);
}

CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
Expand Down

0 comments on commit dd209ce

Please sign in to comment.