Add app_bridge component and bridge_zigbee app (support on_off light device)

This commit is contained in:
WanqQixiang
2022-02-09 16:55:33 +08:00
parent 92b356c557
commit 685a6c8a06
22 changed files with 1096 additions and 0 deletions
+2
View File
@@ -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);
+45
View File
@@ -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)
+101
View File
@@ -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")
+82
View File
@@ -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();
}
+135
View File
@@ -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);
}
+54
View File
@@ -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
+10
View File
@@ -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
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
3 sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition
4 nvs, data, nvs, 0x10000, 0x6000,
5 otadata, data, ota, , 0x2000
6 phy_init, data, phy, , 0x1000,
7 ota_0, app, ota_0, 0x20000, 0x1D0000,
8 ota_1, app, ota_1, , 0x1D0000,
9 fctry, data, nvs, , 0x6000,
10 zb_storage, data, fat, , 0x20000
+35
View File
@@ -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