[Zigbee] IAS based Endpoints do not call response callback handler
Author: SLAZ666Created Sep 1, 2026Updated Sep 11, 2026
LabelsIDE: Arduino IDEArea: Zigbee
Board
ESP32-C6
Device Description
Plain Seed Studio XIAO ESP32-C6
Hardware Configuration
Hall sensor switch on pin D1
Version
v3.3.11
Type
Bug
IDE Name
Arduino IDE
Operating System
Linux
Flash frequency
160MHz
PSRAM enabled
no
Upload speed
921600
Description
IAS based Endpoints like ZigbeeContactSwitch or ZigbeeDoorWindowHandle do not call the response callback, which is necessary to implement a proper battery powered device like in the example of Zigbee_Temp_Hum_Sensor_Sleepy
In the minimal example attached the onGlobalResponse callback gets never called even so the state of the contact switch is successfully transferred to the controller. Also using only the onResponse callback it is not working.
The controller is used with Zigbee2mqtt 2.7.2
Sketch
// Copyright 2024 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.
/**
* @brief This example demonstrates Zigbee contact switch (IAS Zone).
*
* The example demonstrates how to use Zigbee library to create a end device contact switch.
* The contact switch is a Zigbee end device, which is reporting data to the Zigbee network.
*
* Proper Zigbee mode must be selected in Tools->Zigbee mode
* and also the correct partition scheme must be selected in Tools->Partition Scheme.
*
* Please check the README.md for instructions and more detailed description.
*
* Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
*/
#include <Arduino.h>
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif
#include "Zigbee.h"
#include <Preferences.h>
#define USE_GLOBAL_ON_RESPONSE_CALLBACK 1 // Set to 0 to use local callback specified directly for the endpoint.
/* Zigbee contact sensor configuration */
#define CONTACT_SWITCH_ENDPOINT_NUMBER 1
uint8_t button = BOOT_PIN;
uint8_t sensor_pin = D1;
ZigbeeContactSwitch zbContactSwitch = ZigbeeContactSwitch(CONTACT_SWITCH_ENDPOINT_NUMBER);
/* Preferences for storing ENROLLED flag to persist across reboots */
Preferences preferences;
#if USE_GLOBAL_ON_RESPONSE_CALLBACK
void onGlobalResponse(zb_cmd_type_t command, esp_zb_zcl_status_t status, uint8_t endpoint, uint16_t cluster) {
Serial.printf("Global response command: %d, status: %s, endpoint: %u, cluster: 0x%04x\r\n", command, esp_zb_zcl_status_to_name(status), endpoint, cluster);
}
#else
void onResponse(zb_cmd_type_t command, esp_zb_zcl_status_t status) {
Serial.printf("Response command: %d, status: %s\r\n", command, esp_zb_zcl_status_to_name(status));
}
#endif
void setup() {
Serial.begin(115200);
preferences.begin("Zigbee", false); // Save ENROLLED flag in flash so it persists across reboots
bool enrolled = preferences.getBool("ENROLLED"); // Get ENROLLED flag from preferences
preferences.end();
// Init button + switch
pinMode(button, INPUT_PULLUP);
pinMode(sensor_pin, INPUT_PULLUP);
// Optional: set Zigbee device name and model
zbContactSwitch.setManufacturerAndModel("Espressif", "ZigbeeContactSwitch");
#if USE_GLOBAL_ON_RESPONSE_CALLBACK
// Global callback for all endpoints with more params to determine the endpoint and cluster in the callback function.
Zigbee.onGlobalDefaultResponse(onGlobalResponse);
#else
// Callback specified for endpoint
zbContactSwitch.onDefaultResponse(onResponse);
#endif
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbContactSwitch);
Serial.println("Starting Zigbee...");
// When all EPs are registered, start Zigbee in End Device mode
if (!Zigbee.begin()) {
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting...");
ESP.restart();
} else {
Serial.println("Zigbee started successfully!");
}
Serial.println("Connecting to network");
while (!Zigbee.connected()) {
Serial.print(".");
delay(100);
}
Serial.println();
// Check if device has been enrolled before restarting - if so, restore IAS Zone enroll, otherwise request new IAS Zone enroll
if (enrolled) {
Serial.println("Device has been enrolled before - restoring IAS Zone enrollment");
zbContactSwitch.restoreIASZoneEnroll();
} else {
Serial.println("Device is factory new - first time joining network - requesting new IAS Zone enrollment");
zbContactSwitch.requestIASZoneEnroll();
}
while (!zbContactSwitch.enrolled()) {
Serial.print(".");
delay(100);
}
Serial.println();
Serial.println("Zigbee enrolled successfully!");
// Store ENROLLED flag only if this was a new enrollment (previous flag was false)
// Skip writing if we just restored enrollment (flag was already true)
if (!enrolled) {
preferences.begin("Zigbee", false);
preferences.putBool("ENROLLED", true); // set ENROLLED flag to true
preferences.end();
Serial.println("ENROLLED flag saved to preferences");
}
}
void loop() {
// Checking pin for contact change
static bool contact = false;
if (digitalRead(sensor_pin) == HIGH && !contact) {
// Update contact sensor value
zbContactSwitch.setOpen();
Serial.println("Contact open");
contact = true;
} else if (digitalRead(sensor_pin) == LOW && contact) {
zbContactSwitch.setClosed();
Serial.println("Contact close");
contact = false;
}
// 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.");
// Clear the ENROLLED flag from preferences
preferences.begin("Zigbee", false);
preferences.putBool("ENROLLED", false); // set ENROLLED flag to false
preferences.end();
Serial.println("ENROLLED flag cleared from preferences");
delay(1000);
Zigbee.factoryReset();
}
}
}
delay(100);
}Debug Message
=========== Before Setup Start ===========
Chip Info:
------------------------------------------
Model : ESP32-C6
Package : 1
Revision : 0.01
Cores : 1
CPU Frequency : 160 MHz
XTAL Frequency : 4tures 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 : 441388 B ( 431.0 KB)
Free Bytes : 408684 B ( 399.1 KB)
Allocated Bytes : 25648 B ( 25.0 KB)
Minimum Free Bytes: 403696 B ( 394.2 KB)
Largest Free Block: 385012 B ( 376.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
Chip Size : 4194304B (4 MB)
Block Size : 65536B ( 64.0 KB)
Sector Size : 4096B ( 4.0 KB)
Page Size : 256B ( 0.2 KB)
Bus Speed : 80 MHz
Flash Frequency : 80 MHz (source: 80 MHz, divider: 1)
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 : Sep 1 2026 21:52:46
Compile Host OS : linux
ESP-IDF Version : v5.5.4
Arduino Version : 3.3.10
------------------------------------------
Board Info:
------------------------------------------
Arduino Board : XIAO_ESP32C6
Arduino Variant : XIAO_ESP32C6
Arduino FQBN : esp32:esp32:XIAO_ESP32C6:UploadSpeed=921600,CDCOnBoot=cdc,CPUFreq=160,FlashFreq=80,FlashMode=qio,FlashSize=4M,PartitionScheme=zigbee,DebugLevel=debug,EraseFlash=all,JTAGAdapter=default,ZigbeeMode=ed
============ Before Setup End ============
[ 1231][I][esp32-hal-periman.c:151] perimanSetPinBus(): Pin 12 already has type USB_DM (38) with bus 0x40812b08
[ 1232][I][esp32-hal-periman.c:151] perimanSetPinBus(): Pin 13 already has type USB_DP (39) with bus 0x40812b08
[ 1233][D][ZigbeeCore.cpp:127] addEndpoint(): Endpoint: 1, Device ID: 0x0402
Starting Zigbee...
[ 1234][D][ZigbeeCore.cpp:175] zigbeeInit(): Initialize Zigbee stack
[ 1305][D][ZigbeeCore.cpp:182] zigbeeInit(): Register all Zigbee EPs in list
[ 1306][I][ZigbeeCore.cpp:190] zigbeeInit(): List of registered Zigbee EPs:
[ 1307][I][ZigbeeCore.cpp:192] zigbeeInit(): Device type: IAS Zone, Endpoint: 1, Device ID: 0x0402
[ 1454][I][ZigbeeCore.cpp:290] esp_zb_app_signal_handler(): Zigbee stack initialized
[ 1454][D][ZigbeeCore.cpp:291] esp_zb_app_signal_handler(): Zigbee channel mask: 0x07fff800
[ 1456][I][ZigbeeCore.cpp:297] esp_zb_app_signal_handler(): Device started up in factory-reset mode
[ 1457][I][ZigbeeCore.cpp:304] esp_zb_app_signal_handler(): Start network steering
Zigbee started successfully!
Connecting to network
...............................[ 4515][I][ZigbeeCore.cpp:358] esp_zb_app_signal_handler(): Joined network successfully (Extended PAN ID: 5b:f6:da:79:14:b1:91:a6, PAN ID: 0x58fb, Channel:11, Short Address: 0xc757)
Device is factory new - first time joining network - requesting new IAS Zone enrollment
...[ 4817][D][ZigbeeCore.cpp:778] searchBindings(): Requesting binding table for address 0xc757
[ 4821][D][ZigbeeCore.cpp:586] bindingTableCb(): Binding table callback for address 0xc757 with status 0
[ 4822][D][ZigbeeCore.cpp:590] bindingTableCb(): Binding table info: total 1, index 0, count 1
[ 4823][D][ZigbeeCore.cpp:635] bindingTableCb(): Processing record 0: src_endp 1, dst_endp 1, cluster_id 0x0500, dst_addr_mode 3
[ 4824][D][ZigbeeCore.cpp:650] bindingTableCb(): Processing final chunk of binding table, total records: 1
[ 4824][D][ZigbeeCore.cpp:671] bindingTableCb(): Processing endpoint 1
[ 4825][D][ZigbeeCore.cpp:717] bindingTableCb(): Processing binding record for EP 1
[ 4825][D][ZigbeeCore.cpp:752] bindingTableCb(): Device bound to EP 1 -> device endpoint: 1, ieee addr: 00:12:4B:00:24:C2:AD:34
[ 4826][D][ZigbeeCore.cpp:765] bindingTableCb(): Filling bounded devices finished
.....
Zigbee enrolled successfully!
ENROLLED flag saved to preferences
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
Total Size : 441388 B ( 431.0 KB)
Free Bytes : 377172 B ( 368.3 KB)
Allocated Bytes : 56392 B ( 55.1 KB)
Minimum Free Bytes: 377064 B ( 368.2 KB)
Largest Free Block: 360436 B ( 352.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
GPIO : BUS_TYPE[bus/unit][chan]
--------------------------------------
1 : GPIO
3 : GPIO
9 : GPIO
12 : USB_DM
13 : USB_DP
14 : GPIO
============ After Setup End =============
Contact open
Contact close
Contact open
Contact close
Contact open
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.
Source: espressif/arduino-esp32