Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zigbee On/Off Switch bounds only to 1st Endpoint and Ignores Additional Endpoints on the Light Device #11006

Open
1 task done
sebastian-ionita opened this issue Feb 23, 2025 · 8 comments
Assignees
Labels
Area: Zigbee Issues and Feature Request about Zigbee Status: Test needed Issue needs testing

Comments

@sebastian-ionita
Copy link

Board

ESP32c6

Device Description

2 x Esp32c6

Hardware Configuration

Default configuration

Version

v3.1.2

IDE Name

Arduino

Operating System

Windows 11

Flash frequency

40Mhz

PSRAM enabled

yes

Upload speed

115200

Description

When using a Zigbee On/Off Switch, it always prints "Endpoint 10", even if the On/Off Light device is configured with a different endpoint. Additionaly, if the On/Off Light device registers multiple endpoints (e.g., 10 and 11), the switch only sees one endpoint, instead of recognizing both.

Sketch

Light example: 

#define ZIGBEE_LIGHT_ENDPOINT 11
#define ZIGBEE_LIGHT_ENDPOINT2 12

ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT);
ZigbeeLight zbLight2 = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT2);


void setup() {
  Serial.begin(115200);

  // Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood)
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  // Init button for factory reset
  pinMode(button, INPUT_PULLUP);

  //Optional: set Zigbee device name and model
  zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
  zbLight2.setManufacturerAndModel("Espressif", "ZBLightBulb2");

  // Set callback function for light change
  zbLight.onLightChange(setLED);
  zbLight2.onLightChange(setLED2);

  //Add endpoint to Zigbee Core
  Serial.println("Adding ZigbeeLight endpoint to Zigbee Core");
  Zigbee.addEndpoint(&zbLight);
  Zigbee.addEndpoint(&zbLight2);

  // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
  if (!Zigbee.begin()) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println("Connected");
  zbLight.printBoundDevices(Serial);
  zbLight2.printBoundDevices(Serial);
}

Switch Example is untouched.

Debug Message

Switch example prints:
Device on endpoint 10, short address: 0x0, ieee address: 40:4c:ca:ff:fe:5e:d3:c0

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@sebastian-ionita sebastian-ionita added the Status: Awaiting triage Issue is waiting for triage label Feb 23, 2025
@P-R-O-C-H-Y
Copy link
Member

Hi @sebastian-ionita, have you enabled in switch example that it can bound to multiple lights?
If yes (correct), its maybe possible that as it have the same ieee address its only bounded to the 1st endpoint.
But you can use the commands for controlling the light in the switch, where you can specify the endpoint/address.

@P-R-O-C-H-Y P-R-O-C-H-Y added Area: Zigbee Issues and Feature Request about Zigbee Type: Question Only question and removed Status: Awaiting triage Issue is waiting for triage labels Feb 24, 2025
@sebastian-ionita
Copy link
Author

sebastian-ionita commented Feb 24, 2025

Yes, zbSwitch.allowMultipleBinding(true).The light exmple has two endpoints, 11 and 12. Switch example binds to endpoint 10 which shouldn't exist, this is what it prints in the console: Device on endpoint 10, short address: 0x0, ieee address: 40:4c:ca:ff:fe:5e:d3:c0. Doesn't matter what i configure in light example, switch will always bind to endpoint 10

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Feb 25, 2025

Can you turn on erase flash when uploading on both devices, to make sure there is nothing left in a flash from previous uploads?
You can enable it in the Arduino IDE->Tools menu->Erase Flash before upload–>Enabled.

Can you post please whole log from both Switch and Light? Please set Verbose logging in the Tools menu.

@sebastian-ionita
Copy link
Author

sebastian-ionita commented Feb 25, 2025

Switch bound to endpoint 11 after I enabled Erase flash before upload, but it only sees one endpoint.
Here are the logs from Switch:

