Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ota-requestor] Build QueryImage based on Basic cluster attributes (#…
Browse files Browse the repository at this point in the history
Damian-Nordic authored and pull[bot] committed Jun 1, 2022

Verified

This commit was signed with the committer’s verified signature.
jalaziz Jameel Al-Aziz
1 parent 241794a commit 1474760
Showing 9 changed files with 186 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -776,7 +776,7 @@
"mfgCode": null,
"define": "BASIC_CLUSTER",
"side": "server",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "StartUp",
@@ -3711,5 +3711,6 @@
"endpointVersion": 1,
"deviceIdentifier": 22
}
]
],
"log": []
}
160 changes: 82 additions & 78 deletions src/app/clusters/ota-requestor/OTARequestor.cpp
Original file line number Diff line number Diff line change
@@ -29,61 +29,36 @@

#include "BDXDownloader.h"

#include <app-common/zap-generated/attributes/Accessors.h>
#include <controller/CHIPDeviceControllerFactory.h>
#include <controller/CommissioneeDeviceProxy.h>
#include <controller/ExampleOperationalCredentialsIssuer.h>

#include <zap-generated/CHIPClientCallbacks.h>
#include <zap-generated/CHIPClusters.h>

using chip::ByteSpan;
using chip::CASESessionManager;
using chip::CASESessionManagerConfig;
using chip::CharSpan;
using chip::DeviceProxy;
using chip::EndpointId;
using chip::FabricIndex;
using chip::FabricInfo;
using chip::NodeId;
using chip::OnDeviceConnected;
using chip::OnDeviceConnectionFailure;
using chip::PeerId;
using chip::Server;
using chip::VendorId;
using chip::bdx::TransferSession;
using chip::Callback::Callback;
using chip::System::Layer;
using chip::Transport::PeerAddress;
// using namespace chip::ArgParser;
using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::bdx;
using namespace chip::Messaging;
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands;
using chip::Inet::IPAddress;

namespace {
// Global instance of the OTARequestorInterface.
OTARequestorInterface * globalOTARequestorInstance = nullptr;

constexpr uint32_t kImmediateStartDelayMs = 1; // Start the timer with this value when starting OTA "immediately"

// Callbacks for connection management
void OnConnected(void * context, chip::OperationalDeviceProxy * deviceProxy);
Callback<OnDeviceConnected> mOnConnectedCallback(OnConnected, nullptr);
Callback::Callback<OnDeviceConnected> mOnConnectedCallback(OnConnected, nullptr);

void OnConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error);
Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback(OnConnectionFailure, nullptr);
Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback(OnConnectionFailure, nullptr);

void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response);
void OnQueryImageFailure(void * context, EmberAfStatus status);

void SetRequestorInstance(OTARequestorInterface * instance)
{
globalOTARequestorInstance = instance;
}

OTARequestorInterface * GetRequestorInstance()
{
return globalOTARequestorInstance;
}

void StartDelayTimerHandler(chip::System::Layer * systemLayer, void * appState)
{
VerifyOrReturn(appState != nullptr);
@@ -95,6 +70,17 @@ void OnQueryImageFailure(void * context, EmberAfStatus status)
ChipLogDetail(SoftwareUpdate, "QueryImage failure response %" PRIu8, status);
}

// Called whenever FindOrEstablishSession is successful. Finds the Requestor instance
// and calls the corresponding OTARequestor member function
void OnConnected(void * context, chip::OperationalDeviceProxy * deviceProxy)
{
OTARequestor * requestorCore = static_cast<OTARequestor *>(GetRequestorInstance());

VerifyOrDie(requestorCore != nullptr);

requestorCore->mOnConnected(context, deviceProxy);
}

void OnConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error)
{
ChipLogError(SoftwareUpdate, "failed to connect to 0x%" PRIX64 ": %" CHIP_ERROR_FORMAT, deviceId, error.Format());
@@ -104,10 +90,27 @@ void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableTyp
{
OTARequestor * requestorCore = static_cast<OTARequestor *>(GetRequestorInstance());

assert(requestorCore != nullptr);
VerifyOrDie(requestorCore != nullptr);

requestorCore->mOnQueryImageResponse(context, response);
}
} // namespace

