diff --git a/examples/ota-provider-app/esp32/README.md b/examples/ota-provider-app/esp32/README.md index 5cf19e3aebe287..7ae2797c93b959 100644 --- a/examples/ota-provider-app/esp32/README.md +++ b/examples/ota-provider-app/esp32/README.md @@ -5,40 +5,31 @@ A prototype application that demonstrates OTA provider capabilities. ## Supported Devices - This example supports ESP32 and ESP32C3. For details please check - [here](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#supported-devices). + [here](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/esp32#supported-devices). -## Building the Example Application - -- If you are building for the first time please check - [Building the Example Application](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#building-the-example-application) - guide. -- Otherwise, `idf.py build` works! +## Copy the OTA image -## Flashing the Example Application +- Copy the binary file which you are going to send to the OTA Requestor to + `./spiffs_image` path and make sure the `OTA_IMAGE_NAME` is the same as the + name of the image file you placed in `./spiffs_image`. ``` -idf.py -p flash +idf.py menuconfig ``` -## Flashing the hello-world.bin OTA image - -Flash hello-world OTA image on OTA Provider's "ota_data" flash partition. Please -find hello-world.bin -[here](http://shubhamdp.github.io/esp_ota/esp32/hello-world-flash-in-ota-provider-partition.bin). -This OTA image is built for ESP32, it will not work on other devices. This is -the OTA upgrade image and will be sent to OTA requestor. +- Edit the `OTA_IMAGE_NAME` through `Demo`->`OTA image file name`. -``` -esptool.py -p write_flash 0x206400 hello-world-flash-in-ota-provider-partition.bin -``` +## Building the Example Application -NOTE: This is a modified binary which contains the size of OTA image at first 4 -bytes. +- If you are building for the first time please check + [Building the Example Application](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/esp32#building-the-example-application) + guide. +- Otherwise, `idf.py build` works! -Run the idf monitor +## Flashing the Example Application ``` -idf.py -p monitor +idf.py -p flash ``` ## Commissioning over BLE using chip-tool diff --git a/examples/ota-provider-app/esp32/main/CMakeLists.txt b/examples/ota-provider-app/esp32/main/CMakeLists.txt index a85dcdb35d4b82..9b4998f94db781 100644 --- a/examples/ota-provider-app/esp32/main/CMakeLists.txt +++ b/examples/ota-provider-app/esp32/main/CMakeLists.txt @@ -45,7 +45,8 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common" EXCLUDE_SRCS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp" - PRIV_REQUIRES chip QRCode bt console) + PRIV_REQUIRES chip QRCode bt console spiffs) +spiffs_create_partition_image(img_storage ../spiffs_image FLASH_IN_PROJECT) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14) target_compile_options(${COMPONENT_LIB} PRIVATE "-DLWIP_IPV6_SCOPES=0" "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/ota-provider-app/esp32/main/Kconfig.projbuild b/examples/ota-provider-app/esp32/main/Kconfig.projbuild index 96a7f14d5c69ec..b5a506f24a24fc 100644 --- a/examples/ota-provider-app/esp32/main/Kconfig.projbuild +++ b/examples/ota-provider-app/esp32/main/Kconfig.projbuild @@ -47,4 +47,10 @@ menu "Demo" default 4 if RENDEZVOUS_MODE_THREAD default 8 if RENDEZVOUS_MODE_ETHERNET + config OTA_IMAGE_NAME + string "OTA image file name" + default "hello_world.bin" + help + Name of OTA image file which will be added to '/spiffs_image/' and sent to the OTA Requestor. + endmenu diff --git a/examples/ota-provider-app/esp32/main/main.cpp b/examples/ota-provider-app/esp32/main/main.cpp index d50b11c3d3a730..3f5c8deae79636 100644 --- a/examples/ota-provider-app/esp32/main/main.cpp +++ b/examples/ota-provider-app/esp32/main/main.cpp @@ -21,6 +21,7 @@ #include "esp_log.h" #include "esp_netif.h" #include "esp_spi_flash.h" +#include "esp_spiffs.h" #include "esp_system.h" #include "esp_wifi.h" #include "freertos/FreeRTOS.h" @@ -60,7 +61,8 @@ void OnTransferComplete(void * context); void OnTransferFailed(void * context, BdxSenderErrorTypes status); namespace { -const char * TAG = "ota-provider-app"; +const char * TAG = "ota-provider-app"; +const uint8_t kMaxImagePathlen = 35; static DeviceCallbacks EchoCallbacks; BdxOtaSender bdxServer; @@ -69,10 +71,11 @@ constexpr chip::EndpointId kOtaProviderEndpoint = 0; constexpr uint32_t kMaxBdxBlockSize = 1024; constexpr chip::System::Clock::Timeout kBdxTimeout = chip::System::Clock::Seconds16(5 * 60); // Specification mandates >= 5 minutes constexpr chip::System::Clock::Timeout kBdxPollFreq = chip::System::Clock::Milliseconds32(500); -const char * otaFilename = "hello-world.bin"; -const esp_partition_t * otaPartition = nullptr; +const char * otaFilename = CONFIG_OTA_IMAGE_NAME; +FILE * otaImageFile = NULL; uint32_t otaImageLen = 0; uint32_t otaTransferInProgress = false; +static OTAProviderExample otaProvider; chip::Callback::Callback onBlockQueryCallback(OnBlockQuery, nullptr); chip::Callback::Callback onTransferCompleteCallback(OnTransferComplete, nullptr); @@ -83,22 +86,17 @@ CHIP_ERROR OnBlockQuery(void * context, chip::System::PacketBufferHandle & block { if (otaTransferInProgress == false) { - if (otaPartition == nullptr || otaImageLen == 0) + if (otaImageFile == NULL || otaImageLen == 0) { - ESP_LOGE(TAG, "OTA partition not found"); + ESP_LOGE(TAG, "Failed to open the OTA image file"); return CHIP_ERROR_OPEN_FAILED; } otaTransferInProgress = true; } - uint16_t blockBufAvailableLength = blockBuf->AvailableDataLength(); uint16_t transferBlockSize = bdxServer.GetTransferBlockSize(); size = (blockBufAvailableLength < transferBlockSize) ? blockBufAvailableLength : transferBlockSize; - - // There are two types of messages requestor can use to query a block: `BlockQuery` and `BlockQueryWithSkip` so, - // to handle both case in a single callback offset is used which is managed by the `BdxOtaSender`. - // So, offset + size will not overflow and even if it overflows the esp_partition_read API will return an error. if (offset + size >= otaImageLen) { size = otaImageLen - offset; @@ -108,17 +106,15 @@ CHIP_ERROR OnBlockQuery(void * context, chip::System::PacketBufferHandle & block { isEof = false; } - - esp_err_t err = esp_partition_read(otaPartition, offset + sizeof(otaImageLen), blockBuf->Start(), size); - if (err != ESP_OK) + size_t size_read = fread(blockBuf->Start(), 1, size, otaImageFile); + if (size_read != size) { - ESP_LOGI(TAG, "Failed to read %d bytes from offset %d", size, offset + sizeof(otaImageLen)); + ESP_LOGE(TAG, "Failed to read %d bytes from %s", size, otaFilename); size = 0; isEof = false; return CHIP_ERROR_READ_FAILED; } - - ESP_LOGI(TAG, "Read %d bytes from offset %d", size, offset + sizeof(otaImageLen)); + ESP_LOGI(TAG, "Read %d bytes from %s", size, otaFilename); return CHIP_NO_ERROR; } @@ -157,8 +153,6 @@ extern "C" void app_main() return; } - OTAProviderExample otaProvider; - CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); CHIP_ERROR error = deviceMgr.Init(&EchoCallbacks); @@ -188,26 +182,34 @@ extern "C" void app_main() callbacks.onTransferFailed = &onTransferFailedCallback; bdxServer.SetCallbacks(callbacks); - // If OTA image is available in flash storage then set to update available - otaPartition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "ota_data"); - if (otaPartition != nullptr) - { - ESP_LOGI(TAG, "Partition found %s address:0x%x size:0x%x", otaPartition->label, otaPartition->address, otaPartition->size); + esp_vfs_spiffs_conf_t spiffs_conf = { + .base_path = "/spiffs", + .partition_label = NULL, + .max_files = 3, + .format_if_mount_failed = false, + }; - // TODO: Use the OTA image header specified in the specification - // Right now we are using just image length instead of full header - esp_partition_read(otaPartition, 0, &otaImageLen, sizeof(otaImageLen)); - if (otaImageLen > otaPartition->size) - { - otaImageLen = 0; - } - ESP_LOGI(TAG, "OTA image length %d bytes", otaImageLen); + err = esp_vfs_spiffs_register(&spiffs_conf); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(err)); + return; } - else + size_t total = 0, used = 0; + err = esp_spiffs_info(NULL, &total, &used); + ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); + char otaImagePath[kMaxImagePathlen]; + sprintf(otaImagePath, "/spiffs/%s", otaFilename); + otaImageFile = fopen(otaImagePath, "r"); + if (otaImageFile == NULL) { - ESP_LOGE(TAG, "OTA partition not found"); + ESP_LOGE(TAG, "Failed to open %s", otaFilename); + return; } - + fseek(otaImageFile, 0, SEEK_END); + otaImageLen = ftell(otaImageFile); + rewind(otaImageFile); + ESP_LOGI(TAG, "The OTA image size: %d", otaImageLen); if (otaImageLen > 0) { otaProvider.SetQueryImageBehavior(OTAProviderExample::kRespondWithUpdateAvailable); diff --git a/examples/ota-provider-app/esp32/partitions.csv b/examples/ota-provider-app/esp32/partitions.csv index 671212345e7887..074db5a06dbe17 100644 --- a/examples/ota-provider-app/esp32/partitions.csv +++ b/examples/ota-provider-app/esp32/partitions.csv @@ -1,10 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, , 0x6000, -otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, -# Factory partition size about 1.9MB -factory, app, factory, , 1945K, -# OTA partition of size 1M -ota_data, data, nvs, , 1M, -# ota_1, app, ota_1, , 512K, +# Factory partition size about 1.5MB +factory, app, factory, , 1500K, +# spiffs partition to storage the image file size about 1.5MB +img_storage, data, spiffs, , 1500K, diff --git a/examples/ota-provider-app/esp32/spiffs_image/hello_world.bin b/examples/ota-provider-app/esp32/spiffs_image/hello_world.bin new file mode 100644 index 00000000000000..79965d499bba45 Binary files /dev/null and b/examples/ota-provider-app/esp32/spiffs_image/hello_world.bin differ diff --git a/examples/ota-requestor-app/esp32/README.md b/examples/ota-requestor-app/esp32/README.md index f90684378f52d0..bcea1698862d97 100644 --- a/examples/ota-requestor-app/esp32/README.md +++ b/examples/ota-requestor-app/esp32/README.md @@ -10,12 +10,12 @@ Before moving ahead, make sure you have ## Supported Devices - This example supports ESP32 and ESP32C3. For details please check - [here](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#supported-devices). + [here](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/esp32#supported-devices). ## Building the Example Application - If you are building for the first time please check - [Building the Example Application](https://github.com/shubhamdp/connectedhomeip/tree/shubhamdp-patch-1/examples/all-clusters-app/esp32#building-the-example-application) + [Building the Example Application](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/esp32#building-the-example-application) guide. - Otherwise, `idf.py build` works! diff --git a/examples/ota-requestor-app/esp32/main/OTARequesterImpl.cpp b/examples/ota-requestor-app/esp32/main/OTARequesterImpl.cpp index d9edae659fc9e7..b6c84742019da4 100644 --- a/examples/ota-requestor-app/esp32/main/OTARequesterImpl.cpp +++ b/examples/ota-requestor-app/esp32/main/OTARequesterImpl.cpp @@ -32,12 +32,12 @@ using chip::ByteSpan; using chip::CharSpan; -using chip::DeviceProxy; using chip::EndpointId; using chip::FabricIndex; using chip::NodeId; using chip::OnDeviceConnected; using chip::OnDeviceConnectionFailure; +using chip::OperationalDeviceProxy; using chip::Optional; using chip::PeerId; using chip::Server; @@ -55,7 +55,7 @@ void OnQueryImageFailure(void * context, EmberAfStatus status); void OnApplyUpdateResponse(void * context, const ApplyUpdateResponse::DecodableType & response); void OnApplyUpdateRequestFailure(void * context, EmberAfStatus status); -void OnConnected(void * context, chip::DeviceProxy * deviceProxy); +void OnConnected(void * context, chip::OperationalDeviceProxy * deviceProxy); void OnConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error); void OnBlockReceived(void * context, const chip::bdx::TransferSession::BlockData & blockdata); @@ -174,7 +174,7 @@ void OnApplyUpdateRequestFailure(void * context, EmberAfStatus status) ChipLogDetail(SoftwareUpdate, "ApplyUpdateRequest failure response %" PRIu8, status); } -void OnConnected(void * context, chip::DeviceProxy * deviceProxy) +void OnConnected(void * context, chip::OperationalDeviceProxy * deviceProxy) { ChipLogDetail(SoftwareUpdate, "Callback OnConnected"); uint8_t * command = reinterpret_cast(context); diff --git a/examples/ota-requestor-app/esp32/main/main.cpp b/examples/ota-requestor-app/esp32/main/main.cpp index 3acbe4f8d0d94e..71f5e3b491b95b 100644 --- a/examples/ota-requestor-app/esp32/main/main.cpp +++ b/examples/ota-requestor-app/esp32/main/main.cpp @@ -17,6 +17,8 @@ #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" +#include "app/util/af-enums.h" +#include "app/util/af.h" #include "esp_heap_caps_init.h" #include "esp_log.h" #include "esp_netif.h" @@ -180,3 +182,14 @@ extern "C" void app_main() ESPInitConsole(); } + +// TODO: We should use the function definition in /src/app/clusters/ota-requestor/ClusterInterface.cpp +// Temporarily add this function. + +bool emberAfOtaSoftwareUpdateRequestorClusterAnnounceOtaProviderCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData) +{ + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); + return true; +}