Skip to content

Commit

Permalink
Implement periodic timer for querying OTA providers, refactor OTARequ…
Browse files Browse the repository at this point in the history
…estor and OTARequestorDriver (#15433)

* Add quasi-state machine for the Requestor

* Use the RequestorDriver scheduling method instead of the platform timer

The Linux OTA scenario works with this change

* Add a commissioning callback

* Add periodic timer for querying the default OTA provider

* Add calls to StartDefaultProvidersTimer()

* Move all calls to StartDefaultProvidersTimer() to RecordNewUpdateState()

* Move some of the Requestor logic to the GenericOTARequestorDriver class

* Update comments

* Fix StartDelayTimerHandler() call

* Add DriverTriggerQuery() method

* Remove obsolet methods from OTARequestor

* Rearrange error logic flow

* Use TriggerImmediateQuery() API when processing AnnounceOTAProviders

* Use DetermineProviderLocation() to pick the provider location

* Introduce mLastUsedProvider

* Rename functions and add comments

* Rework StartDelayTimerHandler

* Cleanup unused parameter, comments

* Clean up spelling

* Fix override compile error

* Restyled by whitespace

* Restyled by clang-format

* Remove unused enum

* Rename variable, fix comments, change private back to protected (merge artifact)

* Restyled by clang-format

* Make periodic query timeout configurable on Linux

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

Co-authored-by: Carol Yang <clyang@apple.com>

* Update examples/ota-requestor-app/linux/README.md

Co-authored-by: Carol Yang <clyang@apple.com>

* Update wording

Co-authored-by: Carol Yang <clyang@apple.com>

* Use seconds for the delay, don't set the state prematurely, use lambda

* Rework enums, query retry logic

* Restyled by whitespace

* Restyled by clang-format

* Restyled by prettier-markdown

* Add word to disctionary

* Delay initial query after commissioning

* Restyled by whitespace

* Restyled by clang-format

* Udate comment

* Introduce GenericOTARequestorDriver::OTACommissioningCallback

* Restyled by whitespace

* Restyled by clang-format

* Rename and move around various OTARequestor and Driver APIs

* Restyled by whitespace

* Restyled by clang-format

* Resolve merge conflicts from the latest merge from master

* Rename variables and update comments

* Restyled by whitespace

* Remove leftover code block

* When connecting to the Provider change the state to kUnknown

* Remove unused function

* Check for kCommissioningComplete; clear current provider

* Set the kQuerying state in TriggerImmediateQueryInternal

* Restyled by clang-format

* Restyled by prettier-markdown

* Clean up missed merge conflicts

* Restyled by prettier-markdown

Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Carol Yang <clyang@apple.com>
  • Loading branch information
3 people authored and pull[bot] committed Oct 25, 2023
1 parent 2a2d342 commit 0961020
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 192 deletions.
1 change: 1 addition & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ peerNodeId
peerSessionId
pem
percentageLiftValue
periodicQueryTimeout
pexpect
pickString
PID
Expand Down
3 changes: 2 additions & 1 deletion examples/ota-requestor-app/efr32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,13 @@ See `examples/lighting-app/efr32/README.md`
- In a terminal start the provider app passing to it the path to the bootable
image file created in the previous step:

rm -r /tmp/chip_*
./out/debug/chip-ota-provider-app -f chip-efr32-ota-requestor-example.gbl

- In a separate terminal run the chip-tool commands to provision the Provider:

rm -r /tmp/chip_*
./out/chip-tool pairing onnetwork 1 20202021
./out/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0

- If the Requestor had been previously commissioned hold Button 0 for six
seconds to factory-reset the device.
Expand Down
27 changes: 12 additions & 15 deletions examples/ota-requestor-app/linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ scripts/examples/gn_build_example.sh examples/ota-requestor-app/linux out/debug
In addition to the general options available to all Linux applications, the
following command line options are available for the OTA Requestor application.

| Directory | Description |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| -q/--delayQuery <Time in seconds> | From boot up, the amount of time to wait before triggering the QueryImage command. If none or zero is supplied, QueryImage will not be triggered automatically. At least one provider location must be written to the DefaultOTAProviders attribute. |
| -c/--requestorCanConsent | If supplied, the RequestorCanConsent field of the QueryImage command is set to true. Otherwise, the value is determined by the driver. |
| -f/--otaDownloadPath <file path> | If supplied, the OTA image is downloaded to the given fully-qualified file-path. Otherwise, the value defaults to /tmp/test.bin. |
| Directory | Description |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| -p/--periodicQueryTimeout <Time in seconds> | Periodic timeout for querying providers in the default OTA provider list. If none or zero is supplied the timeout is set to every 24 hours. |
| -c/--requestorCanConsent | If supplied, the RequestorCanConsent field of the QueryImage command is set to true. Otherwise, the value is determined by the driver. |
| -f/--otaDownloadPath <file path> | If supplied, the OTA image is downloaded to the given fully-qualified file-path. Otherwise, the value defaults to /tmp/test.bin. |

## Software Image Header

Expand Down Expand Up @@ -87,7 +87,8 @@ Follow instructions
#### Run the OTA Requestor application:

```
out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --secured-device-port ${REQUESTOR_UDP_PORT} --KVS ${KVS_STORE_LOCATION} --delayQuery ${TIME_IN_SECONDS} --otaDownloadPath ${OTA_FILE_PATH}
out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --secured-device-port ${REQUESTOR_UDP_PORT} --KVS ${KVS_STORE_LOCATION} --periodicQueryTimeout ${TIME_IN_SECONDS}
```

- `${REQUESTOR_LONG_DISCRIMINATOR}` is the long discriminator specified for
Expand All @@ -100,10 +101,9 @@ out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --sec
- `${KVS_STORE_LOCATION}` is a location where the KVS items will be stored. If
none is supplied, the default is /tmp/chip_kvs. This must be different from
the value used by the OTA Provider application.
- `${TIME_IN_SECONDS}` is the amount of time to wait before triggering the
QueryImage command specified by the DefaultOTAProviders attribute
- `${OTA_FILE_PATH}` is the fully-qualified path for the OTA file download
location
- `${TIME_IN_SECONDS}` is the periodic timeout for querying providers in the
default OTA provider list. If none or zero is supplied the timeout is set to
every 24 hours.

#### Commission the OTA Requestor application

Expand Down Expand Up @@ -215,7 +215,7 @@ scripts/examples/gn_build_example.sh examples/ota-requestor-app/linux/ out chip_
**Run the OTA Requestor application**

```
out/chip-ota-requestor-app --discriminator 18 --secured-device-port 5560 --KVS /tmp/chip_kvs_requestor --delayQuery 30 --otaDownloadPath /tmp/test.bin
out/chip-ota-requestor-app --discriminator 18 --secured-device-port 5560 --KVS /tmp/chip_kvs_requestor --periodicQueryTimeout 60 --otaDownloadPath /tmp/test.bin
```

#### In terminal 3:
Expand All @@ -234,14 +234,11 @@ out/chip-tool pairing onnetwork-long 0x1234567890 20202021 18

**Write to the DefaultOTAProviders attribute**

Note that this must be done within 30 seconds (as specified by the
`--delayQuery 30`) from when the OTA Requestor application was launched

```
out/chip-tool otasoftwareupdaterequestor write default-ota-providers '[{"fabricIndex": 1, "providerNodeID": 3735928559, "endpoint": 0}]' 0x0000001234567890 0
```

After 30 seconds from when the OTA Requestor application has launched, the OTA
Every 60 seconds from when the OTA Requestor application has launched, the OTA
Requestor application with node ID 0x1234567890 will send a QueryImage command
to the OTA Provider with node ID 0xDEADBEEF, as specified in the
`DefaultOTAProviders` attribute.
Expand Down
38 changes: 12 additions & 26 deletions examples/ota-requestor-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,27 @@ BDXDownloader gDownloader;
OTAImageProcessorImpl gImageProcessor;

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue);
void OnStartDelayTimerHandler(Layer * systemLayer, void * appState);

