mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
example: remove light_network_prov example
This commit is contained in:
@@ -111,12 +111,6 @@ examples/ota_provider:
|
|||||||
temporary: true
|
temporary: true
|
||||||
reason: the other targets are not tested yet
|
reason: the other targets are not tested yet
|
||||||
|
|
||||||
examples/light_network_prov:
|
|
||||||
enable:
|
|
||||||
- if: IDF_TARGET in ["esp32s3", "esp32c3", "esp32h2"]
|
|
||||||
temporary: true
|
|
||||||
reason: the other targets are not tested yet
|
|
||||||
|
|
||||||
examples/thread_border_router:
|
examples/thread_border_router:
|
||||||
enable:
|
enable:
|
||||||
- if: IDF_TARGET in ["esp32s3"]
|
- if: IDF_TARGET in ["esp32s3"]
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
# 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)
|
|
||||||
|
|
||||||
if(NOT DEFINED ENV{ESP_MATTER_PATH})
|
|
||||||
message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo")
|
|
||||||
endif(NOT DEFINED ENV{ESP_MATTER_PATH})
|
|
||||||
|
|
||||||
set(PROJECT_VER "1.0")
|
|
||||||
set(PROJECT_VER_NUMBER 1)
|
|
||||||
|
|
||||||
set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH})
|
|
||||||
set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip)
|
|
||||||
|
|
||||||
# This should be done before using the IDF_TARGET variable.
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
|
||||||
include(${ESP_MATTER_PATH}/examples/common/cmake_common/components_include.cmake)
|
|
||||||
|
|
||||||
set(EXTRA_COMPONENT_DIRS
|
|
||||||
"${ESP_MATTER_PATH}/examples/common"
|
|
||||||
"${MATTER_SDK_PATH}/config/esp32/components"
|
|
||||||
"${ESP_MATTER_PATH}/components"
|
|
||||||
${extra_components_dirs_append})
|
|
||||||
|
|
||||||
project(light-network-prov)
|
|
||||||
|
|
||||||
# WARNING: This is just an example for using key for decrypting the encrypted OTA image
|
|
||||||
# Please do not use it as is.
|
|
||||||
if(CONFIG_ENABLE_ENCRYPTED_OTA)
|
|
||||||
target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CONFIG_IDF_TARGET_ESP32C2)
|
|
||||||
include(relinker)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H;-Wno-overloaded-virtual" APPEND)
|
|
||||||
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
|
|
||||||
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
|
|
||||||
# flags that depend on -Wformat
|
|
||||||
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)
|
|
||||||
@@ -1,146 +1,3 @@
|
|||||||
# Light with RainMaker-WiFi-Provisioning
|
# Light Network Provisioning Example
|
||||||
|
|
||||||
This example creates a Color Temperature Light device using the ESP Matter data model and is integrated with ESP-RainMaker and wifi_provisioning.
|
Light Network Provisioning example is available in [esp-rainmaker](https://github.com/espressif/esp-rainmaker/tree/master/examples/matter/matter_light) repository if disabling `CONFIG_EXAMPLE_USE_RAINMAKER_FABRIC` option.
|
||||||
|
|
||||||
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about building and flashing the firmware.
|
|
||||||
|
|
||||||
## 1. Prerequisites
|
|
||||||
|
|
||||||
- ESP32-S3-DevKitM / ESP32-C3-DevKitM
|
|
||||||
- chip-tool (For Matter commissioning)
|
|
||||||
- Android RainMaker APP of version 3.5.0+ or iOS RainMaker APP of version 3.2.1+ (For RainMaker Network Provisioning)
|
|
||||||
- [ESP-IDF](https://github.com/espressif/esp-idf) on tag v5.2.2
|
|
||||||
- [RainMaker CLI](https://github.com/espressif/esp-rainmaker-cli)
|
|
||||||
|
|
||||||
## 2. Additional Environment Setup
|
|
||||||
|
|
||||||
### 2.1 Claiming device certificates
|
|
||||||
|
|
||||||
This example will use [host driven claiming](https://rainmaker.espressif.com/docs/claiming/#host-driven-claiming) via the RainMaker CLI.
|
|
||||||
|
|
||||||
Install esp-rainmaker-cli and login your RainMaker account:
|
|
||||||
|
|
||||||
```
|
|
||||||
python3 -m pip install esp-rainmaker-cli
|
|
||||||
esp-rainmaker-cli login
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure your device is connected to the host machine, login into the CLI and execute this:
|
|
||||||
```
|
|
||||||
$ esp-rainmaker-cli claim --matter <port>
|
|
||||||
```
|
|
||||||
The CLI will fetch the device certificates and flash them into the secure cert partition of your device. The certificates will be used for both the Matter device attestation verification and RainMaker MQTT connection.
|
|
||||||
|
|
||||||
### 2.2 Generating the factory nvs binary
|
|
||||||
|
|
||||||
The factory nvs (fctry partition) needs to be generated using the mfg_tool of esp-matter. It is released on pypi as [esp-matter-mfg-tool](https://pypi.org/project/esp-matter-mfg-tool) and can be installed by running `pip install esp-matter-mfg-tool`
|
|
||||||
|
|
||||||
```
|
|
||||||
$ export ESP_SECURE_CERT_PATH=/path/to/esp_secure_cert_mgr
|
|
||||||
$ esp-matter-mfg-tool -v 0x131B -p 0x2 -cd $RMAKER_PATH/examples/matter/mfg/cd_131B_0002.der --csv $RMAKER_PATH/examples/matter/mfg/keys.csv --mcsv $RMAKER_PATH/examples/matter/mfg/master.csv
|
|
||||||
```
|
|
||||||
This not only generates the factory nvs binary required for matter, but also embeds the RainMaker MQTT Host url into it via the master.csv file. Optionally, you can embed the MQTT host into the firmware itself by using idf.py menuconfig -> ESP RainMaker Config -> ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG and then skipping the --csv and --mcsv options to mfg_tool
|
|
||||||
|
|
||||||
The factory binary generated above should be flashed onto the fctry partition (default : 0x3e0000 for ESP32-S3 and ESP32-C3. Do check your partition table for exact address).
|
|
||||||
|
|
||||||
```
|
|
||||||
$ esptool.py write_flash 0x3e0000 out/131b_2/<node-id>/<node-id>-partition.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 Build the example
|
|
||||||
|
|
||||||
Once the environment and required files are set up, we can now proceed to build and flash the example
|
|
||||||
|
|
||||||
```
|
|
||||||
$ idf.py set-target <target>
|
|
||||||
$ idf.py build
|
|
||||||
$ idf.py flash monitor
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. Post Commissioning Setup
|
|
||||||
|
|
||||||
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#commissioning-and-control) for the information about Matter commissioning with chip-tool. Note that you need to specific the PAA path to the `paa_cert` under the directory of this example when you use the chip-tool to commisioning the device.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./chip-tool pairing ble-wifi <node-id> <ssid> <passcode> <setup-pincode> <discriminator> --paa-trust-store-path <PAA-path>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: The `setup-picode` and `discriminator` is generated with the factory partition binary. You can find it in the `out/131b_2/<node-id>/<node-id>-onb_codes.csv`.
|
|
||||||
|
|
||||||
## 4. Additional BLE GATT Service and BLE Advertisements
|
|
||||||
|
|
||||||
This example uses the BLEManagerImpl::ConfigureExtraServices() to configure the additional BLE GATT service for RainMaker Provisioning. The function should be called before start Matter stack.
|
|
||||||
|
|
||||||
And you can also configure other BLE advertisements with the ble_gap_ext_adv_XX() APIs after the Matter BLE advertisement is started.
|
|
||||||
|
|
||||||
## 5. RainMaker Provisioning
|
|
||||||
|
|
||||||
After you flash the example to the DevKit board, the console will print the QR code for RainMaker Provisioning. After you scan the QR code with the RainMaker Phone App, the RainMaker provisioning will be done and the device will be added to your RainMaker home.
|
|
||||||
|
|
||||||
## 6. Manufacturing Considerations
|
|
||||||
|
|
||||||
This step is only suggested for Privately deployed Production and not required for test set up.
|
|
||||||
|
|
||||||
### 6.1 RainMaker MQTT Host
|
|
||||||
|
|
||||||
Find your private deployment's mqtt hostname (if applicable) by sending a GET request at `https://<Rainmaker-API-endpoint>/mqtt_host`. You should replace the mqtt host in master.csv (As described in the section above) with this to generate the factory nvs binary.
|
|
||||||
|
|
||||||
### 6.2 Matter VID/PID
|
|
||||||
|
|
||||||
For production devices which may have a different matter vid and pid, please set the values of DEVICE_VENDOR_ID and DEVICE_PRODUCT_ID by using `idf.py menuconfig` -> `Component config` -> `CHIP Device Layer` -> `Device Identification Options`. These same should also be used in the `mfg_tool`.
|
|
||||||
|
|
||||||
**Note**: The CD used by `mfg_tool` should also be changed when VID/PID is changed. Please refer to [this](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/certification.html#certification-declaration) about how to generate a test CD file.
|
|
||||||
|
|
||||||
### 6.3 Matter DAC
|
|
||||||
|
|
||||||
For public RainMaker, some test DACs are provided via claiming. For private deployments, test DACs can be generated using `mfg_tool`.
|
|
||||||
|
|
||||||
```
|
|
||||||
export ESP_SECURE_CERT_PATH=/path/to/esp_secure_cert_mgr
|
|
||||||
esp-matter-mfg-tool -v <vendor-id> -p <product-id> --pai -k <pai-key> -c <pai-cert> -cd <cert-dclrn> --csv /path/to/keys.csv --mcsv /path/to/master.csv
|
|
||||||
```
|
|
||||||
|
|
||||||
Samples of keys.csv and master.csv can be found in $RMAKER_PATH/examples/matter/mfg/.
|
|
||||||
|
|
||||||
For testing, you can use the test VID, PID, PAI and CD as shown below.
|
|
||||||
```
|
|
||||||
$ esp-matter-mfg-tool --dac-in-secure-cert -v 0xFFF2 -p 0x8001 --pai -k $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Key.pem -c $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Cert.pem -cd $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-FFF2-8001.der --csv $RMAKER_PATH/examples/matter/mfg/keys.csv --mcsv $RMAKER_PATH/examples/matter/mfg/master.csv
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the path where the files are generated after running the above command since it will be required later.
|
|
||||||
|
|
||||||
### 6.4 Configure your app
|
|
||||||
|
|
||||||
Open the project configuration menu using
|
|
||||||
```
|
|
||||||
idf.py menuconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
In the configuration menu, set the following additional configuration to use custom factory partition and different values for Data and Device Info Providers.
|
|
||||||
|
|
||||||
1. Enable ESP32 Factory Data Provider [Component config → CHIP Device Layer → Commissioning options → Use ESP32 Factory Data Provider]
|
|
||||||
|
|
||||||
Enable config option CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER to use ESP32 specific implementation of CommissionableDataProvider and DeviceAttestationCredentialsProvider.
|
|
||||||
|
|
||||||
2. Enable ESP32 Device Instance Info Provider [Component config → CHIP Device Layer → Commissioning options → Use ESP32 Device Instance Info Provider]
|
|
||||||
|
|
||||||
Enable config option ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER to get device instance info from factory partition.
|
|
||||||
|
|
||||||
3. Enable Attestation - Secure Cert [ Component config → ESP Matter → DAC Provider options → Attestation - Secure Cert]
|
|
||||||
|
|
||||||
Enable config option CONFIG_FACTORY_PARTITION_DAC_PROVIDER to use DAC certificates from the secure_cert partition during Attestation.
|
|
||||||
|
|
||||||
4. Set chip-factory namespace partition label [Component config → CHIP Device Layer → Matter Manufacturing Options → chip-factory namespace partition label]
|
|
||||||
|
|
||||||
Set config option CHIP_FACTORY_NAMESPACE_PARTITION_LABEL to choose the label of the partition to store key-values in the "chip-factory" namespace. The default chosen partition label is nvs, change it to fctry.
|
|
||||||
|
|
||||||
|
|
||||||
Connect your esp32 device to your computer. Enter the below command to flash certificates and factory partition
|
|
||||||
|
|
||||||
```
|
|
||||||
$ esptool.py write_flash 0xd000 /out/<vendor-id>_<product-id>/<node-id>/<node-id>_esp_secure_cert.bin 0x3e0000 ./out/<vendor-id>_<product-id>/<node-id>/<node-id>-partition.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
The csv file generate at `/out/<vendor-id>_<product-id>/cn_dacs-<date>-<time>.csv` should be registered to your private RainMaker deployment (if applicable) using the steps mentioned here.
|
|
||||||
|
|
||||||
> **In production use case, the DACs will be pre-provisioned in the modules and a csv file will be provided by the Espressif factory directly. Optionally, even the fctry partitions can be pre programmed. If not, use the mfg_tool to generate these nvs binaries**
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
idf_component_register(SRC_DIRS "." "./network_prov_scheme"
|
|
||||||
PRIV_INCLUDE_DIRS "." "${ESP_MATTER_PATH}/examples/common/utils" "./network_prov_scheme")
|
|
||||||
|
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <esp_log.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <esp_matter.h>
|
|
||||||
#include <esp_rmaker_utils.h>
|
|
||||||
#include "bsp/esp-bsp.h"
|
|
||||||
|
|
||||||
#include <app_priv.h>
|
|
||||||
#include <common_macros.h>
|
|
||||||
|
|
||||||
using namespace chip::app::Clusters;
|
|
||||||
using namespace esp_matter;
|
|
||||||
|
|
||||||
static const char *TAG = "app_driver";
|
|
||||||
extern uint16_t light_endpoint_id;
|
|
||||||
|
|
||||||
/* Do any conversions/remapping for the actual value here */
|
|
||||||
esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, bool val)
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
if (val) {
|
|
||||||
err = led_indicator_start(handle, BSP_LED_ON);
|
|
||||||
} else {
|
|
||||||
err = led_indicator_start(handle, BSP_LED_OFF);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "LED set power: %d", val);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, int val)
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
return led_indicator_set_brightness(handle, val);
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "LED set brightness: %d", val);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, int val)
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
led_indicator_ihsv_t hsv;
|
|
||||||
hsv.value = led_indicator_get_hsv(handle);
|
|
||||||
hsv.h = val;
|
|
||||||
return led_indicator_set_hsv(handle, hsv.value);
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "LED set hue: %d", val);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, int val)
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
led_indicator_ihsv_t hsv;
|
|
||||||
hsv.value = led_indicator_get_hsv(handle);
|
|
||||||
hsv.s = val;
|
|
||||||
return led_indicator_set_hsv(handle, hsv.value);
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "LED set saturation: %d", val);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, int val)
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
return led_indicator_set_color_temperature(handle, val);
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "LED set temperature: %ld", val);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void app_driver_button_toggle_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Toggle button pressed");
|
|
||||||
uint16_t endpoint_id = light_endpoint_id;
|
|
||||||
uint32_t cluster_id = OnOff::Id;
|
|
||||||
uint32_t attribute_id = OnOff::Attributes::OnOff::Id;
|
|
||||||
|
|
||||||
attribute_t *attribute = attribute::get(endpoint_id, cluster_id, attribute_id);
|
|
||||||
|
|
||||||
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
val.val.b = !val.val.b;
|
|
||||||
attribute::update(endpoint_id, cluster_id, attribute_id, &val);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
|
|
||||||
uint32_t attribute_id, esp_matter_attr_val_t *val)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
if (endpoint_id == light_endpoint_id) {
|
|
||||||
led_indicator_handle_t handle = (led_indicator_handle_t)driver_handle;
|
|
||||||
if (cluster_id == OnOff::Id) {
|
|
||||||
if (attribute_id == OnOff::Attributes::OnOff::Id) {
|
|
||||||
err = app_driver_light_set_power(handle, val->val.b);
|
|
||||||
}
|
|
||||||
} else if (cluster_id == LevelControl::Id) {
|
|
||||||
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
|
|
||||||
err = app_driver_light_set_brightness(handle, val->val.u8);
|
|
||||||
}
|
|
||||||
} else if (cluster_id == ColorControl::Id) {
|
|
||||||
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
|
|
||||||
err = app_driver_light_set_hue(handle, val->val.u16);
|
|
||||||
} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {
|
|
||||||
err = app_driver_light_set_saturation(handle, val->val.u16);
|
|
||||||
} else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {
|
|
||||||
err = app_driver_light_set_temperature(handle, val->val.u16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
void *priv_data = endpoint::get_priv_data(endpoint_id);
|
|
||||||
led_indicator_handle_t handle = (led_indicator_handle_t)priv_data;
|
|
||||||
attribute_t *attribute = NULL;
|
|
||||||
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
|
|
||||||
|
|
||||||
/* Setting brightness */
|
|
||||||
attribute = attribute::get(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
err |= app_driver_light_set_brightness(handle, val.val.u8);
|
|
||||||
|
|
||||||
/* Setting color */
|
|
||||||
attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorMode::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation) {
|
|
||||||
/* Setting hue */
|
|
||||||
attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
err |= app_driver_light_set_hue(handle, val.val.u16);
|
|
||||||
/* Setting saturation */
|
|
||||||
attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
err |= app_driver_light_set_saturation(handle, val.val.u16);
|
|
||||||
} else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) {
|
|
||||||
/* Setting temperature */
|
|
||||||
attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
err |= app_driver_light_set_temperature(handle, val.val.u16);
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Color mode not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setting power */
|
|
||||||
attribute = attribute::get(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id);
|
|
||||||
attribute::get_val(attribute, &val);
|
|
||||||
err |= app_driver_light_set_power(handle, val.val.b);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_driver_handle_t app_driver_light_init()
|
|
||||||
{
|
|
||||||
#if CONFIG_BSP_LEDS_NUM > 0
|
|
||||||
/* Initialize led */
|
|
||||||
led_indicator_handle_t leds[CONFIG_BSP_LEDS_NUM];
|
|
||||||
ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, CONFIG_BSP_LEDS_NUM));
|
|
||||||
led_indicator_set_hsv(leds[0], SET_HSV(DEFAULT_HUE, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS));
|
|
||||||
|
|
||||||
return (app_driver_handle_t)leds[0];
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool perform_factory_reset = false;
|
|
||||||
|
|
||||||
static void button_factory_reset_pressed_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
if (!perform_factory_reset) {
|
|
||||||
ESP_LOGI(TAG, "Factory reset triggered. Release the button to start factory reset.");
|
|
||||||
perform_factory_reset = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void button_factory_reset_released_cb(void *arg, void *data)
|
|
||||||
{
|
|
||||||
if (perform_factory_reset) {
|
|
||||||
ESP_LOGI(TAG, "Starting factory reset");
|
|
||||||
// Do RainMaker factory reset immediately and wait for 10 seconds
|
|
||||||
// so that the device can finish Matter factory reset.
|
|
||||||
esp_rmaker_factory_reset(0, 10);
|
|
||||||
esp_matter::factory_reset();
|
|
||||||
perform_factory_reset = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app_driver_handle_t app_driver_button_init()
|
|
||||||
{
|
|
||||||
/* Initialize button */
|
|
||||||
button_handle_t btns[BSP_BUTTON_NUM];
|
|
||||||
ESP_ERROR_CHECK(bsp_iot_button_create(btns, NULL, BSP_BUTTON_NUM));
|
|
||||||
ESP_ERROR_CHECK(iot_button_register_cb(btns[0], BUTTON_PRESS_DOWN, NULL, app_driver_button_toggle_cb, NULL));
|
|
||||||
ESP_ERROR_CHECK(iot_button_register_cb(btns[0], BUTTON_LONG_PRESS_HOLD, NULL, button_factory_reset_pressed_cb, NULL));
|
|
||||||
ESP_ERROR_CHECK(iot_button_register_cb(btns[0], BUTTON_PRESS_UP, NULL, button_factory_reset_released_cb, NULL));
|
|
||||||
return (app_driver_handle_t)btns[0];
|
|
||||||
}
|
|
||||||
@@ -1,452 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_log.h>
|
|
||||||
#include <nvs_flash.h>
|
|
||||||
|
|
||||||
#include <esp_matter.h>
|
|
||||||
#include <esp_matter_attribute_utils.h>
|
|
||||||
#include <esp_matter_console.h>
|
|
||||||
#include <esp_matter_ota.h>
|
|
||||||
|
|
||||||
#include <esp_rmaker_console.h>
|
|
||||||
#include <esp_rmaker_core.h>
|
|
||||||
#include <esp_rmaker_scenes.h>
|
|
||||||
#include <esp_rmaker_schedule.h>
|
|
||||||
#include <esp_rmaker_standard_devices.h>
|
|
||||||
#include <esp_rmaker_standard_params.h>
|
|
||||||
#include <esp_rmaker_standard_types.h>
|
|
||||||
#include <esp_rmaker_user_mapping.h>
|
|
||||||
|
|
||||||
#include <app_priv.h>
|
|
||||||
#include <app_reset.h>
|
|
||||||
#include <app_network.h>
|
|
||||||
#include <common_macros.h>
|
|
||||||
#include "app-common/zap-generated/ids/Attributes.h"
|
|
||||||
#include "app-common/zap-generated/ids/Clusters.h"
|
|
||||||
#include "network_provisioning/manager.h"
|
|
||||||
#include "platform/CHIPDeviceEvent.h"
|
|
||||||
#include "platform/PlatformManager.h"
|
|
||||||
#include "support/CodeUtils.h"
|
|
||||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
|
||||||
#include <platform/ThreadStackManager.h>
|
|
||||||
#include <platform/ESP32/OpenthreadLauncher.h>
|
|
||||||
#endif
|
|
||||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
|
||||||
#include <platform/ESP32/ESP32Utils.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <app/server/CommissioningWindowManager.h>
|
|
||||||
#include <app/server/Server.h>
|
|
||||||
#include <network_prov_scheme/protocomm_matter_ble.h>
|
|
||||||
|
|
||||||
static const char *TAG = "app_main";
|
|
||||||
uint16_t light_endpoint_id = 0;
|
|
||||||
|
|
||||||
using namespace esp_matter;
|
|
||||||
using namespace esp_matter::attribute;
|
|
||||||
using namespace esp_matter::endpoint;
|
|
||||||
using namespace chip::app::Clusters;
|
|
||||||
|
|
||||||
constexpr auto k_timeout_seconds = 300;
|
|
||||||
|
|
||||||
#if CONFIG_ENABLE_ENCRYPTED_OTA
|
|
||||||
extern const char decryption_key_start[] asm("_binary_esp_image_encryption_key_pem_start");
|
|
||||||
extern const char decryption_key_end[] asm("_binary_esp_image_encryption_key_pem_end");
|
|
||||||
|
|
||||||
static const char *s_decryption_key = decryption_key_start;
|
|
||||||
static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key_start;
|
|
||||||
#endif // CONFIG_ENABLE_ENCRYPTED_OTA
|
|
||||||
|
|
||||||
static esp_rmaker_device_t *light_device;
|
|
||||||
static bool rmaker_init_done = false;
|
|
||||||
|
|
||||||
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
|
||||||
{
|
|
||||||
if (!event) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (event->Type) {
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:
|
|
||||||
ESP_LOGI(TAG, "Interface IP Address changed");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete:
|
|
||||||
ESP_LOGI(TAG, "Commissioning complete");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired:
|
|
||||||
ESP_LOGI(TAG, "Commissioning failed, fail safe timer expired");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted:
|
|
||||||
ESP_LOGI(TAG, "Commissioning session started");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped:
|
|
||||||
ESP_LOGI(TAG, "Commissioning session stopped");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened:
|
|
||||||
ESP_LOGI(TAG, "Commissioning window opened");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed:
|
|
||||||
ESP_LOGI(TAG, "Commissioning window closed");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kFabricRemoved: {
|
|
||||||
ESP_LOGI(TAG, "Fabric removed successfully");
|
|
||||||
if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) {
|
|
||||||
chip::CommissioningWindowManager &commissionMgr =
|
|
||||||
chip::Server::GetInstance().GetCommissioningWindowManager();
|
|
||||||
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds);
|
|
||||||
if (!commissionMgr.IsCommissioningWindowOpen()) {
|
|
||||||
/* After removing last fabric, this example does not remove the Wi-Fi credentials
|
|
||||||
* and still has IP connectivity so, only advertising on DNS-SD.
|
|
||||||
*/
|
|
||||||
CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(
|
|
||||||
kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly);
|
|
||||||
if (err != CHIP_NO_ERROR) {
|
|
||||||
ESP_LOGE(TAG, "Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kThreadConnectivityChange: {
|
|
||||||
// When Thread is attached with network provisioning, try to start DNS-SD server to advertise Matter
|
|
||||||
// commissionable service
|
|
||||||
if (event->ThreadConnectivityChange.Result == chip::DeviceLayer::kConnectivity_Established) {
|
|
||||||
chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t){ chip::app::DnssdServer::Instance().StartServer(); },
|
|
||||||
reinterpret_cast<intptr_t>(nullptr));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved:
|
|
||||||
ESP_LOGI(TAG, "Fabric will be removed");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kFabricUpdated:
|
|
||||||
ESP_LOGI(TAG, "Fabric is updated");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kFabricCommitted:
|
|
||||||
ESP_LOGI(TAG, "Fabric is committed");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized:
|
|
||||||
ESP_LOGI(TAG, "BLE deinitialized and memory reclaimed");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case chip::DeviceLayer::DeviceEventType::kCHIPoBLEAdvertisingChange:
|
|
||||||
if (event->CHIPoBLEAdvertisingChange.Result == chip::DeviceLayer::kActivity_Started) {
|
|
||||||
start_secondary_ble_adv();
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t app_matter_report_power(bool val)
|
|
||||||
{
|
|
||||||
esp_matter_attr_val_t value = esp_matter_bool(val);
|
|
||||||
return attribute::report(light_endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t app_matter_report_hue(int val)
|
|
||||||
{
|
|
||||||
esp_matter_attr_val_t value = esp_matter_uint8(REMAP_TO_RANGE(val, STANDARD_HUE, MATTER_HUE));
|
|
||||||
return attribute::report(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t app_matter_report_saturation(int val)
|
|
||||||
{
|
|
||||||
esp_matter_attr_val_t value = esp_matter_uint8(REMAP_TO_RANGE(val, STANDARD_SATURATION, MATTER_SATURATION));
|
|
||||||
return attribute::report(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t app_matter_report_brightness(int val)
|
|
||||||
{
|
|
||||||
esp_matter_attr_val_t value = esp_matter_nullable_uint8(REMAP_TO_RANGE(val, STANDARD_BRIGHTNESS, MATTER_BRIGHTNESS));
|
|
||||||
return attribute::report(light_endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *app_matter_get_rmaker_param_name_from_id(uint32_t cluster_id, uint32_t attribute_id)
|
|
||||||
{
|
|
||||||
if (cluster_id == OnOff::Id) {
|
|
||||||
if (attribute_id == OnOff::Attributes::OnOff::Id) {
|
|
||||||
return ESP_RMAKER_DEF_POWER_NAME;
|
|
||||||
}
|
|
||||||
} else if (cluster_id == LevelControl::Id) {
|
|
||||||
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
|
|
||||||
return ESP_RMAKER_DEF_BRIGHTNESS_NAME;
|
|
||||||
}
|
|
||||||
} else if (cluster_id == ColorControl::Id) {
|
|
||||||
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
|
|
||||||
return ESP_RMAKER_DEF_HUE_NAME;
|
|
||||||
} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {
|
|
||||||
return ESP_RMAKER_DEF_SATURATION_NAME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_rmaker_param_val_t app_matter_get_rmaker_val(esp_matter_attr_val_t *val, uint32_t cluster_id,
|
|
||||||
uint32_t attribute_id)
|
|
||||||
{
|
|
||||||
/* Attributes which need to be remapped */
|
|
||||||
if (cluster_id == LevelControl::Id) {
|
|
||||||
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
|
|
||||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS);
|
|
||||||
return esp_rmaker_int(value);
|
|
||||||
}
|
|
||||||
} else if (cluster_id == ColorControl::Id) {
|
|
||||||
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
|
|
||||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE);
|
|
||||||
return esp_rmaker_int(value);
|
|
||||||
} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {
|
|
||||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION);
|
|
||||||
return esp_rmaker_int(value);
|
|
||||||
}
|
|
||||||
} else if (cluster_id == OnOff::Id) {
|
|
||||||
if (attribute_id == OnOff::Attributes::OnOff::Id) {
|
|
||||||
return esp_rmaker_bool(val->val.b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return esp_rmaker_int(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[],
|
|
||||||
uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
if (ctx) {
|
|
||||||
ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src));
|
|
||||||
}
|
|
||||||
app_driver_handle_t light_handle = (app_driver_handle_t)priv_data;
|
|
||||||
ESP_LOGI(TAG, "Light received %d params in write", count);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
const esp_rmaker_param_t *param = write_req[i].param;
|
|
||||||
esp_rmaker_param_val_t val = write_req[i].val;
|
|
||||||
const char *device_name = esp_rmaker_device_get_name(device);
|
|
||||||
const char *param_name = esp_rmaker_param_get_name(param);
|
|
||||||
if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) {
|
|
||||||
ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b ? "true" : "false", device_name, param_name);
|
|
||||||
app_driver_light_set_power(light_handle, val.val.b);
|
|
||||||
app_matter_report_power(val.val.b);
|
|
||||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) {
|
|
||||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
|
||||||
app_driver_light_set_brightness(light_handle, val.val.i);
|
|
||||||
app_matter_report_brightness(val.val.i);
|
|
||||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) {
|
|
||||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
|
||||||
app_driver_light_set_hue(light_handle, val.val.i);
|
|
||||||
app_matter_report_hue(val.val.i);
|
|
||||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) {
|
|
||||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
|
||||||
app_driver_light_set_saturation(light_handle, val.val.i);
|
|
||||||
app_matter_report_saturation(val.val.i);
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "Updating for %s", param_name);
|
|
||||||
}
|
|
||||||
esp_rmaker_param_update(param, val);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This callback is invoked when clients interact with the Identify Cluster.
|
|
||||||
// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light).
|
|
||||||
static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,
|
|
||||||
uint8_t effect_variant, void *priv_data)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This callback is called for every attribute update. The callback implementation shall
|
|
||||||
// handle the desired attributes and return an appropriate error code. If the attribute
|
|
||||||
// is not of your interest, please do not return an error code and strictly return ESP_OK.
|
|
||||||
static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
|
|
||||||
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
|
|
||||||
if (type == PRE_UPDATE) {
|
|
||||||
/* Driver update */
|
|
||||||
app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data;
|
|
||||||
err = app_driver_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val);
|
|
||||||
} else if (type == POST_UPDATE) {
|
|
||||||
if (!rmaker_init_done) {
|
|
||||||
ESP_LOGI(TAG, "RainMaker init not done. Not processing attribute update");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RainMaker update */
|
|
||||||
const char *device_name = "Light";
|
|
||||||
const char *param_name = app_matter_get_rmaker_param_name_from_id(cluster_id, attribute_id);
|
|
||||||
if (!param_name) {
|
|
||||||
ESP_LOGD(TAG, "param name not handled");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_rmaker_node_t *node = esp_rmaker_get_node();
|
|
||||||
esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(node, device_name);
|
|
||||||
esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, param_name);
|
|
||||||
if (!param) {
|
|
||||||
ESP_LOGE(TAG, "Param %s not found", param_name);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_rmaker_param_val_t rmaker_val = app_matter_get_rmaker_val(val, cluster_id, attribute_id);
|
|
||||||
return esp_rmaker_param_update_and_report(param, rmaker_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void app_main()
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
|
|
||||||
/* Initialize the ESP NVS layer */
|
|
||||||
nvs_flash_init();
|
|
||||||
|
|
||||||
/* Initialize driver */
|
|
||||||
app_driver_handle_t light_handle = app_driver_light_init();
|
|
||||||
app_driver_button_init();
|
|
||||||
|
|
||||||
/* Create a Matter node and add the mandatory Root Node device type on endpoint 0 */
|
|
||||||
node::config_t node_config;
|
|
||||||
|
|
||||||
// node handle can be used to add/modify other endpoints.
|
|
||||||
node_t *node = node::create(&node_config, app_attribute_update_cb, app_identification_cb);
|
|
||||||
ABORT_APP_ON_FAILURE(node != nullptr, ESP_LOGE(TAG, "Failed to create Matter node"));
|
|
||||||
|
|
||||||
extended_color_light::config_t light_config;
|
|
||||||
light_config.on_off.on_off = DEFAULT_POWER;
|
|
||||||
light_config.on_off_lighting.start_up_on_off = nullptr;
|
|
||||||
light_config.level_control.current_level = DEFAULT_BRIGHTNESS;
|
|
||||||
light_config.level_control.on_level = DEFAULT_BRIGHTNESS;
|
|
||||||
light_config.level_control_lighting.start_up_current_level = DEFAULT_BRIGHTNESS;
|
|
||||||
light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
|
|
||||||
light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
|
|
||||||
light_config.color_control_color_temperature.start_up_color_temperature_mireds = nullptr;
|
|
||||||
|
|
||||||
// endpoint handles can be used to add/modify clusters.
|
|
||||||
endpoint_t *endpoint = extended_color_light::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);
|
|
||||||
ABORT_APP_ON_FAILURE(endpoint != nullptr, ESP_LOGE(TAG, "Failed to create extended color light endpoint"));
|
|
||||||
|
|
||||||
light_endpoint_id = endpoint::get_id(endpoint);
|
|
||||||
ESP_LOGI(TAG, "Light created with endpoint_id %d", light_endpoint_id);
|
|
||||||
|
|
||||||
/* Mark deferred persistence for some attributes that might be changed rapidly */
|
|
||||||
attribute_t *current_level_attribute =
|
|
||||||
attribute::get(light_endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id);
|
|
||||||
attribute::set_deferred_persistence(current_level_attribute);
|
|
||||||
|
|
||||||
attribute_t *current_x_attribute = attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentX::Id);
|
|
||||||
attribute::set_deferred_persistence(current_x_attribute);
|
|
||||||
attribute_t *current_y_attribute = attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentY::Id);
|
|
||||||
attribute::set_deferred_persistence(current_y_attribute);
|
|
||||||
attribute_t *color_temp_attribute =
|
|
||||||
attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
|
||||||
attribute::set_deferred_persistence(color_temp_attribute);
|
|
||||||
|
|
||||||
err = esp_event_loop_create_default();
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Error create default event loop");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
app_network_init();
|
|
||||||
esp_rmaker_config_t rainmaker_cfg = {
|
|
||||||
.enable_time_sync = false,
|
|
||||||
};
|
|
||||||
esp_rmaker_node_t *rmaker_node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Device", "Lightbulb");
|
|
||||||
if (!rmaker_node) {
|
|
||||||
ESP_LOGE(TAG, "Could not initialise node. Aborting!!!");
|
|
||||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
light_device = esp_rmaker_lightbulb_device_create("Light", light_handle, DEFAULT_POWER);
|
|
||||||
esp_rmaker_device_add_bulk_cb(light_device, bulk_write_cb, NULL);
|
|
||||||
|
|
||||||
esp_rmaker_device_add_param(light_device,
|
|
||||||
esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, DEFAULT_BRIGHTNESS));
|
|
||||||
esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, DEFAULT_HUE));
|
|
||||||
esp_rmaker_device_add_param(light_device,
|
|
||||||
esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, DEFAULT_SATURATION));
|
|
||||||
|
|
||||||
esp_rmaker_node_add_device(rmaker_node, light_device);
|
|
||||||
|
|
||||||
esp_rmaker_ota_enable_default();
|
|
||||||
|
|
||||||
esp_rmaker_timezone_service_enable();
|
|
||||||
|
|
||||||
esp_rmaker_schedule_enable();
|
|
||||||
|
|
||||||
err = app_network_set_custom_mfg_data(MGF_DATA_DEVICE_TYPE_LIGHT, MFG_DATA_DEVICE_SUBTYPE_LIGHT);
|
|
||||||
|
|
||||||
err = app_network_start(POP_TYPE_MAC);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Could not start Wifi. Aborting!!!");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Matter start */
|
|
||||||
err = esp_matter::start(app_event_cb);
|
|
||||||
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to start Matter, err:%d", err));
|
|
||||||
|
|
||||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
|
||||||
esp_openthread_platform_config_t ot_config = {
|
|
||||||
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
|
|
||||||
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
|
|
||||||
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
|
|
||||||
};
|
|
||||||
set_openthread_platform_config(&ot_config);
|
|
||||||
// This will not really initialize Thread stack as the thread stack has been initialized in app_network.
|
|
||||||
// We call this function to pass the OpenThread instance to GenericThreadStackManagerImpl_OpenThread
|
|
||||||
// so that it can be used for SRP service registration and network commissioning driver.
|
|
||||||
chip::DeviceLayer::ThreadStackMgr().InitThreadStack();
|
|
||||||
// Then try to start DNS-SD advertisement if Thread is provisioned.
|
|
||||||
if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned()) {
|
|
||||||
chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t){ chip::app::DnssdServer::Instance().StartServer(); },
|
|
||||||
reinterpret_cast<intptr_t>(nullptr));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Starting driver with default values */
|
|
||||||
app_driver_light_set_defaults(light_endpoint_id);
|
|
||||||
|
|
||||||
#if CONFIG_ENABLE_ENCRYPTED_OTA
|
|
||||||
err = esp_matter_ota_requestor_encrypted_init(s_decryption_key, s_decryption_key_len);
|
|
||||||
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to initialized the encrypted OTA, err: %d", err));
|
|
||||||
#endif // CONFIG_ENABLE_ENCRYPTED_OTA
|
|
||||||
bool is_network_provisioned = false;
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
network_prov_mgr_is_wifi_provisioned(&is_network_provisioned);
|
|
||||||
#else
|
|
||||||
network_prov_mgr_is_thread_provisioned(&is_network_provisioned);
|
|
||||||
#endif
|
|
||||||
if (is_network_provisioned && esp_rmaker_user_node_mapping_get_state() == ESP_RMAKER_USER_MAPPING_DONE) {
|
|
||||||
chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t) { chip::DeviceLayer::Internal::BLEMgr().Shutdown(); });
|
|
||||||
}
|
|
||||||
rmaker_init_done = true;
|
|
||||||
|
|
||||||
#if CONFIG_ENABLE_CHIP_SHELL
|
|
||||||
esp_matter::console::diagnostics_register_commands();
|
|
||||||
esp_matter::console::wifi_register_commands();
|
|
||||||
esp_matter::console::factoryreset_register_commands();
|
|
||||||
esp_matter::console::init();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -1,590 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
#include <esp_event.h>
|
|
||||||
#include <esp_idf_version.h>
|
|
||||||
#include <esp_log.h>
|
|
||||||
#include <esp_rmaker_utils.h>
|
|
||||||
#include <esp_wifi.h>
|
|
||||||
#include <esp_mac.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
#include <freertos/event_groups.h>
|
|
||||||
#include <freertos/task.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <esp_netif.h>
|
|
||||||
#include <network_prov_scheme_matter_ble.h>
|
|
||||||
#include <network_provisioning/manager.h>
|
|
||||||
|
|
||||||
#include <app_network.h>
|
|
||||||
#include <esp_rmaker_core.h>
|
|
||||||
#include <esp_timer.h>
|
|
||||||
#include <nvs.h>
|
|
||||||
#include <nvs_flash.h>
|
|
||||||
#include <platform/CHIPDeviceLayer.h>
|
|
||||||
#include <platform/PlatformManager.h>
|
|
||||||
#include <qrcode.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
#include <esp_vfs_eventfd.h>
|
|
||||||
#include <esp_openthread.h>
|
|
||||||
#include <esp_openthread_cli.h>
|
|
||||||
#include <esp_openthread_lock.h>
|
|
||||||
#include <esp_openthread_netif_glue.h>
|
|
||||||
#include <esp_openthread_types.h>
|
|
||||||
|
|
||||||
#include <openthread/cli.h>
|
|
||||||
#include <openthread/instance.h>
|
|
||||||
#include <openthread/logging.h>
|
|
||||||
#include <openthread/tasklet.h>
|
|
||||||
#include <openthread/thread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(APP_NETWORK_EVENT);
|
|
||||||
|
|
||||||
static const char *TAG = "app_network";
|
|
||||||
|
|
||||||
#define PROV_QR_VERSION "v1"
|
|
||||||
|
|
||||||
#define PROV_TRANSPORT_BLE "ble"
|
|
||||||
#define QRCODE_BASE_URL "https://rainmaker.espressif.com/qrcode.html"
|
|
||||||
|
|
||||||
#define CREDENTIALS_NAMESPACE "rmaker_creds"
|
|
||||||
#define RANDOM_NVS_KEY "random"
|
|
||||||
|
|
||||||
#define POP_STR_SIZE 9
|
|
||||||
static esp_timer_handle_t prov_stop_timer;
|
|
||||||
/* Timeout period in minutes */
|
|
||||||
#define APP_NETWORK_PROV_TIMEOUT_PERIOD 30
|
|
||||||
/* Autofetch period in micro-seconds */
|
|
||||||
static uint64_t prov_timeout_period = (APP_NETWORK_PROV_TIMEOUT_PERIOD * 60 * 1000000LL);
|
|
||||||
|
|
||||||
#define APP_PROV_STOP_ON_CREDS_MISMATCH
|
|
||||||
|
|
||||||
#define ESP_RAINMAKER_GITHUB_EXAMPLES_PATH "https://github.com/espressif/esp-rainmaker/blob/master/examples"
|
|
||||||
#define ESP_RAINMAKER_INTRO_LINK "https://rainmaker.espressif.com"
|
|
||||||
#define ESP_RMAKER_PHONE_APP_LINK "http://bit.ly/esp-rmaker"
|
|
||||||
char esp_rainmaker_ascii_art[] =
|
|
||||||
" ______ _____ _____ _____ _____ _ _ __ __ _ ________ _____\n"
|
|
||||||
" | ____|/ ____| __ \\ | __ \\ /\\ |_ _| \\ | | \\/ | /\\ | |/ / ____| __ \\\n"
|
|
||||||
" | |__ | (___ | |__) | | |__) | / \\ | | | \\| | \\ / | / \\ | ' /| |__ | |__) |\n"
|
|
||||||
" | __| \\___ \\| ___/ | _ / / /\\ \\ | | | . ` | |\\/| | / /\\ \\ | < | __| | _ /\n"
|
|
||||||
" | |____ ____) | | | | \\ \\ / ____ \\ _| |_| |\\ | | | |/ ____ \\| . \\| |____| | \\ \\\n"
|
|
||||||
" |______|_____/|_| |_| \\_\\/_/ \\_\\_____|_| \\_|_| |_/_/ \\_\\_|\\_\\______|_| \\_\\\n";
|
|
||||||
|
|
||||||
static uint8_t *custom_mfg_data = NULL;
|
|
||||||
static size_t custom_mfg_data_len = 0;
|
|
||||||
|
|
||||||
esp_err_t app_network_set_custom_mfg_data(uint16_t device_type, uint8_t device_subtype)
|
|
||||||
{
|
|
||||||
int8_t mfg_data[] = {(int8_t)MFG_DATA_HEADER, MGF_DATA_APP_ID, MFG_DATA_VERSION, MFG_DATA_CUSTOMER_ID};
|
|
||||||
size_t mfg_data_len = sizeof(mfg_data) + 4; // 4 bytes of device type, subtype, and extra-code
|
|
||||||
custom_mfg_data = (uint8_t *)MEM_ALLOC_EXTRAM(mfg_data_len);
|
|
||||||
if (custom_mfg_data == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory to custom mfg data");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
memcpy(custom_mfg_data, mfg_data, sizeof(mfg_data));
|
|
||||||
custom_mfg_data[8] = 0xff & (device_type >> 8);
|
|
||||||
custom_mfg_data[9] = 0xff & device_type;
|
|
||||||
custom_mfg_data[10] = device_subtype;
|
|
||||||
custom_mfg_data[11] = 0;
|
|
||||||
custom_mfg_data_len = mfg_data_len;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t qrcode_display(const char *text)
|
|
||||||
{
|
|
||||||
#define MAX_QRCODE_VERSION 5
|
|
||||||
esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
|
|
||||||
cfg.max_qrcode_version = MAX_QRCODE_VERSION;
|
|
||||||
return esp_qrcode_generate(&cfg, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void app_network_print_qr(const char *name, const char *pop, const char *transport)
|
|
||||||
{
|
|
||||||
if (!name || !transport) {
|
|
||||||
ESP_LOGW(TAG, "Cannot generate QR code payload. Data missing.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char payload[150];
|
|
||||||
if (pop) {
|
|
||||||
snprintf(payload, sizeof(payload),
|
|
||||||
"{\"ver\":\"%s\",\"name\":\"%s\""
|
|
||||||
",\"pop\":\"%s\",\"transport\":\"%s\"}",
|
|
||||||
PROV_QR_VERSION, name, pop, transport);
|
|
||||||
} else {
|
|
||||||
snprintf(payload, sizeof(payload),
|
|
||||||
"{\"ver\":\"%s\",\"name\":\"%s\""
|
|
||||||
",\"transport\":\"%s\"}",
|
|
||||||
PROV_QR_VERSION, name, transport);
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "Scan this QR code from the ESP RainMaker phone app for Provisioning.");
|
|
||||||
qrcode_display(payload);
|
|
||||||
ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL,
|
|
||||||
payload);
|
|
||||||
esp_event_post(APP_NETWORK_EVENT, APP_NETWORK_EVENT_QR_DISPLAY, payload, strlen(payload) + 1, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Event handler for catching system events */
|
|
||||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
static int retries = 0;
|
|
||||||
static int failed_cnt = 0;
|
|
||||||
|
|
||||||
if (event_base == NETWORK_PROV_EVENT) {
|
|
||||||
switch (event_id) {
|
|
||||||
case NETWORK_PROV_START:
|
|
||||||
ESP_LOGI(TAG, "Provisioning started");
|
|
||||||
break;
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
case NETWORK_PROV_WIFI_CRED_RECV: {
|
|
||||||
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
|
|
||||||
ESP_LOGI(TAG,
|
|
||||||
"Received Wi-Fi credentials"
|
|
||||||
"\n\tSSID : %s\n\tPassword : %s",
|
|
||||||
(const char *)wifi_sta_cfg->ssid, (const char *)wifi_sta_cfg->password);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NETWORK_PROV_WIFI_CRED_FAIL: {
|
|
||||||
network_prov_wifi_sta_fail_reason_t *reason = (network_prov_wifi_sta_fail_reason_t *)event_data;
|
|
||||||
ESP_LOGE(TAG,
|
|
||||||
"Provisioning failed!\n\tReason : %s"
|
|
||||||
"\n\tPlease reset to factory and retry provisioning",
|
|
||||||
(*reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) ? "Wi-Fi station authentication failed"
|
|
||||||
: "Wi-Fi access-point not found");
|
|
||||||
retries++;
|
|
||||||
if (retries >= 5) {
|
|
||||||
ESP_LOGI(TAG, "Failed to connect with provisioned AP, reseting provisioned credentials");
|
|
||||||
network_prov_mgr_reset_wifi_sm_state_on_failure();
|
|
||||||
esp_event_post(APP_NETWORK_EVENT, APP_NETWORK_EVENT_PROV_RESTART, NULL, 0, portMAX_DELAY);
|
|
||||||
ESP_LOGW(TAG, "Failed to connect with provisioned AP, please reset to provisioning manually");
|
|
||||||
retries = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NETWORK_PROV_WIFI_CRED_SUCCESS:
|
|
||||||
ESP_LOGI(TAG, "Provisioning successful");
|
|
||||||
retries = 0;
|
|
||||||
break;
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
case NETWORK_PROV_THREAD_DATASET_RECV: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NETWORK_PROV_THREAD_DATASET_FAIL: {
|
|
||||||
retries++;
|
|
||||||
if (retries >= 5) {
|
|
||||||
ESP_LOGI(TAG, "Failed to connect with provisioned network, reseting provisioned dataset");
|
|
||||||
network_prov_mgr_reset_thread_sm_state_on_failure();
|
|
||||||
esp_event_post(APP_NETWORK_EVENT, APP_NETWORK_EVENT_PROV_RESTART, NULL, 0, portMAX_DELAY);
|
|
||||||
retries = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NETWORK_PROV_THREAD_DATASET_SUCCESS:
|
|
||||||
ESP_LOGI(TAG, "Provisioning successful");
|
|
||||||
retries = 0;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case NETWORK_PROV_END:
|
|
||||||
if (prov_stop_timer) {
|
|
||||||
esp_timer_stop(prov_stop_timer);
|
|
||||||
esp_timer_delete(prov_stop_timer);
|
|
||||||
prov_stop_timer = NULL;
|
|
||||||
}
|
|
||||||
/* De-initialize manager once provisioning is finished */
|
|
||||||
network_prov_mgr_deinit();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (event_base == PROTOCOMM_SECURITY_SESSION_EVENT) {
|
|
||||||
switch (event_id) {
|
|
||||||
case PROTOCOMM_SECURITY_SESSION_SETUP_OK:
|
|
||||||
ESP_LOGI(TAG, "Secured session established!");
|
|
||||||
esp_rmaker_start();
|
|
||||||
break;
|
|
||||||
case PROTOCOMM_SECURITY_SESSION_INVALID_SECURITY_PARAMS:
|
|
||||||
/* fall-through */
|
|
||||||
case PROTOCOMM_SECURITY_SESSION_CREDENTIALS_MISMATCH:
|
|
||||||
ESP_LOGE(TAG, "Received incorrect PoP or invalid security params! event: %d", (int)event_id);
|
|
||||||
if (++failed_cnt >= 5) {
|
|
||||||
/* stop provisioning for security reasons */
|
|
||||||
network_prov_mgr_stop_provisioning();
|
|
||||||
ESP_LOGW(TAG,
|
|
||||||
"Max PoP attempts reached! Provisioning disabled for security reasons. Please reboot device "
|
|
||||||
"to restart provisioning");
|
|
||||||
esp_event_post(APP_NETWORK_EVENT, APP_NETWORK_EVENT_PROV_CRED_MISMATCH, NULL, 0, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
|
||||||
ESP_LOGI(TAG, "Disconnected. Connecting to the AP again...");
|
|
||||||
esp_wifi_connect();
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
static esp_netif_t* init_openthread_netif(const esp_openthread_platform_config_t* config)
|
|
||||||
{
|
|
||||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
|
|
||||||
esp_netif_t* netif = esp_netif_new(&cfg);
|
|
||||||
assert(netif != NULL);
|
|
||||||
ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config)));
|
|
||||||
|
|
||||||
return netif;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ot_task_worker(void* aContext)
|
|
||||||
{
|
|
||||||
esp_openthread_platform_config_t config = {
|
|
||||||
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
|
|
||||||
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
|
|
||||||
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
|
|
||||||
};
|
|
||||||
/* Initialize the OpenThread stack */
|
|
||||||
ESP_ERROR_CHECK(esp_openthread_init(&config));
|
|
||||||
#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
|
|
||||||
/* The OpenThread log level directly matches ESP log level */
|
|
||||||
(void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
|
|
||||||
#endif
|
|
||||||
esp_netif_t *openthread_netif = init_openthread_netif(&config);
|
|
||||||
/* Initialize the esp_netif bindings */
|
|
||||||
esp_netif_set_default_netif(openthread_netif);
|
|
||||||
|
|
||||||
/* Run the main loop */
|
|
||||||
esp_openthread_launch_mainloop();
|
|
||||||
/* Clean up */
|
|
||||||
esp_netif_destroy(openthread_netif);
|
|
||||||
esp_openthread_netif_glue_deinit();
|
|
||||||
|
|
||||||
esp_vfs_eventfd_unregister();
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
|
|
||||||
/* Free random_bytes after use only if function returns ESP_OK */
|
|
||||||
static esp_err_t read_random_bytes_from_nvs(uint8_t **random_bytes, size_t *len)
|
|
||||||
{
|
|
||||||
nvs_handle handle;
|
|
||||||
esp_err_t err;
|
|
||||||
*len = 0;
|
|
||||||
|
|
||||||
if ((err = nvs_open_from_partition(CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME, CREDENTIALS_NAMESPACE, NVS_READONLY,
|
|
||||||
&handle)) != ESP_OK) {
|
|
||||||
ESP_LOGD(TAG, "NVS open for %s %s %s failed with error %d", CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME,
|
|
||||||
CREDENTIALS_NAMESPACE, RANDOM_NVS_KEY, err);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = nvs_get_blob(handle, RANDOM_NVS_KEY, NULL, len)) != ESP_OK) {
|
|
||||||
ESP_LOGD(TAG, "Error %d. Failed to read key %s.", err, RANDOM_NVS_KEY);
|
|
||||||
nvs_close(handle);
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*random_bytes = (uint8_t *)calloc(*len, 1);
|
|
||||||
if (*random_bytes) {
|
|
||||||
nvs_get_blob(handle, RANDOM_NVS_KEY, *random_bytes, len);
|
|
||||||
nvs_close(handle);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
nvs_close(handle);
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *custom_pop;
|
|
||||||
esp_err_t app_network_set_custom_pop(const char *pop)
|
|
||||||
{
|
|
||||||
/* NULL PoP is not allowed here. Use POP_TYPE_NONE instead. */
|
|
||||||
if (!pop) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Freeing up the PoP in case it is already allocated */
|
|
||||||
if (custom_pop) {
|
|
||||||
free(custom_pop);
|
|
||||||
custom_pop = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
custom_pop = strdup(pop);
|
|
||||||
if (!custom_pop) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t get_device_service_name(char *service_name, size_t max)
|
|
||||||
{
|
|
||||||
uint8_t *nvs_random = NULL;
|
|
||||||
const char *ssid_prefix = "PROV";
|
|
||||||
size_t nvs_random_size = 0;
|
|
||||||
if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 3) {
|
|
||||||
uint8_t mac_addr[6];
|
|
||||||
esp_read_mac(mac_addr, ESP_MAC_BASE);
|
|
||||||
snprintf(service_name, max, "%s_%02x%02x%02x", ssid_prefix, mac_addr[3], mac_addr[4], mac_addr[5]);
|
|
||||||
} else {
|
|
||||||
snprintf(service_name, max, "%s_%02x%02x%02x", ssid_prefix, nvs_random[nvs_random_size - 3],
|
|
||||||
nvs_random[nvs_random_size - 2], nvs_random[nvs_random_size - 1]);
|
|
||||||
}
|
|
||||||
if (nvs_random) {
|
|
||||||
free(nvs_random);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *get_device_pop(app_network_pop_type_t pop_type)
|
|
||||||
{
|
|
||||||
if (pop_type == POP_TYPE_NONE) {
|
|
||||||
return NULL;
|
|
||||||
} else if (pop_type == POP_TYPE_CUSTOM) {
|
|
||||||
if (!custom_pop) {
|
|
||||||
ESP_LOGE(TAG, "Custom PoP not set. Please use app_wifi_set_custom_pop().");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return strdup(custom_pop);
|
|
||||||
}
|
|
||||||
char *pop = (char *)calloc(1, POP_STR_SIZE);
|
|
||||||
if (!pop) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for PoP.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pop_type == POP_TYPE_MAC) {
|
|
||||||
uint8_t mac_addr[6];
|
|
||||||
esp_err_t err = esp_read_mac(mac_addr, ESP_MAC_BASE);
|
|
||||||
if (err == ESP_OK) {
|
|
||||||
snprintf(pop, POP_STR_SIZE, "%02x%02x%02x%02x", mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
|
||||||
return pop;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Failed to get MAC address to generate PoP.");
|
|
||||||
goto pop_err;
|
|
||||||
}
|
|
||||||
} else if (pop_type == POP_TYPE_RANDOM) {
|
|
||||||
uint8_t *nvs_random = NULL;
|
|
||||||
size_t nvs_random_size = 0;
|
|
||||||
if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 4) {
|
|
||||||
ESP_LOGE(TAG, "Failed to read random bytes from NVS to generate PoP.");
|
|
||||||
if (nvs_random) {
|
|
||||||
free(nvs_random);
|
|
||||||
}
|
|
||||||
goto pop_err;
|
|
||||||
} else {
|
|
||||||
snprintf(pop, POP_STR_SIZE, "%02x%02x%02x%02x", nvs_random[0], nvs_random[1], nvs_random[2], nvs_random[3]);
|
|
||||||
free(nvs_random);
|
|
||||||
return pop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pop_err:
|
|
||||||
free(pop);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_network_init(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
wifi_init_config_t cfg;
|
|
||||||
esp_err_t err = esp_netif_init();
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to initialize esp_netif");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lets not create a default station interface if already present
|
|
||||||
if (!esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")) {
|
|
||||||
if (!esp_netif_create_default_wifi_sta()) {
|
|
||||||
ESP_LOGE(TAG, "Failed to create the WiFi STA netif");
|
|
||||||
return;
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the ESP WiFi layer.
|
|
||||||
cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
err = esp_wifi_init(&cfg);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to initialize esp_wifi");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
/* Initialize TCP/IP */
|
|
||||||
esp_netif_init();
|
|
||||||
esp_vfs_eventfd_config_t eventfd_config = {
|
|
||||||
.max_fds = 3,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
|
|
||||||
xTaskCreate(ot_task_worker, "ot_task", 6144, xTaskGetCurrentTaskHandle(), 5, NULL);
|
|
||||||
#endif
|
|
||||||
/* Register our event handler for Wi-Fi, IP and Provisioning related events */
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
|
||||||
#ifdef APP_PROV_STOP_ON_CREDS_MISMATCH
|
|
||||||
ESP_ERROR_CHECK(
|
|
||||||
esp_event_handler_register(PROTOCOMM_SECURITY_SESSION_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
}
|
|
||||||
|
|
||||||
static void app_network_prov_stop(void *priv)
|
|
||||||
{
|
|
||||||
ESP_LOGW(TAG, "Provisioning timed out. Please reboot device to restart provisioning.");
|
|
||||||
network_prov_mgr_stop_provisioning();
|
|
||||||
esp_event_post(APP_NETWORK_EVENT, APP_NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_network_start_timer(void)
|
|
||||||
{
|
|
||||||
if (prov_timeout_period == 0) {
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
esp_timer_create_args_t prov_stop_timer_conf = {.callback = app_network_prov_stop,
|
|
||||||
.arg = NULL,
|
|
||||||
.dispatch_method = ESP_TIMER_TASK,
|
|
||||||
.name = "app_wifi_prov_stop_tm"};
|
|
||||||
if (esp_timer_create(&prov_stop_timer_conf, &prov_stop_timer) == ESP_OK) {
|
|
||||||
esp_timer_start_once(prov_stop_timer, prov_timeout_period);
|
|
||||||
ESP_LOGI(TAG, "Provisioning will auto stop after %d minute(s).", APP_NETWORK_PROV_TIMEOUT_PERIOD);
|
|
||||||
return ESP_OK;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Failed to create Provisioning auto stop timer.");
|
|
||||||
}
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t app_network_start(app_network_pop_type_t pop_type)
|
|
||||||
{
|
|
||||||
/* Configuration for the provisioning manager */
|
|
||||||
network_prov_mgr_config_t config = {
|
|
||||||
.scheme = network_prov_scheme_matter_ble,
|
|
||||||
|
|
||||||
/* Any default scheme specific event handler that you would
|
|
||||||
* like to choose. Since our example application requires
|
|
||||||
* neither BT nor BLE, we can choose to release the associated
|
|
||||||
* memory once provisioning is complete, or not needed
|
|
||||||
* (in case when device is already provisioned). Choosing
|
|
||||||
* appropriate scheme specific event handler allows the manager
|
|
||||||
* to take care of this automatically. This can be set to
|
|
||||||
* WIFI_PROV_EVENT_HANDLER_NONE when using wifi_prov_scheme_softap*/
|
|
||||||
.scheme_event_handler = NETWORK_PROV_EVENT_HANDLER_NONE,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Initialize provisioning manager with the
|
|
||||||
* configuration parameters set above */
|
|
||||||
ESP_ERROR_CHECK(network_prov_mgr_init(config));
|
|
||||||
|
|
||||||
bool provisioned = false;
|
|
||||||
/* Let's find out if the device is provisioned */
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
network_prov_mgr_is_wifi_provisioned(&provisioned);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
network_prov_mgr_is_thread_provisioned(&provisioned);
|
|
||||||
#endif
|
|
||||||
/* If device is not yet provisioned start provisioning service */
|
|
||||||
if (!provisioned) {
|
|
||||||
ESP_LOGI(TAG, "Starting provisioning");
|
|
||||||
|
|
||||||
/* What is the Device Service Name that we want
|
|
||||||
* This translates to :
|
|
||||||
* - Wi-Fi SSID when scheme is wifi_prov_scheme_softap
|
|
||||||
* - device name when scheme is wifi_prov_scheme_ble
|
|
||||||
*/
|
|
||||||
char service_name[12];
|
|
||||||
get_device_service_name(service_name, sizeof(service_name));
|
|
||||||
|
|
||||||
/* What is the service key (Wi-Fi password)
|
|
||||||
* NULL = Open network
|
|
||||||
* This is ignored when scheme is wifi_prov_scheme_ble
|
|
||||||
*/
|
|
||||||
const char *service_key = NULL;
|
|
||||||
|
|
||||||
/* What is the security level that we want (0 or 1):
|
|
||||||
* - WIFI_PROV_SECURITY_0 is simply plain text communication.
|
|
||||||
* - WIFI_PROV_SECURITY_1 is secure communication which consists of secure handshake
|
|
||||||
* using X25519 key exchange and proof of possession (pop) and AES-CTR
|
|
||||||
* for encryption/decryption of messages.
|
|
||||||
*/
|
|
||||||
network_prov_security_t security = NETWORK_PROV_SECURITY_1;
|
|
||||||
|
|
||||||
/* Do we want a proof-of-possession (ignored if Security 0 is selected):
|
|
||||||
* - this should be a string with length > 0
|
|
||||||
* - NULL if not used
|
|
||||||
*/
|
|
||||||
char *pop = get_device_pop(pop_type);
|
|
||||||
if ((pop_type != POP_TYPE_NONE) && (pop == NULL)) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This step is only useful when scheme is wifi_prov_scheme_ble. This will
|
|
||||||
* set a custom 128 bit UUID which will be included in the BLE advertisement
|
|
||||||
* and will correspond to the primary GATT service that provides provisioning
|
|
||||||
* endpoints as GATT characteristics. Each GATT characteristic will be
|
|
||||||
* formed using the primary service UUID as base, with different auto assigned
|
|
||||||
* 12th and 13th bytes (assume counting starts from 0th byte). The client side
|
|
||||||
* applications must identify the endpoints by reading the User Characteristic
|
|
||||||
* Description descriptor (0x2901) for each characteristic, which contains the
|
|
||||||
* endpoint name of the characteristic */
|
|
||||||
uint8_t custom_service_uuid[] = {
|
|
||||||
/* This is a random uuid. This can be modified if you want to change the BLE uuid. */
|
|
||||||
/* 12th and 13th bit will be replaced by internal bits. */
|
|
||||||
0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02,
|
|
||||||
};
|
|
||||||
esp_err_t err = network_prov_scheme_matter_ble_set_service_uuid(custom_service_uuid, sizeof(custom_service_uuid));
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "wifi_prov_scheme_ble_set_service_uuid failed %d", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (custom_mfg_data) {
|
|
||||||
err = network_prov_scheme_matter_ble_set_mfg_data(custom_mfg_data, custom_mfg_data_len);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to set mfg data, err=0x%x", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start provisioning service */
|
|
||||||
ESP_ERROR_CHECK(network_prov_mgr_start_provisioning(security, pop, service_name, service_key));
|
|
||||||
/* Print QR code for provisioning */
|
|
||||||
app_network_print_qr(service_name, pop, PROV_TRANSPORT_BLE);
|
|
||||||
ESP_LOGI(TAG, "Provisioning Started. Name : %s, POP : %s", service_name, pop ? pop : "<null>");
|
|
||||||
if (pop) {
|
|
||||||
free(pop);
|
|
||||||
}
|
|
||||||
app_network_start_timer();
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA");
|
|
||||||
/* We don't need the manager as device is already provisioned,
|
|
||||||
* so let's release it's resources */
|
|
||||||
network_prov_mgr_deinit();
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
|
||||||
esp_wifi_connect();
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
|
||||||
otInstance* instance = esp_openthread_get_instance();
|
|
||||||
(void)otIp6SetEnabled(instance, true);
|
|
||||||
(void)otThreadSetEnabled(instance, true);
|
|
||||||
esp_openthread_lock_release();
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
esp_rmaker_start();
|
|
||||||
}
|
|
||||||
if (custom_mfg_data) {
|
|
||||||
free(custom_mfg_data);
|
|
||||||
custom_mfg_data = NULL;
|
|
||||||
custom_mfg_data_len = 0;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_event.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define MFG_DATA_HEADER 0xe5, 0x02
|
|
||||||
#define MGF_DATA_APP_ID 'N', 'o', 'v'
|
|
||||||
#define MFG_DATA_VERSION 'a'
|
|
||||||
#define MFG_DATA_CUSTOMER_ID 0x00, 0x01
|
|
||||||
|
|
||||||
#define MGF_DATA_DEVICE_TYPE_LIGHT 0x0005
|
|
||||||
#define MGF_DATA_DEVICE_TYPE_SWITCH 0x0080
|
|
||||||
|
|
||||||
#define MFG_DATA_DEVICE_SUBTYPE_SWITCH 0x01
|
|
||||||
#define MFG_DATA_DEVICE_SUBTYPE_LIGHT 0x01
|
|
||||||
|
|
||||||
#define MFG_DATA_DEVICE_EXTRA_CODE 0x00
|
|
||||||
|
|
||||||
/** ESP RainMaker Event Base */
|
|
||||||
ESP_EVENT_DECLARE_BASE(APP_NETWORK_EVENT);
|
|
||||||
|
|
||||||
/** App Wi-Fir Events */
|
|
||||||
typedef enum {
|
|
||||||
/** QR code available for display. Associated data is the NULL terminated QR payload. */
|
|
||||||
APP_NETWORK_EVENT_QR_DISPLAY = 1,
|
|
||||||
/** Provisioning timed out */
|
|
||||||
APP_NETWORK_EVENT_PROV_TIMEOUT,
|
|
||||||
/** Provisioning has restarted due to failures (Invalid SSID/Passphrase) */
|
|
||||||
APP_NETWORK_EVENT_PROV_RESTART,
|
|
||||||
/** Provisioning closed due to invalid credentials */
|
|
||||||
APP_NETWORK_EVENT_PROV_CRED_MISMATCH,
|
|
||||||
} app_network_event_t;
|
|
||||||
|
|
||||||
/** Types of Proof of Possession */
|
|
||||||
typedef enum {
|
|
||||||
/** Use MAC address to generate PoP */
|
|
||||||
POP_TYPE_MAC,
|
|
||||||
/** Use random stream generated and stored in fctry partition during claiming process as PoP */
|
|
||||||
POP_TYPE_RANDOM,
|
|
||||||
/** Do not use any PoP.
|
|
||||||
* Use this option with caution. Consider using `CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD` with this.
|
|
||||||
*/
|
|
||||||
POP_TYPE_NONE,
|
|
||||||
/** Use a custom PoP.
|
|
||||||
* Set a custom PoP using app_wifi_set_custom_pop() first.
|
|
||||||
*/
|
|
||||||
POP_TYPE_CUSTOM
|
|
||||||
} app_network_pop_type_t;
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
#include <esp_openthread_types.h>
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.radio_mode = RADIO_MODE_NATIVE, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.storage_partition_name = "nvs", \
|
|
||||||
.netif_queue_size = 10, \
|
|
||||||
.task_queue_size = 10, \
|
|
||||||
}
|
|
||||||
#endif // CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
|
|
||||||
|
|
||||||
/** Initialize network
|
|
||||||
*
|
|
||||||
* This initializes network and the network provisioning manager
|
|
||||||
*/
|
|
||||||
void app_network_init();
|
|
||||||
|
|
||||||
/** Start network
|
|
||||||
*
|
|
||||||
* This will start provisioning if the node is not provisioned and will connect to Wi-Fi/Thread
|
|
||||||
* if node is provisioned. Function will return successfully only after Wi-Fi/Thread is connect
|
|
||||||
*
|
|
||||||
* @param[in] pop_type The type for Proof of Possession (PoP) pin
|
|
||||||
*
|
|
||||||
* @return ESP_OK on success (Wi-Fi/Thread connected).
|
|
||||||
* @return error in case of failure.
|
|
||||||
*/
|
|
||||||
esp_err_t app_network_start(app_network_pop_type_t pop_type);
|
|
||||||
|
|
||||||
/** Set custom manufacturing data
|
|
||||||
*
|
|
||||||
* This can be used to add some custom manufacturing data in BLE advertisements during
|
|
||||||
* provisioning. This can be used by apps to filter the scanned BLE devices and show
|
|
||||||
* only the relevant one. Supported by Nova Home app for light and switch
|
|
||||||
*
|
|
||||||
* @param[in] device_type Type of the device, like light or switch
|
|
||||||
* @param[in] device_subtype Sub Type of the device (application specific)
|
|
||||||
*
|
|
||||||
* @return ESP_OK on success.
|
|
||||||
* @return error in case of failure.
|
|
||||||
*/
|
|
||||||
esp_err_t app_network_set_custom_mfg_data(uint16_t device_type, uint8_t device_subtype);
|
|
||||||
|
|
||||||
/** Set custom PoP
|
|
||||||
*
|
|
||||||
* This can be used to set a custom Proof of Possession (PoP) pin for provisioning.
|
|
||||||
* Applicable only if POP_TYPE_CUSTOM is used for app_wifi_start().
|
|
||||||
*
|
|
||||||
* @param[in] pop A NULL terminated PoP string (typically 8 characters alphanumeric)
|
|
||||||
*
|
|
||||||
* @return ESP_OK on success.
|
|
||||||
* @return error in case of failure.
|
|
||||||
*/
|
|
||||||
esp_err_t app_network_set_custom_pop(const char *pop);
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "led_indicator.h"
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_matter.h>
|
|
||||||
|
|
||||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
|
||||||
#include "esp_openthread_types.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Standard max values (used for remapping attributes) */
|
|
||||||
#define STANDARD_BRIGHTNESS 100
|
|
||||||
#define STANDARD_HUE 360
|
|
||||||
#define STANDARD_SATURATION 100
|
|
||||||
#define STANDARD_TEMPERATURE_FACTOR 1000000
|
|
||||||
|
|
||||||
/** Matter max values (used for remapping attributes) */
|
|
||||||
#define MATTER_BRIGHTNESS 254
|
|
||||||
#define MATTER_HUE 254
|
|
||||||
#define MATTER_SATURATION 254
|
|
||||||
#define MATTER_TEMPERATURE_FACTOR 1000000
|
|
||||||
|
|
||||||
/** Default attribute values used during initialization */
|
|
||||||
#define DEFAULT_POWER true
|
|
||||||
#define DEFAULT_BRIGHTNESS 64
|
|
||||||
#define DEFAULT_HUE 128
|
|
||||||
#define DEFAULT_SATURATION 254
|
|
||||||
|
|
||||||
typedef void *app_driver_handle_t;
|
|
||||||
|
|
||||||
/** Initialize the light driver
|
|
||||||
*
|
|
||||||
* This initializes the light driver associated with the selected board.
|
|
||||||
*
|
|
||||||
* @return Handle on success.
|
|
||||||
* @return NULL in case of failure.
|
|
||||||
*/
|
|
||||||
app_driver_handle_t app_driver_light_init();
|
|
||||||
|
|
||||||
/** Initialize the button driver
|
|
||||||
*
|
|
||||||
* This initializes the button driver associated with the selected board.
|
|
||||||
*
|
|
||||||
* @return Handle on success.
|
|
||||||
* @return NULL in case of failure.
|
|
||||||
*/
|
|
||||||
app_driver_handle_t app_driver_button_init();
|
|
||||||
|
|
||||||
/** Driver Update
|
|
||||||
*
|
|
||||||
* This API should be called to update the driver for the attribute being updated.
|
|
||||||
* This is usually called from the common `app_attribute_update_cb()`.
|
|
||||||
*
|
|
||||||
* @param[in] endpoint_id Endpoint ID of the attribute.
|
|
||||||
* @param[in] cluster_id Cluster ID of the attribute.
|
|
||||||
* @param[in] attribute_id Attribute ID of the attribute.
|
|
||||||
* @param[in] val Pointer to `esp_matter_attr_val_t`. Use appropriate elements as per the value type.
|
|
||||||
*
|
|
||||||
* @return ESP_OK on success.
|
|
||||||
* @return error in case of failure.
|
|
||||||
*/
|
|
||||||
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
|
|
||||||
uint32_t attribute_id, esp_matter_attr_val_t *val);
|
|
||||||
|
|
||||||
/** Set defaults for light driver
|
|
||||||
*
|
|
||||||
* Set the attribute drivers to their default values from the created data model.
|
|
||||||
*
|
|
||||||
* @param[in] endpoint_id Endpoint ID of the driver.
|
|
||||||
*
|
|
||||||
* @return ESP_OK on success.
|
|
||||||
* @return error in case of failure.
|
|
||||||
*/
|
|
||||||
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id);
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, bool val);
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, int val);
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, int val);
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, int val);
|
|
||||||
|
|
||||||
esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, int val);
|
|
||||||
|
|
||||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.radio_mode = RADIO_MODE_NATIVE, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
|
||||||
{ \
|
|
||||||
.storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
dependencies:
|
|
||||||
esp_bsp_devkit:
|
|
||||||
version: "^3"
|
|
||||||
espressif/led_strip:
|
|
||||||
version: "^2.0.0"
|
|
||||||
espressif/esp_rainmaker:
|
|
||||||
version: "^1.4.2"
|
|
||||||
espressif/qrcode:
|
|
||||||
version: "^0.1.0~2"
|
|
||||||
-204
@@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "network_prov_scheme_matter_ble.h"
|
|
||||||
#include "protocomm_matter_ble.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_log.h>
|
|
||||||
#include <esp_wifi_types.h>
|
|
||||||
#include <protocomm.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define TAG "NETWORK_PROV"
|
|
||||||
|
|
||||||
static uint8_t custom_service_uuid[BLE_UUID128_VAL_LENGTH];
|
|
||||||
static bool custom_service_uuid_set = false;
|
|
||||||
static uint8_t *custom_manufacturer_data = nullptr;
|
|
||||||
static size_t custom_manufacturer_data_len = 0;
|
|
||||||
|
|
||||||
static esp_err_t prov_start(protocomm_t *pc, void *config)
|
|
||||||
{
|
|
||||||
if (!pc) {
|
|
||||||
ESP_LOGE(TAG, "Protocomm handle cannot be null");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config) {
|
|
||||||
ESP_LOGE(TAG, "Cannot start with null configuration");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
|
||||||
|
|
||||||
#if defined(CONFIG_WIFI_PROV_BLE_BONDING)
|
|
||||||
ble_config->ble_bonding = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_WIFI_PROV_BLE_SEC_CONN)
|
|
||||||
ble_config->ble_sm_sc = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION)
|
|
||||||
ble_config->ble_link_encryption = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (protocomm_matter_ble_start(pc, ble_config) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to start protocomm BLE service");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t prov_stop(protocomm_t *pc)
|
|
||||||
{
|
|
||||||
return protocomm_matter_ble_stop(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t network_prov_scheme_matter_ble_set_service_uuid(uint8_t *uuid, size_t uuid_size)
|
|
||||||
{
|
|
||||||
if (uuid_size != sizeof(custom_service_uuid)) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
memcpy(custom_service_uuid, uuid, sizeof(custom_service_uuid));
|
|
||||||
custom_service_uuid_set = true;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t network_prov_scheme_matter_ble_set_mfg_data(uint8_t *mfg_data, size_t mfg_data_len)
|
|
||||||
{
|
|
||||||
if (custom_manufacturer_data) {
|
|
||||||
free(custom_manufacturer_data);
|
|
||||||
}
|
|
||||||
custom_manufacturer_data = (uint8_t *)malloc(mfg_data_len);
|
|
||||||
if (!custom_manufacturer_data) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
custom_manufacturer_data_len = mfg_data_len;
|
|
||||||
memcpy(custom_manufacturer_data, mfg_data, mfg_data_len);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *new_config()
|
|
||||||
{
|
|
||||||
protocomm_matter_ble_config_t *ble_config =
|
|
||||||
(protocomm_matter_ble_config_t *)calloc(1, sizeof(protocomm_matter_ble_config_t));
|
|
||||||
if (!ble_config) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating memory for new configuration");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
const uint8_t service_uuid[16] = {
|
|
||||||
0x07, 0xed, 0x9b, 0x2d, 0x0f, 0x06, 0x7c, 0x87, 0x9b, 0x43, 0x43, 0x6b, 0x4d, 0x24, 0x75, 0x17,
|
|
||||||
};
|
|
||||||
memcpy(ble_config->service_uuid, service_uuid, sizeof(ble_config->service_uuid));
|
|
||||||
return ble_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void delete_config(void *config)
|
|
||||||
{
|
|
||||||
if (!config) {
|
|
||||||
ESP_LOGE(TAG, "Cannot delete null configuration");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
|
||||||
for (size_t i = 0; i < ble_config->name_uuid_array_len; i++) {
|
|
||||||
free((void *)ble_config->name_uuid_array[i].name);
|
|
||||||
}
|
|
||||||
free(ble_config->name_uuid_array);
|
|
||||||
free(ble_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t set_config_service(void *config, const char *service_name, const char *service_key)
|
|
||||||
{
|
|
||||||
if (!config) {
|
|
||||||
ESP_LOGE(TAG, "Cannot set null configuration");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
if (!service_name) {
|
|
||||||
ESP_LOGE(TAG, "Service name cannot be NULL");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
|
||||||
strlcpy(ble_config->device_name, service_name, sizeof(ble_config->device_name));
|
|
||||||
if (custom_service_uuid_set) {
|
|
||||||
memcpy(ble_config->service_uuid, custom_service_uuid, sizeof(ble_config->service_uuid));
|
|
||||||
}
|
|
||||||
if (custom_manufacturer_data && custom_manufacturer_data_len) {
|
|
||||||
/* Manufacturer Data Length + 2 Byte header + BLE Device name + 2 Byte
|
|
||||||
* header <= 31 Bytes */
|
|
||||||
size_t mfg_data_len = custom_manufacturer_data_len;
|
|
||||||
size_t dev_name_len = strnlen(ble_config->device_name, MAX_BLE_DEVNAME_LEN);
|
|
||||||
|
|
||||||
if ((dev_name_len + 2) >= MAX_BLE_MANUFACTURER_DATA_LEN) {
|
|
||||||
/* No space left for manufacturer data */
|
|
||||||
ESP_LOGE(TAG, "No space left for Manufacturer data ");
|
|
||||||
ble_config->manufacturer_data = nullptr;
|
|
||||||
ble_config->manufacturer_data_len = 0;
|
|
||||||
} else {
|
|
||||||
if ((mfg_data_len + (dev_name_len ? (dev_name_len + 2) : 0)) > MAX_BLE_MANUFACTURER_DATA_LEN) {
|
|
||||||
ESP_LOGE(TAG, "Manufacturer data length is more than the max allowed size; expect truncated mfg_data ");
|
|
||||||
/* Truncate the mfg_data to fit in the available length */
|
|
||||||
mfg_data_len = MAX_BLE_MANUFACTURER_DATA_LEN - (dev_name_len ? (dev_name_len + 2) : 0);
|
|
||||||
}
|
|
||||||
ble_config->manufacturer_data = custom_manufacturer_data;
|
|
||||||
ble_config->manufacturer_data_len = mfg_data_len;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ble_config->manufacturer_data = nullptr;
|
|
||||||
ble_config->manufacturer_data_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, uint16_t uuid)
|
|
||||||
{
|
|
||||||
if (!config) {
|
|
||||||
ESP_LOGE(TAG, "Cannot set null configuration");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!endpoint_name) {
|
|
||||||
ESP_LOGE(TAG, "EP name cannot be null");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
|
||||||
|
|
||||||
char *copy_ep_name = strdup(endpoint_name);
|
|
||||||
if (!copy_ep_name) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating memory for EP name");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
protocomm_matter_ble_name_uuid_t *name_uuid_array = (protocomm_matter_ble_name_uuid_t *)realloc(
|
|
||||||
ble_config->name_uuid_array, (ble_config->name_uuid_array_len + 1) * sizeof(protocomm_matter_ble_name_uuid_t));
|
|
||||||
if (!name_uuid_array) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating memory for EP-UUID lookup table");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
name_uuid_array[ble_config->name_uuid_array_len].name = copy_ep_name;
|
|
||||||
name_uuid_array[ble_config->name_uuid_array_len].uuid = uuid;
|
|
||||||
ble_config->name_uuid_array = name_uuid_array;
|
|
||||||
ble_config->name_uuid_array_len += 1;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const network_prov_scheme_t network_prov_scheme_matter_ble = {.prov_start = prov_start,
|
|
||||||
.prov_stop = prov_stop,
|
|
||||||
.new_config = new_config,
|
|
||||||
.delete_config = delete_config,
|
|
||||||
.set_config_service = set_config_service,
|
|
||||||
.set_config_endpoint = set_config_endpoint,
|
|
||||||
#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
|
|
||||||
.wifi_mode = WIFI_MODE_STA
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <protocomm.h>
|
|
||||||
#include <protocomm_ble.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <esp_err.h>
|
|
||||||
|
|
||||||
#include <network_provisioning/manager.h>
|
|
||||||
|
|
||||||
extern const network_prov_scheme_t network_prov_scheme_matter_ble;
|
|
||||||
|
|
||||||
#define NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM { \
|
|
||||||
.event_cb = network_prov_scheme_ble_event_cb_free_btdm, \
|
|
||||||
.user_data = NULL \
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_prov_scheme_matter_ble_event_cb_free_btdm(void *user_data, network_prov_cb_event_t event, void *event_data);
|
|
||||||
|
|
||||||
esp_err_t network_prov_scheme_matter_ble_set_service_uuid(uint8_t *uuid, size_t uuid_size);
|
|
||||||
|
|
||||||
esp_err_t network_prov_scheme_matter_ble_set_mfg_data(uint8_t *mfg_data, size_t mfg_data_len);
|
|
||||||
@@ -1,559 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <platform/internal/CHIPDeviceLayerInternal.h>
|
|
||||||
#include <platform/CHIPDeviceConfig.h>
|
|
||||||
#include <ble/CHIPBleServiceData.h>
|
|
||||||
#include <platform/internal/BLEManager.h>
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <host/ble_gap.h>
|
|
||||||
#include <host/ble_gatt.h>
|
|
||||||
#include <host/ble_uuid.h>
|
|
||||||
#include <host/util/util.h>
|
|
||||||
#include <protocomm.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "protocomm_matter_ble.h"
|
|
||||||
#include "esp_cpu.h"
|
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT);
|
|
||||||
|
|
||||||
int ble_uuid_flat(const ble_uuid_t *, void *);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
protocomm_t *pc_matter_ble;
|
|
||||||
uint8_t ble_uuid_base[BLE_UUID128_VAL_LENGTH];
|
|
||||||
protocomm_matter_ble_name_uuid_t *g_name_uuid_array;
|
|
||||||
ssize_t g_name_uuid_array_len;
|
|
||||||
uint16_t gatt_mtu;
|
|
||||||
unsigned ble_link_encryption:1;
|
|
||||||
} _protocomm_matter_ble_internal_t;
|
|
||||||
|
|
||||||
static _protocomm_matter_ble_internal_t *protoble_internal = nullptr;
|
|
||||||
static struct ble_gatt_svc_def *s_gatt_db = nullptr;
|
|
||||||
static ble_hs_adv_fields s_secondary_adv_fields;
|
|
||||||
static ble_hs_adv_fields s_secondary_resp_fields;
|
|
||||||
|
|
||||||
#define BLE_GATT_UUID_CHAR_DSC 0x2901
|
|
||||||
#define TAG "protocomm_matter_ble"
|
|
||||||
|
|
||||||
struct data_mbuf {
|
|
||||||
SLIST_ENTRY(data_mbuf) node;
|
|
||||||
uint8_t *outbuf;
|
|
||||||
ssize_t outlen;
|
|
||||||
uint16_t attr_handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
static SLIST_HEAD(data_mbuf_head, data_mbuf) data_mbuf_list =
|
|
||||||
SLIST_HEAD_INITIALIZER(data_mbuf_list);
|
|
||||||
|
|
||||||
static struct data_mbuf *find_attr_with_handle(uint16_t attr_handle)
|
|
||||||
{
|
|
||||||
struct data_mbuf *cur;
|
|
||||||
SLIST_FOREACH(cur, &data_mbuf_list, node) {
|
|
||||||
if (cur->attr_handle == attr_handle) {
|
|
||||||
return cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_gatt_ble_misc_memory(struct ble_gatt_svc_def * svc_def)
|
|
||||||
{
|
|
||||||
if (svc_def) {
|
|
||||||
if (svc_def->characteristics) {
|
|
||||||
for (int i = 0; i < protoble_internal->g_name_uuid_array_len; ++i) {
|
|
||||||
if (svc_def->characteristics[i].descriptors) {
|
|
||||||
free((void *)svc_def->characteristics[i].descriptors->uuid);
|
|
||||||
free(svc_def->characteristics[i].descriptors);
|
|
||||||
}
|
|
||||||
free((void *)svc_def->characteristics[i].uuid);
|
|
||||||
}
|
|
||||||
free((void *)svc_def->characteristics);
|
|
||||||
}
|
|
||||||
if (svc_def->uuid) {
|
|
||||||
free((void *)svc_def->uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void protocomm_matter_ble_cleanup()
|
|
||||||
{
|
|
||||||
if (protoble_internal) {
|
|
||||||
if (protoble_internal->g_name_uuid_array) {
|
|
||||||
for (unsigned i = 0; i < protoble_internal->g_name_uuid_array_len; ++i) {
|
|
||||||
if (protoble_internal->g_name_uuid_array[i].name) {
|
|
||||||
free((void *)protoble_internal->g_name_uuid_array[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(protoble_internal->g_name_uuid_array);
|
|
||||||
}
|
|
||||||
free(protoble_internal);
|
|
||||||
protoble_internal = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ble_gatt_add_primary_svcs(struct ble_gatt_svc_def *gatt_db_svc, int char_count)
|
|
||||||
{
|
|
||||||
gatt_db_svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
|
|
||||||
gatt_db_svc->characteristics =
|
|
||||||
(struct ble_gatt_chr_def *) calloc((char_count + 1), sizeof(struct ble_gatt_chr_def));
|
|
||||||
if (!gatt_db_svc->characteristics) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *uuid128_to_handler(uint8_t *uuid)
|
|
||||||
{
|
|
||||||
uint8_t *uuid16 = uuid + 12;
|
|
||||||
for (int i = 0; i < protoble_internal->g_name_uuid_array_len; i++) {
|
|
||||||
if (protoble_internal->g_name_uuid_array[i].uuid == *(uint16_t *)uuid16) {
|
|
||||||
ESP_LOGD(TAG, "UUID (0x%x) matched with proto-name = %s", *uuid16, protoble_internal->g_name_uuid_array[i].name);
|
|
||||||
return protoble_internal->g_name_uuid_array[i].name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int matter_ble_gatts_get_attr_value(uint16_t attr_handle, ssize_t *outlen, uint8_t **outbuf)
|
|
||||||
{
|
|
||||||
struct data_mbuf *attr_mbuf = find_attr_with_handle(attr_handle);
|
|
||||||
if (!attr_mbuf) {
|
|
||||||
ESP_LOGE(TAG, "Outbuf with handle %d not found", attr_handle);
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
*outbuf = attr_mbuf->outbuf;
|
|
||||||
*outlen = attr_mbuf->outlen;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int matter_ble_gatts_set_attr_value(uint16_t attr_handle, ssize_t outlen, uint8_t *outbuf)
|
|
||||||
{
|
|
||||||
struct data_mbuf *attr_mbuf = find_attr_with_handle(attr_handle);
|
|
||||||
if (!attr_mbuf) {
|
|
||||||
attr_mbuf = (struct data_mbuf *)calloc(1, sizeof(struct data_mbuf));
|
|
||||||
if (!attr_mbuf) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for storing outbuf and outlen");
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
SLIST_INSERT_HEAD(&data_mbuf_list, attr_mbuf, node);
|
|
||||||
attr_mbuf->attr_handle = attr_handle;
|
|
||||||
} else {
|
|
||||||
free(attr_mbuf->outbuf);
|
|
||||||
}
|
|
||||||
attr_mbuf->outbuf = outbuf;
|
|
||||||
attr_mbuf->outlen = outlen;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int matter_ble_gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
|
||||||
void *arg)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
esp_err_t err;
|
|
||||||
char buf[BLE_UUID_STR_LEN] = { 0 };
|
|
||||||
ssize_t temp_outlen = 0;
|
|
||||||
uint8_t *temp_outbuf = nullptr;
|
|
||||||
uint8_t *uuid = nullptr;
|
|
||||||
uint8_t *data_buf = nullptr;
|
|
||||||
uint16_t data_len = 0;
|
|
||||||
uint16_t data_buf_len = 0;
|
|
||||||
switch (ctxt->op) {
|
|
||||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
|
||||||
ESP_LOGD(TAG, "Read attempted for characteristic UUID = %s, attr_handle = %d",
|
|
||||||
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle);
|
|
||||||
rc = matter_ble_gatts_get_attr_value(attr_handle, &temp_outlen, &temp_outbuf);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "Characteristic with attr_handle = %d is not added to the list", attr_handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (os_mbuf_append(ctxt->om, temp_outbuf, static_cast<uint16_t>(temp_outlen)) != 0) {
|
|
||||||
rc = BLE_ATT_ERR_INSUFFICIENT_RES;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
|
||||||
if (ctxt->om->om_len == 0) {
|
|
||||||
ESP_LOGD(TAG,"Empty packet");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uuid = (uint8_t *) calloc(BLE_UUID128_VAL_LENGTH, sizeof(uint8_t));
|
|
||||||
if (!uuid) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating memory for 128 bit UUID");
|
|
||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
|
||||||
}
|
|
||||||
assert(ctxt->chr->uuid->type == BLE_UUID_TYPE_128);
|
|
||||||
{
|
|
||||||
const ble_uuid128_t *uuid128 = (const ble_uuid128_t *)ctxt->chr->uuid;
|
|
||||||
memcpy(uuid, uuid128->value, BLE_UUID128_VAL_LENGTH);
|
|
||||||
}
|
|
||||||
if (rc != 0) {
|
|
||||||
free(uuid);
|
|
||||||
ESP_LOGE(TAG, "Error fetching Characteristic UUID128");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
data_len = OS_MBUF_PKTLEN(ctxt->om);
|
|
||||||
ESP_LOGD(TAG, "Write attempt for uuid = %s, attr_handle = %d, data_len = %d",
|
|
||||||
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle, data_len);
|
|
||||||
data_buf = (uint8_t *)calloc(1, data_len);
|
|
||||||
if (!data_buf) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating memory for characteristic value");
|
|
||||||
free(uuid);
|
|
||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
|
||||||
}
|
|
||||||
rc = ble_hs_mbuf_to_flat(ctxt->om, data_buf, data_len, &data_buf_len);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "Error getting data from memory buffers");
|
|
||||||
free(uuid);
|
|
||||||
free(data_buf);
|
|
||||||
return BLE_ATT_ERR_UNLIKELY;
|
|
||||||
}
|
|
||||||
err = protocomm_req_handle(protoble_internal->pc_matter_ble, uuid128_to_handler(uuid), conn_handle, data_buf,
|
|
||||||
data_buf_len, &temp_outbuf, &temp_outlen);
|
|
||||||
free(uuid);
|
|
||||||
free(data_buf);
|
|
||||||
if (err == ESP_OK) {
|
|
||||||
rc = matter_ble_gatts_set_attr_value(attr_handle, temp_outlen, temp_outbuf);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "Failed to set outbuf for characteristic with attr_handle = %d", attr_handle);
|
|
||||||
free(temp_outbuf);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Invalid content received, killing connection");
|
|
||||||
rc = BLE_ATT_ERR_INVALID_PDU;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rc = BLE_ATT_ERR_UNLIKELY;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int matter_ble_gatt_svr_dsc_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
|
||||||
void *arg)
|
|
||||||
{
|
|
||||||
if (ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC) {
|
|
||||||
return BLE_ATT_ERR_UNLIKELY;
|
|
||||||
}
|
|
||||||
int rc;
|
|
||||||
size_t temp_outlen = strlen((const char *)ctxt->dsc->arg);
|
|
||||||
rc = os_mbuf_append(ctxt->om, ctxt->dsc->arg, (uint16_t)temp_outlen);
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ble_gatt_add_characteristics(void *character, int idx)
|
|
||||||
{
|
|
||||||
struct ble_gatt_chr_def *characteristics = (struct ble_gatt_chr_def *)character;
|
|
||||||
ble_uuid128_t temp_uuid128 = { 0 };
|
|
||||||
temp_uuid128.u.type = BLE_UUID_TYPE_128;
|
|
||||||
memcpy(temp_uuid128.value, protoble_internal->ble_uuid_base, BLE_UUID128_VAL_LENGTH);
|
|
||||||
memcpy(&temp_uuid128.value[12], &protoble_internal->g_name_uuid_array[idx].uuid, 2);
|
|
||||||
|
|
||||||
(characteristics + idx)->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE;
|
|
||||||
if (protoble_internal->ble_link_encryption) {
|
|
||||||
(characteristics + idx)->flags |= BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC;
|
|
||||||
}
|
|
||||||
|
|
||||||
(characteristics + idx)->access_cb = matter_ble_gatt_svr_chr_access;
|
|
||||||
|
|
||||||
(characteristics + idx)->uuid = (ble_uuid_t *)calloc(1, sizeof(ble_uuid128_t));
|
|
||||||
if (!(characteristics + idx)->uuid) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
memcpy((void *)(characteristics + idx)->uuid, &temp_uuid128, sizeof(ble_uuid128_t));
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ble_gatt_add_char_dsc(void *ch, int idx, uint16_t dsc_uuid)
|
|
||||||
{
|
|
||||||
struct ble_gatt_chr_def *characteristics = (struct ble_gatt_chr_def *)ch;
|
|
||||||
ble_uuid16_t uuid16;
|
|
||||||
uuid16.u.type = BLE_UUID_TYPE_16;
|
|
||||||
uuid16.value = dsc_uuid;
|
|
||||||
(characteristics + idx)->descriptors =
|
|
||||||
(struct ble_gatt_dsc_def *) calloc(2, sizeof(struct ble_gatt_dsc_def));
|
|
||||||
if (!(characteristics + idx)->descriptors) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
(characteristics + idx)->descriptors[0].uuid = (ble_uuid_t *) calloc(1, sizeof(ble_uuid16_t));
|
|
||||||
if (!(characteristics + idx)->descriptors[0].uuid) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
memcpy((void *)(characteristics + idx)->descriptors[0].uuid, &uuid16,
|
|
||||||
sizeof(ble_uuid16_t));
|
|
||||||
(characteristics + idx)->descriptors[0].att_flags = BLE_ATT_F_READ;
|
|
||||||
(characteristics + idx)->descriptors[0].access_cb = matter_ble_gatt_svr_dsc_access;
|
|
||||||
(characteristics + idx)->descriptors[0].arg = (void *)protoble_internal->g_name_uuid_array[idx].name;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t populate_gatt_db(struct ble_gatt_svc_def **gatt_db_svc_ptr, const protocomm_matter_ble_config_t *config)
|
|
||||||
{
|
|
||||||
if (*gatt_db_svc_ptr) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
*gatt_db_svc_ptr = (struct ble_gatt_svc_def *) calloc(1, sizeof(struct ble_gatt_svc_def));
|
|
||||||
if (!*gatt_db_svc_ptr) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
(*gatt_db_svc_ptr)->uuid = (ble_uuid_t *) calloc(1, sizeof(ble_uuid128_t));
|
|
||||||
if (!(*gatt_db_svc_ptr)->uuid) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
ble_uuid128_t uuid128 = { 0 };
|
|
||||||
uuid128.u.type = BLE_UUID_TYPE_128;
|
|
||||||
memcpy(uuid128.value, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
|
||||||
memcpy((void *) (*gatt_db_svc_ptr)->uuid, &uuid128, sizeof(ble_uuid128_t));
|
|
||||||
// Add primary service
|
|
||||||
esp_err_t err = ble_gatt_add_primary_svcs(*gatt_db_svc_ptr, config->name_uuid_array_len);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < config->name_uuid_array_len; ++i) {
|
|
||||||
err = ble_gatt_add_characteristics((void *)(*gatt_db_svc_ptr)->characteristics, i);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = ble_gatt_add_char_dsc((void *) (*gatt_db_svc_ptr)->characteristics,
|
|
||||||
i, BLE_GATT_UUID_CHAR_DSC);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void transport_matter_ble_connect(struct ble_gap_event *event, void *arg)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
ESP_LOGD(TAG, "Inside BLE connect w/ conn_id - %d", event->connect.conn_handle);
|
|
||||||
|
|
||||||
if (!protoble_internal) {
|
|
||||||
ESP_LOGI(TAG,"Protocomm layer has already stopped");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = protocomm_open_session(protoble_internal->pc_matter_ble, event->connect.conn_handle);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "error creating the session");
|
|
||||||
} else {
|
|
||||||
protocomm_matter_ble_event_t ble_event = {};
|
|
||||||
ble_event.evt_type = PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED;
|
|
||||||
ble_event.conn_handle = event->connect.conn_handle;
|
|
||||||
ble_event.conn_status = event->connect.status;
|
|
||||||
if (esp_event_post(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT, PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED, &ble_event,
|
|
||||||
sizeof(protocomm_matter_ble_event_t), portMAX_DELAY) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to post transport pairing event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void transport_matter_ble_disconnect(struct ble_gap_event *event, void *arg)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
ESP_LOGD(TAG, "Inside disconnect w/ session - %d", event->disconnect.conn.conn_handle);
|
|
||||||
if (!protoble_internal) {
|
|
||||||
ESP_LOGI(TAG,"Protocomm layer has already stopped");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (protoble_internal->pc_matter_ble) {
|
|
||||||
err = protocomm_close_session(protoble_internal->pc_matter_ble, event->disconnect.conn.conn_handle);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "error closing the session after disconnect");
|
|
||||||
} else {
|
|
||||||
protocomm_matter_ble_event_t ble_event = {};
|
|
||||||
ble_event.evt_type = PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED;
|
|
||||||
ble_event.conn_handle = event->disconnect.conn.conn_handle;
|
|
||||||
ble_event.disconnect_reason = event->disconnect.reason;
|
|
||||||
if (esp_event_post(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT, PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED, &ble_event,
|
|
||||||
sizeof(protocomm_matter_ble_event_t), portMAX_DELAY) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to post transport disconnection event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protoble_internal->gatt_mtu = BLE_ATT_MTU_DFLT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void transport_matter_ble_set_mtu(struct ble_gap_event *event, void *arg)
|
|
||||||
{
|
|
||||||
protoble_internal->gatt_mtu = event->mtu.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int protocomm_matter_ble_gap_event(struct ble_gap_event *event, void *arg)
|
|
||||||
{
|
|
||||||
struct ble_gap_conn_desc desc;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
switch (event->type) {
|
|
||||||
case BLE_GAP_EVENT_CONNECT:
|
|
||||||
if (event->connect.status == 0) {
|
|
||||||
transport_matter_ble_connect(event, arg);
|
|
||||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "No open connection with the specified handle");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BLE_GAP_EVENT_DISCONNECT:
|
|
||||||
transport_matter_ble_disconnect(event, arg);
|
|
||||||
start_secondary_ble_adv();
|
|
||||||
break;
|
|
||||||
case BLE_GAP_EVENT_MTU:
|
|
||||||
transport_matter_ble_set_mtu(event, arg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start_secondary_ble_adv()
|
|
||||||
{
|
|
||||||
if (!ble_hs_is_enabled()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int ret = 0;
|
|
||||||
uint8_t secondary_own_addr_type;
|
|
||||||
ret = ble_hs_util_ensure_addr(0);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_hs_util_ensure_addr() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = ble_hs_id_infer_auto(0, &secondary_own_addr_type);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_hs_id_infer_auto() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ble_gap_ext_adv_params adv_params;
|
|
||||||
memset(&adv_params, 0, sizeof(adv_params));
|
|
||||||
adv_params.scannable = 1;
|
|
||||||
adv_params.own_addr_type = secondary_own_addr_type;
|
|
||||||
adv_params.legacy_pdu = 1;
|
|
||||||
adv_params.connectable = 1;
|
|
||||||
adv_params.itvl_min = 0x100;
|
|
||||||
adv_params.itvl_max = 0x100;
|
|
||||||
|
|
||||||
if (ble_gap_ext_adv_active(1)) {
|
|
||||||
ESP_LOGI(TAG, "Device already advertising, stop active advertisement and restart");
|
|
||||||
ret = ble_gap_ext_adv_stop(1);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_gap_ext_adv_stop() failed, cannot restart");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ble_gap_ext_adv_configure(1, &adv_params, NULL, protocomm_matter_ble_gap_event, NULL);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_gap_ext_adv_configure() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
struct os_mbuf * data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0);
|
|
||||||
assert(data);
|
|
||||||
ret = ble_hs_adv_set_fields_mbuf(&s_secondary_adv_fields, data);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_hs_adv_set_fields_mbuf() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = ble_gap_ext_adv_set_data(1, data);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_gap_ext_adv_set_data()");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
struct os_mbuf * resp_data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0);
|
|
||||||
assert(resp_data);
|
|
||||||
ret = ble_hs_adv_set_fields_mbuf(&s_secondary_resp_fields, resp_data);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_hs_adv_set_fields_mbuf() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = ble_gap_ext_adv_rsp_set_data(1, resp_data);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_gap_ext_adv_rsp_set_data() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = ble_gap_ext_adv_start(1, 0, 0);
|
|
||||||
if (ret != 0) {
|
|
||||||
ESP_LOGE(TAG, "ble_gap_ext_adv_start() failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t protocomm_matter_ble_start(protocomm_t *pc, const protocomm_matter_ble_config_t *config)
|
|
||||||
{
|
|
||||||
if (!pc || !config || !config->name_uuid_array_len || !config->name_uuid_array) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
if (protoble_internal) {
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
protoble_internal = (_protocomm_matter_ble_internal_t *) calloc(1, sizeof(_protocomm_matter_ble_internal_t));
|
|
||||||
if (!protoble_internal) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
memcpy(protoble_internal->ble_uuid_base, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
|
||||||
protoble_internal->g_name_uuid_array_len = config->name_uuid_array_len;
|
|
||||||
protoble_internal->g_name_uuid_array = (protocomm_matter_ble_name_uuid_t *)malloc(config->name_uuid_array_len * sizeof(protocomm_matter_ble_name_uuid_t));
|
|
||||||
if (!protoble_internal->g_name_uuid_array) {
|
|
||||||
protocomm_matter_ble_cleanup();
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < protoble_internal->g_name_uuid_array_len; i++) {
|
|
||||||
protoble_internal->g_name_uuid_array[i].uuid = config->name_uuid_array[i].uuid;
|
|
||||||
protoble_internal->g_name_uuid_array[i].name = strdup(config->name_uuid_array[i].name);
|
|
||||||
if (!protoble_internal->g_name_uuid_array[i].name) {
|
|
||||||
ESP_LOGE(TAG, "Error allocating internal name UUID entry");
|
|
||||||
protocomm_matter_ble_cleanup();
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protoble_internal->pc_matter_ble = pc;
|
|
||||||
protoble_internal->gatt_mtu = BLE_ATT_MTU_DFLT;
|
|
||||||
protoble_internal->ble_link_encryption = config->ble_link_encryption;
|
|
||||||
|
|
||||||
if (populate_gatt_db(&s_gatt_db, config) != ESP_OK) {
|
|
||||||
free_gatt_ble_misc_memory(s_gatt_db);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<struct ble_gatt_svc_def> extGattSvcs;
|
|
||||||
extGattSvcs.push_back(*s_gatt_db);
|
|
||||||
chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureExtraServices(extGattSvcs, false);
|
|
||||||
memset(&s_secondary_adv_fields, 0, sizeof(s_secondary_adv_fields));
|
|
||||||
s_secondary_adv_fields.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
|
||||||
s_secondary_adv_fields.num_uuids128 = 1;
|
|
||||||
s_secondary_adv_fields.uuids128_is_complete = 1;
|
|
||||||
static ble_uuid128_t s_secondary_adv_uuid;
|
|
||||||
s_secondary_adv_uuid.u.type = BLE_UUID_TYPE_128;
|
|
||||||
memcpy(s_secondary_adv_uuid.value, config->service_uuid, sizeof(config->service_uuid));
|
|
||||||
s_secondary_adv_fields.uuids128 = &s_secondary_adv_uuid;
|
|
||||||
|
|
||||||
memset(&s_secondary_resp_fields, 0, sizeof(s_secondary_resp_fields));
|
|
||||||
s_secondary_resp_fields.name = (const uint8_t *)config->device_name;
|
|
||||||
s_secondary_resp_fields.name_len = (uint8_t)strlen(config->device_name);
|
|
||||||
s_secondary_resp_fields.name_is_complete = 1;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t protocomm_matter_ble_stop(protocomm_t *pc)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "protocomm_ble_stop called here...");
|
|
||||||
|
|
||||||
if ((pc != NULL) && (protoble_internal != NULL ) && (pc == protoble_internal->pc_matter_ble)) {
|
|
||||||
protoble_internal->pc_matter_ble = nullptr;
|
|
||||||
}
|
|
||||||
chip::DeviceLayer::Internal::BLEMgr().Shutdown();
|
|
||||||
free_gatt_ble_misc_memory(s_gatt_db);
|
|
||||||
protocomm_matter_ble_cleanup();
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_event.h>
|
|
||||||
#include <protocomm.h>
|
|
||||||
|
|
||||||
|
|
||||||
ESP_EVENT_DECLARE_BASE(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT);
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED,
|
|
||||||
PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED,
|
|
||||||
} protocomm_transport_matter_ble_event_t;
|
|
||||||
|
|
||||||
#define BLE_UUID128_VAL_LENGTH 16
|
|
||||||
|
|
||||||
#define MAX_BLE_MANUFACTURER_DATA_LEN 29
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *name;
|
|
||||||
uint16_t uuid;
|
|
||||||
} protocomm_matter_ble_name_uuid_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t evt_type;
|
|
||||||
uint16_t conn_handle;
|
|
||||||
union {
|
|
||||||
int conn_status;
|
|
||||||
int disconnect_reason;
|
|
||||||
};
|
|
||||||
} protocomm_matter_ble_event_t;
|
|
||||||
|
|
||||||
typedef struct protocomm_matter_ble_config {
|
|
||||||
char device_name[30];
|
|
||||||
uint8_t service_uuid[BLE_UUID128_VAL_LENGTH];
|
|
||||||
uint8_t *manufacturer_data;
|
|
||||||
ssize_t manufacturer_data_len;
|
|
||||||
ssize_t name_uuid_array_len;
|
|
||||||
protocomm_matter_ble_name_uuid_t *name_uuid_array;
|
|
||||||
unsigned ble_bonding:1;
|
|
||||||
unsigned ble_sm_sc:1;
|
|
||||||
unsigned ble_link_encryption:1;
|
|
||||||
} protocomm_matter_ble_config_t;
|
|
||||||
|
|
||||||
esp_err_t protocomm_matter_ble_start(protocomm_t *pc, const protocomm_matter_ble_config_t *config);
|
|
||||||
|
|
||||||
esp_err_t protocomm_matter_ble_stop(protocomm_t *pc);
|
|
||||||
|
|
||||||
int start_secondary_ble_adv();
|
|
||||||
Binary file not shown.
@@ -1,10 +0,0 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
|
||||||
# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
|
|
||||||
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
|
|
||||||
nvs, data, nvs, 0x10000, 0xC000,
|
|
||||||
nvs_keys, data, nvs_keys,, 0x1000, encrypted
|
|
||||||
otadata, data, ota, , 0x2000
|
|
||||||
phy_init, data, phy, , 0x1000,
|
|
||||||
ota_0, app, ota_0, 0x20000, 0x1E0000,
|
|
||||||
ota_1, app, ota_1, , 0x1E0000,
|
|
||||||
fctry, data, nvs, 0x3E0000, 0x6000
|
|
||||||
|
@@ -1,186 +0,0 @@
|
|||||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
|
||||||
|
|
||||||
# Compiler options
|
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
|
||||||
|
|
||||||
#enable BT
|
|
||||||
CONFIG_BT_ENABLED=y
|
|
||||||
CONFIG_BT_NIMBLE_ENABLED=y
|
|
||||||
CONFIG_BT_NIMBLE_ROLE_CENTRAL=n
|
|
||||||
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
|
|
||||||
CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING=y
|
|
||||||
|
|
||||||
# Enable Extended advertisement of NIMBLE
|
|
||||||
CONFIG_BT_NIMBLE_EXT_ADV=y
|
|
||||||
CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
|
|
||||||
|
|
||||||
#disable BT connection reattempt
|
|
||||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
|
||||||
|
|
||||||
#enable lwip ipv6 autoconfig
|
|
||||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
|
||||||
|
|
||||||
# Use a custom partition table
|
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
|
||||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
|
||||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
|
||||||
|
|
||||||
# Enable chip shell
|
|
||||||
CONFIG_ENABLE_CHIP_SHELL=y
|
|
||||||
|
|
||||||
#enable lwIP route hooks
|
|
||||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
|
||||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
|
||||||
|
|
||||||
# Button
|
|
||||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
|
||||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
|
||||||
|
|
||||||
# disable softap by default
|
|
||||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
|
||||||
|
|
||||||
# Disable DS Peripheral
|
|
||||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
|
||||||
|
|
||||||
# Enable HKDF in mbedtls
|
|
||||||
CONFIG_MBEDTLS_HKDF_C=y
|
|
||||||
|
|
||||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
|
||||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
|
||||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
|
||||||
|
|
||||||
# mbedtls
|
|
||||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
|
||||||
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
|
|
||||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
|
||||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
|
||||||
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=n
|
|
||||||
CONFIG_MBEDTLS_ERROR_STRINGS=n
|
|
||||||
|
|
||||||
# Fix for Timer Overflows
|
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
|
|
||||||
|
|
||||||
# Decrease Max endpoints
|
|
||||||
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=2
|
|
||||||
|
|
||||||
# Additional configurations
|
|
||||||
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
|
|
||||||
CONFIG_ESP_RMAKER_NO_CLAIM=y
|
|
||||||
CONFIG_ESP_RMAKER_USE_ESP_SECURE_CERT_MGR=y
|
|
||||||
CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN=y
|
|
||||||
|
|
||||||
CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION_LABEL="fctry"
|
|
||||||
CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y
|
|
||||||
CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y
|
|
||||||
CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER=y
|
|
||||||
CONFIG_SEC_CERT_DAC_PROVIDER=y
|
|
||||||
|
|
||||||
# This example only use 2 dynamic endpoints
|
|
||||||
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=2
|
|
||||||
|
|
||||||
# Enable Newlib nano format for flash optimization
|
|
||||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
|
||||||
|
|
||||||
# Flash Optimization
|
|
||||||
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
|
|
||||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
|
||||||
|
|
||||||
# Exclude unused clusters to optimize flash and memory usage
|
|
||||||
CONFIG_SUPPORT_ACCOUNT_LOGIN_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ACTIVATED_CARBON_FILTER_MONITORING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_AIR_QUALITY_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_APPLICATION_BASIC_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_APPLICATION_LAUNCHER_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_AUDIO_OUTPUT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_BOOLEAN_STATE_CONFIGURATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CAMERA_AV_SETTINGS_USER_LEVEL_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CHANNEL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CHIME_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CLOSURE_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CLOSURE_DIMENSION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_COMMISSIONER_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CONTENT_LAUNCHER_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CONTENT_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_CONTENT_APP_OBSERVER_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DEVICE_ENERGY_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DEVICE_ENERGY_MANAGEMENT_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DIAGNOSTIC_LOGS_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DISHWASHER_ALARM_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DISHWASHER_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MICROWAVE_OVEN_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_DOOR_LOCK_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ECOSYSTEM_INFORMATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ELECTRICAL_ENERGY_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ELECTRICAL_POWER_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ENERGY_EVSE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ENERGY_EVSE_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ENERGY_PREFERENCE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_FAN_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_FAULT_INJECTION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_FIXED_LABEL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_FORMALDEHYDE_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_HEPA_FILTER_MONITORING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ICD_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_KEYPAD_INPUT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_LAUNDRY_WASHER_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_LOCALIZATION_CONFIGURATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_LOW_POWER_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MEDIA_INPUT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MEDIA_PLAYBACK_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MICROWAVE_OVEN_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MESSAGES_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_MODE_SELECT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_SAMPLE_MEI_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OCCUPANCY_SENSING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_POWER_TOPOLOGY_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OPERATIONAL_STATE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OPERATIONAL_STATE_OVEN_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OPERATIONAL_STATE_RVC_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OVEN_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_OZONE_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_PM10_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_PM1_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_PM2_5_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_POWER_SOURCE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_POWER_SOURCE_CONFIGURATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_PUMP_CONFIGURATION_AND_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_RADON_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_REFRIGERATOR_ALARM_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_RVC_CLEAN_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_RVC_RUN_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_SERVICE_AREA_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_SMOKE_CO_ALARM_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_SOFTWARE_DIAGNOSTICS_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_SWITCH_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TARGET_NAVIGATOR_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TEMPERATURE_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_THERMOSTAT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_THREAD_NETWORK_DIRECTORY_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TIME_FORMAT_LOCALIZATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TIME_SYNCHRONIZATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TIMER_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_TVOC_CONCENTRATION_MEASUREMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_UNIT_TESTING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_USER_LABEL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_WAKE_ON_LAN_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_LAUNDRY_WASHER_CONTROLS_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_LAUNDRY_DRYER_CONTROLS_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_WIFI_NETWORK_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_WINDOW_COVERING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_WATER_HEATER_MANAGEMENT_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_WATER_HEATER_MODE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_ELECTRICAL_GRID_CONDITIONS_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_COMMODITY_PRICE_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_METER_IDENTIFICATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_UNIT_LOCALIZATION_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_COMMODITY_METERING_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_COMMODITY_TARIFF_CLUSTER=n
|
|
||||||
CONFIG_SUPPORT_PUSH_AV_STREAM_TRANSPORT_CLUSTER=n
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32c3"
|
|
||||||
|
|
||||||
# ESP32-C3-DevKitC-02 Settings
|
|
||||||
# Buttons
|
|
||||||
CONFIG_BSP_BUTTONS_NUM=1
|
|
||||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
|
||||||
CONFIG_BSP_BUTTON_1_GPIO=9
|
|
||||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
|
||||||
# LEDs
|
|
||||||
CONFIG_BSP_LEDS_NUM=1
|
|
||||||
CONFIG_BSP_LED_TYPE_RGB=y
|
|
||||||
CONFIG_BSP_LED_RGB_GPIO=8
|
|
||||||
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
|
|
||||||
|
|
||||||
# Memory Optimization
|
|
||||||
CONFIG_ESP_WIFI_IRAM_OPT=n
|
|
||||||
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
|
|
||||||
CONFIG_ESP_MATTER_MAX_DEVICE_TYPE_COUNT=2
|
|
||||||
CONFIG_ESP_MATTER_BINDING_TABLE_SIZE=1
|
|
||||||
CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=512
|
|
||||||
CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE=256
|
|
||||||
CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE=256
|
|
||||||
CONFIG_MAX_EXCHANGE_CONTEXTS=5
|
|
||||||
CONFIG_MAX_BINDINGS=2
|
|
||||||
CONFIG_MAX_PEER_NODES=8
|
|
||||||
CONFIG_NUM_TCP_ENDPOINTS=1
|
|
||||||
CONFIG_NUM_UDP_ENDPOINTS=6
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32h2"
|
|
||||||
|
|
||||||
# Flash size optimization
|
|
||||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
|
||||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
|
||||||
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
|
|
||||||
|
|
||||||
# Increase IPv6 address number in netif structure
|
|
||||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
|
||||||
|
|
||||||
# Disable Route hook
|
|
||||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=n
|
|
||||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=n
|
|
||||||
|
|
||||||
# Enable OpenThread
|
|
||||||
CONFIG_OPENTHREAD_ENABLED=y
|
|
||||||
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
|
|
||||||
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
|
|
||||||
CONFIG_OPENTHREAD_DNS64_CLIENT=y
|
|
||||||
CONFIG_ENABLE_THREAD_TELEMETRY=y
|
|
||||||
|
|
||||||
# esp_matter::start() will not initialize Thread stack as we initialize it in app_network.
|
|
||||||
CONFIG_ESP_MATTER_ENABLE_OPENTHREAD=n
|
|
||||||
|
|
||||||
# Use platform mDNS
|
|
||||||
CONFIG_USE_MINIMAL_MDNS=n
|
|
||||||
|
|
||||||
# Disable Matter over Wi-Fi
|
|
||||||
CONFIG_ENABLE_WIFI_STATION=n
|
|
||||||
CONFIG_ENABLE_WIFI_TELEMETRY=n
|
|
||||||
|
|
||||||
# Disable ECDSA Peripheral
|
|
||||||
CONFIG_USE_ESP32_ECDSA_PERIPHERAL=n
|
|
||||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
|
||||||
|
|
||||||
# Memory Optimization
|
|
||||||
CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=512
|
|
||||||
CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE=256
|
|
||||||
CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE=256
|
|
||||||
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=2
|
|
||||||
|
|
||||||
# BSP Configuration
|
|
||||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
|
||||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
|
||||||
CONFIG_BSP_BUTTONS_NUM=1
|
|
||||||
CONFIG_BSP_BUTTON_1_GPIO=9
|
|
||||||
CONFIG_BSP_LED_TYPE_RGB=y
|
|
||||||
CONFIG_BSP_LED_RGB_GPIO=8
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
CONFIG_IDF_TARGET="esp32s3"
|
|
||||||
|
|
||||||
# ESP32-S3-DevKitC-1 Settings
|
|
||||||
# Buttons
|
|
||||||
CONFIG_BSP_BUTTONS_NUM=1
|
|
||||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
|
||||||
CONFIG_BSP_BUTTON_1_GPIO=0
|
|
||||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
|
||||||
Reference in New Issue
Block a user