void SetRequestorInstance(OTARequestorInterface * instance)
{
globalOTARequestorInstance = instance;
}

OTARequestorInterface * GetRequestorInstance()
{
return globalOTARequestorInstance;
}

struct OTARequestor::QueryImageRequest
{
char location[2];
QueryImage::Type args;
};

void OTARequestor::mOnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response)
{
@@ -297,7 +300,7 @@ void OTARequestor::ConnectToProvider()

// Explicitly calling UpdateDeviceData() should not be needed once OperationalDeviceProxy can resolve IP address from node ID
// and fabric index
PeerAddress addr = PeerAddress::UDP(mIpAddress, CHIP_PORT);
Transport::PeerAddress addr = Transport::PeerAddress::UDP(mIpAddress, CHIP_PORT);
operationalDeviceProxy->UpdateDeviceData(addr, operationalDeviceProxy->GetMRPConfig());

CHIP_ERROR err = operationalDeviceProxy->Connect(&mOnConnectedCallback, &mOnConnectionFailureCallback);
@@ -307,58 +310,25 @@ void OTARequestor::ConnectToProvider()
}
}

// Called whenever FindOrEstablishSession is successful. Finds the Requestor instance
// and calls the corresponding OTARequestor member function
void OnConnected(void * context, chip::OperationalDeviceProxy * deviceProxy)
{
OTARequestor * requestorCore = static_cast<OTARequestor *>(GetRequestorInstance());

assert(requestorCore != nullptr);

requestorCore->mOnConnected(context, deviceProxy);
}

// Member function called whenever FindOrEstablishSession is successful
void OTARequestor::mOnConnected(void * context, chip::DeviceProxy * deviceProxy)
{
switch (onConnectedState)
{
case kQueryImage: {
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Controller::OtaSoftwareUpdateProviderCluster cluster;
constexpr EndpointId kOtaProviderEndpoint = 0;

// These QueryImage params have been chosen arbitrarily
constexpr VendorId kExampleVendorId = VendorId::Common;
constexpr uint16_t kExampleProductId = 77;
constexpr uint16_t kExampleHWVersion = 3;
constexpr uint16_t kExampleSoftwareVersion = 0;
constexpr EmberAfOTADownloadProtocol kExampleProtocolsSupported[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS };
const char locationBuf[] = { 'U', 'S' };
CharSpan exampleLocation(locationBuf);
constexpr bool kExampleClientCanConsent = false;
ByteSpan metadata;

err = cluster.Associate(deviceProxy, kOtaProviderEndpoint);
if (err != CHIP_NO_ERROR)
{
ChipLogError(SoftwareUpdate, "Associate() failed: %" CHIP_ERROR_FORMAT, err.Format());
return;
}
QueryImage::Type args;
args.vendorId = kExampleVendorId;
args.productId = kExampleProductId;
args.softwareVersion = kExampleSoftwareVersion;
args.protocolsSupported = kExampleProtocolsSupported;
args.hardwareVersion.Emplace(kExampleHWVersion);
args.location.Emplace(exampleLocation);
args.requestorCanConsent.Emplace(kExampleClientCanConsent);
args.metadataForProvider.Emplace(metadata);
err = cluster.InvokeCommand(args, /* context = */ nullptr, OnQueryImageResponse, OnQueryImageFailure);
if (err != CHIP_NO_ERROR)
{
ChipLogError(SoftwareUpdate, "QueryImage() failed: %" CHIP_ERROR_FORMAT, err.Format());
}
QueryImageRequest request;
CHIP_ERROR err = BuildQueryImageRequest(request);
VerifyOrReturn(err == CHIP_NO_ERROR,
ChipLogError(SoftwareUpdate, "Failed to build QueryImage command: %" CHIP_ERROR_FORMAT, err.Format()));

Controller::OtaSoftwareUpdateProviderCluster cluster;
cluster.Associate(deviceProxy, kOtaProviderEndpoint);

err = cluster.InvokeCommand(request.args, /* context = */ nullptr, OnQueryImageResponse, OnQueryImageFailure);
VerifyOrReturn(err == CHIP_NO_ERROR,
ChipLogError(SoftwareUpdate, "Failed to send QueryImage command: %" CHIP_ERROR_FORMAT, err.Format()));

break;
}
@@ -410,3 +380,37 @@ void OTARequestor::TriggerImmediateQuery()
// Perhaps we don't need a separate function ConnectToProvider, revisit this
ConnectToProvider();
}

CHIP_ERROR OTARequestor::BuildQueryImageRequest(QueryImageRequest & request)
{
constexpr EmberAfOTADownloadProtocol kProtocolsSupported[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS };
constexpr bool kRequestorCanConsent = false;
QueryImage::Type & args = request.args;

uint16_t vendorId;
VerifyOrReturnError(Basic::Attributes::VendorID::Get(kRootEndpointId, &vendorId) == EMBER_ZCL_STATUS_SUCCESS,
CHIP_ERROR_READ_FAILED);
args.vendorId = static_cast<VendorId>(vendorId);

VerifyOrReturnError(Basic::Attributes::ProductID::Get(kRootEndpointId, &args.productId) == EMBER_ZCL_STATUS_SUCCESS,
CHIP_ERROR_READ_FAILED);

VerifyOrReturnError(Basic::Attributes::SoftwareVersion::Get(kRootEndpointId, &args.softwareVersion) == EMBER_ZCL_STATUS_SUCCESS,
CHIP_ERROR_READ_FAILED);

args.protocolsSupported = kProtocolsSupported;
args.requestorCanConsent.SetValue(kRequestorCanConsent);

uint16_t hardwareVersion;
if (Basic::Attributes::HardwareVersion::Get(kRootEndpointId, &hardwareVersion) == EMBER_ZCL_STATUS_SUCCESS)
{
args.hardwareVersion.SetValue(hardwareVersion);
}

if (Basic::Attributes::Location::Get(kRootEndpointId, MutableCharSpan(request.location)) == EMBER_ZCL_STATUS_SUCCESS)
{
args.location.SetValue(CharSpan(request.location));
}

return CHIP_NO_ERROR;
}
3 changes: 3 additions & 0 deletions src/app/clusters/ota-requestor/OTARequestor.h
Original file line number Diff line number Diff line change
@@ -85,6 +85,8 @@ class OTARequestor : public OTARequestorInterface
kStartBDX,
};

