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

Implement BDXDownloader for new OTA Requestor API #12560

Merged
merged 8 commits into from
Dec 4, 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
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);
selissia marked this conversation as resolved.
Show resolved Hide resolved
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;
selissia marked this conversation as resolved.
Show resolved Hide resolved
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
holbrookt marked this conversation as resolved.
Show resolved Hide resolved
// 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