Skip to content

Commit

Permalink
Implement BDXDownloader for new OTA Requestor API (#12560)
Browse files Browse the repository at this point in the history
* WIP: OTADownloader and BDXDownloader

* integrate BDXDownloader

* fix exchange context closing

* cleaning up

* fix some namespacing

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

* remove unused OTADownloader reference

* update README

Co-authored-by: Carol Yang <[email protected]>
  • Loading branch information
holbrookt and carol-apple authored Dec 4, 2021
1 parent ba69e73 commit b1e0023
Show file tree
Hide file tree
Showing 9 changed files with 408 additions and 156 deletions.
42 changes: 18 additions & 24 deletions examples/ota-requestor-app/linux/LinuxOTAImageProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@

namespace chip {

// TODO: Dummy function to be removed once BDX downloader is implemented and can return a real instance
OTADownloader * GetDownloaderInstance()
{
return nullptr;
}

CHIP_ERROR LinuxOTAImageProcessor::PrepareDownload()
{
if (mParams.imageFile.empty())
Expand Down Expand Up @@ -83,29 +77,29 @@ CHIP_ERROR LinuxOTAImageProcessor::ProcessBlock(ByteSpan & block)

void LinuxOTAImageProcessor::HandlePrepareDownload(intptr_t context)
{
OTADownloader * downloader = GetDownloaderInstance();
if (downloader == nullptr)
auto * imageProcessor = reinterpret_cast<LinuxOTAImageProcessor *>(context);
if (imageProcessor == nullptr)
{
ChipLogError(SoftwareUpdate, "No known OTA downloader");
ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
return;
}

auto * imageProcessor = reinterpret_cast<LinuxOTAImageProcessor *>(context);
if (imageProcessor == nullptr)
else if (imageProcessor->mDownloader == nullptr)
{
downloader->OnPreparedForDownload(CHIP_ERROR_INVALID_ARGUMENT);
ChipLogError(SoftwareUpdate, "mDownloader is null");
return;
}

imageProcessor->mOfs.open(imageProcessor->mParams.imageFile.data(),
std::ofstream::out | std::ofstream::ate | std::ofstream::app);
if (!imageProcessor->mOfs.good())
{
downloader->OnPreparedForDownload(CHIP_ERROR_OPEN_FAILED);
imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_OPEN_FAILED);
return;
}

downloader->OnPreparedForDownload(CHIP_NO_ERROR);
// TODO: if file already exists and is not empty, erase previous contents

imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
}

void LinuxOTAImageProcessor::HandleFinalize(intptr_t context)
Expand All @@ -118,6 +112,8 @@ void LinuxOTAImageProcessor::HandleFinalize(intptr_t context)

imageProcessor->mOfs.close();
imageProcessor->ReleaseBlock();

ChipLogProgress(SoftwareUpdate, "OTA image downloaded to %s", imageProcessor->mParams.imageFile.data());
}

void LinuxOTAImageProcessor::HandleAbort(intptr_t context)
Expand All @@ -135,17 +131,15 @@ void LinuxOTAImageProcessor::HandleAbort(intptr_t context)

void LinuxOTAImageProcessor::HandleProcessBlock(intptr_t context)
{
OTADownloader * downloader = GetDownloaderInstance();
if (downloader == nullptr)
auto * imageProcessor = reinterpret_cast<LinuxOTAImageProcessor *>(context);
if (imageProcessor == nullptr)
{
ChipLogError(SoftwareUpdate, "No known OTA downloader");
ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
return;
}

auto * imageProcessor = reinterpret_cast<LinuxOTAImageProcessor *>(context);
if (imageProcessor == nullptr)
else if (imageProcessor->mDownloader == nullptr)
{
downloader->OnBlockProcessed(CHIP_ERROR_INVALID_ARGUMENT, OTADownloader::kEnd);
ChipLogError(SoftwareUpdate, "mDownloader is null");
return;
}

Expand All @@ -154,12 +148,12 @@ void LinuxOTAImageProcessor::HandleProcessBlock(intptr_t context)
if (!imageProcessor->mOfs.write(reinterpret_cast<const char *>(imageProcessor->mBlock.data()),
static_cast<std::streamsize>(imageProcessor->mBlock.size())))
{
downloader->OnBlockProcessed(CHIP_ERROR_WRITE_FAILED, OTADownloader::kEnd);
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}

imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size();
downloader->OnBlockProcessed(CHIP_NO_ERROR, OTADownloader::kGetNext);
imageProcessor->mDownloader->FetchNextData();
}

CHIP_ERROR LinuxOTAImageProcessor::SetBlock(ByteSpan & block)
Expand Down
4 changes: 4 additions & 0 deletions examples/ota-requestor-app/linux/LinuxOTAImageProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once

#include <app/clusters/ota-requestor/OTADownloader.h>
#include <app/clusters/ota-requestor/OTAImageProcessor.h>
#include <platform/CHIPDeviceLayer.h>

Expand All @@ -34,6 +35,8 @@ class LinuxOTAImageProcessor : public OTAImageProcessorInterface
CHIP_ERROR Abort() override;
CHIP_ERROR ProcessBlock(ByteSpan & block) override;

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

private:
//////////// Actual handlers for the OTAImageProcessorInterface ///////////////
static void HandlePrepareDownload(intptr_t context);
Expand All @@ -53,6 +56,7 @@ class LinuxOTAImageProcessor : public OTAImageProcessorInterface

std::ofstream mOfs;
MutableByteSpan mBlock;
OTADownloader * mDownloader;
};

} // namespace chip
41 changes: 23 additions & 18 deletions examples/ota-requestor-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@

