Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ce648f3

Browse files
Damian-Nordicpull[bot]
authored andcommittedApr 18, 2022
[ota] Automatic NotifyUpdateApplied (#16103)
* [ota] Automatic NotifyUpdateApplied Add two methods to OTAImageProcessor: - IsFirstImageRun() to determine if the currently running image is executed for the first time - ConfirmCurrentImage() to confirm that the current image is stable and the update can be left permanently. Add storing and loading the current provider and the update token in OTARequestor. Then extend GenericOTARequestorDriver to automatically confirm the current image and send NotifyUpdateApplied command to the last provider. * Fix build
1 parent 9f5d8ea commit ce648f3

22 files changed

+128
-34
lines changed
 

‎examples/ota-requestor-app/p6/src/AppTask.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ CHIP_ERROR AppTask::Init()
203203
chip::OTARequestorInterface * requestor = chip::GetRequestorInstance();
204204
if (requestor != nullptr)
205205
{
206-
requestor->NotifyUpdateApplied(savedSoftwareVersion);
206+
requestor->NotifyUpdateApplied();
207207
}
208208
}
209209

‎src/app/clusters/ota-requestor/GenericOTARequestorDriver.cpp

+25-5
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,41 @@ namespace chip {
3939
namespace DeviceLayer {
4040
namespace {
4141

42-
constexpr uint32_t kDelayQueryUponCommissioningSec = 30; // Delay before sending the initial image query after commissioning
43-
constexpr uint32_t kImmediateStartDelaySec = 1; // Delay before sending a query in response to UrgentUpdateAvailable
44-
4542
using namespace app::Clusters::OtaSoftwareUpdateRequestor;
4643
using namespace app::Clusters::OtaSoftwareUpdateRequestor::Structs;
4744

45+
constexpr uint32_t kDelayQueryUponCommissioningSec = 30; // Delay before sending the initial image query after commissioning
46+
constexpr uint32_t kImmediateStartDelaySec = 1; // Delay before sending a query in response to UrgentUpdateAvailable
47+
constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(120);
48+
4849
GenericOTARequestorDriver * ToDriver(void * context)
4950
{
5051
return static_cast<GenericOTARequestorDriver *>(context);
5152
}
5253

53-
constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(120);
54-
5554
} // namespace
5655

56+
void GenericOTARequestorDriver::Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor)
57+
{
58+
mRequestor = requestor;
59+
mImageProcessor = processor;
60+
61+
if (mImageProcessor->IsFirstImageRun())
62+
{
63+
SystemLayer().ScheduleLambda([this] {
64+
CHIP_ERROR error = mImageProcessor->ConfirmCurrentImage();
65+
66+
if (error != CHIP_NO_ERROR)
67+
{
68+
ChipLogError(SoftwareUpdate, "Failed to confirm image: %" CHIP_ERROR_FORMAT, error.Format());
69+
return;
70+
}
71+
72+
mRequestor->NotifyUpdateApplied();
73+
});
74+
}
75+
}
76+
5777
bool GenericOTARequestorDriver::CanConsent()
5878
{
5979
return false;

‎src/app/clusters/ota-requestor/GenericOTARequestorDriver.h

+8-9
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,16 @@ namespace DeviceLayer {
3232
class GenericOTARequestorDriver : public OTARequestorDriver
3333
{
3434
public:
35-
//// Public API methods
3635
/**
37-
* Called to perform some initialization including:
38-
* - Set the OTA requestor instance used to direct download progress
39-
* - Set the OTA image processor instance used to apply/abort the downloaded image
36+
* Initialize OTA requestor driver.
37+
*
38+
* Set OTA requestor instance to be controlled by the driver, and OTA image processor, used to
39+
* apply/abort the downloaded image.
40+
*
41+
* Additionally, if the current image is executed for the first time, approve the current image
42+
* to make the update permanent, and send NotifyUpdateApplied command to the last OTA provider.
4043
*/
41-
void Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor)
42-
{
43-
mRequestor = requestor;
44-
mImageProcessor = processor;
45-
}
44+
void Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor);
4645

4746
// Set the timeout (in seconds) for querying providers on the default OTA provider list; must be non-zero
4847
void SetPeriodicQueryTimeout(uint32_t timeout)

‎src/app/clusters/ota-requestor/OTARequestor.cpp

+19-5
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ void OTARequestor::OnQueryImageResponse(void * context, const QueryImageResponse
159159
memcpy(fileDesignator.data(), update.fileDesignator.data(), update.fileDesignator.size());
160160
fileDesignator.reduce_size(update.fileDesignator.size());
161161
requestorCore->mFileDesignator = fileDesignator;
162+
requestorCore->StoreCurrentUpdateInfo();
162163

163164
requestorCore->mOtaRequestorDriver->UpdateAvailable(update,
164165
System::Clock::Seconds32(response.delayedActionTime.ValueOr(0)));
@@ -508,11 +509,8 @@ void OTARequestor::ApplyUpdate()
508509
ConnectToProvider(kApplyUpdate);
509510
}
510511

511-
void OTARequestor::NotifyUpdateApplied(uint32_t version)
512+
void OTARequestor::NotifyUpdateApplied()
512513
{
513-
// New version is executing so update where applicable
514-
mCurrentVersion = version;
515-
516514
// Log the VersionApplied event
517515
uint16_t productId;
518516
if (DeviceLayer::ConfigurationMgr().GetProductId(productId) != CHIP_NO_ERROR)
@@ -522,7 +520,7 @@ void OTARequestor::NotifyUpdateApplied(uint32_t version)
522520
return;
523521
}
524522

525-
OtaRequestorServerOnVersionApplied(version, productId);
523+
OtaRequestorServerOnVersionApplied(mCurrentVersion, productId);
526524

527525
// There is no response for a notify so consider this OTA complete
528526
RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess);
@@ -795,6 +793,22 @@ CHIP_ERROR OTARequestor::SendNotifyUpdateAppliedRequest(OperationalDeviceProxy &
795793
return cluster.InvokeCommand(args, this, OnNotifyUpdateAppliedResponse, OnNotifyUpdateAppliedFailure);
796794
}
797795

796+
void OTARequestor::StoreCurrentUpdateInfo()
797+
{
798+
// TODO: change OTA requestor storage interface to store both values at once
799+
CHIP_ERROR error = mStorage->StoreCurrentProviderLocation(mProviderLocation.Value());
800+
801+
if (error == CHIP_NO_ERROR)
802+
{
803+
mStorage->StoreUpdateToken(mUpdateToken);
804+
}
805+
806+
if (error != CHIP_NO_ERROR)
807+
{
808+
ChipLogError(SoftwareUpdate, "Failed to store current update: %" CHIP_ERROR_FORMAT, error.Format());
809+
}
810+
}
811+
798812
// Invoked when the device becomes commissioned
799813
void OTARequestor::OnCommissioningCompleteRequestor(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
800814
{

‎src/app/clusters/ota-requestor/OTARequestor.h

+20-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe
6161
void ApplyUpdate() override;
6262

6363
// Initiate the session to send NotifyUpdateApplied command
64-
void NotifyUpdateApplied(uint32_t version) override;
64+
void NotifyUpdateApplied() override;
6565

6666
// Get image update progress in percents unit
6767
CHIP_ERROR GetUpdateProgress(EndpointId endpointId, app::DataModel::Nullable<uint8_t> & progress) override;
@@ -114,12 +114,23 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe
114114
mOtaRequestorDriver = &driver;
115115
mBdxDownloader = &downloader;
116116

117-
uint32_t version;
118-
ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(version));
119-
mCurrentVersion = version;
117+
ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(mCurrentVersion));
120118

121119
storage.LoadDefaultProviders(mDefaultOtaProviderList);
122120

121+
ProviderLocationType providerLocation;
122+
if (storage.LoadCurrentProviderLocation(providerLocation) == CHIP_NO_ERROR)
123+
{
124+
mProviderLocation.SetValue(providerLocation);
125+
}
126+
127+
MutableByteSpan updateToken(mUpdateTokenBuffer);
128+
if (storage.LoadUpdateToken(updateToken) == CHIP_NO_ERROR)
129+
{
130+
mUpdateToken = updateToken;
131+
}
132+
133+
123134
// Schedule the initializations that needs to be performed in the CHIP context
124135
DeviceLayer::PlatformMgr().ScheduleWork(InitState, reinterpret_cast<intptr_t>(this));
125136

@@ -270,6 +281,11 @@ class OTARequestor : public OTARequestorInterface, public BDXDownloader::StateDe
270281
*/
271282
CHIP_ERROR SendNotifyUpdateAppliedRequest(OperationalDeviceProxy & deviceProxy);
272283

284+
/**
285+
* Store current update information to KVS
286+
*/
287+
void StoreCurrentUpdateInfo();
288+
273289
/**
274290
* Session connection callbacks
275291
*/

‎src/app/clusters/ota-requestor/OTARequestorInterface.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class OTARequestorInterface
178178
virtual void ApplyUpdate() = 0;
179179

180180
// Initiate the session to send NotifyUpdateApplied command
181-
virtual void NotifyUpdateApplied(uint32_t version) = 0;
181+
virtual void NotifyUpdateApplied() = 0;
182182

183183
// Get image update progress in percents unit
184184
virtual CHIP_ERROR GetUpdateProgress(EndpointId endpointId, chip::app::DataModel::Nullable<uint8_t> & progress) = 0;

‎src/include/platform/OTAImageProcessor.h

+11
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@ class DLL_EXPORT OTAImageProcessorInterface
9090
*/
9191
virtual uint64_t GetBytesDownloaded() { return mParams.downloadedBytes; }
9292

93+
/**
94+
* Called to check if the current image is executed for the first time.
95+
*/
96+
virtual bool IsFirstImageRun() = 0;
97+
98+
/**
99+
* Called to confirm the current image in case it is running tentatively after applying
100+
* a software update.
101+
*/
102+
virtual CHIP_ERROR ConfirmCurrentImage() = 0;
103+
93104
protected:
94105
OTAImageProgress mParams;
95106
};