struct QueryImageRequest;

// TODO: the application should define this, along with initializing the BDXDownloader

// This class is purely for delivering messages and sending outgoing messages to/from the BDXDownloader.
@@ -169,4 +171,5 @@ class OTARequestor : public OTARequestorInterface

// Functions
CHIP_ERROR SetupCASESessionManager(chip::FabricIndex fabricIndex);
CHIP_ERROR BuildQueryImageRequest(QueryImageRequest & req);
};
7 changes: 4 additions & 3 deletions src/lib/core/DataModelTypes.h
Original file line number Diff line number Diff line change
@@ -43,9 +43,10 @@ typedef uint32_t FieldId;
typedef uint16_t ListIndex;
typedef uint32_t TransactionId;

static constexpr FabricIndex kUndefinedFabricIndex = 0;
static constexpr EndpointId kInvalidEndpointId = 0xFFFF;
static constexpr ListIndex kInvalidListIndex = 0xFFFF; // List index is a uint16 thus 0xFFFF is a invalid list index.
constexpr FabricIndex kUndefinedFabricIndex = 0;
constexpr EndpointId kInvalidEndpointId = 0xFFFF;
constexpr EndpointId kRootEndpointId = 0;
constexpr ListIndex kInvalidListIndex = 0xFFFF; // List index is a uint16 thus 0xFFFF is a invalid list index.

// ClusterId, AttributeId and EventId are MEIs,
// 0xFFFF is not a valid manufacturer code, thus 0xFFFF'FFFF is not a valid MEI.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 67 additions & 32 deletions zzz_generated/ota-requestor-app/zap-generated/endpoint_config.h

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions zzz_generated/ota-requestor-app/zap-generated/gen_config.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1474760

Please sign in to comment.