mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
Add app_bridge component and bridge_zigbee app (support on_off light device)
This commit is contained in:
@@ -4,3 +4,5 @@ compile_commands.json
|
|||||||
build/
|
build/
|
||||||
sdkconfig
|
sdkconfig
|
||||||
sdkconfig.old
|
sdkconfig.old
|
||||||
|
dependencies.lock
|
||||||
|
managed_components/
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS "${CMAKE_CURRENT_LIST_DIR}/esp_matter_bridge.cpp"
|
||||||
|
INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}"
|
||||||
|
REQUIRES esp_matter)
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_matter.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <esp_matter_bridge.h>
|
||||||
|
|
||||||
|
static const char *TAG = "esp_matter_bridge";
|
||||||
|
esp_matter_endpoint_bridged_node_config_t bridged_node_config = ENDPOINT_CONFIG_BRIDGED_NODE_DEFAULT();
|
||||||
|
|
||||||
|
esp_matter_bridge_device_t *esp_matter_bridge_create_device(esp_matter_node_t *node)
|
||||||
|
{
|
||||||
|
esp_matter_bridge_device_t *dev = (esp_matter_bridge_device_t *)calloc(1, sizeof(esp_matter_bridge_device_t));
|
||||||
|
dev->node = node;
|
||||||
|
dev->endpoint = esp_matter_endpoint_create_bridged_node(node, &bridged_node_config, ENDPOINT_MASK_DELETABLE);
|
||||||
|
if (!(dev->endpoint)) {
|
||||||
|
ESP_LOGE(TAG, "Could not create esp_matter endpoint for bridged device");
|
||||||
|
free(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dev->endpoint_id = esp_matter_endpoint_get_id(dev->endpoint);
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_device)
|
||||||
|
{
|
||||||
|
if (!bridged_device) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
esp_err_t error = esp_matter_endpoint_delete(bridged_device->node, bridged_device->endpoint);
|
||||||
|
if (error != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to delete bridged endpoint");
|
||||||
|
}
|
||||||
|
free(bridged_device);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
|
||||||
|
#include <esp_err.h>
|
||||||
|
#include <esp_matter_core.h>
|
||||||
|
|
||||||
|
#define MAX_BRIDGED_DEVICE_COUNT CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT - 1
|
||||||
|
// There is an endpoint reserved as root endpoint
|
||||||
|
|
||||||
|
typedef struct esp_matter_bridge_device {
|
||||||
|
esp_matter_node_t *node;
|
||||||
|
esp_matter_endpoint_t *endpoint;
|
||||||
|
int endpoint_id;
|
||||||
|
} esp_matter_bridge_device_t;
|
||||||
|
|
||||||
|
esp_matter_bridge_device_t *esp_matter_bridge_create_device(esp_matter_node_t *node);
|
||||||
|
|
||||||
|
esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_device);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# 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})
|
||||||
|
|
||||||
|
if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
|
||||||
|
if("${IDF_TARGET}" STREQUAL "esp32" OR "${IDF_TARGET}" STREQUAL "")
|
||||||
|
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32_devkit_c)
|
||||||
|
elseif("${IDF_TARGET}" STREQUAL "esp32c3")
|
||||||
|
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c3_devkit_m)
|
||||||
|
elseif("${IDF_TARGET}" STREQUAL "esp32s2")
|
||||||
|
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32s2_devkit_c)
|
||||||
|
elseif("${IDF_TARGET}" STREQUAL "esp32s3")
|
||||||
|
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32s3_devkit_c)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unsupported IDF_TARGET")
|
||||||
|
endif()
|
||||||
|
endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
|
||||||
|
|
||||||
|
set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH})
|
||||||
|
set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip)
|
||||||
|
set(ZAP_GENERATED_PATH ${CMAKE_CURRENT_LIST_DIR}/main/zap-generated)
|
||||||
|
|
||||||
|
# This should be done before using the IDF_TARGET variable.
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake)
|
||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS
|
||||||
|
"../common"
|
||||||
|
"${IDF_PATH}/examples/common_components/qrcode"
|
||||||
|
"${MATTER_SDK_PATH}/config/esp32/components"
|
||||||
|
"${ESP_MATTER_PATH}/components"
|
||||||
|
"${ESP_MATTER_PATH}/device_hal/device"
|
||||||
|
${extra_components_dirs_append})
|
||||||
|
|
||||||
|
project(bridge_zigbee)
|
||||||
|
|
||||||
|
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++14;-Os;-DLWIP_IPV6_SCOPES=0;-DCHIP_HAVE_CONFIG_H;-fpermissive" APPEND)
|
||||||
|
idf_build_set_property(C_COMPILE_OPTIONS "-Os;-DLWIP_IPV6_SCOPES=0" 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)
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# Bridge Example
|
||||||
|
|
||||||
|
## Building and Flashing the Firmware
|
||||||
|
|
||||||
|
This example should be built on IDF commit [b05b70c7f3](https://github.com/espressif/esp-idf/tree/b05b70c7f39a45b9bb8d09498b45edbe3b7bfc22)
|
||||||
|
|
||||||
|
See the [README.md](../../README.md) file for more information about building and flashing the firmware.
|
||||||
|
|
||||||
|
The Matter Bridge device is composed of two parts: The RCP running on ESP32-H2 and the bridge app
|
||||||
|
running on ESP32.
|
||||||
|
|
||||||
|
### Hardware connection
|
||||||
|
|
||||||
|
Connect the two SoCs via UART, below is an example setup with ESP32 DevKitC and ESP32-H2 DevKitC:
|
||||||
|
|
||||||
|
ESP32 Pin | ESP32-H2 Pin
|
||||||
|
-------------|--------------
|
||||||
|
GND | GND
|
||||||
|
GPIO4 | GPIO7
|
||||||
|
GPIO5 | GPIO8
|
||||||
|
|
||||||
|
### Build and flash the RCP (ESP32-H2)
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd ${IDF_PATH}/examples/zigbee/esp_zigbee_rcp/
|
||||||
|
$ idf.py --preview set-target esp32h2
|
||||||
|
$ idf.py -p <port> build flash
|
||||||
|
```
|
||||||
|
|
||||||
|
The Matter Bridge app will run on the ESP32 and ZigBee network will be formed.
|
||||||
|
|
||||||
|
## Build chip-tool and provision the Matter Bridge device
|
||||||
|
|
||||||
|
Open a new terminal window and active matter environment
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd esp-matter/connectedhomeip/connectedhomeip/examples/chip-tool
|
||||||
|
$ gn gen out
|
||||||
|
$ ninja -C out
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can provision the Matter Bridge device with `./out/chip-tool` (Please ensure that your PC
|
||||||
|
and the bridge device are on the same local network).
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./out/chip-tool pairing ble-wifi 12344321 {wifi-ssid} {wifi-password} 20202021 3840
|
||||||
|
```
|
||||||
|
|
||||||
|
After Provisioning success, you can read the parts list in Bridge app to get the number of the bridged devices.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./out/chip-tool descriptor read parts-list 12344321 0
|
||||||
|
```
|
||||||
|
|
||||||
|
If there is no other ZigBee device on the ZigBee Network, you will get an empty result.
|
||||||
|
|
||||||
|
```
|
||||||
|
[1639378931.513638][1808055:1808060] CHIP:DMG: Data = [
|
||||||
|
[1639378931.513641][1808055:1808060] CHIP:DMG:
|
||||||
|
[1639378931.513645][1808055:1808060] CHIP:DMG: ],
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup ZigBee Bulb on ESP32-H2
|
||||||
|
|
||||||
|
Build and run ZigBee Bulb app on another ESP32-H2 board. Open another terminal window and repeat Step 2 again.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd ${IDF_PATH}/examples/zigbee/light_sample/light_bulb
|
||||||
|
$ idf.py --preview set-target esp32h2
|
||||||
|
$ idf.py -p <port> build flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
The Zigbee Bulb will be added to the ZigBee Network and a dynamic endpoint will be added on the Bridge device. You can read the parts list again to get the dynamic endpoint ID.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./out/chip-tool descriptor read parts-list 12344321 0
|
||||||
|
...
|
||||||
|
[1639379769.737877][1809119:1809124] CHIP:DMG: Data = [
|
||||||
|
[1639379769.737881][1809119:1809124] CHIP:DMG: 1,
|
||||||
|
[1639379769.737885][1809119:1809124] CHIP:DMG: ],
|
||||||
|
```
|
||||||
|
|
||||||
|
It means that the ZigBee Bulb is added as Endpoint 1 on the Bridge device. You can read the cluster servers list on the dynamic endpoint.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./out/chip-tool descriptor read server-list 12344321 1
|
||||||
|
...
|
||||||
|
[1639380020.748687][1809427:1809432] CHIP:TOO: OnDescriptorServerListListAttributeResponse: 4 entries
|
||||||
|
[1639380020.748695][1809427:1809432] CHIP:TOO: [1]: 6
|
||||||
|
[1639380020.748699][1809427:1809432] CHIP:TOO: [2]: 29
|
||||||
|
[1639380020.748703][1809427:1809432] CHIP:TOO: [3]: 57
|
||||||
|
[1639380020.748706][1809427:1809432] CHIP:TOO: [4]: 64
|
||||||
|
```
|
||||||
|
|
||||||
|
## Control the bulb with chip-tool
|
||||||
|
|
||||||
|
Now you can control the ZigBee bulb on chip tool.
|
||||||
|
```
|
||||||
|
$ ./out/chip-tool onoff toggle 12344321 1
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
set(PRIV_REQUIRES_LIST device esp_matter esp_matter_console route_hook app_qrcode esp_matter_ota app_bridge esp-zboss-lib)
|
||||||
|
|
||||||
|
idf_component_register(SRC_DIRS "."
|
||||||
|
PRIV_INCLUDE_DIRS "."
|
||||||
|
PRIV_REQUIRES ${PRIV_REQUIRES_LIST})
|
||||||
|
|
||||||
|
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14)
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE "-DLWIP_IPV6_SCOPES=0" "-DCHIP_HAVE_CONFIG_H")
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
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_console.h>
|
||||||
|
#include <esp_matter_ota.h>
|
||||||
|
#include <esp_route_hook.h>
|
||||||
|
|
||||||
|
#include <app_bridge_zigbee_device.h>
|
||||||
|
#include <app_qrcode.h>
|
||||||
|
#include <app_zboss.h>
|
||||||
|
|
||||||
|
#include "zigbee_bridge.h"
|
||||||
|
static const char *TAG = "app_main";
|
||||||
|
|
||||||
|
static esp_matter_node_config_t node_config = NODE_CONFIG_DEFAULT();
|
||||||
|
|
||||||
|
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
||||||
|
{
|
||||||
|
if (event->Type == chip::DeviceLayer::DeviceEventType::PublicEventTypes::kInterfaceIpAddressChanged) {
|
||||||
|
chip::app::DnssdServer::Instance().StartServer();
|
||||||
|
esp_route_hook_init(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Current free heap: %zu", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id,
|
||||||
|
int attribute_id, esp_matter_attr_val_t val, void *priv_data)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
if (type == ESP_MATTER_CALLBACK_TYPE_PRE_ATTRIBUTE) {
|
||||||
|
err = zigbee_bridge_attribute_update(endpoint_id, cluster_id, attribute_id, val);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void app_main()
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
/* Initialize the ESP NVS layer */
|
||||||
|
nvs_flash_init();
|
||||||
|
|
||||||
|
/* Create matter device */
|
||||||
|
esp_matter_node_t *node = esp_matter_node_create(&node_config, app_attribute_update_cb, NULL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
These node and endpoint handles can be used to create and add other endpoints and other clusters to the endpoints.
|
||||||
|
*/
|
||||||
|
if (!node) {
|
||||||
|
ESP_LOGE(TAG, "Matter device creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Matter start */
|
||||||
|
err = esp_matter_start(app_event_cb);
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Matter start failed: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
app_qrcode_print();
|
||||||
|
|
||||||
|
#if CONFIG_ENABLE_CHIP_SHELL
|
||||||
|
esp_matter_console_diagnostics_register_commands();
|
||||||
|
esp_matter_console_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_ENABLE_OTA_REQUESTOR
|
||||||
|
esp_matter_ota_requestor_init();
|
||||||
|
#endif
|
||||||
|
launch_app_zboss();
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
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 "zigbee_bridge.h"
|
||||||
|
#include <app_zboss.h>
|
||||||
|
#include <esp_err.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <zboss_api.h>
|
||||||
|
|
||||||
|
#if (!defined ZB_MACSPLIT_HOST)
|
||||||
|
#error "Zigbee host option should be enabled to use this example"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *TAG = "esp_zboss";
|
||||||
|
|
||||||
|
static void bdb_start_top_level_commissioning_cb(zb_uint8_t mode_mask)
|
||||||
|
{
|
||||||
|
if (!bdb_start_top_level_commissioning(mode_mask)) {
|
||||||
|
ESP_LOGE(TAG, "In BDB commissioning, an error occurred (for example: the device has already been running)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Zigbee stack event handler.
|
||||||
|
*
|
||||||
|
* @param bufid Reference to the Zigbee stack buffer used to pass signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void zboss_signal_handler(zb_bufid_t bufid)
|
||||||
|
{
|
||||||
|
// Read signal desription
|
||||||
|
zb_zdo_app_signal_hdr_t *p_sg_p = NULL;
|
||||||
|
zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &p_sg_p);
|
||||||
|
zb_ret_t status = ZB_GET_APP_SIGNAL_STATUS(bufid);
|
||||||
|
zb_zdo_signal_device_annce_params_t *device_annce_params = NULL;
|
||||||
|
|
||||||
|
switch (sig) {
|
||||||
|
case ZB_ZDO_SIGNAL_SKIP_STARTUP:
|
||||||
|
ESP_LOGI(TAG, "Zigbee stack initialized");
|
||||||
|
bdb_start_top_level_commissioning(ZB_BDB_INITIALIZATION);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZB_MACSPLIT_DEVICE_BOOT:
|
||||||
|
ESP_LOGI(TAG, "Zigbee rcp device booted");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
|
||||||
|
if (status == RET_OK) {
|
||||||
|
ESP_LOGI(TAG, "Start network formation");
|
||||||
|
bdb_start_top_level_commissioning(ZB_BDB_NETWORK_FORMATION);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize Zigbee stack (status: %d)", status);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZB_BDB_SIGNAL_FORMATION:
|
||||||
|
if (status == RET_OK) {
|
||||||
|
zb_ieee_addr_t ieee_address;
|
||||||
|
zb_get_long_address(ieee_address);
|
||||||
|
ESP_LOGI(TAG, "Formed network successfully");
|
||||||
|
ESP_LOGI(TAG, "ieee extended address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx)",
|
||||||
|
ieee_address[7], ieee_address[6], ieee_address[5], ieee_address[4], ieee_address[3],
|
||||||
|
ieee_address[2], ieee_address[1], ieee_address[0], ZB_PIBCACHE_PAN_ID());
|
||||||
|
bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "Restart network formation (status: %d)", status);
|
||||||
|
ZB_SCHEDULE_APP_ALARM((zb_callback_t)bdb_start_top_level_commissioning_cb, ZB_BDB_NETWORK_FORMATION,
|
||||||
|
ZB_TIME_ONE_SECOND);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZB_BDB_SIGNAL_STEERING:
|
||||||
|
if (status == RET_OK) {
|
||||||
|
ESP_LOGI(TAG, "Network steering started");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZB_ZDO_SIGNAL_DEVICE_ANNCE:
|
||||||
|
device_annce_params = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_device_annce_params_t);
|
||||||
|
ESP_LOGI(TAG, "New device commissioned or rejoined (short: 0x%04hx)", device_annce_params->device_short_addr);
|
||||||
|
status =
|
||||||
|
ZB_SCHEDULE_APP_ALARM(zigbee_bridge_match_bridged_onoff_light, bufid, MATCH_BRIDGED_DEVICE_START_DELAY);
|
||||||
|
if (status != RET_OK) {
|
||||||
|
ESP_LOGD(TAG, "Could not start schedule alarm for matching bridged device");
|
||||||
|
}
|
||||||
|
status =
|
||||||
|
ZB_SCHEDULE_APP_ALARM(zigbee_bridge_match_bridged_onoff_light_timeout, bufid, MATCH_BRIDGED_DEVICE_TIMEOUT);
|
||||||
|
if (status != RET_OK) {
|
||||||
|
ESP_LOGD(TAG, "Could not start schedule alarm for matching bridged device timeout");
|
||||||
|
}
|
||||||
|
// this buf will be free in zboss_match_bridged_device_callback/zboss_match_bridged_device_timeout later
|
||||||
|
bufid = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGI(TAG, "status: %d", status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* All callbacks should either reuse or free passed buffers. If bufid == 0, the buffer is invalid (not passed) */
|
||||||
|
if (bufid) {
|
||||||
|
zb_buf_free(bufid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zboss_task()
|
||||||
|
{
|
||||||
|
ZB_INIT("bridge zigbee");
|
||||||
|
zb_set_network_coordinator_role(IEEE_CHANNEL_MASK);
|
||||||
|
zb_set_nvram_erase_at_start(ERASE_PERSISTENT_CONFIG);
|
||||||
|
zb_set_max_children(MAX_CHILDREN);
|
||||||
|
/* initiate Zigbee Stack start without zb_send_no_autostart_signal auto-start */
|
||||||
|
ESP_ERROR_CHECK(zboss_start_no_autostart());
|
||||||
|
while (1) {
|
||||||
|
zboss_main_loop_iteration();
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void launch_app_zboss(void)
|
||||||
|
{
|
||||||
|
zb_esp_platform_config_t config = {
|
||||||
|
.radio_config = ZB_ESP_DEFAULT_RADIO_CONFIG(),
|
||||||
|
.host_config = ZB_ESP_DEFAULT_HOST_CONFIG(),
|
||||||
|
};
|
||||||
|
/* load Zigbee gateway platform config to initialization */
|
||||||
|
ESP_ERROR_CHECK(zb_esp_platform_config(&config));
|
||||||
|
xTaskCreate(zboss_task, "zboss_main", 10240, xTaskGetCurrentTaskHandle(), 5, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <zigbee_bridge.h>
|
||||||
|
|
||||||
|
/*Zigbee Configuration*/
|
||||||
|
#define IEEE_CHANNEL_MASK (1l << 22) /**< ZigBee default channel */
|
||||||
|
#define ERASE_PERSISTENT_CONFIG ZB_TRUE /**< Full device erase for all network devices before running example. */
|
||||||
|
#define MAX_CHILDREN 10 /**< The maximum amount of connected devices */
|
||||||
|
|
||||||
|
#define MATCH_DESC_REQ_ROLE ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE
|
||||||
|
#define MATCH_BRIDGED_DEVICE_START_DELAY (2 * ZB_TIME_ONE_SECOND)
|
||||||
|
#define MATCH_BRIDGED_DEVICE_TIMEOUT (5 * ZB_TIME_ONE_SECOND)
|
||||||
|
|
||||||
|
#define ZB_ESP_DEFAULT_RADIO_CONFIG() \
|
||||||
|
{ \
|
||||||
|
.radio_mode = RADIO_MODE_UART_RCP, \
|
||||||
|
.radio_uart_config = { \
|
||||||
|
.port = 1, \
|
||||||
|
.uart_config = \
|
||||||
|
{ \
|
||||||
|
.baud_rate = 115200, \
|
||||||
|
.data_bits = UART_DATA_8_BITS, \
|
||||||
|
.parity = UART_PARITY_DISABLE, \
|
||||||
|
.stop_bits = UART_STOP_BITS_1, \
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
|
||||||
|
.rx_flow_ctrl_thresh = 0, \
|
||||||
|
.source_clk = UART_SCLK_APB, \
|
||||||
|
}, \
|
||||||
|
.rx_pin = 4, \
|
||||||
|
.tx_pin = 5, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ZB_ESP_DEFAULT_HOST_CONFIG() \
|
||||||
|
{ \
|
||||||
|
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
|
||||||
|
}
|
||||||
|
|
||||||
|
void launch_app_zboss(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
espressif/esp-zboss-lib: "~=0.0.4"
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: ">=5.0.0"
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Project CHIP Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY ZAP
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <esp_matter_cluster.h>
|
||||||
|
|
||||||
|
#define MATTER_PLUGINS_INIT esp_matter_cluster_plugin_init_callback_common();
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Project CHIP Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Silicon Labs
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
// This file is generated by Simplicity Studio. Please do not edit manually.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
// Enclosing macro to prevent multiple inclusion
|
||||||
|
#ifndef __AF_GEN_EVENT__
|
||||||
|
#define __AF_GEN_EVENT__
|
||||||
|
|
||||||
|
// Code used to configure the cluster event mechanism
|
||||||
|
#define EMBER_AF_GENERATED_EVENT_CODE \
|
||||||
|
EmberEventControl emberAfLevelControlClusterServerTickCallbackControl1; \
|
||||||
|
static void clusterTickWrapper(EmberEventControl * control, EmberAfTickFunction callback, uint8_t endpoint) \
|
||||||
|
{ \
|
||||||
|
/* emberAfPushEndpointNetworkIndex(endpoint); */ \
|
||||||
|
emberEventControlSetInactive(control); \
|
||||||
|
(*callback)(endpoint); \
|
||||||
|
/* emberAfPopNetworkIndex(); */ \
|
||||||
|
} \
|
||||||
|
void emberAfLevelControlClusterServerTickCallbackWrapperFunction1(void) \
|
||||||
|
{ \
|
||||||
|
clusterTickWrapper(&emberAfLevelControlClusterServerTickCallbackControl1, emberAfLevelControlClusterServerTickCallback, \
|
||||||
|
1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmberEventData structs used to populate the EmberEventData table
|
||||||
|
#define EMBER_AF_GENERATED_EVENTS \
|
||||||
|
{ &emberAfLevelControlClusterServerTickCallbackControl1, emberAfLevelControlClusterServerTickCallbackWrapperFunction1 },
|
||||||
|
|
||||||
|
#define EMBER_AF_GENERATED_EVENT_STRINGS "Level Control Cluster Server EP 1",
|
||||||
|
|
||||||
|
// The length of the event context table used to track and retrieve cluster events
|
||||||
|
#define EMBER_AF_EVENT_CONTEXT_LENGTH 1
|
||||||
|
|
||||||
|
// EmberAfEventContext structs used to populate the EmberAfEventContext table
|
||||||
|
#define EMBER_AF_GENERATED_EVENT_CONTEXT \
|
||||||
|
{ 0x1, 0x8, false, EMBER_AF_LONG_POLL, EMBER_AF_OK_TO_SLEEP, &emberAfLevelControlClusterServerTickCallbackControl1 },
|
||||||
|
|
||||||
|
#endif // __AF_GEN_EVENT__
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Project CHIP Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY ZAP
|
||||||
|
|
||||||
|
// Prevent multiple inclusion
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define GENERATED_ATTRIBUTES \
|
||||||
|
{}
|
||||||
|
|
||||||
|
#define GENERATED_CLUSTERS \
|
||||||
|
{}
|
||||||
|
|
||||||
|
#define GENERATED_ENDPOINT_TYPES \
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Largest attribute size is needed for various buffers
|
||||||
|
#define ATTRIBUTE_LARGEST (401)
|
||||||
|
|
||||||
|
// Total size of attribute storage
|
||||||
|
#define ATTRIBUTE_MAX_SIZE (0)
|
||||||
|
|
||||||
|
// Number of fixed endpoints
|
||||||
|
#define FIXED_ENDPOINT_COUNT (0)
|
||||||
|
#ifdef CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT
|
||||||
|
#undef CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT
|
||||||
|
#endif
|
||||||
|
#define CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT (16)
|
||||||
|
|
||||||
|
// Array of endpoints that are supported, the data inside
|
||||||
|
// the array is the endpoint number.
|
||||||
|
#define FIXED_ENDPOINT_ARRAY \
|
||||||
|
{0}
|
||||||
|
|
||||||
|
// Array of profile ids
|
||||||
|
#define FIXED_PROFILE_IDS \
|
||||||
|
{0}
|
||||||
|
|
||||||
|
// Array of device ids
|
||||||
|
#define FIXED_DEVICE_IDS \
|
||||||
|
{0}
|
||||||
|
|
||||||
|
// Array of device versions
|
||||||
|
#define FIXED_DEVICE_VERSIONS \
|
||||||
|
{0}
|
||||||
|
|
||||||
|
// Array of endpoint types supported on each endpoint
|
||||||
|
#define FIXED_ENDPOINT_TYPES \
|
||||||
|
{0}
|
||||||
|
|
||||||
|
// Array of networks supported on each endpoint
|
||||||
|
#define FIXED_NETWORKS \
|
||||||
|
{0}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
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_matter_bridge.h"
|
||||||
|
#include <esp_check.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_matter.h>
|
||||||
|
|
||||||
|
#include <app_bridge_zigbee_device.h>
|
||||||
|
#include <app_zboss.h>
|
||||||
|
#include <esp_matter_core.h>
|
||||||
|
#include <zboss_api_buf.h>
|
||||||
|
#include <zigbee_bridge.h>
|
||||||
|
|
||||||
|
static const char *TAG = "zigbee_bridge";
|
||||||
|
|
||||||
|
static esp_matter_cluster_on_off_config_t on_off_config = CLUSTER_CONFIG_ON_OFF_DEFAULT();
|
||||||
|
|
||||||
|
static esp_err_t init_bridged_onoff_light(esp_matter_bridge_device_t *dev)
|
||||||
|
{
|
||||||
|
if (!dev) {
|
||||||
|
ESP_LOGE(TAG, "Invalid bridge device to be initialized");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
esp_matter_cluster_create_on_off(dev->endpoint, &on_off_config, CLUSTER_MASK_SERVER);
|
||||||
|
if (esp_matter_endpoint_enable(dev->endpoint) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "ESP Matter enable dynamic endpoint failed");
|
||||||
|
esp_matter_endpoint_delete(dev->node, dev->endpoint);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zigbee_bridge_match_bridged_onoff_light_cb(zb_bufid_t bufid)
|
||||||
|
{
|
||||||
|
zb_zdo_match_desc_resp_t *p_resp = (zb_zdo_match_desc_resp_t *)zb_buf_begin(bufid);
|
||||||
|
zb_apsde_data_indication_t *p_ind = ZB_BUF_GET_PARAM(bufid, zb_apsde_data_indication_t);
|
||||||
|
zb_uint8_t *p_match_ep;
|
||||||
|
zb_ret_t zb_err_code;
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
if ((p_resp->status == ZB_ZDP_STATUS_SUCCESS) && (p_resp->match_len > 0)) {
|
||||||
|
p_match_ep = (zb_uint8_t *)(p_resp + 1);
|
||||||
|
esp_matter_node_t *node = esp_matter_node_get();
|
||||||
|
ESP_GOTO_ON_FALSE(node, ESP_ERR_INVALID_STATE, exit, TAG, "Could not find esp_matter node");
|
||||||
|
if (app_bridge_get_zigbee_device_by_zigbee_shortaddr(p_ind->src_addr)) {
|
||||||
|
ESP_LOGI(TAG, "Bridged node for 0x%04x zigbee device on endpoint %d has been created", p_ind->src_addr,
|
||||||
|
app_bridge_get_matter_endpointid_by_zigbee_shortaddr(p_ind->src_addr));
|
||||||
|
} else {
|
||||||
|
app_bridge_zigbee_device_t *dev = app_bridge_create_zigbee_device(node, *p_match_ep, p_ind->src_addr);
|
||||||
|
ESP_GOTO_ON_FALSE(dev, ESP_FAIL, exit, TAG, "Failed to create zigbee bridged device (on_off light)");
|
||||||
|
ESP_GOTO_ON_ERROR(init_bridged_onoff_light(dev->dev), exit, TAG, "Failed to initialize the bridged node");
|
||||||
|
ESP_LOGI(TAG, "Create/Update bridged node for 0x%04x zigbee device on endpoint %d", p_ind->src_addr,
|
||||||
|
app_bridge_get_matter_endpointid_by_zigbee_shortaddr(p_ind->src_addr));
|
||||||
|
}
|
||||||
|
zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(zigbee_bridge_match_bridged_onoff_light_timeout, ZB_ALARM_ANY_PARAM);
|
||||||
|
if (zb_err_code != RET_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to cancel alarm for match_bridged_device_timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
if (bufid) {
|
||||||
|
zb_buf_free(bufid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zigbee_bridge_match_bridged_onoff_light(zb_bufid_t bufid)
|
||||||
|
{
|
||||||
|
zb_zdo_match_desc_param_t *p_req;
|
||||||
|
|
||||||
|
zb_zdo_app_signal_hdr_t *p_sg_p = NULL;
|
||||||
|
zb_get_app_signal(bufid, &p_sg_p);
|
||||||
|
zb_zdo_signal_device_annce_params_t *dev_annce_params =
|
||||||
|
ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_device_annce_params_t);
|
||||||
|
|
||||||
|
zb_uint16_t shortaddr = dev_annce_params->device_short_addr;
|
||||||
|
p_req = (zb_zdo_match_desc_param_t *)zb_buf_initial_alloc(
|
||||||
|
bufid, sizeof(zb_zdo_match_desc_param_t) + (1) * sizeof(zb_uint16_t));
|
||||||
|
p_req->nwk_addr = shortaddr;
|
||||||
|
p_req->addr_of_interest = shortaddr;
|
||||||
|
p_req->profile_id = ZB_AF_HA_PROFILE_ID;
|
||||||
|
|
||||||
|
p_req->num_in_clusters = 1;
|
||||||
|
p_req->num_out_clusters = 0;
|
||||||
|
p_req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_ON_OFF;
|
||||||
|
|
||||||
|
zb_zdo_match_desc_req(bufid, zigbee_bridge_match_bridged_onoff_light_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zigbee_bridge_match_bridged_onoff_light_timeout(zb_bufid_t bufid)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "The device is not an onoff light");
|
||||||
|
if (bufid) {
|
||||||
|
zb_buf_free(bufid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zigbee_bridge_send_on(zb_uint8_t buf, zb_uint16_t zigbee_shortaddr)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *dev = app_bridge_get_zigbee_device_by_zigbee_shortaddr(zigbee_shortaddr);
|
||||||
|
ZB_ZCL_ON_OFF_SEND_REQ(buf, zigbee_shortaddr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, dev->zigbee_endpointid,
|
||||||
|
dev->dev->endpoint_id, ZB_AF_HA_PROFILE_ID, ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
|
||||||
|
ZB_ZCL_CMD_ON_OFF_ON_ID, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zigbee_bridge_send_off(zb_uint8_t buf, zb_uint16_t zigbee_shortaddr)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *dev = app_bridge_get_zigbee_device_by_zigbee_shortaddr(zigbee_shortaddr);
|
||||||
|
ZB_ZCL_ON_OFF_SEND_REQ(buf, zigbee_shortaddr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, dev->zigbee_endpointid,
|
||||||
|
dev->dev->endpoint_id, ZB_AF_HA_PROFILE_ID, ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
|
||||||
|
ZB_ZCL_CMD_ON_OFF_OFF_ID, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *zigbee_device = app_bridge_get_zigbee_device_by_matter_endpointid(endpoint_id);
|
||||||
|
if (zigbee_device && zigbee_device->dev && zigbee_device->dev->endpoint) {
|
||||||
|
if (cluster_id == ZCL_ON_OFF_CLUSTER_ID) {
|
||||||
|
if (attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) {
|
||||||
|
zb_buf_get_out_delayed_ext((val.val.b ? zigbee_bridge_send_on : zigbee_bridge_send_off),
|
||||||
|
zigbee_device->zigbee_shortaddr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <esp_matter_attribute.h>
|
||||||
|
#include <zboss_api.h>
|
||||||
|
#include <zboss_api_zcl.h>
|
||||||
|
|
||||||
|
#include <zb_ha.h>
|
||||||
|
|
||||||
|
void zigbee_bridge_match_bridged_onoff_light(zb_bufid_t bufid);
|
||||||
|
|
||||||
|
void zigbee_bridge_match_bridged_onoff_light_timeout(zb_bufid_t bufid);
|
||||||
|
|
||||||
|
esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# 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
|
||||||
|
sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition
|
||||||
|
nvs, data, nvs, 0x10000, 0x6000,
|
||||||
|
otadata, data, ota, , 0x2000
|
||||||
|
phy_init, data, phy, , 0x1000,
|
||||||
|
ota_0, app, ota_0, 0x20000, 0x1D0000,
|
||||||
|
ota_1, app, ota_1, , 0x1D0000,
|
||||||
|
fctry, data, nvs, , 0x6000,
|
||||||
|
zb_storage, data, fat, , 0x20000
|
||||||
|
@@ -0,0 +1,35 @@
|
|||||||
|
# Default to 921600 baud when flashing and monitoring device
|
||||||
|
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||||
|
CONFIG_ESPTOOLPY_BAUD=921600
|
||||||
|
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
|
||||||
|
#enable BT
|
||||||
|
CONFIG_BT_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_TASK_STACK_SIZE=5120
|
||||||
|
|
||||||
|
#enable lwip ipv6 autoconfig
|
||||||
|
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||||
|
|
||||||
|
# Use a custom partition table
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Watchdog
|
||||||
|
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
|
||||||
|
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n
|
||||||
|
|
||||||
|
# Zboss
|
||||||
|
CONFIG_ZB_ENABLED=y
|
||||||
|
CONFIG_ZB_ZCZR=y
|
||||||
|
CONFIG_ZB_HOST=y
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Default to 921600 baud when flashing and monitoring device
|
||||||
|
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||||
|
CONFIG_ESPTOOLPY_BAUD=921600
|
||||||
|
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
|
||||||
|
#enable BT
|
||||||
|
CONFIG_BT_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_TASK_STACK_SIZE=5120
|
||||||
|
|
||||||
|
#enable lwip ipv6 autoconfig
|
||||||
|
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||||
|
|
||||||
|
# Use a custom partition table
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Watchdog
|
||||||
|
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
|
||||||
|
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n
|
||||||
|
|
||||||
|
# Zboss
|
||||||
|
CONFIG_ZB_ENABLED=y
|
||||||
|
CONFIG_ZB_ZCZR=y
|
||||||
|
CONFIG_ZB_HOST=y
|
||||||
|
|
||||||
|
# System event stack size
|
||||||
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
if(CONFIG_ZB_ENABLED)
|
||||||
|
set(srcs app_bridge_zigbee_device.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS "${srcs}"
|
||||||
|
INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}"
|
||||||
|
REQUIRES esp_matter_bridge)
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_matter.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <app_bridge_zigbee_device.h>
|
||||||
|
|
||||||
|
static const char *TAG = "esp_matter_bridge_zigbee";
|
||||||
|
static app_bridge_zigbee_device_t *device_list = NULL;
|
||||||
|
static uint8_t current_bridged_device_count = 0;
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_create_zigbee_device(esp_matter_node_t *node, uint8_t zigbee_endpointid,
|
||||||
|
uint16_t zigbee_shortaddr)
|
||||||
|
{
|
||||||
|
if (current_bridged_device_count >= MAX_BRIDGED_DEVICE_COUNT) {
|
||||||
|
ESP_LOGE(TAG, "The device list is full, Could not add a zigbee bridged device");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
app_bridge_zigbee_device_t *new_dev = (app_bridge_zigbee_device_t *)calloc(1, sizeof(app_bridge_zigbee_device_t));
|
||||||
|
new_dev->dev = esp_matter_bridge_create_device(node);
|
||||||
|
if (!(new_dev->dev)) {
|
||||||
|
ESP_LOGE(TAG, "Failed to create the basic bridged device");
|
||||||
|
free(new_dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
new_dev->zigbee_shortaddr = zigbee_shortaddr;
|
||||||
|
new_dev->zigbee_endpointid = zigbee_endpointid;
|
||||||
|
new_dev->next = device_list;
|
||||||
|
device_list = new_dev;
|
||||||
|
current_bridged_device_count++;
|
||||||
|
return new_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t app_bridge_get_zigbee_shortaddr_by_matter_endpointid(int matter_endpointid)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *current_dev = device_list;
|
||||||
|
while (current_dev) {
|
||||||
|
if (current_dev->dev && (current_dev->dev->endpoint_id == matter_endpointid)) {
|
||||||
|
return current_dev->zigbee_shortaddr;
|
||||||
|
}
|
||||||
|
current_dev = current_dev->next;
|
||||||
|
}
|
||||||
|
return 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_bridge_get_matter_endpointid_by_zigbee_shortaddr(uint16_t zigbee_shortaddr)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *current_dev = device_list;
|
||||||
|
while (current_dev) {
|
||||||
|
if (current_dev->zigbee_shortaddr == zigbee_shortaddr && current_dev->dev) {
|
||||||
|
return current_dev->dev->endpoint_id;
|
||||||
|
}
|
||||||
|
current_dev = current_dev->next;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_get_zigbee_device_by_matter_endpointid(int matter_endpointid)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *current_dev = device_list;
|
||||||
|
while (current_dev) {
|
||||||
|
if (current_dev->dev && (current_dev->dev->endpoint_id == matter_endpointid)) {
|
||||||
|
return current_dev;
|
||||||
|
}
|
||||||
|
current_dev = current_dev->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_get_zigbee_device_by_zigbee_shortaddr(uint16_t zigbee_shortaddr)
|
||||||
|
{
|
||||||
|
app_bridge_zigbee_device_t *current_dev = device_list;
|
||||||
|
while (current_dev) {
|
||||||
|
if (current_dev->zigbee_shortaddr == zigbee_shortaddr && current_dev->dev) {
|
||||||
|
return current_dev;
|
||||||
|
}
|
||||||
|
current_dev = current_dev->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t app_bridge_remove_zigbee_device(app_bridge_zigbee_device_t *bridged_device)
|
||||||
|
{
|
||||||
|
esp_err_t error = ESP_OK;
|
||||||
|
app_bridge_zigbee_device_t *current_dev = NULL;
|
||||||
|
if (!bridged_device) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (device_list == bridged_device) {
|
||||||
|
// the delete bridged device is on the head of device list
|
||||||
|
device_list = bridged_device->next;
|
||||||
|
} else {
|
||||||
|
current_dev = device_list;
|
||||||
|
while (current_dev && current_dev->next) {
|
||||||
|
if (current_dev->next == bridged_device) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_dev = current_dev->next;
|
||||||
|
}
|
||||||
|
if (current_dev->next == bridged_device) {
|
||||||
|
current_dev->next = bridged_device->next;
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error = esp_matter_bridge_remove_device(bridged_device->dev);
|
||||||
|
if (error != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to delete basic bridged devie");
|
||||||
|
}
|
||||||
|
free(bridged_device);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#if CONFIG_ZB_ENABLED
|
||||||
|
#include <esp_matter_bridge.h>
|
||||||
|
|
||||||
|
typedef struct app_bridge_zigbee_device {
|
||||||
|
esp_matter_bridge_device_t *dev;
|
||||||
|
uint8_t zigbee_endpointid;
|
||||||
|
uint16_t zigbee_shortaddr;
|
||||||
|
struct app_bridge_zigbee_device *next;
|
||||||
|
} app_bridge_zigbee_device_t;
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_create_zigbee_device(esp_matter_node_t *node, uint8_t zigbee_endpointid,
|
||||||
|
uint16_t zigbee_shortaddr);
|
||||||
|
|
||||||
|
uint16_t app_bridge_get_zigbee_shortaddr_by_matter_endpointid(int matter_endpointid);
|
||||||
|
|
||||||
|
int app_bridge_get_matter_endpointid_by_zigbee_shortaddr(uint16_t zigbee_shortaddr);
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_get_zigbee_device_by_matter_endpointid(int matter_endpointid);
|
||||||
|
|
||||||
|
app_bridge_zigbee_device_t *app_bridge_get_zigbee_device_by_zigbee_shortaddr(uint16_t zigbee_shortaddr);
|
||||||
|
|
||||||
|
esp_err_t app_bridge_remove_zigbee_device(app_bridge_zigbee_device_t *bridged_device);
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user