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 miscellaneous OTA Provider cluster spec changes #9874

Merged
merged 12 commits into from
Sep 30, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,20 @@ void OTAProviderExample::SetOTAFilePath(const char * path)
}

EmberAfStatus OTAProviderExample::HandleQueryImage(chip::app::CommandHandler * commandObj, uint16_t vendorId, uint16_t productId,
uint16_t imageType, uint16_t hardwareVersion, uint32_t currentVersion,
uint8_t protocolsSupported, const chip::Span<const char> & location,
bool clientCanConsent, const chip::ByteSpan & metadataForServer)
uint16_t hardwareVersion, uint32_t softwareVersion, uint8_t protocolsSupported,
carol-apple marked this conversation as resolved.
Show resolved Hide resolved
const chip::Span<const char> & location, bool requestorCanConsent,
const chip::ByteSpan & metadataForProvider)
{
// TODO: add confiuration for returning BUSY status

EmberAfOTAQueryStatus queryStatus = EMBER_ZCL_OTA_QUERY_STATUS_NOT_AVAILABLE;
uint32_t softwareVersion = currentVersion + 1; // This implementation will always indicate that an update is available
// (if the user provides a file).
bool userConsentNeeded = false;
uint8_t updateToken[kUpdateTokenLen] = { 0 };
char strBuf[kUpdateTokenStrLen] = { 0 };
char uriBuf[kUriMaxLen] = { 0 };
uint32_t newSoftwareVersion = softwareVersion + 1; // This implementation will always indicate that an update is available
// (if the user provides a file).
constexpr char kExampleSoftwareString[] = "Example-Image-V0.1";
bool userConsentNeeded = false;
uint8_t updateToken[kUpdateTokenLen] = { 0 };
char strBuf[kUpdateTokenStrLen] = { 0 };
char uriBuf[kUriMaxLen] = { 0 };

GenerateUpdateToken(updateToken, kUpdateTokenLen);
GetUpdateTokenString(ByteSpan(updateToken), strBuf, kUpdateTokenStrLen);
Expand Down Expand Up @@ -159,7 +160,8 @@ EmberAfStatus OTAProviderExample::HandleQueryImage(chip::app::CommandHandler * c
VerifyOrReturnError(writer->Put(ContextTag(tagNum++), queryStatus) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->Put(ContextTag(tagNum++), mDelayedActionTimeSec) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->PutString(ContextTag(tagNum++), uriBuf) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->Put(ContextTag(tagNum++), softwareVersion) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->Put(ContextTag(tagNum++), newSoftwareVersion) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->PutString(ContextTag(tagNum++), kExampleSoftwareString) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->PutBytes(ContextTag(tagNum++), updateToken, kUpdateTokenLen) == CHIP_NO_ERROR,
EMBER_ZCL_STATUS_FAILURE);
VerifyOrReturnError(writer->Put(ContextTag(tagNum++), userConsentNeeded) == CHIP_NO_ERROR, EMBER_ZCL_STATUS_FAILURE);
Expand Down Expand Up @@ -196,12 +198,12 @@ EmberAfStatus OTAProviderExample::HandleApplyUpdateRequest(chip::app::CommandHan
return EMBER_ZCL_STATUS_SUCCESS;
}

EmberAfStatus OTAProviderExample::HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t currentVersion)
EmberAfStatus OTAProviderExample::HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion)
{
char tokenBuf[kUpdateTokenStrLen] = { 0 };

GetUpdateTokenString(updateToken, tokenBuf, kUpdateTokenStrLen);
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, currentVersion);
ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, softwareVersion);

emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class OTAProviderExample : public OTAProviderDelegate

// Inherited from OTAProviderDelegate
EmberAfStatus HandleQueryImage(chip::app::CommandHandler * commandObj, uint16_t vendorId, uint16_t productId,
uint16_t imageType, uint16_t hardwareVersion, uint32_t currentVersion,
uint8_t protocolsSupported, const chip::Span<const char> & location, bool clientCanConsent,
uint16_t hardwareVersion, uint32_t softwareVersion, uint8_t protocolsSupported,
const chip::Span<const char> & location, bool requestorCanConsent,
const chip::ByteSpan & metadataForServer) override;
EmberAfStatus HandleApplyUpdateRequest(chip::app::CommandHandler * commandObj, const chip::ByteSpan & updateToken,
uint32_t newVersion) override;
EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t currentVersion) override;
EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion) override;

