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

[ESP32] CLI option to set delayed action time in OTA Provider app and restart OTA Requestor once ApplyUpdate is successful #13620

Merged
merged 5 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,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
shubhamdp marked this conversation as resolved.
Show resolved Hide resolved
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
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
shubhamdp marked this conversation as resolved.
Show resolved Hide resolved
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();
shubhamdp marked this conversation as resolved.
Show resolved Hide resolved
}
} // 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