‎src/lib/shell/commands/Ota.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,9 @@ CHIP_ERROR ApplyImageHandler(int argc, char ** argv)
5050
CHIP_ERROR NotifyImageHandler(int argc, char ** argv)
5151
{
5252
VerifyOrReturnError(GetRequestorInstance() != nullptr, CHIP_ERROR_INCORRECT_STATE);
53-
VerifyOrReturnError(argc == 1, CHIP_ERROR_INVALID_ARGUMENT);
54-
55-
const intptr_t version = static_cast<intptr_t>(strtoul(argv[0], nullptr, 10));
53+
VerifyOrReturnError(argc == 0, CHIP_ERROR_INVALID_ARGUMENT);
5654

57-
PlatformMgr().ScheduleWork([](intptr_t arg) { GetRequestorInstance()->NotifyUpdateApplied(static_cast<uint32_t>(arg)); },
58-
version);
55+
PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->NotifyUpdateApplied(); });
5956
return CHIP_NO_ERROR;
6057
}
6158

‎src/platform/Ameba/AmebaOTAImageProcessor.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,9 @@ void AmebaOTAImageProcessor::HandleApply(intptr_t context)
374374
OTARequestorInterface * requestor = chip::GetRequestorInstance();
375375
if (requestor != nullptr)
376376
{
377-
// TODO: Use software version from Configuration Manager
378-
requestor->NotifyUpdateApplied(imageProcessor->mSoftwareVersion);
377+
// TODO: Implement restarting into new image instead of changing the version
378+
DeviceLayer::ConfigurationMgr().StoreSoftwareVersion(imageProcessor->mSoftwareVersion);
379+
requestor->NotifyUpdateApplied();
379380
}
380381