constexpr uint16_t kOptionDelayQuery = 'q';
constexpr uint16_t kOptionRequestorCanConsent = 'c';
constexpr uint16_t kOptionOtaDownloadPath = 'f';
constexpr size_t kMaxFilePathSize = 256;
constexpr uint16_t kOptionPeriodicQueryTimeout = 'p';
constexpr uint16_t kOptionRequestorCanConsent = 'c';
constexpr uint16_t kOptionOtaDownloadPath = 'f';
constexpr size_t kMaxFilePathSize = 256;

uint16_t delayQueryTimeInSec = 0;
uint32_t gPeriodicQueryTimeoutSec = (24 * 60 * 60);
chip::Optional<bool> gRequestorCanConsent;
static char gOtaDownloadPath[kMaxFilePathSize] = "/tmp/test.bin";

OptionDef cmdLineOptionsDef[] = {
{ "delayQuery", chip::ArgParser::kArgumentRequired, kOptionDelayQuery },
{ "periodicQueryTimeout", chip::ArgParser::kArgumentRequired, kOptionPeriodicQueryTimeout },
{ "requestorCanConsent", chip::ArgParser::kNoArgument, kOptionRequestorCanConsent },
{ "otaDownloadPath", chip::ArgParser::kArgumentRequired, kOptionOtaDownloadPath },
{},
};

OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS",
" -q/--delayQuery <Time in seconds>\n"
" From boot up, the amount of time to wait before triggering the QueryImage\n"
" command. If none or zero is supplied, QueryImage will not be triggered automatically. At "
"least one provider location must be written to the DefaultOTAProviders attribute.\n"
" -p/--periodicQueryTimeout <Time in seconds>\n"
" Periodic timeout for querying providers in the default OTA provider list\n"
" If none or zero is supplied the timeout is set to every 24 hours. \n"
" -c/--requestorCanConsent\n"
" If supplied, the RequestorCanConsent field of the QueryImage command is set to true.\n"
" Otherwise, the value is determined by the driver.\n "
Expand All @@ -91,6 +89,7 @@ static void InitOTARequestor(void)

gRequestorCore.Init(&(chip::Server::GetInstance()), &gRequestorUser, &gDownloader);
gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
gRequestorUser.SetPeriodicQueryTimeout(gPeriodicQueryTimeoutSec);

// 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.
Expand All @@ -109,8 +108,8 @@ bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier,

switch (aIdentifier)
{
case kOptionDelayQuery:
delayQueryTimeInSec = static_cast<uint16_t>(strtol(aValue, NULL, 0));
case kOptionPeriodicQueryTimeout:
gPeriodicQueryTimeoutSec = static_cast<uint32_t>(strtoul(aValue, NULL, 0));
break;
case kOptionRequestorCanConsent:
gRequestorCanConsent.SetValue(true);
Expand Down Expand Up @@ -138,13 +137,6 @@ void ApplicationInit()

// Initialize all OTA download components
InitOTARequestor();

// If a delay is provided, after the timer expires, QueryImage from default OTA provider
if (delayQueryTimeInSec > 0)
{
chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(delayQueryTimeInSec * 1000),
OnStartDelayTimerHandler, nullptr);
}
}

int main(int argc, char * argv[])
Expand All @@ -153,9 +145,3 @@ int main(int argc, char * argv[])
ChipLinuxAppMainLoop();
return 0;
}

// Test mode operation
void OnStartDelayTimerHandler(Layer * systemLayer, void * appState)
{
static_cast<OTARequestor *>(GetRequestorInstance())->TriggerImmediateQuery();
}
Loading

0 comments on commit 0961020

Please sign in to comment.