From 685a6c8a06bd0568e137a908cfcc63936176d0e6 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 9 Feb 2022 16:55:33 +0800 Subject: [PATCH] Add app_bridge component and bridge_zigbee app (support on_off light device) --- .gitignore | 2 + components/esp_matter_bridge/CMakeLists.txt | 3 + .../esp_matter_bridge/esp_matter_bridge.cpp | 49 +++++++ .../esp_matter_bridge/esp_matter_bridge.h | 32 +++++ examples/bridge_zigbee/CMakeLists.txt | 45 ++++++ examples/bridge_zigbee/README.md | 101 +++++++++++++ examples/bridge_zigbee/main/CMakeLists.txt | 8 ++ examples/bridge_zigbee/main/app_main.cpp | 82 +++++++++++ examples/bridge_zigbee/main/app_zboss.c | 135 ++++++++++++++++++ examples/bridge_zigbee/main/app_zboss.h | 54 +++++++ examples/bridge_zigbee/main/idf_component.yml | 6 + .../PluginApplicationCallbacks.h | 24 ++++ .../main/zap-generated/af-gen-event.h | 71 +++++++++ .../main/zap-generated/endpoint_config.h | 68 +++++++++ examples/bridge_zigbee/main/zigbee_bridge.cpp | 132 +++++++++++++++++ examples/bridge_zigbee/main/zigbee_bridge.h | 30 ++++ examples/bridge_zigbee/partitions.csv | 10 ++ examples/bridge_zigbee/sdkconfig.defaults | 35 +++++ .../bridge_zigbee/sdkconfig.defaults.esp32s3 | 38 +++++ examples/common/app_bridge/CMakeLists.txt | 7 + .../app_bridge/app_bridge_zigbee_device.cpp | 125 ++++++++++++++++ .../app_bridge/app_bridge_zigbee_device.h | 39 +++++ 22 files changed, 1096 insertions(+) create mode 100644 components/esp_matter_bridge/CMakeLists.txt create mode 100644 components/esp_matter_bridge/esp_matter_bridge.cpp create mode 100644 components/esp_matter_bridge/esp_matter_bridge.h create mode 100644 examples/bridge_zigbee/CMakeLists.txt create mode 100644 examples/bridge_zigbee/README.md create mode 100644 examples/bridge_zigbee/main/CMakeLists.txt create mode 100644 examples/bridge_zigbee/main/app_main.cpp create mode 100644 examples/bridge_zigbee/main/app_zboss.c create mode 100644 examples/bridge_zigbee/main/app_zboss.h create mode 100644 examples/bridge_zigbee/main/idf_component.yml create mode 100644 examples/bridge_zigbee/main/zap-generated/PluginApplicationCallbacks.h create mode 100644 examples/bridge_zigbee/main/zap-generated/af-gen-event.h create mode 100644 examples/bridge_zigbee/main/zap-generated/endpoint_config.h create mode 100644 examples/bridge_zigbee/main/zigbee_bridge.cpp create mode 100644 examples/bridge_zigbee/main/zigbee_bridge.h create mode 100644 examples/bridge_zigbee/partitions.csv create mode 100644 examples/bridge_zigbee/sdkconfig.defaults create mode 100644 examples/bridge_zigbee/sdkconfig.defaults.esp32s3 create mode 100644 examples/common/app_bridge/CMakeLists.txt create mode 100644 examples/common/app_bridge/app_bridge_zigbee_device.cpp create mode 100644 examples/common/app_bridge/app_bridge_zigbee_device.h diff --git a/.gitignore b/.gitignore index 50bb4bb10..db1a50cec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ compile_commands.json build/ sdkconfig sdkconfig.old +dependencies.lock +managed_components/ diff --git a/components/esp_matter_bridge/CMakeLists.txt b/components/esp_matter_bridge/CMakeLists.txt new file mode 100644 index 000000000..d2a975173 --- /dev/null +++ b/components/esp_matter_bridge/CMakeLists.txt @@ -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) diff --git a/components/esp_matter_bridge/esp_matter_bridge.cpp b/components/esp_matter_bridge/esp_matter_bridge.cpp new file mode 100644 index 000000000..f8dbd67d1 --- /dev/null +++ b/components/esp_matter_bridge/esp_matter_bridge.cpp @@ -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 +#include +#include + +#include + +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; +} diff --git a/components/esp_matter_bridge/esp_matter_bridge.h b/components/esp_matter_bridge/esp_matter_bridge.h new file mode 100644 index 000000000..a7b7b2ef8 --- /dev/null +++ b/components/esp_matter_bridge/esp_matter_bridge.h @@ -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 + +#include +#include + +#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); diff --git a/examples/bridge_zigbee/CMakeLists.txt b/examples/bridge_zigbee/CMakeLists.txt new file mode 100644 index 000000000..aeb5a01e9 --- /dev/null +++ b/examples/bridge_zigbee/CMakeLists.txt @@ -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) diff --git a/examples/bridge_zigbee/README.md b/examples/bridge_zigbee/README.md new file mode 100644 index 000000000..70b2035db --- /dev/null +++ b/examples/bridge_zigbee/README.md @@ -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 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 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 +``` + diff --git a/examples/bridge_zigbee/main/CMakeLists.txt b/examples/bridge_zigbee/main/CMakeLists.txt new file mode 100644 index 000000000..be4ed6371 --- /dev/null +++ b/examples/bridge_zigbee/main/CMakeLists.txt @@ -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") diff --git a/examples/bridge_zigbee/main/app_main.cpp b/examples/bridge_zigbee/main/app_main.cpp new file mode 100644 index 000000000..e78e584f0 --- /dev/null +++ b/examples/bridge_zigbee/main/app_main.cpp @@ -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 +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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(); +} diff --git a/examples/bridge_zigbee/main/app_zboss.c b/examples/bridge_zigbee/main/app_zboss.c new file mode 100644 index 000000000..e1e8aa96d --- /dev/null +++ b/examples/bridge_zigbee/main/app_zboss.c @@ -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 +#include +#include +#include +#include +#include + +#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); +} diff --git a/examples/bridge_zigbee/main/app_zboss.h b/examples/bridge_zigbee/main/app_zboss.h new file mode 100644 index 000000000..f461c8408 --- /dev/null +++ b/examples/bridge_zigbee/main/app_zboss.h @@ -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 +#include + +/*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 diff --git a/examples/bridge_zigbee/main/idf_component.yml b/examples/bridge_zigbee/main/idf_component.yml new file mode 100644 index 000000000..9825e1cd1 --- /dev/null +++ b/examples/bridge_zigbee/main/idf_component.yml @@ -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" diff --git a/examples/bridge_zigbee/main/zap-generated/PluginApplicationCallbacks.h b/examples/bridge_zigbee/main/zap-generated/PluginApplicationCallbacks.h new file mode 100644 index 000000000..7ab176d68 --- /dev/null +++ b/examples/bridge_zigbee/main/zap-generated/PluginApplicationCallbacks.h @@ -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 + +#define MATTER_PLUGINS_INIT esp_matter_cluster_plugin_init_callback_common(); diff --git a/examples/bridge_zigbee/main/zap-generated/af-gen-event.h b/examples/bridge_zigbee/main/zap-generated/af-gen-event.h new file mode 100644 index 000000000..aa361a290 --- /dev/null +++ b/examples/bridge_zigbee/main/zap-generated/af-gen-event.h @@ -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__ diff --git a/examples/bridge_zigbee/main/zap-generated/endpoint_config.h b/examples/bridge_zigbee/main/zap-generated/endpoint_config.h new file mode 100644 index 000000000..90afa212c --- /dev/null +++ b/examples/bridge_zigbee/main/zap-generated/endpoint_config.h @@ -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} diff --git a/examples/bridge_zigbee/main/zigbee_bridge.cpp b/examples/bridge_zigbee/main/zigbee_bridge.cpp new file mode 100644 index 000000000..f15e8ce1a --- /dev/null +++ b/examples/bridge_zigbee/main/zigbee_bridge.cpp @@ -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 +#include +#include + +#include +#include +#include +#include +#include + +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; +} diff --git a/examples/bridge_zigbee/main/zigbee_bridge.h b/examples/bridge_zigbee/main/zigbee_bridge.h new file mode 100644 index 000000000..0e4b211fb --- /dev/null +++ b/examples/bridge_zigbee/main/zigbee_bridge.h @@ -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 + +#include +#include +#include + +#include + +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 diff --git a/examples/bridge_zigbee/partitions.csv b/examples/bridge_zigbee/partitions.csv new file mode 100644 index 000000000..3f2c8cd5a --- /dev/null +++ b/examples/bridge_zigbee/partitions.csv @@ -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 diff --git a/examples/bridge_zigbee/sdkconfig.defaults b/examples/bridge_zigbee/sdkconfig.defaults new file mode 100644 index 000000000..b83e3c80d --- /dev/null +++ b/examples/bridge_zigbee/sdkconfig.defaults @@ -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 diff --git a/examples/bridge_zigbee/sdkconfig.defaults.esp32s3 b/examples/bridge_zigbee/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000..5da5fdc4b --- /dev/null +++ b/examples/bridge_zigbee/sdkconfig.defaults.esp32s3 @@ -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 diff --git a/examples/common/app_bridge/CMakeLists.txt b/examples/common/app_bridge/CMakeLists.txt new file mode 100644 index 000000000..be96ab727 --- /dev/null +++ b/examples/common/app_bridge/CMakeLists.txt @@ -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) diff --git a/examples/common/app_bridge/app_bridge_zigbee_device.cpp b/examples/common/app_bridge/app_bridge_zigbee_device.cpp new file mode 100644 index 000000000..5e9a288a0 --- /dev/null +++ b/examples/common/app_bridge/app_bridge_zigbee_device.cpp @@ -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 +#include +#include + +#include + +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; +} diff --git a/examples/common/app_bridge/app_bridge_zigbee_device.h b/examples/common/app_bridge/app_bridge_zigbee_device.h new file mode 100644 index 000000000..6cb744108 --- /dev/null +++ b/examples/common/app_bridge/app_bridge_zigbee_device.h @@ -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 +#if CONFIG_ZB_ENABLED +#include + +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