Skip to content

Commit

Permalink
Add ability to customize OTA responses in DarwinFWTool (#22277)
Browse files Browse the repository at this point in the history
  • Loading branch information
krypton36 authored Sep 12, 2022
1 parent 5ecb77a commit 81f7284
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 53 deletions.
3 changes: 1 addition & 2 deletions examples/darwin-framework-tool/commands/provider/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ void registerClusterOtaSoftwareUpdateProviderInteractive(Commands & commands)

commands_list clusterCommands = {
make_unique<OTASoftwareUpdateSetFilePath>(), //
make_unique<OTASoftwareUpdateSetStatus>(), //

make_unique<OTASoftwareUpdateSetParams>(), //
};

commands.Register(clusterName, clusterCommands);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,9 @@ typedef NS_ENUM(uint8_t, UserConsentState) {
@property (strong, nonatomic, nullable) NSNumber * nodeID;
@property (nonatomic, readwrite) MTROtaSoftwareUpdateProviderOTAQueryStatus queryImageStatus;
@property (nonatomic, readwrite) UserConsentState userConsentState;
@property (nonatomic, readwrite) MTROtaSoftwareUpdateProviderOTAApplyUpdateAction action;
@property (nonatomic, readwrite, nullable) NSNumber * delayedActionTime;
@property (nonatomic, readwrite, nullable) NSNumber * timedInvokeTimeoutMs;
@property (nonatomic, readwrite, nullable) NSNumber * userConsentNeeded;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ - (instancetype)init
{
if (self = [super init]) {
_selectedCandidate = [[DeviceSoftwareVersionModel alloc] init];
_action = MTROtaSoftwareUpdateProviderOTAApplyUpdateActionProceed;
_userConsentState = OTAProviderUserUnknown;
_delayedActionTime = nil;
_timedInvokeTimeoutMs = nil;
_userConsentNeeded = nil;
_queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusNotAvailable;
}
return self;
}
Expand Down Expand Up @@ -63,35 +68,13 @@ - (void)handleQueryImageForNodeID:(NSNumber * _Nonnull)nodeID
}

_selectedCandidate.updateToken = [self generateUpdateToken];
NSLog(@"Query Image Status: %hhu", _queryImageStatus);
_selectedCandidate.status = @(_queryImageStatus);

if (params.requestorCanConsent.integerValue == 1) {
_selectedCandidate.status = @(MTROtaSoftwareUpdateProviderOTAQueryStatusUpdateAvailable);
_selectedCandidate.userConsentNeeded
= (_userConsentState == OTAProviderUserUnknown || _userConsentState == OTAProviderUserDenied) ? @(1) : @(0);
if (params.requestorCanConsent.integerValue == 1 && _userConsentNeeded) {
_selectedCandidate.userConsentNeeded = _userConsentNeeded;
NSLog(@"User Consent Needed: %@", _selectedCandidate.userConsentNeeded);
completionHandler(_selectedCandidate, nil);
return;
}

NSLog(@"Requestor cannot obtain user consent. Our State: %hhu", _userConsentState);
switch (_userConsentState) {
case OTAProviderUserGranted:
NSLog(@"User Consent Granted");
_queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusUpdateAvailable;
break;

case OTAProviderUserObtaining:
NSLog(@"User Consent Obtaining");
_queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusBusy;
break;

case OTAProviderUserDenied:
case OTAProviderUserUnknown:
NSLog(@"User Consent Denied or Uknown");
_queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusNotAvailable;
break;
}
_selectedCandidate.status = @(_queryImageStatus);
completionHandler(_selectedCandidate, nil);
}

Expand All @@ -104,7 +87,14 @@ - (void)handleApplyUpdateRequestForNodeID:(NSNumber * _Nonnull)nodeID
{
MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * applyUpdateResponseParams =
[[MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams alloc] init];
applyUpdateResponseParams.action = @(MTROtaSoftwareUpdateProviderOTAApplyUpdateActionProceed);
applyUpdateResponseParams.action = @(_action);
if (_delayedActionTime) {
applyUpdateResponseParams.delayedActionTime = _delayedActionTime;
}
if (_timedInvokeTimeoutMs) {
applyUpdateResponseParams.timedInvokeTimeoutMs = _timedInvokeTimeoutMs;
}

completionHandler(applyUpdateResponseParams, nil);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ class OTASoftwareUpdateBase : public CHIPCommandBridge {
{
}
CHIP_ERROR SetCandidatesFromFilePath(char * _Nonnull filePath);
CHIP_ERROR SetUserConsentStatus(char * _Nonnull status);
CHIP_ERROR SetActionReplyStatus(uint16_t action);
CHIP_ERROR SetReplyStatus(uint16_t status);
CHIP_ERROR SetUserConsentStatus(uint16_t status);
CHIP_ERROR SetUserConsentNeeded(uint16_t status);
static constexpr size_t kFilepathBufLen = 256;

CHIP_ERROR Run() override;
Expand Down Expand Up @@ -56,17 +59,31 @@ class OTASoftwareUpdateSetFilePath : public OTASoftwareUpdateBase {
char * _Nonnull mOTACandidatesFilePath;
};

class OTASoftwareUpdateSetStatus : public OTASoftwareUpdateBase {
class OTASoftwareUpdateSetParams : public OTASoftwareUpdateBase {
public:
OTASoftwareUpdateSetStatus()
: OTASoftwareUpdateBase("set-consent-status")
OTASoftwareUpdateSetParams()
: OTASoftwareUpdateBase("set-reply-params")
{
AddArgument("status", &mUserConsentStatus);
AddArgument("action", 0, UINT16_MAX, &mAction);
AddArgument("status", 0, UINT16_MAX, &mStatus);
AddArgument("consent", 0, UINT16_MAX, &mUserConsentStatus);
AddArgument("consentNeeded", 0, UINT16_MAX, &mUserConsentNeeded);
AddArgument("delayedActionTime", 0, UINT64_MAX, &mDelayedActionTime);
AddArgument("timedInvokeTimeoutMs", 0, UINT64_MAX, &mTimedInvokeTimeoutMs);
}

/////////// CHIPCommandBridge Interface /////////
CHIP_ERROR RunCommand() override;

CHIP_ERROR SetParams(chip::Optional<uint16_t> action, chip::Optional<uint16_t> status, chip::Optional<uint16_t> consent,
chip::Optional<uint16_t> userConsentNeeded, chip::Optional<uint64_t> delayedActionTime,
chip::Optional<uint64_t> timedInvokeTimeoutMs);

private:
char * _Nonnull mUserConsentStatus;
chip::Optional<uint16_t> mAction;
chip::Optional<uint16_t> mStatus;
chip::Optional<uint16_t> mUserConsentStatus;
chip::Optional<uint16_t> mUserConsentNeeded;
chip::Optional<uint64_t> mDelayedActionTime;
chip::Optional<uint64_t> mTimedInvokeTimeoutMs;
};
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,128 @@ static bool ParseJsonFileAndPopulateCandidates(
return error;
}

CHIP_ERROR OTASoftwareUpdateSetStatus::RunCommand()
CHIP_ERROR OTASoftwareUpdateSetParams::RunCommand()
{
auto error = SetUserConsentStatus(mUserConsentStatus);
auto error = SetParams(mAction, mStatus, mUserConsentStatus, mUserConsentNeeded, mDelayedActionTime, mTimedInvokeTimeoutMs);
SetCommandExitStatus(nil);
return error;
}

CHIP_ERROR OTASoftwareUpdateSetParams::SetParams(chip::Optional<uint16_t> action, chip::Optional<uint16_t> status,
chip::Optional<uint16_t> consent, chip::Optional<uint16_t> userConsentNeeded, chip::Optional<uint64_t> delayedActionTime,
chip::Optional<uint64_t> timedInvokeTimeoutMs)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (action.HasValue()) {
error = SetActionReplyStatus(action.Value());
if (error != CHIP_NO_ERROR) {
return error;
}
}
if (delayedActionTime.HasValue()) {
mOTADelegate.delayedActionTime = @(delayedActionTime.Value());
}
if (timedInvokeTimeoutMs.HasValue()) {
mOTADelegate.timedInvokeTimeoutMs = @(timedInvokeTimeoutMs.Value());
}
if (status.HasValue()) {
error = SetReplyStatus(status.Value());
if (error != CHIP_NO_ERROR) {
return error;
}
}
if (consent.HasValue()) {
error = SetUserConsentStatus(consent.Value());
if (error != CHIP_NO_ERROR) {
return error;
}
}
if (userConsentNeeded.HasValue()) {
error = SetUserConsentNeeded(userConsentNeeded.Value());
if (error != CHIP_NO_ERROR) {
return error;
}
}

return error;
}

CHIP_ERROR OTASoftwareUpdateBase::SetActionReplyStatus(uint16_t action)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (action == 0) {
mOTADelegate.action = MTROtaSoftwareUpdateProviderOTAApplyUpdateActionProceed;
ChipLogDetail(chipTool, "Successfully set action to: MTROtaSoftwareUpdateProviderOTAApplyUpdateActionProceed");
} else if (action == 1) {
mOTADelegate.action = MTROtaSoftwareUpdateProviderOTAApplyUpdateActionAwaitNextAction;
ChipLogDetail(chipTool, "Successfully set action to: MTROtaSoftwareUpdateProviderOTAApplyUpdateActionAwaitNextAction");
} else if (action == 2) {
mOTADelegate.action = MTROtaSoftwareUpdateProviderOTAApplyUpdateActionDiscontinue;
ChipLogDetail(chipTool, "Successfully set action to: MTROtaSoftwareUpdateProviderOTAApplyUpdateActionDiscontinue");
} else {
ChipLogError(chipTool, "Only accepts the following: 0 (Proceed), 1 (Await Next Action), 2 (Discontinue)");
error = CHIP_ERROR_INTERNAL;
}
return error;
}
CHIP_ERROR OTASoftwareUpdateBase::SetReplyStatus(uint16_t status)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (status == 0) {
mOTADelegate.queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusUpdateAvailable;
ChipLogDetail(chipTool, "Successfully set status to: MTROtaSoftwareUpdateProviderOTAQueryStatusUpdateAvailable");
} else if (status == 1) {
mOTADelegate.queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusBusy;
ChipLogDetail(chipTool, "Successfully set status to: MTROtaSoftwareUpdateProviderOTAQueryStatusBusy");
} else if (status == 2) {
mOTADelegate.queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusNotAvailable;
ChipLogDetail(chipTool, "Successfully set status to: MTROtaSoftwareUpdateProviderOTAQueryStatusNotAvailable");
} else if (status == 4) {
mOTADelegate.queryImageStatus = MTROtaSoftwareUpdateProviderOTAQueryStatusDownloadProtocolNotSupported;
ChipLogDetail(
chipTool, "Successfully set status to: MTROtaSoftwareUpdateProviderOTAQueryStatusDownloadProtocolNotSupported");
} else {
ChipLogError(chipTool, "Only accepts the following: 0 (Available), 1 (Busy), 2 (Not Available), 3 (Not Supported)");
error = CHIP_ERROR_INTERNAL;
}
return error;
}

CHIP_ERROR OTASoftwareUpdateBase::SetUserConsentStatus(uint16_t consent)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (consent == 0) {
mOTADelegate.userConsentState = OTAProviderUserGranted;
ChipLogDetail(chipTool, "Successfully set User Consent to: OTAProviderUserGranted");
} else if (consent == 1) {
mOTADelegate.userConsentState = OTAProviderUserObtaining;
ChipLogDetail(chipTool, "Successfully set User Consent to: OTAProviderUserObtaining");
} else if (consent == 2) {
mOTADelegate.userConsentState = OTAProviderUserDenied;
ChipLogDetail(chipTool, "Successfully set User Consent to: OTAProviderUserDenied");
} else {
ChipLogError(chipTool, "Only accepts the following: 0 (granted), 1 (obtaining), and 2 (denied).");
error = CHIP_ERROR_INTERNAL;
}
return error;
}

