Skip to content

Commit

Permalink
Added OTA provider app for esp32
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Patil <[email protected]>
  • Loading branch information
shubhamdp committed Nov 2, 2021
1 parent fb514e3 commit 70e6874
Show file tree
Hide file tree
Showing 16 changed files with 998 additions and 45 deletions.
33 changes: 33 additions & 0 deletions examples/ota-provider-app/esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#
# Copyright (c) 2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/../../common/cmake/idf_flashing.cmake)

set(EXTRA_COMPONENT_DIRS
"${CMAKE_CURRENT_LIST_DIR}/third_party/connectedhomeip/config/esp32/components"
"${CMAKE_CURRENT_LIST_DIR}/../../common/QRCode"
)

project(chip-ota-provider-app)
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++14;-Os;-DLWIP_IPV6_SCOPES=0;-DCHIP_HAVE_CONFIG_H" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "-Os;-DLWIP_IPV6_SCOPES=0" APPEND)

flashing_script()
44 changes: 44 additions & 0 deletions examples/ota-provider-app/esp32/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ota-provider-app (ESP32)

### Build and flash OTA apps
- Build and flash [ESP32 OTA provider app](.) and [ESP32 OTA Requestor app](../../ota-requestor-app)
```
$ cd examples/ota-provider-app/esp32
$ idf.py -p <RequestorSerialPort> build flash
$ cd examples/ota-requestor-app/esp32
$ idf.py -p <ProviderSerialPort> build flash
```

- Flash hello-world OTA binary in providor app. Please find hello-world.bin [here](http://shubhamdp.github.io/esp_ota/esp32/hello-world-flash-in-ota-provider-partition.bin)
```
esptool.py -p <ProviderSerialPort> write_flash 0x206400 hello-world-flash-in-ota-provider-partition.bin
```

- Run IDF monitor for both applications in separate terminals
```
idf.py -p <RequestorSerialPort> monitor
idf.py -p <ProviderSerialPort> monitor
```

### Commission both apps
```
# Commission OTA Provider
$ ./chip-tool pairing ble-wifi 12345 <ssid> <passphrase> 0 20202021 3841
# Commission OTA Requestor
$ ./chip-tool pairing ble-wifi 123456 <ssid> <passphrase> 0 20202021 3840
```

## QueryImage from requestor console
```
esp32> QueryImage <ip> 12345 // node id should be in decimal
```

When the image download is complete device waits for an ApplyUpdate command, so fire following command from Requestor app

```
esp32> ApplyUpdateRequest <ip> 12345 // node id should be in decimal
```

After this Requestor will run hello-world application.
105 changes: 105 additions & 0 deletions examples/ota-provider-app/esp32/main/CHIPDeviceManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* This file implements the CHIP Device Interface that is used by
* applications to interact with the CHIP stack
*
*/

#include <stdlib.h>

#include "CHIPDeviceManager.h"
#include <app/ConcreteAttributePath.h>
#include <app/util/basic-types.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <setup_payload/SetupPayload.h>

using namespace ::chip;

namespace chip {

namespace DeviceManager {

using namespace ::chip::DeviceLayer;

void CHIPDeviceManager::CommonDeviceEventHandler(const ChipDeviceEvent * event, intptr_t arg)
{
CHIPDeviceManagerCallbacks * cb = reinterpret_cast<CHIPDeviceManagerCallbacks *>(arg);
if (cb != nullptr)
{
cb->DeviceEventCallback(event, reinterpret_cast<intptr_t>(cb));
}
}

CHIP_ERROR CHIPDeviceManager::Init(CHIPDeviceManagerCallbacks * cb)
{
CHIP_ERROR err;
mCB = cb;
RendezvousInformationFlags flags = RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE);

// Initialize the CHIP stack.
err = PlatformMgr().InitChipStack();
SuccessOrExit(err);

if (flags.Has(RendezvousInformationFlag::kBLE))
{
ConnectivityMgr().SetBLEAdvertisingEnabled(true);
}
else if (flags.Has(RendezvousInformationFlag::kSoftAP))
{
// TODO(cecille): Fix for the case where BLE and SoftAP are both enabled.`
ConnectivityMgr().SetBLEAdvertisingEnabled(false);
ConnectivityMgr().SetWiFiAPMode(ConnectivityManager::kWiFiAPMode_Enabled);
}
else
{
// If rendezvous is bypassed, enable SoftAP so that the device can still
// be communicated with via its SoftAP as needed.
ConnectivityMgr().SetWiFiAPMode(ConnectivityManager::kWiFiAPMode_Enabled);
}

err = Platform::MemoryInit();
SuccessOrExit(err);

// Register a function to receive events from the CHIP device layer. Note that calls to
// this function will happen on the CHIP event loop thread, not the app_main thread.
PlatformMgr().AddEventHandler(CHIPDeviceManager::CommonDeviceEventHandler, reinterpret_cast<intptr_t>(cb));

// Start a task to run the CHIP Device event loop.
err = PlatformMgr().StartEventLoopTask();
SuccessOrExit(err);

exit:
return err;
}
} // namespace DeviceManager
} // namespace chip