enum queryImageBehaviorType
{
Expand Down
18 changes: 9 additions & 9 deletions examples/ota-requestor-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ chip::Messaging::ExchangeContext * exchangeCtx = nullptr;
Device * providerDevice = nullptr;
BdxDownloader bdxDownloader;
void OnQueryImageResponse(void * context, uint8_t status, uint32_t delayedActionTime, uint8_t * imageURI, uint32_t softwareVersion,
carol-apple marked this conversation as resolved.
Show resolved Hide resolved
chip::ByteSpan updateToken, bool userConsentNeeded, chip::ByteSpan metadataForRequestor)
uint8_t * softwareVersionString, chip::ByteSpan updateToken, bool userConsentNeeded,
chip::ByteSpan metadataForRequestor)
{
ChipLogDetail(SoftwareUpdate, "%s", __FUNCTION__);

Expand Down Expand Up @@ -113,11 +114,10 @@ void OnConnection(void * context, Device * device)
chip::Callback::Cancelable * failureCallback = mOnQueryFailureCallback.Cancel();

// These QueryImage params have been chosen arbitrarily
constexpr VendorId kExampleVendorId = VendorId::Common;
constexpr uint16_t kExampleProductId = 77;
constexpr uint16_t kExampleImageType = 0;
constexpr uint16_t kExampleHWVersion = 3;
constexpr uint16_t kExampleCurentVersion = 0;
constexpr VendorId kExampleVendorId = VendorId::Common;
constexpr uint16_t kExampleProductId = 77;
constexpr uint16_t kExampleHWVersion = 3;
constexpr uint16_t kExampleSoftwareVersion = 0;
constexpr uint8_t kExampleProtocolsSupported =
EMBER_ZCL_OTA_DOWNLOAD_PROTOCOL_BDX_SYNCHRONOUS; // TODO: support this as a list once ember adds list support
const uint8_t locationBuf[] = { 'U', 'S' };
Expand All @@ -131,9 +131,9 @@ void OnConnection(void * context, Device * device)
ChipLogError(SoftwareUpdate, "Associate() failed: %s", chip::ErrorStr(err));
return;
}
err = cluster.QueryImage(successCallback, failureCallback, kExampleVendorId, kExampleProductId, kExampleImageType,
kExampleHWVersion, kExampleCurentVersion, kExampleProtocolsSupported, exampleLocation,
kExampleClientCanConsent, metadata);
err = cluster.QueryImage(successCallback, failureCallback, kExampleVendorId, kExampleProductId, kExampleHWVersion,
kExampleSoftwareVersion, kExampleProtocolsSupported, exampleLocation, kExampleClientCanConsent,
metadata);
if (err != CHIP_NO_ERROR)
{
ChipLogError(SoftwareUpdate, "QueryImage() failed: %s", chip::ErrorStr(err));
Expand Down
8 changes: 4 additions & 4 deletions src/app/clusters/ota-provider/ota-provider-delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ class OTAProviderDelegate
{
public:
// TODO(#8605): protocolsSupported should be list of OTADownloadProtocol enums, not uint8_t
virtual EmberAfStatus HandleQueryImage(CommandHandler * commandObj, uint16_t vendorId, uint16_t productId, uint16_t imageType,
uint16_t hardwareVersion, uint32_t currentVersion, uint8_t protocolsSupported,
const chip::Span<const char> & location, bool clientCanConsent,
virtual EmberAfStatus HandleQueryImage(CommandHandler * commandObj, uint16_t vendorId, uint16_t productId,
uint16_t hardwareVersion, uint32_t softwareVersion, uint8_t protocolsSupported,
const chip::Span<const char> & location, bool requestorCanConsent,
const chip::ByteSpan & metadataForProvider) = 0;

virtual EmberAfStatus HandleApplyUpdateRequest(CommandHandler * commandObj, const chip::ByteSpan & updateToken,
uint32_t newVersion) = 0;

virtual EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t currentVersion) = 0;
virtual EmberAfStatus HandleNotifyUpdateApplied(const chip::ByteSpan & updateToken, uint32_t softwareVersion) = 0;

virtual ~OTAProviderDelegate() = default;
};
Expand Down
39 changes: 20 additions & 19 deletions src/app/clusters/ota-provider/ota-provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ using namespace chip;
using chip::app::clusters::OTAProviderDelegate;

namespace {
constexpr size_t kMaxMetadataLen = 512; // The maximum length of Metadata in any OTA Provider command
constexpr size_t kUpdateTokenParamLength = 32; // The expected length of the Update Token parameter used in multiple commands
constexpr size_t kMaxMetadataLen = 512; // The maximum length of Metadata in any OTA Provider command
constexpr size_t kUpdateTokenMaxLength = 32; // The expected length of the Update Token parameter used in multiple commands
constexpr size_t kUpdateTokenMinLength = 8; // The expected length of the Update Token parameter used in multiple commands

OTAProviderDelegate * gDelegateTable[EMBER_AF_OTA_PROVIDER_CLUSTER_SERVER_ENDPOINT_COUNT] = { nullptr };

Expand Down Expand Up @@ -80,9 +81,9 @@ bool emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback(EndpointI
return true;
}

if (updateToken.size() != kUpdateTokenParamLength)
if (updateToken.size() > kUpdateTokenMaxLength || updateToken.size() < kUpdateTokenMinLength)
{
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenParamLength, updateToken.size());
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenMaxLength, updateToken.size());
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_ARGUMENT);
}