#include "LinuxOTAImageProcessor.h"
#include "LinuxOTARequestorDriver.h"
#include "app/clusters/ota-requestor/OTADownloader.h"
#include "app/clusters/ota-requestor/BDXDownloader.h"
#include "app/clusters/ota-requestor/OTARequestor.h"

using chip::BDXDownloader;
using chip::ByteSpan;
using chip::CharSpan;
using chip::DeviceProxy;
Expand All @@ -37,7 +38,7 @@ using chip::LinuxOTAImageProcessor;
using chip::NodeId;
using chip::OnDeviceConnected;
using chip::OnDeviceConnectionFailure;
using chip::OTADownloader;
using chip::OTAImageProcessorParams;
using chip::PeerId;
using chip::Server;
using chip::VendorId;
Expand All @@ -49,6 +50,11 @@ using namespace chip::ArgParser;
using namespace chip::Messaging;
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands;

OTARequestor requestorCore;
LinuxOTARequestorDriver requestorUser;
BDXDownloader downloader;
LinuxOTAImageProcessor imageProcessor;

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue);
void OnStartDelayTimerHandler(Layer * systemLayer, void * appState);

Expand Down Expand Up @@ -195,40 +201,39 @@ int main(int argc, char * argv[])
SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());

// Initialize and interconnect the Requestor and Image Processor objects -- START
// Initialize the instance of the main Requestor Class
OTARequestor * requestorCore = new OTARequestor;
SetRequestorInstance(requestorCore);

// Initialize an instance of the Requestor Driver
LinuxOTARequestorDriver * requestorUser = new LinuxOTARequestorDriver;
SetRequestorInstance(&requestorCore);

// Connect the Requestor and Requestor Driver objects
requestorCore->SetOtaRequestorDriver(requestorUser);
requestorCore.SetOtaRequestorDriver(&requestorUser);

// Initialize the Downloader object
OTADownloader * downloaderCore = new OTADownloader;
// TODO: enable SetDownloaderInstance(downloaderCore);

// Initialize the Image Processor object
LinuxOTAImageProcessor * downloaderUser = new LinuxOTAImageProcessor;
// WARNING: this is probably not realistic to know such details of the image or to even have an OTADownloader instantiated at
// the beginning of program execution. We're using hardcoded values here for now since this is a reference application.
// TODO: instatiate and initialize these values when QueryImageResponse tells us an image is available
// TODO: add API for OTARequestor to pass QueryImageResponse info to the application to use for OTADownloader init
OTAImageProcessorParams ipParams;
ipParams.imageFile = CharSpan("test.txt");
imageProcessor.SetOTAImageProcessorParams(ipParams);
imageProcessor.SetOTADownloader(&downloader);

// Connect the Downloader and Image Processor objects
downloaderCore->SetImageProcessorDelegate(downloaderUser);
downloader.SetImageProcessorDelegate(&imageProcessor);

requestorCore.SetBDXDownloader(&downloader);
// Initialize and interconnect the Requestor and Image Processor objects -- END

// Pass the IP Address to the OTARequestor object: Use of explicit IP address is temporary
// until the Exchange Layer implements address resolution
{
IPAddress ipAddr;
IPAddress::FromString(ipAddress, ipAddr);
requestorCore->SetIpAddress(ipAddr);
requestorCore.SetIpAddress(ipAddr);
}

// Test Mode operation: If a delay is provided, QueryImage after the timer expires
if (delayQueryTimeInSec > 0)
{
// In this mode Provider node ID and fabric idx must be supplied explicitly from program args
requestorCore->TestModeSetProviderParameters(providerNodeId, providerFabricIndex);
requestorCore.TestModeSetProviderParameters(providerNodeId, providerFabricIndex);

chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(delayQueryTimeInSec * 1000),
OnStartDelayTimerHandler, nullptr);
Expand Down
Loading

0 comments on commit b1e0023

Please sign in to comment.