void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t mask, uint8_t type, uint16_t size,
uint8_t * value)
{
chip::DeviceManager::CHIPDeviceManagerCallbacks * cb =
chip::DeviceManager::CHIPDeviceManager::GetInstance().GetCHIPDeviceManagerCallbacks();
if (cb != nullptr)
{
cb->PostAttributeChangeCallback(path.mEndpointId, path.mClusterId, path.mAttributeId, mask, type, size, value);
}
}
54 changes: 54 additions & 0 deletions examples/ota-provider-app/esp32/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# Copyright (c) 2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
idf_component_register(PRIV_INCLUDE_DIRS
"${CMAKE_CURRENT_LIST_DIR}"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/third_party/nlio/repo/include"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-provider-app/"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/"
"${CMAKE_CURRENT_LIST_DIR}/include"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app"
SRC_DIRS
"${CMAKE_CURRENT_LIST_DIR}"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-provider-app/zap-generated"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/device"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet_network_diagnostics_server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread_network_diagnostics_server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi_network_diagnostics_server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software_diagnostics_server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general_diagnostics_server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-provider"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common"
PRIV_REQUIRES chip QRCode bt console)

set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14)
target_compile_options(${COMPONENT_LIB} PRIVATE "-DLWIP_IPV6_SCOPES=0" "-DCHIP_HAVE_CONFIG_H")
122 changes: 122 additions & 0 deletions examples/ota-provider-app/esp32/main/DeviceCallbacks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file DeviceCallbacks.cpp
*
* Implements all the callbacks to the application from the CHIP Stack
*
**/
#include "DeviceCallbacks.h"
// #include "OTARequesterImpl.h"

#include "esp_heap_caps.h"
#include "esp_log.h"
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/cluster-id.h>
#include <app/server/Dnssd.h>
#include <lib/support/CodeUtils.h>

static const char * TAG = "echo-devicecallbacks";

using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::DeviceLayer;

// void OnStartDelayTimerHandler(Layer * systemLayer, void *appState)
// {
// ESP_LOGI(TAG, "Calling SendQueryImageCommand()");
// OTARequesterImpl::GetInstance().SendQueryImageCommand();
// }

void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg)
{
switch (event->Type)
{
case DeviceEventType::kInternetConnectivityChange:
OnInternetConnectivityChange(event);
break;

case DeviceEventType::kSessionEstablished:
OnSessionEstablished(event);
break;
case DeviceEventType::kInterfaceIpAddressChanged:
if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) ||
(event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned))
{
// MDNS server restart on any ip assignment: if link local ipv6 is configured, that
// will not trigger a 'internet connectivity change' as there is no internet
// connectivity. MDNS still wants to refresh its listening interfaces to include the
// newly selected address.
chip::app::DnssdServer::Instance().StartServer();
}
break;
// case DeviceEventType::kCommissioningComplete:
// ESP_LOGI(TAG, "Commissioning complete");
//
// /* Start on shot timer to Query for OTA image once commissinoning is complete */
// chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32( 30 * 1000),
// OnStartDelayTimerHandler, nullptr);
// break;

}
ESP_LOGI(TAG, "Current free heap: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT));
}

void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t mask,
uint8_t type, uint16_t size, uint8_t * value)
{
ESP_LOGI(TAG, "PostAttributeChangeCallback - Cluster ID: '0x%04x', EndPoint ID: '0x%02x', Attribute ID: '0x%04x'", clusterId,
endpointId, attributeId);

// TODO handle this callback in switch statement
ESP_LOGI(TAG, "Unhandled cluster ID: %d", clusterId);

ESP_LOGI(TAG, "Current free heap: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT));
}

void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event)
{
if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established)
{
ESP_LOGI(TAG, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT);
chip::app::DnssdServer::Instance().StartServer();
}
else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost)
{
ESP_LOGE(TAG, "Lost IPv4 connectivity...");
}
if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established)
{
ESP_LOGI(TAG, "IPv6 Server ready...");
chip::app::DnssdServer::Instance().StartServer();
}
else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost)
{
ESP_LOGE(TAG, "Lost IPv6 connectivity...");
}
}

void DeviceCallbacks::OnSessionEstablished(const ChipDeviceEvent * event)
{
if (event->SessionEstablished.IsCommissioner)
{
ESP_LOGI(TAG, "Commissioner detected!");
}
}
Loading

0 comments on commit 70e6874

Please sign in to comment.