Expand All @@ -100,12 +101,13 @@ bool emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback(EndpointI
*
*
* @param updateToken Identifier for the Software Image that was applied. Should be 32 octets long.
* @param currentVersion The current SoftwareVersion value. Should match the SoftwarVersion attribute in the
* @param softwareVersion The current SoftwareVersion value. Should match the SoftwarVersion attribute in the
* OTA Requestor's Basic Information Cluster.
*/

bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(EndpointId endpoint, app::CommandHandler * commandObj,
ByteSpan updateToken, uint32_t currentVersion)
bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(chip::EndpointId endpoint,
chip::app::CommandHandler * commandObj,
chip::ByteSpan updateToken, uint32_t softwareVersion)
{
EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
OTAProviderDelegate * delegate = GetDelegate(endpoint);
Expand All @@ -117,13 +119,13 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(Endpoint
return true;
}

if (updateToken.size() != kUpdateTokenParamLength)
if (updateToken.size() > kUpdateTokenMaxLength || updateToken.size() < kUpdateTokenMinLength)
{
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenParamLength, updateToken.size());
ChipLogError(Zcl, "expected size %zu for UpdateToken, got %zu", kUpdateTokenMaxLength, updateToken.size());
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_ARGUMENT);
}

status = delegate->HandleNotifyUpdateApplied(updateToken, currentVersion);
status = delegate->HandleNotifyUpdateApplied(updateToken, softwareVersion);
if (status != EMBER_ZCL_STATUS_SUCCESS)
{
emberAfSendImmediateDefaultResponse(status);
Expand All @@ -140,7 +142,7 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(Endpoint
* @param imageType A Vendor-specific numerical value that may help an OTA Provider select the correct payload.
* @param hardwareVersion The OTA Requestor’s hardware version. Should match the HardwareVersion attribute of the Client's Basic
* Information Cluster.
* @param currentVersion The current version running on the OTA Requestor. Should match the SoftwareVersion attribute of the
* @param softwareVersion The current version running on the OTA Requestor. Should match the SoftwareVersion attribute of the
* Client's Basic Information Cluster.
* @param protocolsSupported A list of OTADownloadProtocol enum values indicating download protocols supported by the OTA Requestor
* (max length 8 entries).
Expand All @@ -149,12 +151,11 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(Endpoint
* @param metadataForProvider Optional, max 512 octets. A TLV-encoded Vendor-specific payload.
*/

bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(EndpointId endpoint, app::CommandHandler * commandObj,
uint16_t vendorId, uint16_t productId, uint16_t imageType,
uint16_t hardwareVersion, uint32_t currentVersion,
/* TODO(#8605): change this to list */ uint8_t protocolsSupported,
uint8_t * location, bool clientCanConsent,
ByteSpan metadataForProvider)
bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(chip::EndpointId endpoint, chip::app::CommandHandler * commandObj,
uint16_t vendorId, uint16_t productId, uint16_t hardwareVersion,
uint32_t softwareVersion, uint8_t protocolsSupported,
uint8_t * location, bool requestorCanConsent,
chip::ByteSpan metadataForProvider)
{
EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
OTAProviderDelegate * delegate = GetDelegate(endpoint);
Expand All @@ -177,8 +178,8 @@ bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(EndpointId endpoi
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_ARGUMENT);
}

status = delegate->HandleQueryImage(commandObj, vendorId, productId, imageType, hardwareVersion, currentVersion,
protocolsSupported, locationSpan, clientCanConsent, metadataForProvider);
status = delegate->HandleQueryImage(commandObj, vendorId, productId, hardwareVersion, softwareVersion, protocolsSupported,
locationSpan, requestorCanConsent, metadataForProvider);
if (status != EMBER_ZCL_STATUS_SUCCESS)
{
emberAfSendImmediateDefaultResponse(status);
Expand Down
10 changes: 5 additions & 5 deletions src/app/zap-templates/zcl/data-model/chip/chip-ota.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ limitations under the License.
<description>Determine availability of a new Software Image</description>
<arg name="vendorId" type="INT16U"/>
<arg name="productId" type="INT16U"/>
<arg name="imageType" type="INT16U"/>
<arg name="hardwareVersion" type="INT16U"/>
<arg name="currentVersion" type="INT32U"/>
<arg name="softwareVersion" type="INT32U"/>
<arg name="protocolsSupported" type="OTADownloadProtocol"/> <!-- TODO(#8605): add array="true" when lists are supported -->
<arg name="location" type="CHAR_STRING" length="2"/>
<arg name="requestorCanConsent" type="BOOLEAN"/>
Expand All @@ -63,14 +62,15 @@ limitations under the License.
<command source="client" code="0x02" name="NotifyUpdateApplied" optional="false" cli="chip ota notifyupdateapplied">
<description>Notify OTA Provider that an update was applied</description>
<arg name="updateToken" type="OCTET_STRING" length="32"/>
<arg name="currentVersion" type="INT32U"/>
<arg name="softwareVersion" type="INT32U"/>
</command>
<command source="server" code="0x03" name="QueryImageResponse" optional="false" cli="chip ota queryimageresponse">
<description>Response to QueryImage command</description>
<arg name="status" type="OTAQueryStatus"/>
<arg name="delayedActionTime" type="INT32U"/>
<arg name="imageURI" type="CHAR_STRING"/>
<arg name="softwareVersion" type="INT32U"/>
<arg name="softwareVersionString" type="CHAR_STRING"/>
<arg name="updateToken" type="OCTET_STRING" length="32"/>
<arg name="userConsentNeeded" type="BOOLEAN" default="false"/>
<arg name="metadataForRequestor" type="OCTET_STRING" length="512"/>
Expand All @@ -85,7 +85,7 @@ limitations under the License.
<cluster code="0x002a"/>
<item name="SimpleAnnouncement" value="0x0"/>
<item name="UpdateAvailable" value="0x1"/>
<item name="CriticalUpdateAvailable" value="0x2"/>
<item name="UrgentUpdateAvailable" value="0x2"/>
</enum>
<cluster>
<name>OTA Software Update Requestor</name>
Expand All @@ -99,7 +99,7 @@ limitations under the License.
<attribute side="server" code="0x0002" define="UPDATE_POSSIBLE" type="BOOLEAN" writable="false" optional="false">update possible</attribute>
<command source="client" code="0" name="AnnounceOtaProvider" optional="true" cli="chip ota announceotaprovider">
<description>Notify OTA Provider that an update was applied</description>
<arg name="serverLocation" type="OCTET_STRING" length="16"/>
<arg name="providerLocation" type="OCTET_STRING" length="16"/>
<arg name="vendorId" type="INT16U"/>
<arg name="announcementReason" type="OTAAnnouncementReason"/>
<arg name="metadataForNode" type="OCTET_STRING" length="512" optional="true"/>
Expand Down
Loading