Skip to content

Commit 4211171

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Align QueryImage and QueryImageResponse XML with the spec (#11336)
* Use type-safe InvokeCommand to do QueryImage in OTA requestor app. * Fully align the XML for QueryImage and QueryImageResponse with the spec.
1 parent 3e046a1 commit 4211171

File tree

9 files changed

+113
-114
lines changed

9 files changed

+113
-114
lines changed

examples/ota-provider-app/ota-provider-common/OTAProviderExample.cpp

+24-27
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ using chip::CharSpan;
3333
using chip::Optional;
3434
using chip::Span;
3535
using chip::app::Clusters::OTAProviderDelegate;
36+
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands;
3637

3738
constexpr uint8_t kUpdateTokenLen = 32; // must be between 8 and 32
3839
constexpr uint8_t kUpdateTokenStrLen = kUpdateTokenLen * 2 + 1; // Hex string needs 2 hex chars for every byte
@@ -94,17 +95,14 @@ void OTAProviderExample::SetOTAFilePath(const char * path)
9495
}
9596

9697
EmberAfStatus OTAProviderExample::HandleQueryImage(chip::app::CommandHandler * commandObj,
97-
const chip::app::ConcreteCommandPath & commandPath, uint16_t vendorId,
98-
uint16_t productId, uint32_t softwareVersion, uint8_t protocolsSupported,
99-
const Optional<uint16_t> & hardwareVersion, const Optional<CharSpan> & location,
100-
const Optional<bool> & requestorCanConsent,
101-
const Optional<ByteSpan> & metadataForProvider)
98+
const chip::app::ConcreteCommandPath & commandPath,
99+
const QueryImage::DecodableType & commandData)
102100
{
103101
// TODO: add confiuration for returning BUSY status
104102

105103
EmberAfOTAQueryStatus queryStatus = EMBER_ZCL_OTA_QUERY_STATUS_NOT_AVAILABLE;
106-
uint32_t newSoftwareVersion = softwareVersion + 1; // This implementation will always indicate that an update is available
107-
// (if the user provides a file).
104+
uint32_t newSoftwareVersion = commandData.softwareVersion + 1; // This implementation will always indicate that an update is
105+
// available (if the user provides a file).
108106
constexpr char kExampleSoftwareString[] = "Example-Image-V0.1";
109107
bool userConsentNeeded = false;
110108
uint8_t updateToken[kUpdateTokenLen] = { 0 };
@@ -149,52 +147,51 @@ EmberAfStatus OTAProviderExample::HandleQueryImage(chip::app::CommandHandler * c
149147
queryStatus = EMBER_ZCL_OTA_QUERY_STATUS_NOT_AVAILABLE;
150148
}
151149

152-
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::Type response;
153-
response.status = queryStatus;
154-
response.delayedActionTime = mDelayedActionTimeSec;
155-
response.imageURI = chip::CharSpan(uriBuf, strlen(uriBuf));
156-
response.softwareVersion = newSoftwareVersion;
157-
response.softwareVersionString = chip::CharSpan(kExampleSoftwareString, strlen(kExampleSoftwareString));
158-
response.updateToken = chip::ByteSpan(updateToken);
159-
response.userConsentNeeded = userConsentNeeded;
160-
// TODO: Once our client is using APIs that handle optional arguments
161-
// correctly, update QueryImageResponse to have the right things optional.
162-
// At that point we can decide whether to send metadataForRequestor as an
163-
// empty ByteSpan or whether to not send it at all.
164-
response.metadataForRequestor = chip::ByteSpan();
150+
QueryImageResponse::Type response;
151+
response.status = queryStatus;
152+
response.delayedActionTime.Emplace(mDelayedActionTimeSec);
153+
response.imageURI.Emplace(chip::CharSpan(uriBuf, strlen(uriBuf)));
154+
response.softwareVersion.Emplace(newSoftwareVersion);
155+
response.softwareVersionString.Emplace(chip::CharSpan(kExampleSoftwareString, strlen(kExampleSoftwareString)));
156+
response.updateToken.Emplace(chip::ByteSpan(updateToken));
157+
response.userConsentNeeded.Emplace(userConsentNeeded);
158+
// Could also just not send metadataForRequestor at all.
159+
response.metadataForRequestor.Emplace(chip::ByteSpan());
165160

166161
VerifyOrReturnError(commandObj->AddResponseData(commandPath, response) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
167162
return EMBER_ZCL_STATUS_SUCCESS;
168163
}
169164

170165
EmberAfStatus OTAProviderExample::HandleApplyUpdateRequest(chip::app::CommandHandler * commandObj,
171166
const chip::app::ConcreteCommandPath & commandPath,
172-
const ByteSpan & updateToken, uint32_t newVersion)
167+
const ApplyUpdateRequest::DecodableType & commandData)
173168
{
174169
// TODO: handle multiple transfers by tracking updateTokens
175170

176171
EmberAfOTAApplyUpdateAction updateAction = EMBER_ZCL_OTA_APPLY_UPDATE_ACTION_PROCEED; // For now, just allow any update request
177172
char tokenBuf[kUpdateTokenStrLen] = { 0 };
178173

179-
GetUpdateTokenString(updateToken, tokenBuf, kUpdateTokenStrLen);
180-
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, newVersion);
174+
GetUpdateTokenString(commandData.updateToken, tokenBuf, kUpdateTokenStrLen);
175+
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, commandData.newVersion);
181176