CHIP_ERROR OTASoftwareUpdateBase::SetUserConsentNeeded(uint16_t userConsentNeeded)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (userConsentNeeded == 0) {
mOTADelegate.userConsentNeeded = @(0);
ChipLogDetail(chipTool, "Successfully set User Consent to: OTAProviderUserGranted");
} else if (userConsentNeeded == 1) {
mOTADelegate.userConsentNeeded = @(1);
ChipLogDetail(chipTool, "Successfully set User Consent to: OTAProviderUserObtaining");
} else {
ChipLogError(chipTool, "Only accepts the following: 0 (Not Needed), and 1 (Needed).");
error = CHIP_ERROR_INTERNAL;
}
return error;
}

CHIP_ERROR OTASoftwareUpdateBase::SetCandidatesFromFilePath(char * _Nonnull filePath)
{
NSMutableArray<DeviceSoftwareVersionModel *> * candidates;
Expand Down Expand Up @@ -167,22 +282,6 @@ static bool ParseJsonFileAndPopulateCandidates(
return CHIP_NO_ERROR;
}

CHIP_ERROR OTASoftwareUpdateBase::SetUserConsentStatus(char * _Nonnull otaSTatus)
{
CHIP_ERROR error = CHIP_NO_ERROR;
if (strcmp(otaSTatus, "granted") == 0) {
mOTADelegate.userConsentState = OTAProviderUserGranted;
} else if (strcmp(otaSTatus, "obtaining") == 0) {
mOTADelegate.userConsentState = OTAProviderUserObtaining;
} else if (strcmp(otaSTatus, "denied") == 0) {
mOTADelegate.userConsentState = OTAProviderUserDenied;
} else {
ChipLogError(chipTool, "Only accepts the following: granted, obtaining, and denied.");
error = CHIP_ERROR_INTERNAL;
}
return error;
}

CHIP_ERROR OTASoftwareUpdateBase::Run()
{
if (!IsInteractive()) {
Expand Down

0 comments on commit 81f7284

Please sign in to comment.