Merge branch 'master' into release/v3.3.x

This commit is contained in:
Me No Dev 2025-03-28 10:48:05 +02:00 committed by GitHub
commit dac2dd907d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 1205 additions and 480 deletions

View file

@ -6281,10 +6281,12 @@ twatchs3.menu.EraseFlash.none.upload.erase_cmd=
twatchs3.menu.EraseFlash.all=Enabled
twatchs3.menu.EraseFlash.all.upload.erase_cmd=-e
twatchs3.menu.Revision.Radio_SX1280=Radio-SX1280
twatchs3.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280
twatchs3.menu.Revision.Radio_SX1262=Radio-SX1262
twatchs3.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262
twatchs3.menu.Revision.Radio_SX1280=Radio-SX1280
twatchs3.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280
twatchs3.menu.Revision.Radio_CC1101=Radio-CC1101
twatchs3.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101
##############################################################
@ -6377,12 +6379,12 @@ twatch_ultra.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB)
twatch_ultra.menu.UploadMode.cdc.upload.use_1200bps_touch=true
twatch_ultra.menu.UploadMode.cdc.upload.wait_for_upload_port=true
twatch_ultra.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS)
twatch_ultra.menu.PartitionScheme.fatflash.build.partitions=ffat
twatch_ultra.menu.PartitionScheme.fatflash.upload.maximum_size=2097152
twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS)
twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB
twatch_ultra.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728
twatch_ultra.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS)
twatch_ultra.menu.PartitionScheme.fatflash.build.partitions=ffat
twatch_ultra.menu.PartitionScheme.fatflash.upload.maximum_size=2097152
twatch_ultra.menu.PartitionScheme.rainmaker=RainMaker
twatch_ultra.menu.PartitionScheme.rainmaker.build.partitions=rainmaker
twatch_ultra.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080
@ -6444,8 +6446,171 @@ twatch_ultra.menu.Revision.Radio_SX1280=Radio-SX1280
twatch_ultra.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280
twatch_ultra.menu.Revision.Radio_SX1262=Radio-SX1262
twatch_ultra.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262
twatch_ultra.menu.Revision.Radio_CC1101=Radio-CC1101
twatch_ultra.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101
##############################################################
tlora_pager.name=LilyGo-T-LoRa-Pager
tlora_pager.bootloader.tool=esptool_py
tlora_pager.bootloader.tool.default=esptool_py
tlora_pager.upload.tool=esptool_py
tlora_pager.upload.tool.default=esptool_py
tlora_pager.upload.tool.network=esp_ota
tlora_pager.upload.maximum_size=1310720
tlora_pager.upload.maximum_data_size=327680
tlora_pager.upload.flags=
tlora_pager.upload.extra_flags=
tlora_pager.upload.use_1200bps_touch=false
tlora_pager.upload.wait_for_upload_port=false
tlora_pager.serial.disableDTR=false
tlora_pager.serial.disableRTS=false
tlora_pager.build.tarch=xtensa
tlora_pager.build.bootloader_addr=0x0
tlora_pager.build.target=esp32s3
tlora_pager.build.mcu=esp32s3
tlora_pager.build.core=esp32
tlora_pager.build.variant=lilygo_tlora_pager
tlora_pager.build.board=T_LORA_PAGER
tlora_pager.build.usb_mode=1
tlora_pager.build.cdc_on_boot=1
tlora_pager.build.msc_on_boot=0
tlora_pager.build.dfu_on_boot=0
tlora_pager.build.f_cpu=240000000L
tlora_pager.build.flash_size=16MB
tlora_pager.build.flash_freq=80m
tlora_pager.build.flash_mode=dio
tlora_pager.build.boot=qio
tlora_pager.build.boot_freq=80m
tlora_pager.build.partitions=app3M_fat9M_16MB
tlora_pager.build.defines=-DBOARD_HAS_PSRAM -DARDUINO_T_LORA_PAGER
tlora_pager.build.loop_core=
tlora_pager.build.event_core=
tlora_pager.build.psram_type=qspi
tlora_pager.build.memory_type={build.boot}_{build.psram_type}
## IDE 2.0 Seems to not update the value
tlora_pager.menu.JTAGAdapter.default=Disabled
tlora_pager.menu.JTAGAdapter.default.build.copy_jtag_files=0
tlora_pager.menu.JTAGAdapter.builtin=Integrated USB JTAG
tlora_pager.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg
tlora_pager.menu.JTAGAdapter.builtin.build.copy_jtag_files=1
tlora_pager.menu.LoopCore.1=Core 1
tlora_pager.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1
tlora_pager.menu.LoopCore.0=Core 0
tlora_pager.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0
tlora_pager.menu.EventsCore.1=Core 1
tlora_pager.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
tlora_pager.menu.EventsCore.0=Core 0
tlora_pager.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0
tlora_pager.menu.USBMode.hwcdc=Hardware CDC and JTAG
tlora_pager.menu.USBMode.hwcdc.build.usb_mode=1
tlora_pager.menu.USBMode.default=USB-OTG (TinyUSB)
tlora_pager.menu.USBMode.default.build.usb_mode=0
tlora_pager.menu.CDCOnBoot.default=Enabled
tlora_pager.menu.CDCOnBoot.default.build.cdc_on_boot=1
tlora_pager.menu.CDCOnBoot.cdc=Disabled
tlora_pager.menu.CDCOnBoot.cdc.build.cdc_on_boot=0
tlora_pager.menu.MSCOnBoot.default=Disabled
tlora_pager.menu.MSCOnBoot.default.build.msc_on_boot=0
tlora_pager.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode)
tlora_pager.menu.MSCOnBoot.msc.build.msc_on_boot=1
tlora_pager.menu.DFUOnBoot.default=Disabled
tlora_pager.menu.DFUOnBoot.default.build.dfu_on_boot=0
tlora_pager.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode)
tlora_pager.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
tlora_pager.menu.UploadMode.default=UART0 / Hardware CDC
tlora_pager.menu.UploadMode.default.upload.use_1200bps_touch=false
tlora_pager.menu.UploadMode.default.upload.wait_for_upload_port=false
tlora_pager.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB)
tlora_pager.menu.UploadMode.cdc.upload.use_1200bps_touch=true
tlora_pager.menu.UploadMode.cdc.upload.wait_for_upload_port=true
tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9.9MB FATFS)
tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB
tlora_pager.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728
tlora_pager.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS)
tlora_pager.menu.PartitionScheme.fatflash.build.partitions=ffat
tlora_pager.menu.PartitionScheme.fatflash.upload.maximum_size=2097152
tlora_pager.menu.PartitionScheme.rainmaker=RainMaker
tlora_pager.menu.PartitionScheme.rainmaker.build.partitions=rainmaker
tlora_pager.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728
tlora_pager.menu.PartitionScheme.esp_sr_16=ESP SR 16M (3MB APP/7MB SPIFFS/2.9MB MODEL)
tlora_pager.menu.PartitionScheme.esp_sr_16.upload.maximum_size=3145728
tlora_pager.menu.PartitionScheme.esp_sr_16.upload.extra_flags=0xD10000 {build.path}/srmodels.bin
tlora_pager.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16
tlora_pager.menu.PartitionScheme.custom=Custom
tlora_pager.menu.PartitionScheme.custom.build.partitions=
tlora_pager.menu.PartitionScheme.custom.upload.maximum_size=16777216
tlora_pager.menu.CPUFreq.240=240MHz (WiFi)
tlora_pager.menu.CPUFreq.240.build.f_cpu=240000000L
tlora_pager.menu.CPUFreq.160=160MHz (WiFi)
tlora_pager.menu.CPUFreq.160.build.f_cpu=160000000L
tlora_pager.menu.CPUFreq.80=80MHz (WiFi)
tlora_pager.menu.CPUFreq.80.build.f_cpu=80000000L
tlora_pager.menu.CPUFreq.40=40MHz
tlora_pager.menu.CPUFreq.40.build.f_cpu=40000000L
tlora_pager.menu.CPUFreq.20=20MHz
tlora_pager.menu.CPUFreq.20.build.f_cpu=20000000L
tlora_pager.menu.CPUFreq.10=10MHz
tlora_pager.menu.CPUFreq.10.build.f_cpu=10000000L
tlora_pager.menu.UploadSpeed.921600=921600
tlora_pager.menu.UploadSpeed.921600.upload.speed=921600
tlora_pager.menu.UploadSpeed.115200=115200
tlora_pager.menu.UploadSpeed.115200.upload.speed=115200
tlora_pager.menu.UploadSpeed.256000.windows=256000
tlora_pager.menu.UploadSpeed.256000.upload.speed=256000
tlora_pager.menu.UploadSpeed.230400.windows.upload.speed=256000
tlora_pager.menu.UploadSpeed.230400=230400
tlora_pager.menu.UploadSpeed.230400.upload.speed=230400
tlora_pager.menu.UploadSpeed.460800.linux=460800
tlora_pager.menu.UploadSpeed.460800.macosx=460800
tlora_pager.menu.UploadSpeed.460800.upload.speed=460800
tlora_pager.menu.UploadSpeed.512000.windows=512000
tlora_pager.menu.UploadSpeed.512000.upload.speed=512000
tlora_pager.menu.DebugLevel.none=None
tlora_pager.menu.DebugLevel.none.build.code_debug=0
tlora_pager.menu.DebugLevel.error=Error
tlora_pager.menu.DebugLevel.error.build.code_debug=1
tlora_pager.menu.DebugLevel.warn=Warn
tlora_pager.menu.DebugLevel.warn.build.code_debug=2
tlora_pager.menu.DebugLevel.info=Info
tlora_pager.menu.DebugLevel.info.build.code_debug=3
tlora_pager.menu.DebugLevel.debug=Debug
tlora_pager.menu.DebugLevel.debug.build.code_debug=4
tlora_pager.menu.DebugLevel.verbose=Verbose
tlora_pager.menu.DebugLevel.verbose.build.code_debug=5
tlora_pager.menu.EraseFlash.none=Disabled
tlora_pager.menu.EraseFlash.none.upload.erase_cmd=
tlora_pager.menu.EraseFlash.all=Enabled
tlora_pager.menu.EraseFlash.all.upload.erase_cmd=-e
tlora_pager.menu.Revision.Radio_SX1280=Radio-SX1280
tlora_pager.menu.Revision.Radio_SX1280.build.board=LILYGO_LORA_SX1280
tlora_pager.menu.Revision.Radio_SX1262=Radio-SX1262
tlora_pager.menu.Revision.Radio_SX1262.build.board=LILYGO_LORA_SX1262
tlora_pager.menu.Revision.Radio_CC1101=Radio-CC1101
tlora_pager.menu.Revision.Radio_CC1101.build.board=LILYGO_LORA_CC1101
##############################################################
micros2.name=microS2
@ -41085,8 +41250,8 @@ Geekble_Nano_ESP32S3.upload.tool.default=esptool_py
Geekble_Nano_ESP32S3.upload.tool.network=esp_ota
Geekble_Nano_ESP32S3.upload.maximum_size=1310720
Geekble_Nano_ESP32S3.upload.maximum_data_size=327680
Geekble_Nano_ESP32S3.upload.speed=921600
Geekble_Nano_ESP32S3.upload.flags=
Geekble_Nano_ESP32S3.upload.extra_flags=
Geekble_Nano_ESP32S3.upload.use_1200bps_touch=false
@ -41112,61 +41277,18 @@ Geekble_Nano_ESP32S3.build.flash_size=4MB
Geekble_Nano_ESP32S3.build.flash_freq=80m
Geekble_Nano_ESP32S3.build.flash_mode=dio
Geekble_Nano_ESP32S3.build.boot=qio
Geekble_Nano_ESP32S3.build.boot_freq=80m
Geekble_Nano_ESP32S3.build.partitions=default
Geekble_Nano_ESP32S3.build.defines=
Geekble_Nano_ESP32S3.build.loop_core=
Geekble_Nano_ESP32S3.build.event_core=
Geekble_Nano_ESP32S3.build.psram_type=qspi
Geekble_Nano_ESP32S3.build.memory_type={build.boot}_{build.psram_type}
Geekble_Nano_ESP32S3.build.memory_type=qio_qspi
Geekble_Nano_ESP32S3.build.loop_core=-DARDUINO_RUNNING_CORE=1
Geekble_Nano_ESP32S3.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
Geekble_Nano_ESP32S3.menu.PSRAM.disabled=Disabled
Geekble_Nano_ESP32S3.menu.PSRAM.disabled.build.defines=
Geekble_Nano_ESP32S3.menu.PSRAM.disabled.build.psram_type=qspi
Geekble_Nano_ESP32S3.menu.PSRAM.enabled=Enabled
Geekble_Nano_ESP32S3.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
Geekble_Nano_ESP32S3.menu.PSRAM.enabled.build.psram_type=qspi
Geekble_Nano_ESP32S3.menu.FlashMode.qio=QIO 80MHz
Geekble_Nano_ESP32S3.menu.FlashMode.qio.build.flash_mode=dio
Geekble_Nano_ESP32S3.menu.FlashMode.qio.build.boot=qio
Geekble_Nano_ESP32S3.menu.FlashMode.qio.build.boot_freq=80m
Geekble_Nano_ESP32S3.menu.FlashMode.qio.build.flash_freq=80m
Geekble_Nano_ESP32S3.menu.FlashMode.qio120=QIO 120MHz
Geekble_Nano_ESP32S3.menu.FlashMode.qio120.build.flash_mode=dio
Geekble_Nano_ESP32S3.menu.FlashMode.qio120.build.boot=qio
Geekble_Nano_ESP32S3.menu.FlashMode.qio120.build.boot_freq=120m
Geekble_Nano_ESP32S3.menu.FlashMode.qio120.build.flash_freq=80m
Geekble_Nano_ESP32S3.menu.LoopCore.1=Core 1
Geekble_Nano_ESP32S3.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1
Geekble_Nano_ESP32S3.menu.LoopCore.0=Core 0
Geekble_Nano_ESP32S3.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0
Geekble_Nano_ESP32S3.menu.EventsCore.1=Core 1
Geekble_Nano_ESP32S3.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
Geekble_Nano_ESP32S3.menu.EventsCore.0=Core 0
Geekble_Nano_ESP32S3.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0
Geekble_Nano_ESP32S3.menu.USBMode.hwcdc=Hardware CDC and JTAG
Geekble_Nano_ESP32S3.menu.USBMode.hwcdc.build.usb_mode=1
Geekble_Nano_ESP32S3.menu.USBMode.default=USB-OTG (TinyUSB)
Geekble_Nano_ESP32S3.menu.USBMode.default.build.usb_mode=0
Geekble_Nano_ESP32S3.menu.CDCOnBoot.default=Disabled
Geekble_Nano_ESP32S3.menu.CDCOnBoot.default.build.cdc_on_boot=0
Geekble_Nano_ESP32S3.menu.CDCOnBoot.cdc=Enabled
Geekble_Nano_ESP32S3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
Geekble_Nano_ESP32S3.menu.MSCOnBoot.default=Disabled
Geekble_Nano_ESP32S3.menu.MSCOnBoot.default.build.msc_on_boot=0
Geekble_Nano_ESP32S3.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode)
Geekble_Nano_ESP32S3.menu.MSCOnBoot.msc.build.msc_on_boot=1
Geekble_Nano_ESP32S3.menu.DFUOnBoot.default=Disabled
Geekble_Nano_ESP32S3.menu.DFUOnBoot.default.build.dfu_on_boot=0
Geekble_Nano_ESP32S3.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode)
Geekble_Nano_ESP32S3.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
Geekble_Nano_ESP32S3.menu.USBMode.default.build.cdc_on_boot=1
Geekble_Nano_ESP32S3.menu.USBMode.hwcdc=Hardware CDC and JTAG
Geekble_Nano_ESP32S3.menu.USBMode.hwcdc.build.usb_mode=1
Geekble_Nano_ESP32S3.menu.USBMode.hwcdc.build.cdc_on_boot=1
Geekble_Nano_ESP32S3.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB)
Geekble_Nano_ESP32S3.menu.UploadMode.cdc.upload.use_1200bps_touch=true
@ -41200,46 +41322,16 @@ Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker.upload.maximum_size=1966080
Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB=RainMaker 4MB No OTA
Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB.build.partitions=rainmaker_4MB_no_ota
Geekble_Nano_ESP32S3.menu.PartitionScheme.rainmaker_4MB.upload.maximum_size=4038656
Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs=OTA no FS (2MB APP with OTA)
Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs.build.custom_partitions=ota_nofs_4MB
Geekble_Nano_ESP32S3.menu.PartitionScheme.otanofs.upload.maximum_size=2031616
Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app=Max APP (4MB APP no OTA)
Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.build.custom_partitions=max_app_4MB
Geekble_Nano_ESP32S3.menu.PartitionScheme.all_app.upload.maximum_size=4063232
Geekble_Nano_ESP32S3.menu.PartitionScheme.custom=Custom
Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.build.partitions=
Geekble_Nano_ESP32S3.menu.PartitionScheme.custom.upload.maximum_size=16777216
Geekble_Nano_ESP32S3.menu.CPUFreq.240=240MHz (WiFi)
Geekble_Nano_ESP32S3.menu.CPUFreq.240.build.f_cpu=240000000L
Geekble_Nano_ESP32S3.menu.CPUFreq.160=160MHz (WiFi)
Geekble_Nano_ESP32S3.menu.CPUFreq.160.build.f_cpu=160000000L
Geekble_Nano_ESP32S3.menu.CPUFreq.80=80MHz (WiFi)
Geekble_Nano_ESP32S3.menu.CPUFreq.80.build.f_cpu=80000000L
Geekble_Nano_ESP32S3.menu.CPUFreq.40=40MHz
Geekble_Nano_ESP32S3.menu.CPUFreq.40.build.f_cpu=40000000L
Geekble_Nano_ESP32S3.menu.CPUFreq.20=20MHz
Geekble_Nano_ESP32S3.menu.CPUFreq.20.build.f_cpu=20000000L
Geekble_Nano_ESP32S3.menu.CPUFreq.10=10MHz
Geekble_Nano_ESP32S3.menu.CPUFreq.10.build.f_cpu=10000000L
Geekble_Nano_ESP32S3.menu.UploadSpeed.921600=921600
Geekble_Nano_ESP32S3.menu.UploadSpeed.921600.upload.speed=921600
Geekble_Nano_ESP32S3.menu.UploadSpeed.115200=115200
Geekble_Nano_ESP32S3.menu.UploadSpeed.115200.upload.speed=115200
Geekble_Nano_ESP32S3.menu.UploadSpeed.256000.windows=256000
Geekble_Nano_ESP32S3.menu.UploadSpeed.256000.upload.speed=256000
Geekble_Nano_ESP32S3.menu.UploadSpeed.230400.windows.upload.speed=256000
Geekble_Nano_ESP32S3.menu.UploadSpeed.230400=230400
Geekble_Nano_ESP32S3.menu.UploadSpeed.230400.upload.speed=230400
Geekble_Nano_ESP32S3.menu.UploadSpeed.460800.linux=460800
Geekble_Nano_ESP32S3.menu.UploadSpeed.460800.macosx=460800
Geekble_Nano_ESP32S3.menu.UploadSpeed.460800.upload.speed=460800
Geekble_Nano_ESP32S3.menu.UploadSpeed.512000.windows=512000
Geekble_Nano_ESP32S3.menu.UploadSpeed.512000.upload.speed=512000
Geekble_Nano_ESP32S3.menu.DebugLevel.none=None
Geekble_Nano_ESP32S3.menu.DebugLevel.none.build.code_debug=0
Geekble_Nano_ESP32S3.menu.DebugLevel.error=Error
@ -41258,7 +41350,6 @@ Geekble_Nano_ESP32S3.menu.EraseFlash.none.upload.erase_cmd=
Geekble_Nano_ESP32S3.menu.EraseFlash.all=Enabled
Geekble_Nano_ESP32S3.menu.EraseFlash.all.upload.erase_cmd=-e
##############################################################
waveshare_esp32_s3_zero.name=Waveshare ESP32-S3-Zero