182177
VerifyOrReturnError(commandObj != nullptr, EMBER_ZCL_STATUS_INVALID_VALUE);
183178

184-
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::Type response;
179+
ApplyUpdateResponse::Type response;
185180
response.action = updateAction;
186181
response.delayedActionTime = mDelayedActionTimeSec;
187182
VerifyOrReturnError(commandObj->AddResponseData(commandPath, response) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
188183

189184
return EMBER_ZCL_STATUS_SUCCESS;
190185
}
191186

192-
EmberAfStatus OTAProviderExample::HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion)
187+
EmberAfStatus OTAProviderExample::HandleNotifyUpdateApplied(chip::app::CommandHandler * commandObj,
188+
const chip::app::ConcreteCommandPath & commandPath,
189+
const NotifyUpdateApplied::DecodableType & commandData)
193190
{
194191
char tokenBuf[kUpdateTokenStrLen] = { 0 };
195192

196-
GetUpdateTokenString(updateToken, tokenBuf, kUpdateTokenStrLen);
197-
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, softwareVersion);
193+
GetUpdateTokenString(commandData.updateToken, tokenBuf, kUpdateTokenStrLen);
194+
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, commandData.softwareVersion);
198195

199196
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
200197

examples/ota-provider-app/ota-provider-common/OTAProviderExample.h

+9-10
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,15 @@ class OTAProviderExample : public chip::app::Clusters::OTAProviderDelegate
3232
void SetOTAFilePath(const char * path);
3333

3434
// Inherited from OTAProviderDelegate
35-
EmberAfStatus HandleQueryImage(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
36-
uint16_t vendorId, uint16_t productId, uint32_t softwareVersion, uint8_t protocolsSupported,
37-
const chip::Optional<uint16_t> & hardwareVersion,
38-
const chip::Optional<chip::CharSpan> & location,
39-
const chip::Optional<bool> & requestorCanConsent,
40-
const chip::Optional<chip::ByteSpan> & metadataForServer) override;
41-
EmberAfStatus HandleApplyUpdateRequest(chip::app::CommandHandler * commandObj,
42-
const chip::app::ConcreteCommandPath & commandPath, const chip::ByteSpan & updateToken,
43-
uint32_t newVersion) override;
44-
EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion) override;
35+
EmberAfStatus HandleQueryImage(
36+
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
37+
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::DecodableType & commandData) override;
38+
EmberAfStatus HandleApplyUpdateRequest(
39+
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
40+
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::DecodableType & commandData) override;
41+
EmberAfStatus HandleNotifyUpdateApplied(
42+
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
43+
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData) override;
4544

