Skip to content

Commit cde357f

Browse files
shubhamdpbzbarsky-applecarol-applerestyled-commits
authored
ESP32: OTA Requestor and OTA Provider example applications (project-chip#11320)
* Added OTA requester and provider app for esp32 * Apply suggestions from code review Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Addressed review comments * Addressed review comments * Apply suggestions from code review Co-authored-by: Carol Yang <clyang@apple.com> * Restyled by clang-format * Addressed review comments * Added few words to spellcheck dictionary * Added .gitignore files to esp32 ota apps Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> Co-authored-by: Carol Yang <clyang@apple.com> Co-authored-by: Restyled.io <commits@restyled.io>
1 parent a4607d3 commit cde357f

36 files changed

+2946
-2
lines changed

.github/.wordlist.txt

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ AppConfig
3939
ApplicationBasic
4040
ApplicationIdentifier
4141
ApplicationLauncher
42+
ApplyUpdateRequest
4243
approver
4344
appspot
4445
aps
@@ -340,6 +341,7 @@ env
340341
esd
341342
ESPPORT
342343
Espressif
344+
esptool
343345
eth
344346
EthernetNetworkDiagnostics
345347
ethernets
@@ -690,6 +692,11 @@ optionsMask
690692
optionsOverride
691693
orgs
692694
OTA
695+
OTAProviderIpAddress
696+
OTAProviderNodeId
697+
OTAProviderSerialPort
698+
OTARequesterImpl
699+
OTARequestorSerialPort
693700
OTBR
694701
otcli
695702
PAA
@@ -848,6 +855,7 @@ SetpointRaiseLower
848855
SetUpPINCode
849856
SetupQRCode
850857
sexualized
858+
shubhamdp
851859
SIGINT
852860
SiLabs
853861
SiliconLabs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.vscode
2+
3+
/build/
4+
/sdkconfig
5+
/sdkconfig.old
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#
2+
# Copyright (c) 2021 Project CHIP Authors
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# The following lines of boilerplate have to be in your project's
18+
# CMakeLists in this exact order for cmake to work correctly
19+
cmake_minimum_required(VERSION 3.5)
20+
21+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
22+
include(${CMAKE_CURRENT_LIST_DIR}/../../common/cmake/idf_flashing.cmake)
23+
24+
set(EXTRA_COMPONENT_DIRS
25+
"${CMAKE_CURRENT_LIST_DIR}/third_party/connectedhomeip/config/esp32/components"
26+
"${CMAKE_CURRENT_LIST_DIR}/../../common/QRCode"
27+
)
28+
29+
project(chip-ota-provider-app)
30+
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++14;-Os;-DLWIP_IPV6_SCOPES=0;-DCHIP_HAVE_CONFIG_H" APPEND)
31+
idf_build_set_property(C_COMPILE_OPTIONS "-Os;-DLWIP_IPV6_SCOPES=0" APPEND)
32+
33+
flashing_script()
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# CHIP ESP32 OTA Provider Example
2+
3+
A prototype application that demonstrates OTA provider capabilities.
4+
5+
## Supported Devices
6+
7+
- This example supports ESP32 and ESP32C3. For details please check
8+
[here](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#supported-devices).
9+
10+
## Building the Example Application
11+
12+
- If you are building for the first time please check
13+
[Building the Example Application](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#building-the-example-application)
14+
guide.
15+
- Otherwise, `idf.py build` works!
16+
17+
## Flashing the Example Application
18+
19+
```
20+
idf.py -p <OTAProviderSerialPort> flash
21+
```
22+
23+
## Flashing the hello-world.bin OTA image
24+
25+
Flash hello-world OTA image on OTA Provider's "ota_data" flash partition. Please
26+
find hello-world.bin
27+
[here](http://shubhamdp.github.io/esp_ota/esp32/hello-world-flash-in-ota-provider-partition.bin).
28+
This OTA image is built for ESP32, it will not work on other devices. This is
29+
the OTA upgrade image and will be sent to OTA requestor.
30+
31+
```
32+
esptool.py -p <OTAProviderSerialPort> write_flash 0x206400 hello-world-flash-in-ota-provider-partition.bin
33+
```
34+
35+
NOTE: This is a modified binary which contains the size of OTA image at first 4
36+
bytes.
37+
38+
Run the idf monitor
39+
40+
```
41+
idf.py -p <OTAProviderSerialPort> monitor
42+
```
43+
44+
## Commissioning over BLE using chip-tool
45+
46+
- Please build the standalone chip-tool as described [here](../../chip-tool)
47+
- Commissioning the OTA Provider
48+
49+
```
50+
./out/debug/chip-tool pairing ble-wifi 12345 <ssid> <passphrase> 0 20202021 3841
51+
```
52+
53+
---
54+
55+
Please note down the IP Address and Node ID of OTA Provider, these are required
56+
for [OTA Requestor Example](../../ota-requestor-app/esp32). Once OTA provider is
57+
commissioned then head over to
58+
[OTA Requestor Example](../../ota-requestor-app/esp32).
59+
60+
---
61+
62+
## Features
63+
64+
- Can complete full BDX transfer
65+
- Provide the full OTA image to Requestor
66+
67+
## Limitations
68+
69+
- Synchronous BDX transfer only
70+
- Does not check VID/PID
71+
- Only one transfer at a time
72+
- Does not check incoming UpdateTokens
73+
- Does not support the header defined in Matter Specification.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
*
3+
* Copyright (c) 2021 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include <BdxOtaSender.h>
19+
20+
#include <lib/core/CHIPError.h>
21+
#include <lib/support/BitFlags.h>
22+
#include <lib/support/CHIPMemString.h>
23+
#include <messaging/ExchangeContext.h>
24+
#include <messaging/Flags.h>
25+
#include <protocols/bdx/BdxTransferSession.h>
26+
27+
using chip::bdx::StatusCode;
28+
using chip::bdx::TransferControlFlags;
29+
using chip::bdx::TransferSession;
30+
31+
void BdxOtaSender::SetCallbacks(BdxOtaSenderCallbacks callbacks)
32+
{
33+
mOnBlockQueryCallback = callbacks.onBlockQuery;
34+
mOnTransferCompleteCallback = callbacks.onTransferComplete;
35+
mOnTransferFailedCallback = callbacks.onTransferFailed;
36+
}
37+
38+
void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & event)
39+
{
40+
CHIP_ERROR err = CHIP_NO_ERROR;
41+
42+
if (event.EventType != TransferSession::OutputEventType::kNone)
43+
{
44+
ChipLogDetail(BDX, "OutputEvent type: %s", event.ToString(event.EventType));
45+
}
46+
47+
switch (event.EventType)
48+
{
49+
case TransferSession::OutputEventType::kNone:
50+
break;
51+
case TransferSession::OutputEventType::kMsgToSend: {
52+
chip::Messaging::SendFlags sendFlags;
53+
if (!event.msgTypeData.HasMessageType(chip::Protocols::SecureChannel::MsgType::StatusReport))
54+
{
55+
// All messages sent from the Sender expect a response, except for a StatusReport which would indicate an error and the
56+
// end of the transfer.
57+
sendFlags.Set(chip::Messaging::SendMessageFlags::kExpectResponse);
58+
}
59+
VerifyOrReturn(mExchangeCtx != nullptr, ChipLogError(BDX, "%s: mExchangeCtx is null", __FUNCTION__));
60+
err = mExchangeCtx->SendMessage(event.msgTypeData.ProtocolId, event.msgTypeData.MessageType, std::move(event.MsgData),
61+
sendFlags);
62+
if (err != CHIP_NO_ERROR)
63+
{
64+
ChipLogError(BDX, "SendMessage failed: %s", chip::ErrorStr(err));
65+
}
66+
break;
67+
}
68+
case TransferSession::OutputEventType::kInitReceived: {
69+
// TransferSession will automatically reject a transfer if there are no
70+
// common supported control modes. It will also default to the smaller
71+
// block size.
72+
TransferSession::TransferAcceptData acceptData;
73+
acceptData.ControlMode = TransferControlFlags::kReceiverDrive; // OTA must use receiver drive
74+
acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize();
75+
acceptData.StartOffset = mTransfer.GetStartOffset();
76+
acceptData.Length = mTransfer.GetTransferLength();
77+
VerifyOrReturn(mTransfer.AcceptTransfer(acceptData) == CHIP_NO_ERROR,
78+
ChipLogError(BDX, "%s: %s", __FUNCTION__, chip::ErrorStr(err)));
79+
break;
80+
}
81+
case TransferSession::OutputEventType::kQueryReceived: {
82+
TransferSession::BlockData blockData;
83+
uint16_t blockSize = mTransfer.GetTransferBlockSize();
84+
uint16_t bytesToRead = blockSize;
85+
86+
chip::System::PacketBufferHandle blockBuf = chip::System::PacketBufferHandle::New(bytesToRead);
87+
if (blockBuf.IsNull())
88+
{
89+
// TODO: AbortTransfer() needs to support GeneralStatusCode failures as well as BDX specific errors.
90+
mTransfer.AbortTransfer(StatusCode::kUnknown);
91+
return;
92+
}
93+
94+
if (mOnBlockQueryCallback != nullptr && mOnBlockQueryCallback->mCall != nullptr)
95+
{
96+
if (CHIP_NO_ERROR !=
97+
mOnBlockQueryCallback->mCall(mOnBlockQueryCallback->mContext, blockBuf, blockData.Length, blockData.IsEof,
98+
mNumBytesSent))
99+
{
100+
ChipLogError(BDX, "onBlockQuery Callback failed");
101+
mTransfer.AbortTransfer(StatusCode::kUnknown);
102+
return;
103+
}
104+
}
105+
else
106+
{
107+
ChipLogError(BDX, "onBlockQuery Callback not set");
108+
mTransfer.AbortTransfer(StatusCode::kUnknown);
109+
return;
110+
}
111+
112+
blockData.Data = blockBuf->Start();
113+
mNumBytesSent = static_cast<uint32_t>(mNumBytesSent + blockData.Length);
114+
115+
VerifyOrReturn(CHIP_NO_ERROR == mTransfer.PrepareBlock(blockData),
116+
ChipLogError(BDX, "%s: PrepareBlock failed: %s", __FUNCTION__, chip::ErrorStr(err)));
117+
break;
118+
}
119+
case TransferSession::OutputEventType::kAckReceived:
120+
break;
121+
case TransferSession::OutputEventType::kAckEOFReceived:
122+
ChipLogDetail(BDX, "Transfer completed, got AckEOF");
123+
if (mOnTransferCompleteCallback != nullptr && mOnTransferCompleteCallback->mCall != nullptr)
124+
{
125+
mOnTransferCompleteCallback->mCall(mOnTransferCompleteCallback->mContext);
126+
}
127+
else
128+
{
129+
ChipLogError(BDX, "onTransferComplete Callback not set");
130+
}
131+
Reset();
132+
break;
133+
case TransferSession::OutputEventType::kStatusReceived:
134+
ChipLogError(BDX, "Got StatusReport %x", static_cast<uint16_t>(event.statusData.statusCode));
135+
if (mOnTransferFailedCallback != nullptr && mOnTransferFailedCallback->mCall != nullptr)
136+
{
137+
mOnTransferFailedCallback->mCall(mOnTransferFailedCallback->mContext, kErrorBdxSenderStatusReceived);
138+
}
139+
else
140+
{
141+
ChipLogError(BDX, "onTransferFailed Callback not set");
142+
}
143+
Reset();
144+
break;
145+
case TransferSession::OutputEventType::kInternalError:
146+
ChipLogError(BDX, "InternalError");
147+
if (mOnTransferFailedCallback != nullptr && mOnTransferFailedCallback->mCall != nullptr)
148+
{
149+
mOnTransferFailedCallback->mCall(mOnTransferFailedCallback->mContext, kErrorBdxSenderInternal);
150+
}
151+
{
152+
ChipLogError(BDX, "onTransferFailed Callback not set");
153+
}
154+
Reset();
155+
break;
156+
case TransferSession::OutputEventType::kTransferTimeout:
157+
ChipLogError(BDX, "Transfer timed out");
158+
if (mOnTransferFailedCallback != nullptr && mOnTransferFailedCallback->mCall != nullptr)
159+
{
160+
mOnTransferFailedCallback->mCall(mOnTransferFailedCallback->mContext, kErrorBdxSenderTimeOut);
161+
}
162+
{
163+
ChipLogError(BDX, "onTransferFailed Callback not set");
164+
}
165+
Reset();
166+
break;
167+
case TransferSession::OutputEventType::kAcceptReceived:
168+
case TransferSession::OutputEventType::kBlockReceived:
169+
default:
170+
// TransferSession should prevent this case from happening.
171+
ChipLogError(BDX, "%s: unsupported event type", __FUNCTION__);
172+
}
173+
}
174+
175+
void BdxOtaSender::Reset()
176+
{
177+
mTransfer.Reset();
178+
if (mExchangeCtx != nullptr)
179+
{
180+
mExchangeCtx->Close();
181+
}
182+
mNumBytesSent = 0;
183+
}
184+
185+
uint16_t BdxOtaSender::GetTransferBlockSize(void)
186+
{
187+
return mTransfer.GetTransferBlockSize();
188+
}
189+
190+
uint64_t BdxOtaSender::GetTransferLength()
191+
{
192+
return mTransfer.GetTransferLength();
193+
}

0 commit comments

Comments
 (0)