381382
// Reboot

‎src/platform/Ameba/AmebaOTAImageProcessor.h

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class AmebaOTAImageProcessor : public OTAImageProcessorInterface
4444
CHIP_ERROR Apply() override;
4545
CHIP_ERROR Abort() override;
4646
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
47+
bool IsFirstImageRun() override { return false; }
48+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
4749
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4850

4951
private:

‎src/platform/CYW30739/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3535
CHIP_ERROR Apply() override;
3636
CHIP_ERROR Abort() override;
3737
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
38+
bool IsFirstImageRun() override { return false; }
39+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3840

3941
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4042

‎src/platform/EFR32/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3535
CHIP_ERROR Apply() override;
3636
CHIP_ERROR Abort() override;
3737
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
38+
bool IsFirstImageRun() override { return false; }
39+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3840

3941
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4042
void SetOTAImageFile(CharSpan name) { mImageFile = name; }

‎src/platform/ESP32/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3535
CHIP_ERROR Abort() override;
3636
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
3737
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; };
38+
bool IsFirstImageRun() override { return false; }
39+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3840

3941
private:
4042
static void HandlePrepareDownload(intptr_t context);

‎src/platform/Linux/OTAImageProcessorImpl.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context)
134134
OTARequestorInterface * requestor = chip::GetRequestorInstance();
135135
if (requestor != nullptr)
136136
{
137-
// TODO: Use software version from Configuration Manager
138-
requestor->NotifyUpdateApplied(imageProcessor->mSoftwareVersion);
137+
// TODO: Implement restarting into new image instead of changing the version
138+
DeviceLayer::ConfigurationMgr().StoreSoftwareVersion(imageProcessor->mSoftwareVersion);
139+
requestor->NotifyUpdateApplied();
139140
}
140141
}
141142