4645
enum queryImageBehaviorType
4746
{

examples/ota-requestor-app/linux/main.cpp

+23-23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include <app-common/zap-generated/callback.h>
20+
#include <app-common/zap-generated/cluster-objects.h>
2021
#include <app/device/OperationalDeviceProxy.h>
2122
#include <app/server/Server.h>
2223
#include <credentials/examples/DeviceAttestationCredsExample.h>
@@ -43,11 +44,10 @@ using chip::Transport::PeerAddress;
4344
using namespace chip::ArgParser;
4445
using namespace chip::Messaging;
4546
using namespace chip::app::device;
47+
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands;
4648

47-
void OnQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, CharSpan imageURI, uint32_t softwareVersion,
48-
CharSpan softwareVersionString, ByteSpan updateToken, bool userConsentNeeded,
49-
ByteSpan metadataForRequestor);
50-
void OnQueryImageFailure(void * context, uint8_t status);
49+
void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response);
50+
void OnQueryImageFailure(void * context, EmberAfStatus status);
5151
void OnConnected(void * context, OperationalDeviceProxy * operationalDeviceProxy);
5252
void OnConnectionFailure(void * context, OperationalDeviceProxy * operationalDeviceProxy, CHIP_ERROR error);
5353
bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue);
@@ -56,8 +56,6 @@ bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier,
5656
OperationalDeviceProxy gOperationalDeviceProxy;
5757
ExchangeContext * exchangeCtx = nullptr;
5858
BdxDownloader bdxDownloader;
59-
Callback<OtaSoftwareUpdateProviderClusterQueryImageResponseCallback> mQueryImageResponseCallback(OnQueryImageResponse, nullptr);
60-
Callback<DefaultFailureCallback> mOnQueryFailureCallback(OnQueryImageFailure, nullptr);
6159
Callback<OnOperationalDeviceConnected> mOnConnectedCallback(OnConnected, nullptr);
6260
Callback<OnOperationalDeviceConnectionFailure> mOnConnectionFailureCallback(OnConnectionFailure, nullptr);
6361

@@ -108,11 +106,9 @@ HelpOptions helpOptions("ota-requestor-app", "Usage: ota-requestor-app [options]
108106

109107
OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr };
110108

111-
void OnQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, CharSpan imageURI, uint32_t softwareVersion,
112-
CharSpan softwareVersionString, ByteSpan updateToken, bool userConsentNeeded,
113-
ByteSpan metadataForRequestor)
109+
void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response)
114110
{
115-
ChipLogDetail(SoftwareUpdate, "QueryImageResponse responded with action %" PRIu8, status);
111+
ChipLogDetail(SoftwareUpdate, "QueryImageResponse responded with action %" PRIu8, response.status);
116112

117113
TransferSession::TransferInitData initOptions;
118114
initOptions.TransferCtlFlags = chip::bdx::TransferControlFlags::kReceiverDrive;
@@ -143,7 +139,7 @@ void OnQueryImageResponse(void * context, uint8_t status, uint32_t delayedAction
143139
chip::System::Clock::Seconds16(20));
144140
}
145141