ESP-ROM:esp32c6-20220919
Build:Sep 19 2022
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:2
load:0x40875720,len:0x1228
load:0x4086c110,len:0xd9c
load:0x4086e610,len:0x2f74
entry 0x4086c110
[     0][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RX (2) successfully set to 0x420066e6
[    12][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_TX (3) successfully set to 0x420066aa
[    23][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_CTS (4) successfully set to 0x4200666e
[    34][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RTS (5) successfully set to 0x42006632
[    46][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RX (2) successfully set to 0x420066e6
[    57][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_TX (3) successfully set to 0x420066aa
[    68][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_CTS (4) successfully set to 0x4200666e
[    80][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RTS (5) successfully set to 0x42006632
[    91][V][ZigbeeEP.cpp:18] ZigbeeEP(): Endpoint: 5
[   103][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 17 successfully set to type UART_RX (2) with bus 0x4080dfa0
[   113][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 16 successfully set to type UART_TX (3) with bus 0x4080dfa0
=========== Before Setup Start ===========
Chip Info:
------------------------------------------
  Model             : ESP32-C6
  Package           : 0
  Revision          : 0.01
  Cores             : 1
  CPU Frequency     : 160 MHz
  XTAL Frequency    : 40 MHz
  Features Bitfield : 0x00000052
  Embedded Flash    : No
  Embedded PSRAM    : No
  2.4GHz WiFi       : Yes
  Classic BT        : No
  BT Low Energy     : Yes
  IEEE 802.15.4     : Yes
------------------------------------------
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   447628 B ( 437.1 KB)
  Free Bytes        :   407752 B ( 398.2 KB)
  Allocated Bytes   :    32748 B (  32.0 KB)
  Minimum Free Bytes:   407752 B ( 398.2 KB)
  Largest Free Block:   376820 B ( 368.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
  Chip Size         : 16777216 B (16 MB)
  Block Size        :    65536 B (  64.0 KB)
  Sector Size       :     4096 B (   4.0 KB)
  Page Size         :      256 B (   0.2 KB)
  Bus Speed         : 40 MHz
  Bus Mode          : QIO
------------------------------------------
Partitions Info:
------------------------------------------
                nvs : addr: 0x00009000, size:    20.0 KB, type: DATA, subtype: NVS
            otadata : addr: 0x0000E000, size:     8.0 KB, type: DATA, subtype: OTA
               app0 : addr: 0x00010000, size:  1280.0 KB, type:  APP, subtype: OTA_0
               app1 : addr: 0x00150000, size:  1280.0 KB, type:  APP, subtype: OTA_1
             spiffs : addr: 0x00290000, size:  1388.0 KB, type: DATA, subtype: SPIFFS
         zb_storage : addr: 0x003EB000, size:    16.0 KB, type: DATA, subtype: FAT
             zb_fct : addr: 0x003EF000, size:     4.0 KB, type: DATA, subtype: FAT
           coredump : addr: 0x003F0000, size:    64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
  Compile Date/Time : Feb 25 2025 11:10:48
  Compile Host OS   : windows
  ESP-IDF Version   : v5.3.2-584-g489d7a2b3a-dirty
  Arduino Version   : 3.1.3
------------------------------------------
Board Info:
------------------------------------------
  Arduino Board     : ESP32C6_DEV
  Arduino Variant   : esp32c6
  Arduino FQBN      : esp32:esp32:esp32c6:UploadSpeed=921600,CDCOnBoot=default,CPUFreq=160,FlashFreq=80,FlashMode=qio,FlashSize=4M,PartitionScheme=zigbee,DebugLevel=verbose,EraseFlash=all,JTAGAdapter=default,ZigbeeMode=zczr
============ Before Setup End ============
[   454][V][esp32-hal-uart.c:421] uartBegin(): UART0 baud(115200) Mode(800001c) rxPin(17) txPin(16)
[   463][V][esp32-hal-uart.c:510] uartBegin(): UART0 not installed. Starting installation
[   472][V][esp32-hal-uart.c:575] uartBegin(): UART0 initialization done.
Adding ZigbeeSwitch endpoint to Zigbee Core
[   478][D][ZigbeeCore.cpp:83] addEndpoint(): Endpoint: 5, Device ID: 0x0000
[   489][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type GPIO (1) successfully set to 0x420049f8
[   500][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 9 successfully set to type GPIO (1) with bus 0xa
[   510][D][ZigbeeCore.cpp:122] zigbeeInit(): Initialize Zigbee stack
[   598][D][ZigbeeCore.cpp:129] zigbeeInit(): Register all Zigbee EPs in list
[   606][I][ZigbeeCore.cpp:137] zigbeeInit(): List of registered Zigbee EPs:
[   613][I][ZigbeeCore.cpp:139] zigbeeInit(): Device type: General On/Off switch, Endpoint: 5, Device ID: 0x0000
[   632][V][ZigbeeCore.cpp:351] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
[   642][I][ZigbeeCore.cpp:218] esp_zb_app_signal_handler(): Zigbee stack initialized
[   656][I][ZigbeeCore.cpp:340] esp_zb_app_signal_handler(): Network(0x4db6) closed, devices joining not allowed.
[   667][I][ZigbeeCore.cpp:224] esp_zb_app_signal_handler(): Device started up in non factory-reset mode
[   677][I][ZigbeeCore.cpp:237] esp_zb_app_signal_handler(): Device rebooted
[   684][I][ZigbeeCore.cpp:241] esp_zb_app_signal_handler(): Opening network for joining for 180 seconds
[   693][D][ZigbeeCore.cpp:478] searchBindings(): Requesting binding table for address 0x0000
[   702][D][ZigbeeCore.cpp:418] bindingTableCb(): Binding table callback for address 0x0000 with status 0
[   712][D][ZigbeeCore.cpp:421] bindingTableCb(): Binding table info: total 1, index 0, count 1
[   720][D][ZigbeeCore.cpp:431] bindingTableCb(): Binding table record: src_endp 5, dst_endp 11, cluster_id 0x0006, dst_addr_mode 3
[   732][D][ZigbeeCore.cpp:448] bindingTableCb(): Device bound to EP 5 -> device endpoint: 11, short addr: 0x0000, ieee addr: 40:4C:CA:FF:FE:5E:BA:24
[   745][D][ZigbeeCore.cpp:469] bindingTableCb(): Filling bounded devices finished
Waiting for Light to bound to the switch
Device on endpoint 11, short address: 0x0
IEEE Address: 40:4C:CA:FF:FE:5E:BA:24
[   772][V][ZigbeeHandlers.cpp:126] zb_cmd_read_attr_resp_handler(): Read attribute response: from address(0xfa6e) src endpoint(11) to dst endpoint(5) cluster(0x0)
[   786][V][ZigbeeHandlers.cpp:135] zb_cmd_read_attr_resp_handler(): Read attribute response: status(134), cluster(0x0), attribute(0x4), type(0x0), value(0)
[  1204][I][ZigbeeCore.cpp:338] esp_zb_app_signal_handler(): Network(0x4db6) is open for 180 seconds
[ 10754][E][ZigbeeEP.cpp:144] readManufacturer(): Error while reading manufacturer
[ 10778][V][ZigbeeHandlers.cpp:126] zb_cmd_read_attr_resp_handler(): Read attribute response: from address(0xfa6e) src endpoint(11) to dst endpoint(5) cluster(0x0)
[ 10792][V][ZigbeeHandlers.cpp:135] zb_cmd_read_attr_resp_handler(): Read attribute response: status(134), cluster(0x0), attribute(0x5), type(0x0), value(0)
[ 20761][E][ZigbeeEP.cpp:180] readModel(): Error while reading model
Connected
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   447628 B ( 437.1 KB)
  Free Bytes        :   380228 B ( 371.3 KB)
  Allocated Bytes   :    59248 B (  57.9 KB)
  Minimum Free Bytes:   380092 B ( 371.2 KB)
  Largest Free Block:   352244 B ( 344.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
  GPIO : BUS_TYPE[bus/unit][chan]
  --------------------------------------  
     9 : GPIO
    16 : UART_TX[0]
    17 : UART_RX[0]
============ After Setup End =============

LOGS for the light:

ESP-ROM:esp32c6-20220919
Build:Sep 19 2022
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:2
load:0x40875720,len:0x1228
load:0x4086c110,len:0xd9c
load:0x4086e610,len:0x2f74
entry 0x4086c110
[     0][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RX (2) successfully set to 0x42006bb2
[    12][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_TX (3) successfully set to 0x42006b76
[    23][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_CTS (4) successfully set to 0x42006b3a
[    34][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RTS (5) successfully set to 0x42006afe
[    46][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RX (2) successfully set to 0x42006bb2
[    57][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_TX (3) successfully set to 0x42006b76
[    68][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_CTS (4) successfully set to 0x42006b3a
[    80][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RTS (5) successfully set to 0x42006afe
[    91][V][ZigbeeEP.cpp:18] ZigbeeEP(): Endpoint: 11
[    96][V][ZigbeeLight.cpp:10] ZigbeeLight(): Light endpoint created 11
[   103][V][ZigbeeEP.cpp:18] ZigbeeEP(): Endpoint: 12
[   108][V][ZigbeeLight.cpp:10] ZigbeeLight(): Light endpoint created 12
[   121][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 17 successfully set to type UART_RX (2) with bus 0x4080f058
[   132][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 16 successfully set to type UART_TX (3) with bus 0x4080f058
=========== Before Setup Start ===========
Chip Info:
------------------------------------------
  Model             : ESP32-C6
  Package           : 0
  Revision          : 0.01
  Cores             : 1
  CPU Frequency     : 160 MHz
  XTAL Frequency    : 40 MHz
  Features Bitfield : 0x00000052
  Embedded Flash    : No
  Embedded PSRAM    : No
  2.4GHz WiFi       : Yes
  Classic BT        : No
  BT Low Energy     : Yes
  IEEE 802.15.4     : Yes
------------------------------------------
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   446140 B ( 435.7 KB)
  Free Bytes        :   405068 B ( 395.6 KB)
  Allocated Bytes   :    33304 B (  32.5 KB)
  Minimum Free Bytes:   405068 B ( 395.6 KB)
  Largest Free Block:   376820 B ( 368.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
  Chip Size         : 16777216 B (16 MB)
  Block Size        :    65536 B (  64.0 KB)
  Sector Size       :     4096 B (   4.0 KB)
  Page Size         :      256 B (   0.2 KB)
  Bus Speed         : 40 MHz
  Bus Mode          : QIO
------------------------------------------
Partitions Info:
------------------------------------------
                nvs : addr: 0x00009000, size:    20.0 KB, type: DATA, subtype: NVS
            otadata : addr: 0x0000E000, size:     8.0 KB, type: DATA, subtype: OTA
               app0 : addr: 0x00010000, size:  1280.0 KB, type:  APP, subtype: OTA_0
               app1 : addr: 0x00150000, size:  1280.0 KB, type:  APP, subtype: OTA_1
             spiffs : addr: 0x00290000, size:  1388.0 KB, type: DATA, subtype: SPIFFS
         zb_storage : addr: 0x003EB000, size:    16.0 KB, type: DATA, subtype: FAT
             zb_fct : addr: 0x003EF000, size:     4.0 KB, type: DATA, subtype: FAT
           coredump : addr: 0x003F0000, size:    64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
  Compile Date/Time : Feb 25 2025 11:15:25
  Compile Host OS   : windows
  ESP-IDF Version   : v5.3.2-584-g489d7a2b3a-dirty
  Arduino Version   : 3.1.3
------------------------------------------
Board Info:
============ Before Setup End ============
[   473][V][esp32-hal-uart.c:421] uartBegin(): UART0 baud(115200) Mode(800001c) rxPin(17) txPin(16)
[   481][V][esp32-hal-uart.c:510] uartBegin(): UART0 not installed. Starting installation
[   490][V][esp32-hal-uart.c:575] uartBegin(): UART0 initialization done.
[   497][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type GPIO (1) successfully set to 0x42004254
[   508][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 8 successfully set to type GPIO (1) with bus 0x9
[   517][V][esp32-hal-rmt.c:454] rmtInit(): GPIO 8 - TX MODE - MemSize[48] - Freq=10000000Hz
[   526][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type RMT_TX (10) successfully set to 0x420058ba
[   537][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type RMT_RX (11) successfully set to 0x420058ba
[   548][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 8 successfully set to type INIT (0) with bus 0x0
[   558][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 8 successfully set to type RMT_TX (10) with bus 0x4081b3b0
[   570][V][esp32-hal-rmt.c:305] _rmtWrite(): GPIO: 8 - Request: 24 RMT Symbols - Blocking - Timeout: -1
[   579][V][esp32-hal-rmt.c:306] _rmtWrite(): GPIO: 8 - Currently in Loop Mode: [NO] | Asked to Loop: NO, LoopCancel: NO
[   590][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type GPIO (1) successfully set to 0x42004254
[   601][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 9 successfully set to type GPIO (1) with bus 0xa
Adding ZigbeeLight endpoint to Zigbee Core
[   611][D][ZigbeeCore.cpp:83] addEndpoint(): Endpoint: 11, Device ID: 0x0100
[   621][D][ZigbeeCore.cpp:83] addEndpoint(): Endpoint: 12, Device ID: 0x0100
[   628][D][ZigbeeCore.cpp:122] zigbeeInit(): Initialize Zigbee stack
[   724][D][ZigbeeCore.cpp:129] zigbeeInit(): Register all Zigbee EPs in list
[   733][I][ZigbeeCore.cpp:137] zigbeeInit(): List of registered Zigbee EPs:
[   739][I][ZigbeeCore.cpp:139] zigbeeInit(): Device type: On/Off Light Device, Endpoint: 11, Device ID: 0x0100
[   749][I][ZigbeeCore.cpp:139] zigbeeInit(): Device type: On/Off Light Device, Endpoint: 12, Device ID: 0x0100
[   762][V][ZigbeeCore.cpp:351] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
[   773][I][ZigbeeCore.cpp:218] esp_zb_app_signal_handler(): Zigbee stack initialized
[   782][I][ZigbeeCore.cpp:224] esp_zb_app_signal_handler(): Device started up in  factory-reset mode
[   791][I][ZigbeeCore.cpp:231] esp_zb_app_signal_handler(): Start network steering
Connecting to network
.......................[  3024][I][ZigbeeCore.cpp:289] esp_zb_app_signal_handler(): Network steering was not successful (status: ESP_FAIL)
.......................................[  6912][I][ZigbeeCore.cpp:282] esp_zb_app_signal_handler(): Joined network successfully (Extended PAN ID: 40:4c:ca:ff:fe:5e:d3:c0, PAN ID: 0x4db6, Channel:24, Short Address: 0xfa6e)
Connected
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   446140 B ( 435.7 KB)
  Free Bytes        :   379340 B ( 370.4 KB)
  Allocated Bytes   :    57976 B (  56.6 KB)
  Minimum Free Bytes:   379340 B ( 370.4 KB)
  Largest Free Block:   352244 B ( 344.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
  GPIO : BUS_TYPE[bus/unit][chan]
  --------------------------------------  
     8 : RMT_TX
     9 : GPIO
    16 : UART_TX[0]
    17 : UART_RX[0]
============ After Setup End =============

@sebastian-ionita
Copy link
Author

sebastian-ionita commented Feb 25, 2025

Here is the complete code for the switch:

#ifndef ZIGBEE_MODE_ZCZR
#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"

/* Zigbee switch configuration */
#define SWITCH_ENDPOINT_NUMBER 5

#define GPIO_INPUT_IO_TOGGLE_SWITCH BOOT_PIN
#define PAIR_SIZE(TYPE_STR_PAIR)    (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0]))

typedef enum {
  SWITCH_ON_CONTROL,
  SWITCH_OFF_CONTROL,
  SWITCH_ONOFF_TOGGLE_CONTROL,
  SWITCH_LEVEL_UP_CONTROL,
  SWITCH_LEVEL_DOWN_CONTROL,
  SWITCH_LEVEL_CYCLE_CONTROL,
  SWITCH_COLOR_CONTROL,
} SwitchFunction;

typedef struct {
  uint8_t pin;
  SwitchFunction func;
} SwitchData;

typedef enum {
  SWITCH_IDLE,
  SWITCH_PRESS_ARMED,
  SWITCH_PRESS_DETECTED,
  SWITCH_PRESSED,
  SWITCH_RELEASE_DETECTED,
} SwitchState;

static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}};

ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER);

/********************* Zigbee functions **************************/
static void onZbButton(SwitchData *button_func_pair) {
  if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) {
    // Send toggle command to the light
    Serial.println("Toggling light");

    std::list<zb_device_params_t *> boundLights = zbSwitch.getBoundDevices();
    for (const auto &device : boundLights) {
      Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
      Serial.printf(
        "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4],
        device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]
      );
      zbSwitch.lightToggle(device->endpoint, device->ieee_addr);
      char *manufacturer = zbSwitch.readManufacturer(device->endpoint, device->short_addr, device->ieee_addr);
      char *model = zbSwitch.readModel(device->endpoint, device->short_addr, device->ieee_addr);
      if (manufacturer != nullptr) {
        Serial.printf("Light manufacturer: %s\r\n", manufacturer);
      }
      if (model != nullptr) {
        Serial.printf("Light model: %s\r\n", model);
      }
    }
  }
}

/********************* GPIO functions **************************/
static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR onGpioInterrupt(void *arg) {
  xQueueSendFromISR(gpio_evt_queue, (SwitchData *)arg, NULL);
}

static void enableGpioInterrupt(bool enabled) {
  for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); ++i) {
    if (enabled) {
      enableInterrupt((buttonFunctionPair[i]).pin);
    } else {
      disableInterrupt((buttonFunctionPair[i]).pin);
    }
  }
}

/********************* Arduino functions **************************/
void setup() {
  Serial.begin(115200);

  //Optional: set Zigbee device name and model
  zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch");

  //Optional to allow multiple light to bind to the switch
  zbSwitch.allowMultipleBinding(true);

  //Add endpoint to Zigbee Core
  Serial.println("Adding ZigbeeSwitch endpoint to Zigbee Core");
  Zigbee.addEndpoint(&zbSwitch);

  //Open network for 180 seconds after boot
  Zigbee.setRebootOpenNetwork(180);

  // Init button switch
  for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) {
    pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP);
    /* create a queue to handle gpio event from isr */
    gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData));
    if (gpio_evt_queue == 0) {
      Serial.println("Queue creating failed, rebooting...");
      ESP.restart();
    }
    attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING);
  }

  // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode
  if (!Zigbee.begin(ZIGBEE_COORDINATOR)) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }

  Serial.println("Waiting for Light to bound to the switch");
  //Wait for switch to bound to a light:
  while (!zbSwitch.bound()) {
    Serial.printf(".");
    delay(500);
  }

  // Optional: List all bound devices and read manufacturer and model name
  std::list<zb_device_params_t *> boundLights = zbSwitch.getBoundDevices();
  for (const auto &device : boundLights) {
    Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
    Serial.printf(
      "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4],
      device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]
    );
    char *manufacturer = zbSwitch.readManufacturer(device->endpoint, device->short_addr, device->ieee_addr);
    char *model = zbSwitch.readModel(device->endpoint, device->short_addr, device->ieee_addr);
    if (manufacturer != nullptr) {
      Serial.printf("Light manufacturer: %s\r\n", manufacturer);
    }
    if (model != nullptr) {
      Serial.printf("Light model: %s\r\n", model);
    }
  }

  Serial.println("Connected");
}

void loop() {
  // Handle button switch in loop()
  uint8_t pin = 0;
  SwitchData buttonSwitch;
  static SwitchState buttonState = SWITCH_IDLE;
  bool eventFlag = false;

  /* check if there is any queue received, if yes read out the buttonSwitch */
  if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) {
    pin = buttonSwitch.pin;
    enableGpioInterrupt(false);
    eventFlag = true;
  }
  while (eventFlag) {
    bool value = digitalRead(pin);
    switch (buttonState) {
      case SWITCH_IDLE:           buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break;
      case SWITCH_PRESS_DETECTED: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break;
      case SWITCH_RELEASE_DETECTED:
        buttonState = SWITCH_IDLE;
        /* callback to button_handler */
        (*onZbButton)(&buttonSwitch);
        break;
      default: break;
    }
    if (buttonState == SWITCH_IDLE) {
      enableGpioInterrupt(true);
      eventFlag = false;
      break;
    }
    vTaskDelay(10 / portTICK_PERIOD_MS);
  }

  // print the bound lights every 10 seconds
  static uint32_t lastPrint = 0;
  if (millis() - lastPrint > 10000) {
    lastPrint = millis();
    zbSwitch.printBoundDevices(Serial);
  }
}

Complete code for the light:

#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"

/* Zigbee light bulb configuration */
#define ZIGBEE_LIGHT_ENDPOINT 11
#define ZIGBEE_LIGHT_ENDPOINT2 12

uint8_t led = RGB_BUILTIN;
uint8_t button = BOOT_PIN;

ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT);
ZigbeeLight zbLight2 = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT2);

/********************* RGB LED functions **************************/
void setLED(bool value) {
  Serial.println("Led1");
  digitalWrite(led, value);
}

/********************* RGB LED functions **************************/
void setLED2(bool value) {
  Serial.println("Led2");
}

/********************* Arduino functions **************************/
void setup() {
  Serial.begin(115200);

  // Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood)
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  // Init button for factory reset
  pinMode(button, INPUT_PULLUP);

  //Optional: set Zigbee device name and model
  zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
  zbLight2.setManufacturerAndModel("Espressif", "ZBLightBulb2");

  // Set callback function for light change
  zbLight.onLightChange(setLED);
  zbLight2.onLightChange(setLED2);

  //Add endpoint to Zigbee Core
  Serial.println("Adding ZigbeeLight endpoint to Zigbee Core");
  Zigbee.addEndpoint(&zbLight);
  Zigbee.addEndpoint(&zbLight2);

  // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
  if (!Zigbee.begin()) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println("Connected");
}

void loop() {
  // Checking button for factory reset
  if (digitalRead(button) == LOW) {  // Push button pressed
    // Key debounce handling
    delay(100);
    int startTime = millis();
    while (digitalRead(button) == LOW) {
      delay(50);
      if ((millis() - startTime) > 3000) {
        // If key pressed for more than 3secs, factory reset Zigbee and reboot
        Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
        delay(1000);
        Zigbee.factoryReset();
      }
    }
    // Toggle light by pressing the button
    zbLight.setLight(!zbLight.getLightState());
  }
  delay(100);
}

@P-R-O-C-H-Y
Copy link
Member

Can you please format the last message so its clear to read it?

@sebastian-ionita
Copy link
Author

sebastian-ionita commented Feb 25, 2025

please check now. Also, please note that I Updated onZbButton function on switch example to send a comand to all endpoints.
smh like this:

for(device in bound-devices) {
    zbSwitch.lightToggle(device->endpoint, device->ieee_addr);
}

@P-R-O-C-H-Y P-R-O-C-H-Y added Status: Test needed Issue needs testing and removed Type: Question Only question labels Feb 25, 2025
@P-R-O-C-H-Y
Copy link
Member

I will setup the same devices and will give it a test and find out what is wrong. Please give me some time for that. Will keep you updated.

@P-R-O-C-H-Y P-R-O-C-H-Y changed the title Zigbee On/Off Switch Always Prints Endpoint 10 and Ignores Additional Endpoints on the Light Device Zigbee On/Off Switch bounds only to 1st Endpoint and Ignores Additional Endpoints on the Light Device Feb 25, 2025
@P-R-O-C-H-Y P-R-O-C-H-Y self-assigned this Feb 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Zigbee Issues and Feature Request about Zigbee Status: Test needed Issue needs testing
Projects
None yet
Development

No branches or pull requests

2 participants