‎src/platform/Linux/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3636
CHIP_ERROR Apply() override;
3737
CHIP_ERROR Abort() override;
3838
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
39+
bool IsFirstImageRun() override { return false; }
40+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3941

4042
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4143
void SetOTAImageFile(CharSpan name) { mImageFile = name; }

‎src/platform/P6/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
4343
CHIP_ERROR Apply() override;
4444
CHIP_ERROR Abort() override;
4545
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
46+
bool IsFirstImageRun() override { return false; }
47+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
4648

4749
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4850

‎src/platform/cc13x2_26x2/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3535
CHIP_ERROR Apply() override;
3636
CHIP_ERROR Abort() override;
3737
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
38+
bool IsFirstImageRun() override { return false; }
39+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3840

3941
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
4042

‎src/platform/mbed/OTAImageProcessorImpl.h

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
6565
*/
6666
CHIP_ERROR ProcessBlock(ByteSpan & block);
6767

68+
bool IsFirstImageRun() override { return false; }
69+
70+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
71+
6872
/**
6973
* Check if memory for update image is works correctly.
7074
*/

‎src/platform/nrfconnect/OTAImageProcessorImpl.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <dfu/dfu_target.h>
2626
#include <dfu/dfu_target_mcuboot.h>
27+
#include <dfu/mcuboot.h>
2728
#include <sys/reboot.h>
2829

2930
namespace chip {
@@ -100,6 +101,16 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
100101
});
101102
}
102103

104+
bool OTAImageProcessorImpl::IsFirstImageRun()
105+
{
106+
return mcuboot_swap_type() == BOOT_SWAP_TYPE_REVERT;
107+
}
108+
109+
CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
110+
{
111+
return System::MapErrorZephyr(boot_write_img_confirmed());
112+
}
113+
103114
CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block)
104115
{
105116
if (mHeaderParser.IsInitialized())

‎src/platform/nrfconnect/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
4040
CHIP_ERROR Abort() override;
4141
CHIP_ERROR Apply() override;
4242
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
43+
bool IsFirstImageRun() override;
44+
CHIP_ERROR ConfirmCurrentImage() override;
4345

4446
private:
4547
CHIP_ERROR PrepareDownloadImpl();

‎src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3333
CHIP_ERROR Apply() override;
3434
CHIP_ERROR Abort() override;
3535
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
36+
bool IsFirstImageRun() override { return false; }
37+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3638

3739
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
3840
void SetOTAImageFile(CharSpan name) { mImageFile = name; }

‎src/platform/qpg/OTAImageProcessorImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
3333
CHIP_ERROR Apply() override;
3434
CHIP_ERROR Abort() override;
3535
CHIP_ERROR ProcessBlock(ByteSpan & block) override;
36+
bool IsFirstImageRun() override { return false; }
37+
CHIP_ERROR ConfirmCurrentImage() override { return CHIP_NO_ERROR; }
3638

3739
void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
3840

0 commit comments

Comments
 (0)
Please sign in to comment.