146-
void OnQueryImageFailure(void * context, uint8_t status)
142+
void OnQueryImageFailure(void * context, EmberAfStatus status)
147143
{
148144
ChipLogDetail(SoftwareUpdate, "QueryImage failure response %" PRIu8, status);
149145
}
@@ -154,17 +150,13 @@ void OnConnected(void * context, OperationalDeviceProxy * operationalDeviceProxy
154150
chip::Controller::OtaSoftwareUpdateProviderCluster cluster;
155151
constexpr EndpointId kOtaProviderEndpoint = 0;
156152

157-
chip::Callback::Cancelable * successCallback = mQueryImageResponseCallback.Cancel();
158-
chip::Callback::Cancelable * failureCallback = mOnQueryFailureCallback.Cancel();
159-
160153
// These QueryImage params have been chosen arbitrarily
161-
constexpr VendorId kExampleVendorId = VendorId::Common;
162-
constexpr uint16_t kExampleProductId = 77;
163-
constexpr uint16_t kExampleHWVersion = 3;
164-
constexpr uint16_t kExampleSoftwareVersion = 0;
165-
constexpr uint8_t kExampleProtocolsSupported =
166-
EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS; // TODO: support this as a list once ember adds list support
167-
const char locationBuf[] = { 'U', 'S' };
154+
constexpr VendorId kExampleVendorId = VendorId::Common;
155+
constexpr uint16_t kExampleProductId = 77;
156+
constexpr uint16_t kExampleHWVersion = 3;
157+
constexpr uint16_t kExampleSoftwareVersion = 0;
158+
constexpr EmberAfOTADownloadProtocol kExampleProtocolsSupported[] = { EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS };
159+
const char locationBuf[] = { 'U', 'S' };
168160
CharSpan exampleLocation(locationBuf);
169161
constexpr bool kExampleClientCanConsent = false;
170162
ByteSpan metadata;
@@ -175,8 +167,16 @@ void OnConnected(void * context, OperationalDeviceProxy * operationalDeviceProxy
175167
ChipLogError(SoftwareUpdate, "Associate() failed: %" CHIP_ERROR_FORMAT, err.Format());
176168
return;
177169
}
178-
err = cluster.QueryImage(successCallback, failureCallback, kExampleVendorId, kExampleProductId, kExampleSoftwareVersion,
179-
kExampleProtocolsSupported, kExampleHWVersion, exampleLocation, kExampleClientCanConsent, metadata);
170+
QueryImage::Type args;
171+
args.vendorId = kExampleVendorId;
172+
args.productId = kExampleProductId;
173+
args.softwareVersion = kExampleSoftwareVersion;
174+
args.protocolsSupported = kExampleProtocolsSupported;
175+
args.hardwareVersion.Emplace(kExampleHWVersion);
176+
args.location.Emplace(exampleLocation);
177+
args.requestorCanConsent.Emplace(kExampleClientCanConsent);
178+
args.metadataForProvider.Emplace(metadata);
179+
err = cluster.InvokeCommand(args, /* context = */ nullptr, OnQueryImageResponse, OnQueryImageFailure);
180180
if (err != CHIP_NO_ERROR)
181181
{
182182
ChipLogError(SoftwareUpdate, "QueryImage() failed: %" CHIP_ERROR_FORMAT, err.Format());

src/app/clusters/ota-provider/ota-provider-delegate.h

+10-9
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
#pragma once
2020

21+
#include <app-common/zap-generated/cluster-objects.h>
2122
#include <app-common/zap-generated/enums.h>
2223
#include <app/CommandHandler.h>
2324
#include <app/ConcreteCommandPath.h>
25+
#include <app/data-model/DecodableList.h>
2426
#include <app/util/af.h>
2527
#include <lib/core/Optional.h>
2628

@@ -35,17 +37,16 @@ namespace Clusters {
3537
class OTAProviderDelegate
3638
{
3739
public:
38-
// TODO(#8605): protocolsSupported should be list of OTADownloadProtocol enums, not uint8_t
39-
virtual EmberAfStatus HandleQueryImage(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, uint16_t vendorId,
40-
uint16_t productId, uint32_t softwareVersion, uint8_t protocolsSupported,
41-
const Optional<uint16_t> & hardwareVersion, const Optional<CharSpan> & location,
42-
const Optional<bool> & requestorCanConsent,
43-
const Optional<ByteSpan> & metadataForProvider) = 0;
40+
virtual EmberAfStatus HandleQueryImage(CommandHandler * commandObj, const ConcreteCommandPath & commandPath,
41+
const OtaSoftwareUpdateProvider::Commands::QueryImage::DecodableType & commandData) = 0;
4442

45-
virtual EmberAfStatus HandleApplyUpdateRequest(CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
46-
const chip::ByteSpan & updateToken, uint32_t newVersion) = 0;
43+
virtual EmberAfStatus
44+
HandleApplyUpdateRequest(CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
45+
const OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::DecodableType & commandData) = 0;
4746

48-
virtual EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion) = 0;
47+
virtual EmberAfStatus
48+
HandleNotifyUpdateApplied(CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
49+
const OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData) = 0;
4950

5051
virtual ~OTAProviderDelegate() = default;
5152
};

src/app/clusters/ota-provider/ota-provider.cpp

+13-8
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ bool emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback(
7272
const Commands::ApplyUpdateRequest::DecodableType & commandData)
7373
{
7474
auto & updateToken = commandData.updateToken;
75-
auto & newVersion = commandData.newVersion;
7675

7776
EndpointId endpoint = commandPath.mEndpointId;
7877

@@ -90,9 +89,10 @@ bool emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback(
9089
{
9190
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenMaxLength, updateToken.size());
9291
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_ARGUMENT);
92+
return true;
9393
}
9494

95-
status = delegate->HandleApplyUpdateRequest(commandObj, commandPath, updateToken, newVersion);
95+
status = delegate->HandleApplyUpdateRequest(commandObj, commandPath, commandData);
9696
if (status != EMBER_ZCL_STATUS_SUCCESS)
9797
{
9898
emberAfSendImmediateDefaultResponse(status);
@@ -114,8 +114,7 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(
114114
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
115115
const Commands::NotifyUpdateApplied::DecodableType & commandData)
116116
{
117-
auto & updateToken = commandData.updateToken;
118-
auto & softwareVersion = commandData.softwareVersion;
117+
auto & updateToken = commandData.updateToken;
119118

120119
EndpointId endpoint = commandPath.mEndpointId;
121120

@@ -133,9 +132,10 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(
133132
{
134133
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenMaxLength, updateToken.size());
135134
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_ARGUMENT);
135+
return true;
136136
}
137137

138-
status = delegate->HandleNotifyUpdateApplied(updateToken, softwareVersion);
138+
status = delegate->HandleNotifyUpdateApplied(commandObj, commandPath, commandData);
139139
if (status != EMBER_ZCL_STATUS_SUCCESS)
140140
{
141141
emberAfSendImmediateDefaultResponse(status);
@@ -188,7 +188,13 @@ bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(app::CommandHandl
188188
ChipLogDetail(Zcl, " VendorID: 0x%" PRIx16, vendorId);
189189
ChipLogDetail(Zcl, " ProductID: %" PRIu16, productId);
190190
ChipLogDetail(Zcl, " SoftwareVersion: %" PRIu32, softwareVersion);
191-
ChipLogDetail(Zcl, " ProtocolsSupported: %" PRIu8, protocolsSupported);
191+
ChipLogDetail(Zcl, " ProtocolsSupported: [");
192+
auto protocolIter = protocolsSupported.begin();
193+
while (protocolIter.Next())
194+
{
195+
ChipLogDetail(Zcl, " %" PRIu8, protocolIter.GetValue());
196+
}
197+
ChipLogDetail(Zcl, " ]");
192198
if (hardwareVersion.HasValue())
193199
{
194200
ChipLogDetail(Zcl, " HardwareVersion: %" PRIu16, hardwareVersion.Value());
@@ -220,8 +226,7 @@ bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(app::CommandHandl
220226
return true;
221227
}
222228

223-
status = delegate->HandleQueryImage(commandObj, commandPath, vendorId, productId, softwareVersion, protocolsSupported,
224-
hardwareVersion, location, requestorCanConsent, metadataForProvider);
229+
status = delegate->HandleQueryImage(commandObj, commandPath, commandData);
225230
if (status != EMBER_ZCL_STATUS_SUCCESS)
226231
{
227232
emberAfSendImmediateDefaultResponse(status);

0 commit comments

Comments
 (0)