View file

@ -133,7 +133,11 @@ void loop() {
// If key pressed for more than 10secs, factory reset Zigbee and reboot
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
delay(1000);
Zigbee.factoryReset();
// Optional set reset in factoryReset to false, to not restart device after erasing nvram, but set it to endless sleep manually instead
Zigbee.factoryReset(false);
Serial.println("Going to endless sleep, press RESET button or power off/on the device to wake up");
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
esp_deep_sleep_start();
}
}
}

View file

@ -91,21 +91,26 @@ bool ZigbeeCore::begin(zigbee_role_t role, bool erase_nvs) {
return started();
}
void ZigbeeCore::addEndpoint(ZigbeeEP *ep) {
bool ZigbeeCore::addEndpoint(ZigbeeEP *ep) {
ep_objects.push_back(ep);
log_d("Endpoint: %d, Device ID: 0x%04x", ep->_endpoint, ep->_device_id);
//Register clusters and ep_list to the ZigbeeCore class's ep_list
if (ep->_ep_config.endpoint == 0 || ep->_cluster_list == nullptr) {
log_e("Endpoint config or Cluster list is not initialized, EP not added to ZigbeeCore's EP list");
return;
return false;
}
esp_err_t ret = ESP_OK;
if (ep->_device_id == ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID) {
esp_zb_ep_list_add_gateway_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
ret = esp_zb_ep_list_add_gateway_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
} else {
esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
ret = esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
}
if (ret != ESP_OK) {
log_e("Failed to add endpoint: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
static void esp_zb_task(void *pvParameters) {
@ -368,16 +373,22 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
case ESP_ZB_ZDO_SIGNAL_LEAVE: // End Device + Router
// Device was removed from the network, factory reset the device
if ((zigbee_role_t)Zigbee.getRole() != ZIGBEE_COORDINATOR) {
Zigbee.factoryReset();
Zigbee.factoryReset(true);
}
break;
default: log_v("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break;
}
}
void ZigbeeCore::factoryReset() {
log_v("Factory resetting Zigbee stack, device will reboot");
esp_zb_factory_reset();
void ZigbeeCore::factoryReset(bool restart) {
if (restart) {
log_v("Factory resetting Zigbee stack, device will reboot");
esp_zb_factory_reset();
} else {
log_v("Factory resetting Zigbee NVRAM to factory default");
log_w("The device will not reboot, to take effect please reboot the device manually");
esp_zb_zcl_reset_nvram_to_factory_default();
}
}
void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor) {

View file

@ -129,7 +129,7 @@ public:
return _role;
}
void addEndpoint(ZigbeeEP *ep);
bool addEndpoint(ZigbeeEP *ep);
//void removeEndpoint(ZigbeeEP *ep);
void setRadioConfig(esp_zb_radio_config_t config);
@ -164,7 +164,7 @@ public:
zigbee_scan_result_t *getScanResult();
void scanDelete();
void factoryReset();
void factoryReset(bool restart = true);
// Friend function declaration to allow access to private members
friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct);

View file

@ -32,71 +32,95 @@ void ZigbeeEP::setVersion(uint8_t version) {
_ep_config.app_device_version = version;
}
void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
bool ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
// Convert manufacturer to ZCL string
size_t length = strlen(name);
if (length > 32) {
log_e("Manufacturer name is too long");
return;
size_t name_length = strlen(name);
size_t model_length = strlen(model);
if (name_length > 32 || model_length > 32) {
log_e("Manufacturer or model name is too long");
return false;
}
// Allocate a new array of size length + 2 (1 for the length, 1 for null terminator)
char *zb_name = new char[length + 2];
char *zb_name = new char[name_length + 2];
char *zb_model = new char[model_length + 2];
// Store the length as the first element
zb_name[0] = static_cast<char>(length); // Cast size_t to char
zb_name[0] = static_cast<char>(name_length); // Cast size_t to char
zb_model[0] = static_cast<char>(model_length);
// Use memcpy to copy the characters to the result array
memcpy(zb_name + 1, name, length);
memcpy(zb_name + 1, name, name_length);
memcpy(zb_model + 1, model, model_length);
// Null-terminate the array
zb_name[length + 1] = '\0';
// Convert model to ZCL string
length = strlen(model);
if (length > 32) {
log_e("Model name is too long");
delete[] zb_name;
return;
}
char *zb_model = new char[length + 2];
zb_model[0] = static_cast<char>(length);
memcpy(zb_model + 1, model, length);
zb_model[length + 1] = '\0';
zb_name[name_length + 1] = '\0';
zb_model[model_length + 1] = '\0';
// Get the basic cluster and update the manufacturer and model attributes
esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name);
esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model);
esp_err_t ret_name = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name);
if (ret_name != ESP_OK) {
log_e("Failed to set manufacturer: 0x%x: %s", ret_name, esp_err_to_name(ret_name));
}
esp_err_t ret_model = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model);
if (ret_model != ESP_OK) {
log_e("Failed to set model: 0x%x: %s", ret_model, esp_err_to_name(ret_model));
}
delete[] zb_name;
delete[] zb_model;
return ret_name == ESP_OK && ret_model == ESP_OK;
}
void ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_percentage) {
bool ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_percentage) {
esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (void *)&power_source);
esp_err_t ret = esp_zb_cluster_update_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (void *)&power_source);
if (ret != ESP_OK) {
log_e("Failed to set power source: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
if (power_source == ZB_POWER_SOURCE_BATTERY) {
// Add power config cluster and battery percentage attribute
if (battery_percentage > 100) {
battery_percentage = 100;
}
battery_percentage = battery_percentage * 2;
esp_zb_attribute_list_t *power_config_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG);
esp_zb_power_config_cluster_add_attr(power_config_cluster, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, (void *)&battery_percentage);
esp_zb_cluster_list_add_power_config_cluster(_cluster_list, power_config_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
ret = esp_zb_power_config_cluster_add_attr(power_config_cluster, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, (void *)&battery_percentage);
if (ret != ESP_OK) {
log_e("Failed to add battery percentage attribute: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_list_add_power_config_cluster(_cluster_list, power_config_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add power config cluster: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
}
_power_source = power_source;
return true;
}
void ZigbeeEP::setBatteryPercentage(uint8_t percentage) {
bool ZigbeeEP::setBatteryPercentage(uint8_t percentage) {
// 100% = 200 in decimal, 0% = 0
// Convert percentage to 0-200 range
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
if (percentage > 100) {
percentage = 100;
}
percentage = percentage * 2;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, &percentage,
false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set battery percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
log_v("Battery percentage updated");
return true;
}
void ZigbeeEP::reportBatteryPercentage() {
bool ZigbeeEP::reportBatteryPercentage() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -107,9 +131,14 @@ void ZigbeeEP::reportBatteryPercentage() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to report battery percentage: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Battery percentage reported");
return true;
}
char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
@ -134,7 +163,9 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
read_req.attr_field = attributes;
// clear read manufacturer
if (_read_manufacturer != nullptr) {
free(_read_manufacturer);
}
_read_manufacturer = nullptr;
esp_zb_lock_acquire(portMAX_DELAY);
@ -170,7 +201,9 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_add
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
read_req.attr_field = attributes;
// clear read model
if (_read_model != nullptr) {
free(_read_model);
}
_read_model = nullptr;
esp_zb_lock_acquire(portMAX_DELAY);
@ -240,7 +273,7 @@ void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) {
}
}
void ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) {
bool ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) {
time_t utc_time = 0;
// Check if time is set
if (time.tm_year > 0) {
@ -250,28 +283,63 @@ void ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) {
// Create time cluster server attributes
esp_zb_attribute_list_t *time_cluster_server = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TIME);
esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, (void *)&gmt_offset);
esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, (void *)&utc_time);
esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, (void *)&_time_status);
esp_err_t ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, (void *)&gmt_offset);
if (ret != ESP_OK) {
log_e("Failed to add time zone attribute: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, (void *)&utc_time);
if (ret != ESP_OK) {
log_e("Failed to add time attribute: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_time_cluster_add_attr(time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, (void *)&_time_status);
if (ret != ESP_OK) {
log_e("Failed to add time status attribute: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
// Create time cluster client attributes
esp_zb_attribute_list_t *time_cluster_client = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TIME);
// Add time clusters to cluster list
esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_server, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_client, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
ret = esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_server, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add time cluster (server role): 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_client, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add time cluster (client role): 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeEP::setTime(tm time) {
bool ZigbeeEP::setTime(tm time) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
time_t utc_time = mktime(&time);
log_d("Setting time to %lld", utc_time);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, &utc_time, false);
ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, &utc_time, false);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set time: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeEP::setTimezone(int32_t gmt_offset) {
bool ZigbeeEP::setTimezone(int32_t gmt_offset) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_d("Setting timezone to %d", gmt_offset);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &gmt_offset, false);
ret =
esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &gmt_offset, false);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set timezone: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
@ -390,7 +458,7 @@ void ZigbeeEP::zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute) {
// uint8_t max_data_size; /*!< The maximum size of OTA data */
// } esp_zb_zcl_ota_upgrade_client_variable_t;
void ZigbeeEP::addOTAClient(
bool ZigbeeEP::addOTAClient(
uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer, uint16_t image_type, uint8_t max_data_size
) {
@ -410,11 +478,27 @@ void ZigbeeEP::addOTAClient(
uint16_t ota_upgrade_server_addr = 0xffff;
uint8_t ota_upgrade_server_ep = 0xff;
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config));
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr));
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE));
esp_err_t ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config);
if (ret != ESP_OK) {
log_e("Failed to add OTA client data: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr);
if (ret != ESP_OK) {
log_e("Failed to add OTA server address: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep);
if (ret != ESP_OK) {
log_e("Failed to add OTA server endpoint: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add OTA cluster: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) {
@ -445,4 +529,42 @@ void ZigbeeEP::requestOTAUpdate() {
esp_zb_lock_release();
}
const char *ZigbeeEP::esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status) {
switch (status) {
case ESP_ZB_ZCL_STATUS_SUCCESS: return "Success";
case ESP_ZB_ZCL_STATUS_FAIL: return "Fail";
case ESP_ZB_ZCL_STATUS_NOT_AUTHORIZED: return "Not authorized";
case ESP_ZB_ZCL_STATUS_MALFORMED_CMD: return "Malformed command";
case ESP_ZB_ZCL_STATUS_UNSUP_CLUST_CMD: return "Unsupported cluster command";
case ESP_ZB_ZCL_STATUS_UNSUP_GEN_CMD: return "Unsupported general command";
case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD: return "Unsupported manufacturer cluster command";
case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD: return "Unsupported manufacturer general command";
case ESP_ZB_ZCL_STATUS_INVALID_FIELD: return "Invalid field";
case ESP_ZB_ZCL_STATUS_UNSUP_ATTRIB: return "Unsupported attribute";
case ESP_ZB_ZCL_STATUS_INVALID_VALUE: return "Invalid value";
case ESP_ZB_ZCL_STATUS_READ_ONLY: return "Read only";
case ESP_ZB_ZCL_STATUS_INSUFF_SPACE: return "Insufficient space";
case ESP_ZB_ZCL_STATUS_DUPE_EXISTS: return "Duplicate exists";
case ESP_ZB_ZCL_STATUS_NOT_FOUND: return "Not found";
case ESP_ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB: return "Unreportable attribute";
case ESP_ZB_ZCL_STATUS_INVALID_TYPE: return "Invalid type";
case ESP_ZB_ZCL_STATUS_WRITE_ONLY: return "Write only";
case ESP_ZB_ZCL_STATUS_INCONSISTENT: return "Inconsistent";
case ESP_ZB_ZCL_STATUS_ACTION_DENIED: return "Action denied";
case ESP_ZB_ZCL_STATUS_TIMEOUT: return "Timeout";
case ESP_ZB_ZCL_STATUS_ABORT: return "Abort";
case ESP_ZB_ZCL_STATUS_INVALID_IMAGE: return "Invalid OTA upgrade image";
case ESP_ZB_ZCL_STATUS_WAIT_FOR_DATA: return "Server does not have data block available yet";
case ESP_ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE: return "No image available";
case ESP_ZB_ZCL_STATUS_REQUIRE_MORE_IMAGE: return "Require more image";
case ESP_ZB_ZCL_STATUS_NOTIFICATION_PENDING: return "Notification pending";
case ESP_ZB_ZCL_STATUS_HW_FAIL: return "Hardware failure";
case ESP_ZB_ZCL_STATUS_SW_FAIL: return "Software failure";
case ESP_ZB_ZCL_STATUS_CALIB_ERR: return "Calibration error";
case ESP_ZB_ZCL_STATUS_UNSUP_CLUST: return "Cluster is not found on the target endpoint";
case ESP_ZB_ZCL_STATUS_LIMIT_REACHED: return "Limit reached";
default: return "Unknown status";
}
}
#endif // CONFIG_ZB_ENABLED

View file

@ -70,21 +70,21 @@ public:
}
// Set Manufacturer name and model
void setManufacturerAndModel(const char *name, const char *model);
bool setManufacturerAndModel(const char *name, const char *model);
// Methods to read manufacturer and model name from selected endpoint and short address
char *readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr);
char *readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr);
// Set Power source and battery percentage for battery powered devices
void setPowerSource(zb_power_source_t power_source, uint8_t percentage = 255);
void setBatteryPercentage(uint8_t percentage);
void reportBatteryPercentage();
bool setPowerSource(zb_power_source_t power_source, uint8_t percentage = 255);
bool setBatteryPercentage(uint8_t percentage);
bool reportBatteryPercentage();
// Set time
void addTimeCluster(tm time = {}, int32_t gmt_offset = 0); // gmt offset in seconds
void setTime(tm time);
void setTimezone(int32_t gmt_offset);
bool addTimeCluster(tm time = {}, int32_t gmt_offset = 0); // gmt offset in seconds
bool setTime(tm time);
bool setTimezone(int32_t gmt_offset);
// Get time from Coordinator or specific endpoint (blocking until response)
struct tm getTime(uint8_t endpoint = 1, int32_t short_addr = 0x0000, esp_zb_ieee_addr_t ieee_addr = {0});
@ -104,8 +104,9 @@ public:
* @param manufacturer The manufacturer code (default: 0x1001).
* @param image_type The image type code (default: 0x1011).
* @param max_data_size The maximum data size for OTA transfer (default and recommended: 223).
* @return true if the OTA client was added successfully, false otherwise.
*/
void addOTAClient(
bool addOTAClient(
uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer = 0x1001, uint16_t image_type = 0x1011,
uint8_t max_data_size = 223
);
@ -114,10 +115,10 @@ public:
*/
void requestOTAUpdate();
// findEndpoind may be implemented by EPs to find and bind devices
// findEndpoint may be implemented by EPs to find and bind devices
virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {};
//list of all handlers function calls, to be override by EPs implementation
// list of all handlers function calls, to be override by EPs implementation
virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {};
virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {};
virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
@ -144,6 +145,9 @@ private:
int32_t _read_timezone;
protected:
// Convert ZCL status to name
const char *esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status);
uint8_t _endpoint;
esp_zb_ha_standard_devices_t _device_id;
esp_zb_endpoint_config_t _ep_config;

View file

@ -1,38 +1,35 @@
#include "ZigbeeAnalog.h"
#if CONFIG_ZB_ENABLED
esp_zb_cluster_list_t *zigbee_analog_clusters_create(zigbee_analog_cfg_t *analog_sensor) {
esp_zb_basic_cluster_cfg_t *basic_cfg = analog_sensor ? &(analog_sensor->basic_cfg) : NULL;
esp_zb_identify_cluster_cfg_t *identify_cfg = analog_sensor ? &(analog_sensor->identify_cfg) : NULL;
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
return cluster_list;
}
ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) {
_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID;
//Create custom analog sensor configuration
zigbee_analog_cfg_t analog_cfg = ZIGBEE_DEFAULT_ANALOG_CONFIG();
_cluster_list = zigbee_analog_clusters_create(&analog_cfg);
//Create basic analog sensor clusters without configuration
_cluster_list = esp_zb_zcl_cluster_list_create();
esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeeAnalog::addAnalogValue() {
esp_zb_cluster_list_add_analog_value_cluster(_cluster_list, esp_zb_analog_value_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
_analog_clusters |= ANALOG_VALUE;
}
void ZigbeeAnalog::addAnalogInput() {
esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
bool ZigbeeAnalog::addAnalogInput() {
esp_err_t ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add Analog Input cluster: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
_analog_clusters |= ANALOG_INPUT;
return true;
}
void ZigbeeAnalog::addAnalogOutput() {
esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
bool ZigbeeAnalog::addAnalogOutput() {
esp_err_t ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
if (ret != ESP_OK) {
log_e("Failed to add Analog Output cluster: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
_analog_clusters |= ANALOG_OUTPUT;
return true;
}
//set attribute method -> method overridden in child class
@ -57,35 +54,26 @@ void ZigbeeAnalog::analogOutputChanged(float analog_output) {
}
}
void ZigbeeAnalog::setAnalogValue(float analog) {
if (!(_analog_clusters & ANALOG_VALUE)) {
log_e("Analog Value cluster not added");
return;
}
// float zb_analog = analog;
log_d("Setting analog value to %.1f", analog);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_VALUE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ANALOG_VALUE_PRESENT_VALUE_ID, &analog, false
);
esp_zb_lock_release();
}
void ZigbeeAnalog::setAnalogInput(float analog) {
bool ZigbeeAnalog::setAnalogInput(float analog) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
if (!(_analog_clusters & ANALOG_INPUT)) {
log_e("Analog Input cluster not added");
return;
return false;
}
// float zb_analog = analog;
log_d("Setting analog input to %.1f", analog);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID, &analog, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set analog input: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeAnalog::reportAnalogInput() {
bool ZigbeeAnalog::reportAnalogInput() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -96,12 +84,17 @@ void ZigbeeAnalog::reportAnalogInput() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send Analog Input report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Analog Input report sent");
return true;
}
void ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
bool ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -118,8 +111,13 @@ void ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_i
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set Analog Input reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -9,32 +9,15 @@
#include "ZigbeeEP.h"
#include "ha/esp_zigbee_ha_standard.h"
// clang-format off
#define ZIGBEE_DEFAULT_ANALOG_CONFIG() \
{ \
.basic_cfg = \
{ \
.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \
.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \
}, \
.identify_cfg = \
{ \
.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \
}, \
}
// clang-format on
//enum for bits set to check what analog cluster were added
enum zigbee_analog_clusters {
ANALOG_VALUE = 1,
ANALOG_INPUT = 2,
ANALOG_OUTPUT = 4
ANALOG_INPUT = 1,
ANALOG_OUTPUT = 2
};
typedef struct zigbee_analog_cfg_s {
esp_zb_basic_cluster_cfg_t basic_cfg;
esp_zb_identify_cluster_cfg_t identify_cfg;
esp_zb_analog_value_cluster_cfg_t analog_value_cfg;
esp_zb_analog_output_cluster_cfg_t analog_output_cfg;
esp_zb_analog_input_cluster_cfg_t analog_input_cfg;
} zigbee_analog_cfg_t;
@ -45,24 +28,22 @@ public:
~ZigbeeAnalog() {}
// Add analog clusters
void addAnalogValue();
void addAnalogInput();
void addAnalogOutput();
bool addAnalogInput();
bool addAnalogOutput();
// Use to set a cb function to be called on analog output change
void onAnalogOutputChange(void (*callback)(float analog)) {
_on_analog_output_change = callback;
}
// Set the analog value / input
void setAnalogValue(float analog);
void setAnalogInput(float analog);
// Set the analog input value
bool setAnalogInput(float analog);
// Report Analog Input
void reportAnalogInput();
// Report Analog Input value
bool reportAnalogInput();
// Set reporting for Analog Input
void setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta);
bool setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta);
private:
void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;

View file

@ -24,25 +24,39 @@ ZigbeeCarbonDioxideSensor::ZigbeeCarbonDioxideSensor(uint8_t endpoint) : ZigbeeE
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeeCarbonDioxideSensor::setMinMaxValue(float min, float max) {
bool ZigbeeCarbonDioxideSensor::setMinMaxValue(float min, float max) {
float zb_min = min / 1000000.0f;
float zb_max = max / 1000000.0f;
esp_zb_attribute_list_t *carbon_dioxide_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min);
esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max);
esp_err_t ret = esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeCarbonDioxideSensor::setTolerance(float tolerance) {
bool ZigbeeCarbonDioxideSensor::setTolerance(float tolerance) {
float zb_tolerance = tolerance / 1000000.0f;
esp_zb_attribute_list_t *carbon_dioxide_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_carbon_dioxide_measurement_cluster_add_attr(
esp_err_t ret = esp_zb_carbon_dioxide_measurement_cluster_add_attr(
carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance
);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeCarbonDioxideSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
bool ZigbeeCarbonDioxideSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -60,24 +74,35 @@ void ZigbeeCarbonDioxideSensor::setReporting(uint16_t min_interval, uint16_t max
memcpy(&reporting_info.u.send_info.delta.s32, &delta_f, sizeof(float));
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeCarbonDioxideSensor::setCarbonDioxide(float carbon_dioxide) {
bool ZigbeeCarbonDioxideSensor::setCarbonDioxide(float carbon_dioxide) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
float zb_carbon_dioxide = carbon_dioxide / 1000000.0f;
log_v("Updating carbon dioxide sensor value...");
/* Update carbon dioxide sensor measured value */
log_d("Setting carbon dioxide to %0.1f", carbon_dioxide);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID,
&zb_carbon_dioxide, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set carbon dioxide: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeCarbonDioxideSensor::report() {
bool ZigbeeCarbonDioxideSensor::report() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -88,9 +113,14 @@ void ZigbeeCarbonDioxideSensor::report() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send carbon dioxide report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Carbon dioxide report sent");
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -42,20 +42,20 @@ public:
~ZigbeeCarbonDioxideSensor() {}
// Set the carbon dioxide value in ppm
void setCarbonDioxide(float carbon_dioxide);
bool setCarbonDioxide(float carbon_dioxide);
// Set the min and max value for the carbon dioxide sensor in ppm
void setMinMaxValue(float min, float max);
bool setMinMaxValue(float min, float max);
// Set the tolerance value for the carbon dioxide sensor in ppm
void setTolerance(float tolerance);
bool setTolerance(float tolerance);
// Set the reporting interval for carbon dioxide measurement in seconds and delta (carbon dioxide change in ppm)
// NOTE: Delta reporting is currently not supported by the carbon dioxide sensor
void setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
// Report the carbon dioxide value
void report();
bool report();
};
#endif // CONFIG_ZB_ENABLED

View file

@ -117,7 +117,8 @@ void ZigbeeColorDimmableLight::lightChanged() {
}
}
void ZigbeeColorDimmableLight::setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue) {
bool ZigbeeColorDimmableLight::setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
//Update all attributes
_current_state = state;
_current_level = level;
@ -126,55 +127,83 @@ void ZigbeeColorDimmableLight::setLight(bool state, uint8_t level, uint8_t red,
espXyColor_t xy_color = espRgbColorToXYColor(_current_color);
espHsvColor_t hsv_color = espRgbColorToHsvColor(_current_color);
uint8_t hue = (uint8_t)hsv_color.h;
log_v("Updating light state: %d, level: %d, color: %d, %d, %d", state, level, red, green, blue);
/* Update light clusters */
esp_zb_lock_acquire(portMAX_DELAY);
//set on/off state
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
//set level
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false
);
//set xy color
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light level: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
//set x color
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, &xy_color.x, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light xy color: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
//set y color
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, &xy_color.y, false
);
//set hsv color
uint8_t hue = (uint8_t)hsv_color.h;
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light y color: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
//set hue
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, &hue, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light hue: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
//set saturation
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, &hsv_color.s, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light saturation: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
void ZigbeeColorDimmableLight::setLightState(bool state) {
setLight(state, _current_level, _current_color.r, _current_color.g, _current_color.b);
bool ZigbeeColorDimmableLight::setLightState(bool state) {
return setLight(state, _current_level, _current_color.r, _current_color.g, _current_color.b);
}
void ZigbeeColorDimmableLight::setLightLevel(uint8_t level) {
setLight(_current_state, level, _current_color.r, _current_color.g, _current_color.b);
bool ZigbeeColorDimmableLight::setLightLevel(uint8_t level) {
return setLight(_current_state, level, _current_color.r, _current_color.g, _current_color.b);
}
void ZigbeeColorDimmableLight::setLightColor(uint8_t red, uint8_t green, uint8_t blue) {
setLight(_current_state, _current_level, red, green, blue);
bool ZigbeeColorDimmableLight::setLightColor(uint8_t red, uint8_t green, uint8_t blue) {
return setLight(_current_state, _current_level, red, green, blue);
}
void ZigbeeColorDimmableLight::setLightColor(espRgbColor_t rgb_color) {
setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
bool ZigbeeColorDimmableLight::setLightColor(espRgbColor_t rgb_color) {
return setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
}
void ZigbeeColorDimmableLight::setLightColor(espHsvColor_t hsv_color) {
bool ZigbeeColorDimmableLight::setLightColor(espHsvColor_t hsv_color) {
espRgbColor_t rgb_color = espHsvColorToRgbColor(hsv_color);
setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
return setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
}
#endif // CONFIG_ZB_ENABLED

View file

@ -62,12 +62,12 @@ public:
lightChanged();
}
void setLightState(bool state);
void setLightLevel(uint8_t level);
void setLightColor(uint8_t red, uint8_t green, uint8_t blue);
void setLightColor(espRgbColor_t rgb_color);
void setLightColor(espHsvColor_t hsv_color);
void setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue);
bool setLightState(bool state);
bool setLightLevel(uint8_t level);
bool setLightColor(uint8_t red, uint8_t green, uint8_t blue);
bool setLightColor(espRgbColor_t rgb_color);
bool setLightColor(espHsvColor_t hsv_color);
bool setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue);
bool getLightState() {
return _current_state;

View file

@ -29,29 +29,39 @@ void ZigbeeContactSwitch::setIASClientEndpoint(uint8_t ep_number) {
_ias_cie_endpoint = ep_number;
}
void ZigbeeContactSwitch::setClosed() {
bool ZigbeeContactSwitch::setClosed() {
log_v("Setting Contact switch to closed");
uint8_t closed = 0; // ALARM1 = 0, ALARM2 = 0
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
esp_err_t ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &closed, false
);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set contact switch to closed: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
_zone_status = closed;
report();
return report();
}
void ZigbeeContactSwitch::setOpen() {
bool ZigbeeContactSwitch::setOpen() {
log_v("Setting Contact switch to open");
uint8_t open = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 | ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2; // ALARM1 = 1, ALARM2 = 1
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false);
esp_err_t ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false
);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set contact switch to open: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
_zone_status = open;
report();
return report();
}
void ZigbeeContactSwitch::report() {
bool ZigbeeContactSwitch::report() {
/* Send IAS Zone status changed notification command */
esp_zb_zcl_ias_zone_status_change_notif_cmd_t status_change_notif_cmd;
@ -66,9 +76,14 @@ void ZigbeeContactSwitch::report() {
status_change_notif_cmd.delay = 0;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd);
esp_err_t ret = esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send IAS Zone status changed notification: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("IAS Zone status changed notification sent");
return true;
}
void ZigbeeContactSwitch::zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) {

View file

@ -48,13 +48,13 @@ public:
void setIASClientEndpoint(uint8_t ep_number);
// Set the contact switch value to closed
void setClosed();
bool setClosed();
// Set the contact switch value to open
void setOpen();
bool setOpen();
// Report the contact switch value, done automatically after setting the position
void report();
bool report();
private:
void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) override;

View file

@ -1,4 +1,3 @@
#include "ZigbeeDimmableLight.h"
#if CONFIG_ZB_ENABLED
@ -52,7 +51,8 @@ void ZigbeeDimmableLight::lightChanged() {
}
}
void ZigbeeDimmableLight::setLight(bool state, uint8_t level) {
bool ZigbeeDimmableLight::setLight(bool state, uint8_t level) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
// Update all attributes
_current_state = state;
_current_level = level;
@ -62,22 +62,32 @@ void ZigbeeDimmableLight::setLight(bool state, uint8_t level) {
/* Update light clusters */
esp_zb_lock_acquire(portMAX_DELAY);
// set on/off state
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
// set level
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light level: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
void ZigbeeDimmableLight::setLightState(bool state) {
setLight(state, _current_level);
bool ZigbeeDimmableLight::setLightState(bool state) {
return setLight(state, _current_level);
}
void ZigbeeDimmableLight::setLightLevel(uint8_t level) {
setLight(_current_state, level);
bool ZigbeeDimmableLight::setLightLevel(uint8_t level) {
return setLight(_current_state, level);
}
esp_zb_cluster_list_t *ZigbeeDimmableLight::zigbee_dimmable_light_clusters_create(zigbee_dimmable_light_cfg_t *light_cfg) {

View file

@ -76,9 +76,9 @@ public:
lightChanged();
}
void setLightState(bool state);
void setLightLevel(uint8_t level);
void setLight(bool state, uint8_t level);
bool setLightState(bool state);
bool setLightLevel(uint8_t level);
bool setLight(bool state, uint8_t level);
bool getLightState() {
return _current_state;
@ -89,7 +89,6 @@ public:
private:
void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;
void lightChanged();
// callback function to be called on light change (State, Level)
void (*_on_light_change)(bool, uint8_t);

View file

@ -29,41 +29,58 @@ void ZigbeeDoorWindowHandle::setIASClientEndpoint(uint8_t ep_number) {
_ias_cie_endpoint = ep_number;
}
void ZigbeeDoorWindowHandle::setClosed() {
bool ZigbeeDoorWindowHandle::setClosed() {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Setting Door/Window handle to closed");
uint8_t closed = 0; // ALARM1 = 0, ALARM2 = 0
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &closed, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set door/window handle to closed: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
_zone_status = closed;
report();
return report();
}
void ZigbeeDoorWindowHandle::setOpen() {
bool ZigbeeDoorWindowHandle::setOpen() {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Setting Door/Window handle to open");
uint8_t open = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 | ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2; // ALARM1 = 1, ALARM2 = 1
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false);
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &open, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set door/window handle to open: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
_zone_status = open;
report();
return report();
}
void ZigbeeDoorWindowHandle::setTilted() {
bool ZigbeeDoorWindowHandle::setTilted() {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Setting Door/Window handle to tilted");
uint8_t tilted = ESP_ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1; // ALARM1 = 1, ALARM2 = 0
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &tilted, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set door/window handle to tilted: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
_zone_status = tilted;
report();
return report();
}
void ZigbeeDoorWindowHandle::report() {
bool ZigbeeDoorWindowHandle::report() {
/* Send IAS Zone status changed notification command */
esp_zb_zcl_ias_zone_status_change_notif_cmd_t status_change_notif_cmd;
@ -77,10 +94,12 @@ void ZigbeeDoorWindowHandle::report() {
status_change_notif_cmd.zone_id = _zone_id;
status_change_notif_cmd.delay = 0;
//NOTE: Check result of esp_zb_zcl_ias_zone_status_change_notif_cmd_req() and return true if success, false if failure
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_ias_zone_status_change_notif_cmd_req(&status_change_notif_cmd);
esp_zb_lock_release();
log_v("IAS Zone status changed notification sent");
return true;
}
void ZigbeeDoorWindowHandle::zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) {

View file

@ -49,16 +49,16 @@ public:
void setIASClientEndpoint(uint8_t ep_number);
// Set the door/window handle value to closed
void setClosed();
bool setClosed();
// Set the door/window handle value to open
void setOpen();
bool setOpen();
// Set the door/window handle value to tilted
void setTilted();
bool setTilted();
// Report the door/window handle value, done automatically after setting the position
void report();
bool report();
private:
void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) override;

View file

@ -22,24 +22,37 @@ ZigbeeFlowSensor::ZigbeeFlowSensor(uint8_t endpoint) : ZigbeeEP(endpoint) {
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeeFlowSensor::setMinMaxValue(float min, float max) {
bool ZigbeeFlowSensor::setMinMaxValue(float min, float max) {
uint16_t zb_min = (uint16_t)(min * 10);
uint16_t zb_max = (uint16_t)(max * 10);
esp_zb_attribute_list_t *flow_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min);
esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max);
esp_err_t ret = esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeFlowSensor::setTolerance(float tolerance) {
// Convert tolerance to ZCL uint16_t
bool ZigbeeFlowSensor::setTolerance(float tolerance) {
uint16_t zb_tolerance = (uint16_t)(tolerance * 10);
esp_zb_attribute_list_t *flow_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_flow_meas_cluster_add_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
esp_err_t ret = esp_zb_flow_meas_cluster_add_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeFlowSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
bool ZigbeeFlowSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -54,24 +67,39 @@ void ZigbeeFlowSensor::setReporting(uint16_t min_interval, uint16_t max_interval
reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 10); // Convert delta to ZCL uint16_t
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeFlowSensor::setFlow(float flow) {
bool ZigbeeFlowSensor::setFlow(float flow) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
uint16_t zb_flow = (uint16_t)(flow * 10);
log_v("Updating flow sensor value...");
/* Update temperature sensor measured value */
log_d("Setting flow to %d", zb_flow);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID, &zb_flow, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set flow value: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeFlowSensor::report() {
bool ZigbeeFlowSensor::report() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -82,9 +110,15 @@ void ZigbeeFlowSensor::report() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send flow report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Flow report sent");
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -42,19 +42,19 @@ public:
~ZigbeeFlowSensor() {}
// Set the flow value in 0,1 m3/h
void setFlow(float value);
bool setFlow(float value);
// Set the min and max value for the flow sensor in 0,1 m3/h
void setMinMaxValue(float min, float max);
bool setMinMaxValue(float min, float max);
// Set the tolerance value for the flow sensor in 0,01 m3/h
void setTolerance(float tolerance);
bool setTolerance(float tolerance);
// Set the reporting interval for flow measurement in seconds and delta (temp change in 0,1 m3/h)
void setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
// Report the flow value
void report();
bool report();
};
#endif // CONFIG_ZB_ENABLED

View file

@ -10,20 +10,34 @@ ZigbeeIlluminanceSensor::ZigbeeIlluminanceSensor(uint8_t endpoint) : ZigbeeEP(en
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeeIlluminanceSensor::setMinMaxValue(uint16_t min, uint16_t max) {
bool ZigbeeIlluminanceSensor::setMinMaxValue(uint16_t min, uint16_t max) {
esp_zb_attribute_list_t *light_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&min);
esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&max);
esp_err_t ret = esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeIlluminanceSensor::setTolerance(uint16_t tolerance) {
bool ZigbeeIlluminanceSensor::setTolerance(uint16_t tolerance) {
esp_zb_attribute_list_t *light_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_illuminance_meas_cluster_add_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance);
esp_err_t ret = esp_zb_illuminance_meas_cluster_add_attr(light_measure_cluster, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeIlluminanceSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
bool ZigbeeIlluminanceSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -38,24 +52,37 @@ void ZigbeeIlluminanceSensor::setReporting(uint16_t min_interval, uint16_t max_i
reporting_info.u.send_info.delta.u16 = delta;
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeIlluminanceSensor::setIlluminance(uint16_t illuminanceValue) {
bool ZigbeeIlluminanceSensor::setIlluminance(uint16_t illuminanceValue) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Updating Illuminance...");
/* Update illuminance sensor measured illuminance */
log_d("Setting Illuminance to %d", illuminanceValue);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID,
&illuminanceValue, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set illuminance: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeIlluminanceSensor::report() {
bool ZigbeeIlluminanceSensor::report() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -66,9 +93,14 @@ void ZigbeeIlluminanceSensor::report() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send illuminance report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Illuminance report sent");
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -33,19 +33,19 @@ public:
~ZigbeeIlluminanceSensor() {}
// Set the illuminance value
void setIlluminance(uint16_t value);
bool setIlluminance(uint16_t value);
// Set the min and max value for the illuminance sensor
void setMinMaxValue(uint16_t min, uint16_t max);
bool setMinMaxValue(uint16_t min, uint16_t max);
// Set the tolerance value for the illuminance sensor
void setTolerance(uint16_t tolerance);
bool setTolerance(uint16_t tolerance);
// Set the reporting interval for illuminance measurement in seconds and delta
void setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
// Report the illuminance value
void report();
bool report();
};
#endif // CONFIG_ZB_ENABLED

View file

@ -33,17 +33,24 @@ void ZigbeeLight::lightChanged() {
}
}
void ZigbeeLight::setLight(bool state) {
bool ZigbeeLight::setLight(bool state) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
_current_state = state;
lightChanged();
log_v("Updating on/off light state to %d", state);
/* Update on/off light state */
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -23,7 +23,7 @@ public:
lightChanged();
}
// Use to control light state
void setLight(bool state);
bool setLight(bool state);
// Use to get light state
bool getLightState() {
return _current_state;

View file

@ -22,26 +22,41 @@ ZigbeeOccupancySensor::ZigbeeOccupancySensor(uint8_t endpoint) : ZigbeeEP(endpoi
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeeOccupancySensor::setSensorType(uint8_t sensor_type) {
bool ZigbeeOccupancySensor::setSensorType(uint8_t sensor_type) {
uint8_t sensor_type_bitmap = 1 << sensor_type;
esp_zb_attribute_list_t *occupancy_sens_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (void *)&sensor_type);
esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap);
esp_err_t ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (void *)&sensor_type);
if (ret != ESP_OK) {
log_e("Failed to set sensor type: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap);
if (ret != ESP_OK) {
log_e("Failed to set sensor type bitmap: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeOccupancySensor::setOccupancy(bool occupied) {
bool ZigbeeOccupancySensor::setOccupancy(bool occupied) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Updating occupancy sensor value...");
/* Update occupancy sensor value */
log_d("Setting occupancy to %d", occupied);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID, &occupied, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set occupancy: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeOccupancySensor::report() {
bool ZigbeeOccupancySensor::report() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -52,9 +67,14 @@ void ZigbeeOccupancySensor::report() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send occupancy report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Occupancy report sent");
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -42,13 +42,13 @@ public:
~ZigbeeOccupancySensor() {}
// Set the occupancy value. True for occupied, false for unoccupied
void setOccupancy(bool occupied);
bool setOccupancy(bool occupied);
// Set the sensor type, see esp_zb_zcl_occupancy_sensing_occupancy_sensor_type_t
void setSensorType(uint8_t sensor_type);
bool setSensorType(uint8_t sensor_type);
// Report the occupancy value
void report();
bool report();
};
#endif // CONFIG_ZB_ENABLED

View file

@ -22,21 +22,33 @@ ZigbeePressureSensor::ZigbeePressureSensor(uint8_t endpoint) : ZigbeeEP(endpoint
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
}
void ZigbeePressureSensor::setMinMaxValue(int16_t min, int16_t max) {
bool ZigbeePressureSensor::setMinMaxValue(int16_t min, int16_t max) {
esp_zb_attribute_list_t *pressure_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, (void *)&min);
esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, (void *)&max);
esp_err_t ret = esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, (void *)&min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, (void *)&max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeePressureSensor::setTolerance(uint16_t tolerance) {
bool ZigbeePressureSensor::setTolerance(uint16_t tolerance) {
esp_zb_attribute_list_t *pressure_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_pressure_meas_cluster_add_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance);
esp_err_t ret = esp_zb_pressure_meas_cluster_add_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
}
return ret == ESP_OK;
}
void ZigbeePressureSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
bool ZigbeePressureSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -52,22 +64,33 @@ void ZigbeePressureSensor::setReporting(uint16_t min_interval, uint16_t max_inte
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeePressureSensor::setPressure(int16_t pressure) {
bool ZigbeePressureSensor::setPressure(int16_t pressure) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Updating pressure sensor value...");
/* Update pressure sensor measured value */
log_d("Setting pressure to %d hPa", pressure);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, &pressure, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set pressure: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeePressureSensor::report() {
bool ZigbeePressureSensor::report() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -78,9 +101,14 @@ void ZigbeePressureSensor::report() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send pressure report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Pressure report sent");
return true;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -42,19 +42,19 @@ public:
~ZigbeePressureSensor() {}
// Set the pressure value in 1 hPa
void setPressure(int16_t value);
bool setPressure(int16_t value);
// Set the min and max value for the pressure sensor in 1 hPa
void setMinMaxValue(int16_t min, int16_t max);
bool setMinMaxValue(int16_t min, int16_t max);
// Set the tolerance value for the pressure sensor in 1 hPa
void setTolerance(uint16_t tolerance);
bool setTolerance(uint16_t tolerance);
// Set the reporting interval for pressure measurement in seconds and delta (pressure change in 1 hPa)
void setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
bool setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta);
// Report the pressure value
void report();
bool report();
};
#endif // CONFIG_ZB_ENABLED

View file

@ -17,24 +17,38 @@ static int16_t zb_float_to_s16(float temp) {
return (int16_t)(temp * 100);
}
void ZigbeeTempSensor::setMinMaxValue(float min, float max) {
bool ZigbeeTempSensor::setMinMaxValue(float min, float max) {
int16_t zb_min = zb_float_to_s16(min);
int16_t zb_max = zb_float_to_s16(max);
esp_zb_attribute_list_t *temp_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min);
esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max);
esp_err_t ret = esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::setTolerance(float tolerance) {
bool ZigbeeTempSensor::setTolerance(float tolerance) {
// Convert tolerance to ZCL uint16_t
uint16_t zb_tolerance = (uint16_t)(tolerance * 100);
esp_zb_attribute_list_t *temp_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
esp_err_t ret = esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
bool ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -50,23 +64,34 @@ void ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::setTemperature(float temperature) {
bool ZigbeeTempSensor::setTemperature(float temperature) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
int16_t zb_temperature = zb_float_to_s16(temperature);
log_v("Updating temperature sensor value...");
/* Update temperature sensor measured value */
log_d("Setting temperature to %d", zb_temperature);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set temperature: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::reportTemperature() {
bool ZigbeeTempSensor::reportTemperature() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -77,9 +102,14 @@ void ZigbeeTempSensor::reportTemperature() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send temperature report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Temperature report sent");
return true;
}
void ZigbeeTempSensor::addHumiditySensor(float min, float max, float tolerance) {
@ -96,20 +126,26 @@ void ZigbeeTempSensor::addHumiditySensor(float min, float max, float tolerance)
_humidity_sensor = true;
}
void ZigbeeTempSensor::setHumidity(float humidity) {
bool ZigbeeTempSensor::setHumidity(float humidity) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
int16_t zb_humidity = zb_float_to_s16(humidity);
log_v("Updating humidity sensor value...");
/* Update humidity sensor measured value */
log_d("Setting humidity to %d", zb_humidity);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &zb_humidity,
false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set humidity: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::reportHumidity() {
bool ZigbeeTempSensor::reportHumidity() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -120,12 +156,17 @@ void ZigbeeTempSensor::reportHumidity() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send humidity report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Humidity report sent");
return true;
}
void ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
bool ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -141,15 +182,22 @@ void ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set humidity reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeTempSensor::report() {
reportTemperature();
bool ZigbeeTempSensor::report() {
bool temp_ret = reportTemperature();
bool hum_ret = true;
if (_humidity_sensor) {
reportHumidity();
hum_ret = reportHumidity();
}
return temp_ret && hum_ret;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -15,34 +15,34 @@ public:
~ZigbeeTempSensor() {}
// Set the temperature value in 0,01°C
void setTemperature(float value);
bool setTemperature(float value);
// Set the min and max value for the temperature sensor in 0,01°C
void setMinMaxValue(float min, float max);
bool setMinMaxValue(float min, float max);
// Set the tolerance value for the temperature sensor in 0,01°C
void setTolerance(float tolerance);
bool setTolerance(float tolerance);
// Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C)
void setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
// Report the temperature value
void reportTemperature();
bool reportTemperature();
// Add humidity cluster to the temperature sensor device
void addHumiditySensor(float min, float max, float tolerance);
// Set the humidity value in 0,01%
void setHumidity(float value);
bool setHumidity(float value);
// Set the reporting interval for humidity measurement in seconds and delta (humidity change in 0,01%)
void setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta);
bool setHumidityReporting(uint16_t min_interval, uint16_t max_interval, float delta);
// Report the humidity value
void reportHumidity();
bool reportHumidity();
// Report the temperature and humidity values if humidity sensor is added
void report();
bool report();
private:
bool _humidity_sensor;

View file

@ -29,16 +29,22 @@ void ZigbeeVibrationSensor::setIASClientEndpoint(uint8_t ep_number) {
_ias_cie_endpoint = ep_number;
}
void ZigbeeVibrationSensor::setVibration(bool sensed) {
bool ZigbeeVibrationSensor::setVibration(bool sensed) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
log_v("Setting Vibration sensor to %s", sensed ? "sensed" : "not sensed");
uint8_t vibration = (uint8_t)sensed;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_IAS_ZONE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, &vibration, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set vibration status: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
_zone_status = vibration;
report();
return true;
}
void ZigbeeVibrationSensor::report() {
@ -49,7 +55,6 @@ void ZigbeeVibrationSensor::report() {
status_change_notif_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
status_change_notif_cmd.zcl_basic_cmd.dst_endpoint = _ias_cie_endpoint; //default is 1
memcpy(status_change_notif_cmd.zcl_basic_cmd.dst_addr_u.addr_long, _ias_cie_addr, sizeof(esp_zb_ieee_addr_t));
status_change_notif_cmd.zone_status = _zone_status;
status_change_notif_cmd.extend_status = 0;
status_change_notif_cmd.zone_id = _zone_id;

View file

@ -48,7 +48,7 @@ public:
void setIASClientEndpoint(uint8_t ep_number);
// Set the vibration sensor value (true = sensed, false = not sensed)
void setVibration(bool sensed);
bool setVibration(bool sensed);
// Report the vibration sensor value, done automatically after setting the sensed value
void report();

View file

@ -28,25 +28,39 @@ static uint16_t zb_windspeed_to_u16(float windspeed) {
return (uint16_t)(windspeed * 100);
}
void ZigbeeWindSpeedSensor::setMinMaxValue(float min, float max) {
bool ZigbeeWindSpeedSensor::setMinMaxValue(float min, float max) {
uint16_t zb_min = zb_windspeed_to_u16(min);
uint16_t zb_max = zb_windspeed_to_u16(max);
esp_zb_attribute_list_t *windspeed_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
//
esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min);
esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max);
esp_err_t ret = esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min);
if (ret != ESP_OK) {
log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max);
if (ret != ESP_OK) {
log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindSpeedSensor::setTolerance(float tolerance) {
bool ZigbeeWindSpeedSensor::setTolerance(float tolerance) {
// Convert tolerance to ZCL uint16_t
uint16_t zb_tolerance = zb_windspeed_to_u16(tolerance);
esp_zb_attribute_list_t *windspeed_measure_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_wind_speed_measurement_cluster_add_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
esp_err_t ret =
esp_zb_wind_speed_measurement_cluster_add_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
if (ret != ESP_OK) {
log_e("Failed to set tolerance: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindSpeedSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
bool ZigbeeWindSpeedSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
esp_zb_zcl_reporting_info_t reporting_info;
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@ -62,24 +76,35 @@ void ZigbeeWindSpeedSensor::setReporting(uint16_t min_interval, uint16_t max_int
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to set reporting: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindSpeedSensor::setWindSpeed(float windspeed) {
bool ZigbeeWindSpeedSensor::setWindSpeed(float windspeed) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
uint16_t zb_windspeed = zb_windspeed_to_u16(windspeed);
log_v("Updating windspeed sensor value...");
/* Update windspeed sensor measured value */
log_d("Setting windspeed to %d", zb_windspeed);
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID,
&zb_windspeed, false
);
esp_zb_lock_release();
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set wind speed: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindSpeedSensor::reportWindSpeed() {
bool ZigbeeWindSpeedSensor::reportWindSpeed() {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@ -90,9 +115,14 @@ void ZigbeeWindSpeedSensor::reportWindSpeed() {
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
if (ret != ESP_OK) {
log_e("Failed to send wind speed report: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
log_v("Wind speed measurement report sent");
return true;
}
#endif //CONFIG_ZB_ENABLED

View file

@ -40,17 +40,17 @@ public:
~ZigbeeWindSpeedSensor() {}
// Set the WindSpeed value in 0,01 m/s
void setWindSpeed(float value);
bool setWindSpeed(float value);
// Set the min and max value for the WindSpeed sensor
void setMinMaxValue(float min, float max);
bool setMinMaxValue(float min, float max);
// Set the tolerance value for the WindSpeed sensor
void setTolerance(float tolerance);
bool setTolerance(float tolerance);
// Set the reporting interval for WindSpeed measurement in seconds and delta
void setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
void reportWindSpeed();
bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta);
bool reportWindSpeed();
};
#endif //CONFIG_ZB_ENABLED

View file

@ -1,4 +1,3 @@
#include "ZigbeeWindowCovering.h"
#if CONFIG_ZB_ENABLED
@ -72,13 +71,18 @@ ZigbeeWindowCovering::ZigbeeWindowCovering(uint8_t endpoint) : ZigbeeEP(endpoint
}
// Configuration methods for window covering
void ZigbeeWindowCovering::setCoveringType(ZigbeeWindowCoveringType covering_type) {
bool ZigbeeWindowCovering::setCoveringType(ZigbeeWindowCoveringType covering_type) {
esp_zb_attribute_list_t *window_covering_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID, (void *)&covering_type);
esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID, (void *)&covering_type);
if (ret != ESP_OK) {
log_e("Failed to set covering type: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindowCovering::setConfigStatus(
bool ZigbeeWindowCovering::setConfigStatus(
bool operational, bool online, bool commands_reversed, bool lift_closed_loop, bool tilt_closed_loop, bool lift_encoder_controlled,
bool tilt_encoder_controlled
) {
@ -93,10 +97,15 @@ void ZigbeeWindowCovering::setConfigStatus(
esp_zb_attribute_list_t *window_covering_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, (void *)&config_status);
esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, (void *)&config_status);
if (ret != ESP_OK) {
log_e("Failed to set config status: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindowCovering::setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on) {
bool ZigbeeWindowCovering::setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on) {
uint8_t mode = (motor_reversed ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_REVERSED_MOTOR_DIRECTION : 0)
| (calibration_mode ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_RUN_IN_CALIBRATION_MODE : 0)
| (maintenance_mode ? ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE : 0)
@ -106,10 +115,15 @@ void ZigbeeWindowCovering::setMode(bool motor_reversed, bool calibration_mode, b
esp_zb_attribute_list_t *window_covering_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID, (void *)&mode);
esp_err_t ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID, (void *)&mode);
if (ret != ESP_OK) {
log_e("Failed to set mode: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
void ZigbeeWindowCovering::setLimits(
bool ZigbeeWindowCovering::setLimits(
uint16_t installed_open_limit_lift, uint16_t installed_closed_limit_lift, uint16_t installed_open_limit_tilt, uint16_t installed_closed_limit_tilt
) {
_installed_open_limit_lift = installed_open_limit_lift;
@ -121,12 +135,41 @@ void ZigbeeWindowCovering::setLimits(
esp_zb_attribute_list_t *window_covering_cluster =
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, (void *)&_installed_open_limit_lift);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, (void *)&_installed_closed_limit_lift);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, (void *)&_installed_open_limit_tilt);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, (void *)&_installed_closed_limit_tilt);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, (void *)&_physical_closed_limit_lift);
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_ID, (void *)&_physical_closed_limit_tilt);
esp_err_t ret =
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, (void *)&_installed_open_limit_lift);
if (ret != ESP_OK) {
log_e("Failed to set installed open limit lift: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret =
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, (void *)&_installed_closed_limit_lift);
if (ret != ESP_OK) {
log_e("Failed to set installed closed limit lift: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, (void *)&_installed_open_limit_tilt);
if (ret != ESP_OK) {
log_e("Failed to set installed open limit tilt: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret =
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, (void *)&_installed_closed_limit_tilt);
if (ret != ESP_OK) {
log_e("Failed to set installed closed limit tilt: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret =
esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, (void *)&_physical_closed_limit_lift);
if (ret != ESP_OK) {
log_e("Failed to set physical closed limit lift: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
ret = esp_zb_cluster_update_attr(window_covering_cluster, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_ID, (void *)&_physical_closed_limit_tilt);
if (ret != ESP_OK) {
log_e("Failed to set physical closed limit tilt: 0x%x: %s", ret, esp_err_to_name(ret));
return false;
}
return true;
}
// Callback for handling incoming messages and commands
@ -183,12 +226,13 @@ void ZigbeeWindowCovering::zbWindowCoveringMovementCmd(const esp_zb_zcl_window_c
if (_current_lift_percentage != message->payload.percentage_lift_value) {
_current_lift_percentage = message->payload.percentage_lift_value;
goToLiftPercentage(_current_lift_percentage);
return;
}
return;
} else if (message->command == ESP_ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE) {
if (_current_tilt_percentage != message->payload.percentage_tilt_value) {
_current_tilt_percentage = message->payload.percentage_tilt_value;
goToTiltPercentage(_current_tilt_percentage);
return;
}
} else {
log_w("Received message ignored. Command: %d not supported for Window Covering", message->command);
@ -229,80 +273,122 @@ void ZigbeeWindowCovering::stop() {
}
// Methods to control window covering from user application
void ZigbeeWindowCovering::setLiftPosition(uint16_t lift_position) {
bool ZigbeeWindowCovering::setLiftPosition(uint16_t lift_position) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
// Update both lift attributes
_current_lift_position = lift_position;
_current_lift_percentage = ((lift_position - _installed_open_limit_lift) * 100) / (_installed_closed_limit_lift - _installed_open_limit_lift);
log_v("Updating window covering lift position to %d (%d%)", _current_lift_position, _current_lift_percentage);
// set lift state
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID,
&_current_lift_position, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set lift position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID,
&_current_lift_percentage, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set lift percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
void ZigbeeWindowCovering::setLiftPercentage(uint8_t lift_percentage) {
bool ZigbeeWindowCovering::setLiftPercentage(uint8_t lift_percentage) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
// Update both lift attributes
_current_lift_percentage = lift_percentage;
_current_lift_position = _installed_open_limit_lift + ((_installed_closed_limit_lift - _installed_open_limit_lift) * lift_percentage) / 100;
log_v("Updating window covering lift percentage to %d%% (%d)", _current_lift_percentage, _current_lift_position);
log_v("Updating window covering lift position to %d (%d%)", _current_lift_position, _current_lift_percentage);
// set lift state
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID,
&_current_lift_position, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set lift position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID,
&_current_lift_percentage, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set lift percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
void ZigbeeWindowCovering::setTiltPosition(uint16_t tilt_position) {
bool ZigbeeWindowCovering::setTiltPosition(uint16_t tilt_position) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
// Update both tilt attributes
_current_tilt_position = tilt_position;
_current_tilt_percentage = ((tilt_position - _installed_open_limit_tilt) * 100) / (_installed_closed_limit_tilt - _installed_open_limit_tilt);
log_v("Updating window covering tilt position to %d (%d%)", _current_tilt_position, _current_tilt_percentage);
// set lift state
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID,
&_current_tilt_position, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set tilt position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID,
&_current_tilt_percentage, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set tilt percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
void ZigbeeWindowCovering::setTiltPercentage(uint8_t tilt_percentage) {
bool ZigbeeWindowCovering::setTiltPercentage(uint8_t tilt_percentage) {
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
// Update both tilt attributes
_current_tilt_percentage = tilt_percentage;
_current_tilt_position = _installed_open_limit_lift + ((_installed_closed_limit_tilt - _installed_open_limit_tilt) * tilt_percentage) / 100;
_current_tilt_position = _installed_open_limit_tilt + ((_installed_closed_limit_tilt - _installed_open_limit_tilt) * tilt_percentage) / 100;
log_v("Updating window covering tilt percentage to %d%% (%d)", _current_tilt_percentage, _current_tilt_position);
log_v("Updating window covering tilt position to %d (%d%)", _current_tilt_position, _current_tilt_percentage);
// set lift state
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID,
&_current_tilt_position, false
);
esp_zb_zcl_set_attribute_val(
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set tilt position: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
ret = esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID,
&_current_tilt_percentage, false
);
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Failed to set tilt percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
goto unlock_and_return;
}
unlock_and_return:
esp_zb_lock_release();
return ret == ESP_ZB_ZCL_STATUS_SUCCESS;
}
#endif // CONFIG_ZB_ENABLED

View file

@ -87,25 +87,25 @@ public:
}
// Set the window covering position in centimeters or percentage (0-100)
void setLiftPosition(uint16_t lift_position);
void setLiftPercentage(uint8_t lift_percentage);
void setTiltPosition(uint16_t tilt_position);
void setTiltPercentage(uint8_t tilt_percentage);
bool setLiftPosition(uint16_t lift_position);
bool setLiftPercentage(uint8_t lift_percentage);
bool setTiltPosition(uint16_t tilt_position);
bool setTiltPercentage(uint8_t tilt_percentage);
// Set the window covering type (see ZigbeeWindowCoveringType)
void setCoveringType(ZigbeeWindowCoveringType covering_type);
bool setCoveringType(ZigbeeWindowCoveringType covering_type);
// Set window covering config/status, for more info see esp_zb_zcl_window_covering_config_status_t
void setConfigStatus(
bool setConfigStatus(
bool operational, bool online, bool commands_reversed, bool lift_closed_loop, bool tilt_closed_loop, bool lift_encoder_controlled,
bool tilt_encoder_controlled
);
// Set configuration mode of window covering, for more info see esp_zb_zcl_window_covering_mode_t
void setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on);
bool setMode(bool motor_reversed, bool calibration_mode, bool maintenance_mode, bool leds_on);
// Set limits of motion, for more info see esp_zb_zcl_window_covering_info_attr_t
void setLimits(
bool setLimits(
uint16_t installed_open_limit_lift, uint16_t installed_closed_limit_lift, uint16_t installed_open_limit_tilt, uint16_t installed_closed_limit_tilt
);

View file

@ -0,0 +1,100 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#ifndef digitalPinToInterrupt
#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1)
#endif
#define USB_VID 0x303a
#define USB_PID 0x82D1
#define USB_MANUFACTURER "LILYGO"
#define USB_PRODUCT "T-LoRa-Pager"
// ST7796
#define DISP_WIDTH (222)
#define DISP_HEIGHT (480)
#define SD_CS (21)
static const uint8_t TX = 43;
static const uint8_t RX = 44;
//BHI260,PCF85063,BQ25896,DRV2605L,ES8311 share I2C Bus
static const uint8_t SDA = 2;
static const uint8_t SCL = 3;
// Default sd cs pin
static const uint8_t SS = SD_CS;
static const uint8_t MOSI = 34;
static const uint8_t MISO = 33;
static const uint8_t SCK = 35;
#define KB_INT (6)
#define KB_BACKLIGHT (46)
// Rotary
#define ROTARY_A (40)
#define ROTARY_B (41)
#define ROTARY_C (7)
// Interrupt IO port
#define RTC_INT (1)
#define NFC_INT (5)
#define SENSOR_INT (8)
#define NFC_CS (39)
// ES8311
#define I2S_WS (18)
#define I2S_SCK (11)
#define I2S_MCLK (10)
#define I2S_SDOUT (45)
#define I2S_SDIN (17)
// GPS
#define GPS_TX (12)
#define GPS_RX (4)
#define GPS_PPS (13)
// LoRa, SD, ST25R3916 card share SPI bus
#define LORA_SCK (SCK) // share spi bus
#define LORA_MISO (MISO) // share spi bus
#define LORA_MOSI (MOSI) // share spi bus
#define LORA_CS (36)
#define LORA_RST (47)
#define LORA_BUSY (48)
#define LORA_IRQ (14)
// SPI interface display
#define DISP_MOSI (MOSI)
#define DISP_MISO (MISO)
#define DISP_SCK (SCK)
#define DISP_RST (-1)
#define DISP_CS (38)
#define DISP_DC (37)
#define DISP_BL (42)
// External expansion chip IO definition
#define EXPANDS_DRV_EN (0)
#define EXPANDS_AMP_EN (1)
#define EXPANDS_KB_RST (2)
#define EXPANDS_LORA_EN (3)
#define EXPANDS_GPS_EN (4)
#define EXPANDS_NFC_EN (5)
#define EXPANDS_DISP_RST (6)
#define EXPANDS_GPS_RST (7)
#define EXPANDS_KB_EN (8)
#define EXPANDS_GPIO_EN (9)
// Peripheral definition exists
#define USING_AUDIO_CODEC
#define USING_XL9555_EXPANDS
#define USING_PPM_MANAGE
#define USING_BQ_GAUGE
#define USING_INPUT_DEV_ROTARY
#define USING_INPUT_DEV_KEYBOARD
#define USING_ST25R3916
#define USING_BHI260_SENSOR
#define HAS_SD_CARD_SOCKET
#endif /* Pins_Arduino_h */

View file

@ -66,4 +66,11 @@ static const uint8_t SCK = 3;
#define GPS_TX (TX)
#define GPS_RX (RX)
// Peripheral definition exists
#define USING_PCM_AMPLIFIER
#define USING_PDM_MICROPHONE
#define USING_PMU_MANAGE
#define USING_INPUT_DEV_TOUCHPAD
#define USING_IR_REMOTE
#endif /* Pins_Arduino_h */

View file

@ -12,27 +12,25 @@
#define USB_MANUFACTURER "LILYGO"
#define USB_PRODUCT "T-Watch-Ultra"
#define DISP_WIDTH (240)
#define DISP_HEIGHT (296)
#define DISP_WIDTH 502
#define DISP_HEIGHT 410
#define DISP_D0 (39)
#define DISP_D1 (40)
#define DISP_D2 (45)
#define DISP_D3 (42)
#define DISP_SCK (41)
#define DISP_RST (6)
#define DISP_CS (38)
#define DISP_TE (37)
// QSPI interface display
#define DISP_D0 (38)
#define DISP_D1 (39)
#define DISP_D2 (42)
#define DISP_D3 (45)
#define DISP_SCK (40)
#define DISP_CS (41)
#define DISP_TE (6)
// touch screen
#define TP_INT (12)
#define TP_RST (46)
// Interrupt IO port
#define TP_INT (12)
#define RTC_INT (1)
#define PMU_INT (7)
#define NFC_INT (5)
#define SENSOR_INT (8)
#define NFC_RST (4)
#define NFC_CS (4)
// PDM microphone
#define MIC_SCK (17)
@ -59,8 +57,9 @@ static const uint8_t MOSI = 34;
static const uint8_t MISO = 33;
static const uint8_t SCK = 35;
#define GPS_TX (TX)
#define GPS_RX (RX)
#define GPS_TX (TX)
#define GPS_RX (RX)
#define GPS_PPS (13)
#define TP_SDA (SDA)
#define TP_SCL (SCL)
@ -74,4 +73,20 @@ static const uint8_t SCK = 35;
#define LORA_BUSY (48)
#define LORA_IRQ (14)
// External expansion chip IO definition
#define EXPANDS_DRV_EN (6)
#define EXPANDS_DISP_EN (7)
#define EXPANDS_TOUCH_RST (10)
#define EXPANDS_DISP_RST (11)
// Peripheral definition exists
#define USING_XL9555_EXPANDS
#define USING_PCM_AMPLIFIER
#define USING_PDM_MICROPHONE
#define USING_PMU_MANAGE
#define USING_INPUT_DEV_TOUCHPAD
#define USING_ST25R3916
#define USING_BHI260_SENSOR
#define HAS_SD_CARD_SOCKET
#endif /* Pins_Arduino_h */