From a42cb647b02f6a9e725a2bee8a41f972db2baeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 21 May 2025 10:22:00 +0200 Subject: [PATCH 1/4] feat(zigbee): Add AC DC ElectricalMeasurement support --- CMakeLists.txt | 1 + .../Zigbee_Electrical_AC_Sensor/README.md | 87 ++ .../Zigbee_Electrical_AC_Sensor.ino | 152 +++ .../Zigbee_Electrical_AC_Sensor/ci.json | 6 + .../README.md | 87 ++ ...Zigbee_Electrical_AC_Sensor_MultiPhase.ino | 190 +++ .../ci.json | 6 + .../Zigbee_Electrical_DC_Sensor/README.md | 85 ++ .../Zigbee_Electrical_DC_Sensor.ino | 137 +++ .../Zigbee_Electrical_DC_Sensor/ci.json | 7 + libraries/Zigbee/src/Zigbee.h | 1 + .../src/ep/ZigbeeElectricalMeasurement.cpp | 1064 +++++++++++++++++ .../src/ep/ZigbeeElectricalMeasurement.h | 104 ++ 13 files changed, 1927 insertions(+) create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/ci.json create mode 100644 libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp create mode 100644 libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14fcb19b6da..72713f85eb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp + libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp ) set(ARDUINO_LIBRARY_BLE_SRCS diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md new file mode 100644 index 00000000000..d8f2c6b2743 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md @@ -0,0 +1,87 @@ +# Arduino-ESP32 Zigbee AC Electrical Measurement Example + +This example shows how to configure the Zigbee router device and use it as a Home Automation (HA) AC electrical measurement device that reports voltage, current, power, and frequency measurements. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## AC Electrical Measurement Functions + + * After this board first starts up, it would be configured locally to report AC electrical measurements: + - AC voltage in volts (0-300.00V) + - AC current in amps (0-10.000A) + - AC power in watts (0-3200.0W) + - AC frequency in hertz (0-65.000Hz) + * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. + * The device reports measurements every 2 seconds with simulated values. + +## Measurement Precision + +The example demonstrates how to set up proper measurement precision using multiplier and divisor values: + * Voltage: 1/100 = 0.01V (1 unit = 10mV) + * Current: 1/1000 = 0.001A (1 unit = 1mA) + * Power: 1/10 = 0.1W (1 unit = 100mW) + * Frequency: 1/1000 = 0.001Hz (1 unit = 1mHz) + +These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the ADC GPIO by changing the `analogPin` variable. By default, it's the pin `A0`. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the Router Zigbee mode: `Tools -> Zigbee mode: Zigbee Router` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the Router device flashed with this example is not connecting to the coordinator, erase the flash of the Router device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino new file mode 100644 index 00000000000..a970d91e301 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino @@ -0,0 +1,152 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee electrical AC measurement device. + * + * The example demonstrates how to use Zigbee library to create a router device that measures + * AC electrical parameters like voltage, current, power, power factor and frequency. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +// Recommended to use Router mode, as this type of device is expected to be mains powered. +#ifndef ZIGBEE_MODE_ZCZR +#error "Zigbee coordinator/router mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee AC measurement device configuration */ +#define AC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER 1 + +uint8_t analogPin = A0; +uint8_t button = BOOT_PIN; + +ZigbeeElectricalMeasurement zbElectricalMeasurement = ZigbeeElectricalMeasurement(AC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER); + +void onAnalogOutputChange(float analog_output) { + Serial.printf("Received analog output change: %.1f\r\n", analog_output); +} + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set analog resolution to 10 bits + analogReadResolution(10); + + // Optional: set Zigbee device name and model + zbElectricalMeasurement.setManufacturerAndModel("Espressif", "ZigbeeElectricalMeasurementAC"); + + // Add analog clusters to Zigbee Analog according your needs + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); // frequency is not phase specific (shared) + + // Optional: set Multiplier/Divisor for the measurements + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) + + // Optional: set Min/max values for the measurements + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz + + // Optional: set power factor for the measurements + zbElectricalMeasurement.setACPowerFactor(ZIGBEE_AC_PHASE_TYPE_A, 98); // 100 = 1.00, 0 = 0.00, -100 = -1.00 + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbElectricalMeasurement); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in Router mode + if (!Zigbee.begin(ZIGBEE_ROUTER)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println("Connected"); + + // Optional: Add reporting for AC measurements (this is overriden by HomeAssistant ZHA if used as a Zigbee coordinator) + zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1V) + zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 100); // report every 30 seconds if value changes by 10 (0.1A) + zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10); // report every 30 seconds if value changes by 10 (1W) + zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 30, 100); // report every 30 seconds if value changes by 100 (0.1Hz) +} + +void loop() { + static uint32_t timeCounter = 0; + + static uint8_t randomizer = 0; + // Read ADC value as current to demonstrate the measurements and update the electrical measurement values every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + uint16_t voltage = 23000 + randomizer; // 230.00 V + uint16_t current = analogReadMilliVolts(analogPin); // demonstrates 0-3.3A + int16_t power = ((voltage/100) * (current/1000) * 10); //calculate power in W + uint16_t frequency = 50135; // 50.000 Hz + Serial.printf("Updating AC voltage to %d (0.01V), current to %d (mA), power to %d (0.1W), frequency to %d (mHz)\r\n", voltage, current, power, frequency); + + // Update the measurements + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, voltage); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, current); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, power); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, frequency); + + // Report the measurements + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); + + randomizer+=10; + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md new file mode 100644 index 00000000000..bc6b2e1a5d7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md @@ -0,0 +1,87 @@ +# Arduino-ESP32 Zigbee AC Electrical MultiPhase Measurement Example + +This example shows how to configure the Zigbee router device and use it as a Home Automation (HA) AC electrical measurement device that reports voltage, current, power, and frequency measurements across three phases. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## AC Electrical Measurement Functions + + * After this board first starts up, it would be configured locally to report AC electrical measurements: + - AC voltage in volts (0-300.00V) for each phase (A, B, C) + - AC current in amps (0-10.000A) for each phase (A, B, C) + - AC power in watts (0-3200.0W) for each phase (A, B, C) + - AC frequency in hertz (0-65.000Hz) shared across all phases + * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. + * The device reports measurements every 2 seconds with simulated values. + +## Measurement Precision + +The example demonstrates how to set up proper measurement precision using multiplier and divisor values: + * Voltage: 1/100 = 0.01V (1 unit = 10mV) + * Current: 1/1000 = 0.001A (1 unit = 1mA) + * Power: 1/10 = 0.1W (1 unit = 100mW) + * Frequency: 1/1000 = 0.001Hz (1 unit = 1mHz) + +These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the ADC GPIO by changing the `analogPin` variable. By default, it's the pin `A0`. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the Router Zigbee mode: `Tools -> Zigbee mode: Zigbee Router` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the Router device flashed with this example is not connecting to the coordinator, erase the flash of the Router device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino new file mode 100644 index 00000000000..34745b5f353 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino @@ -0,0 +1,190 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee electrical AC measurement device with multi-phase support. + * + * The example demonstrates how to use Zigbee library to create a router device that measures + * AC electrical parameters like voltage, current, power, power factor and frequency across + * three phases (A, B, C). This allows monitoring of three-phase power systems commonly used + * in industrial and commercial applications. + * + * The device measures: + * - Per phase: voltage, current, power, power factor + * - Shared: frequency (common across all phases) + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +// Recommended to use Router mode, as this type of device is expected to be mains powered. +#ifndef ZIGBEE_MODE_ZCZR +#error "Zigbee coordinator/router mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee AC measurement device configuration */ +#define AC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER 1 + +uint8_t analogPin = A0; +uint8_t button = BOOT_PIN; + +ZigbeeElectricalMeasurement zbElectricalMeasurement = ZigbeeElectricalMeasurement(AC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER); + +void onAnalogOutputChange(float analog_output) { + Serial.printf("Received analog output change: %.1f\r\n", analog_output); +} + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set analog resolution to 10 bits + analogReadResolution(10); + + // Optional: set Zigbee device name and model + zbElectricalMeasurement.setManufacturerAndModel("Espressif", "ZigbeeElectricalMeasurementAC"); + + // Add analog clusters to Zigbee Analog according your needs + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); + + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B); + + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C); + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C); + + zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); // frequency is not phase specific (shared) + + // Recommended: set Multiplier/Divisor for the measurements (common for all phases) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) + + // Optional: set Min/max values for the measurements + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W + + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B, 0, 32000); // 0-3200.0W + + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C, 0, 32000); // 0-3200.0W + + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbElectricalMeasurement); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in Router mode + if (!Zigbee.begin(ZIGBEE_ROUTER)) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println("Connected"); +} + +void loop() { + static uint32_t timeCounter = 0; + static uint8_t randomizer = 0; + // Read ADC value and update the analog value every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + uint16_t voltage = 23000 + randomizer; // 230.00 V + uint16_t current = analogReadMilliVolts(analogPin); // demonstrates approx 0-3.3A + int16_t power = ((voltage/100) * (current/1000) * 10); //calculate power in W + uint16_t frequency = 50135; // 50.000 Hz + Serial.printf("Updating AC voltage to %d (0.01V), current to %d (mA), power to %d (0.1W), frequency to %d (mHz)\r\n", voltage, current, power, frequency); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, voltage); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, current); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, power); + + // Phase B demonstrates phase shift + current += 500; + voltage += 500; + power = ((voltage/100) * (current/1000) * 10); //calculate power in W + + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B, voltage); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B, current); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B, power); + + // Phase C demonstrates phase shift + current += 500; + voltage += 500; + power = ((voltage/100) * (current/1000) * 10); //calculate power in W + + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C, voltage); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C, current); + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C, power); + + zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, frequency); + + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); + + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B); + + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C); + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C); + + zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); + + randomizer+=10; + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/ci.json b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/ci.json new file mode 100644 index 00000000000..15d6190e4ae --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr", + "requires": [ + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md new file mode 100644 index 00000000000..fae9565ecec --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md @@ -0,0 +1,85 @@ +# Arduino-ESP32 Zigbee DC Electrical Measurement Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) DC electrical measurement device that reports voltage, current, and power measurements. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## DC Electrical Measurement Functions + + * After this board first starts up, it would be configured locally to report DC electrical measurements: + - DC voltage in millivolts (0-5000mV) + - DC current in milliamps (0-1000mA) + - DC power in milliwatts (0-5000mW) + * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. + * The device reports measurements every 30 seconds if the value changes by more than the configured delta. + +## Measurement Precision + +The example demonstrates how to set up proper measurement precision using multiplier and divisor values: + * Voltage: 1/1000 = 0.001V (1 unit = 1mV) + * Current: 1/1000 = 0.001A (1 unit = 1mA) + * Power: 1/1000 = 0.001W (1 unit = 1mW) + +These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the ADC GPIO by changing the `analogPin` variable. By default, it's the pin `A0`. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino new file mode 100644 index 00000000000..1c75169d691 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino @@ -0,0 +1,137 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates a Zigbee DC electrical measurement sensor. + * + * The example shows how to use the Zigbee library to create an end device that measures + * DC voltage, current and power using the Electrical Measurement cluster. + * + * The device reports: + * - DC voltage in millivolts (0-5000mV) + * - DC current in milliamps (0-1000mA) + * - DC power in milliwatts (0-5000mW) + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee DC measurement device configuration */ +#define DC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER 1 + +uint8_t analogPin = A0; +uint8_t button = BOOT_PIN; + +ZigbeeElectricalMeasurement zbElectricalMeasurement = ZigbeeElectricalMeasurement(DC_ELECTRICAL_MEASUREMENT_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set analog resolution to 10 bits + analogReadResolution(10); + + // Optional: set Zigbee device name and model + zbElectricalMeasurement.setManufacturerAndModel("Espressif", "ZigbeeElectricalMeasurementDC"); + + // Add analog clusters to Zigbee Analog according your needs + zbElectricalMeasurement.addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE); + zbElectricalMeasurement.addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT); + zbElectricalMeasurement.addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_POWER); + + // // Optional: set Min/max values for the measurements + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 5000); // 0-5.000V + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 1000); // 0-1.000A + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 5000); // 0-5.000W + + // // Optional: set Multiplier/Divisor for the measurements + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 1, 1000); // 1/1000 = 0.001V (1 unit of measurement = 0.001V = 1mV) + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 1, 1000); // 1/1000 = 0.001W (1 unit of measurement = 0.001W = 1mW) + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbElectricalMeasurement); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println("Connected"); + + // Optional: Add reporting for DC measurements (this is overriden by HomeAssistant ZHA if connected to its network) + zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1V) + zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1A) + zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1W) +} + +void loop() { + static uint32_t timeCounter = 0; + static uint8_t randomizer = 0; + // Read ADC value and update the analog value every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + int16_t voltage_mv = (int16_t)(analogReadMilliVolts(analogPin)); + int16_t current_ma = randomizer; //0-255mA + int16_t power_mw = voltage_mv * current_ma / 1000; //calculate power in mW + Serial.printf("Updating DC voltage to %d mV, current to %d mA, power to %d mW\r\n", voltage_mv, current_ma, power_mw); + zbElectricalMeasurement.setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, voltage_mv); + zbElectricalMeasurement.setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, current_ma); + zbElectricalMeasurement.setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, power_mw); + // Analog input supports reporting + zbElectricalMeasurement.reportDC(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE); + zbElectricalMeasurement.reportDC(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT); + zbElectricalMeasurement.reportDC(ZIGBEE_DC_MEASUREMENT_TYPE_POWER); + + randomizer+=10; + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/src/Zigbee.h b/libraries/Zigbee/src/Zigbee.h index 7f44d7813af..54d3fd96587 100644 --- a/libraries/Zigbee/src/Zigbee.h +++ b/libraries/Zigbee/src/Zigbee.h @@ -21,6 +21,7 @@ #include "ep/ZigbeeCarbonDioxideSensor.h" #include "ep/ZigbeeContactSwitch.h" #include "ep/ZigbeeDoorWindowHandle.h" +#include "ep/ZigbeeElectricalMeasurement.h" #include "ep/ZigbeeFlowSensor.h" #include "ep/ZigbeeIlluminanceSensor.h" #include "ep/ZigbeeOccupancySensor.h" diff --git a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp new file mode 100644 index 00000000000..63716c6a8dd --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp @@ -0,0 +1,1064 @@ +#include "ZigbeeElectricalMeasurement.h" +#if CONFIG_ZB_ENABLED + +// Workaround for wrong name in ZCL header +#define ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DCPOWER_ID + +esp_zb_cluster_list_t *zigbee_electrical_measurement_clusters_create(zigbee_electrical_measurement_cfg_t *electrical_measurement) { + esp_zb_basic_cluster_cfg_t *basic_cfg = electrical_measurement ? &(electrical_measurement->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = electrical_measurement ? &(electrical_measurement->identify_cfg) : NULL; + esp_zb_electrical_meas_cluster_cfg_t *electrical_measurement_cfg = electrical_measurement ? &(electrical_measurement->electrical_measurement_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); + esp_zb_cluster_list_add_electrical_meas_cluster(cluster_list, esp_zb_electrical_meas_cluster_create(electrical_measurement_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeElectricalMeasurement::ZigbeeElectricalMeasurement(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_electrical_measurement_cfg_t electrical_measurement_cfg = ZIGBEE_DEFAULT_ELECTRICAL_MEASUREMENT_CONFIG(); + _cluster_list = zigbee_electrical_measurement_clusters_create(&electrical_measurement_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_METER_INTERFACE_DEVICE_ID, .app_device_version = 0}; +} + +/* DC MEASUREMENT */ + +bool ZigbeeElectricalMeasurement::addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type) { + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + // Set the DC measurement type bit in the measurement type attribute + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_MEASUREMENT; + esp_zb_cluster_update_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID, &measure_type); + + int16_t default_min = -32767; + int16_t default_max = 32767; + int16_t default_measurement = 0; + uint16_t default_multiplier = 1; + uint16_t default_divisor = 1; + + esp_err_t ret = ESP_OK; + // Add the DC Voltage attributes + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE) { + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID, (void *)&default_measurement); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID, (void *)&default_min); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID, (void *)&default_max); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_ID, (void *)&default_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_ID, (void *)&default_divisor); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + // Add the DC Current attributes + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID, (void *)&default_measurement); + if (ret != ESP_OK) { + log_e("Failed to add DC current: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID, (void *)&default_min); + if (ret != ESP_OK) { + log_e("Failed to add DC current min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID, (void *)&default_max); + if (ret != ESP_OK) { + log_e("Failed to add DC current max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID, (void *)&default_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add DC current multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID, (void *)&default_divisor); + if (ret != ESP_OK) { + log_e("Failed to add DC current divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + } + else { //(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) + // Add the DC Power attributes + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID, (void *)&default_measurement); + if (ret != ESP_OK) { + log_e("Failed to add DC power: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MIN_ID, (void *)&default_min); + if (ret != ESP_OK) { + log_e("Failed to add DC power min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MAX_ID, (void *)&default_max); + if (ret != ESP_OK) { + log_e("Failed to add DC power max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID, (void *)&default_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add DC power multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID, (void *)&default_divisor); + if (ret != ESP_OK) { + log_e("Failed to add DC power divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + } + return true; +} + +bool ZigbeeElectricalMeasurement::setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, int16_t min, int16_t max) { + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + esp_zb_zcl_electrical_measurement_attr_t attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID; + if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID; + attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID; + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MIN_ID; + attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MAX_ID; + } + esp_err_t ret = ESP_OK; + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_min, (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(electrical_measurement_cluster, attr_max, (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; +} + +bool ZigbeeElectricalMeasurement::setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, uint16_t multiplier, uint16_t divisor) { + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + esp_zb_zcl_electrical_measurement_attr_t attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_ID; + + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID; + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID; + } + + esp_err_t ret = ESP_OK; + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_multiplier, (void *)&multiplier); + if (ret != ESP_OK) { + log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_divisor, (void *)&divisor); + if (ret != ESP_OK) { + log_e("Failed to set divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeElectricalMeasurement::setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, uint16_t min_interval, uint16_t max_interval, int16_t delta) { + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; + if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; + } + + 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; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = attr_id; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.s16 = 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_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; +} + +bool ZigbeeElectricalMeasurement::setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, int16_t measurement) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + + esp_zb_zcl_electrical_measurement_attr_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; + if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; + } + + log_v("Updating DC measurement value..."); + /* Update DC sensor measured value */ + log_d("Setting DC measurement to %d", measurement); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &measurement, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set DC measurement: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeElectricalMeasurement::reportDC(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type) { + uint16_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; + if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; + } + else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; + } + /* 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; + report_attr_cmd.attributeID = attr_id; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + 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 DC report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("DC report sent"); + return true; +} + +/* AC MEASUREMENT */ + +bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type) { + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + switch(phase_type) { + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + // Non phase specific dont need any bit set + break; + case ZIGBEE_AC_PHASE_TYPE_A: + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_A_MEASUREMENT; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_B_MEASUREMENT; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_C_MEASUREMENT; + break; + default: + log_e("Invalid phase type"); + break; + } + // Set Active measurement bit for active power and power factor, otherwise no bit needed for voltage, current + if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER || measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) { + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_MEASUREMENT; // Active power is used + } + // Update the measurement type attribute + esp_zb_cluster_update_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID, &measure_type); + + // Default values for AC measurements + [[maybe_unused]] int16_t default_ac_power_min = -32767; + [[maybe_unused]] int16_t default_ac_power_max = 32767; + [[maybe_unused]] int16_t default_ac_power_measurement = 0; + [[maybe_unused]] uint16_t default_ac_min = 0x0000; + [[maybe_unused]] uint16_t default_ac_max = 0xffff; + [[maybe_unused]] uint16_t default_ac_measurement = 0x0000; + [[maybe_unused]] uint16_t default_ac_multiplier = 1; + [[maybe_unused]] uint16_t default_ac_divisor = 1; + [[maybe_unused]] int8_t default_ac_power_factor = 100; + + esp_err_t ret = ESP_OK; + + // AC Frequency + if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY) { // No phase specific + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID, (void *)&default_ac_measurement); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MIN_ID, (void *)&default_ac_min); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MAX_ID, (void *)&default_ac_max); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID, (void *)&default_ac_divisor); + if (ret != ESP_OK) { + log_e("Failed to add DC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; + } + // Add the AC Voltage attributes + else if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE) { + esp_zb_zcl_electrical_measurement_attr_t attr_voltage = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_voltage_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_voltage_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_ID; + switch(phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + // already set + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_voltage = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; + attr_voltage_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_B_ID; + attr_voltage_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_voltage = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; + attr_voltage_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_ID; + attr_voltage_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_voltage, (void *)&default_ac_measurement); + if (ret != ESP_OK) { + log_e("Failed to add AC voltage: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_voltage_min, (void *)&default_ac_min); + if (ret != ESP_OK) { + log_e("Failed to add AC voltage min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_voltage_max, (void *)&default_ac_max); + if (ret != ESP_OK) { + log_e("Failed to add AC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + if(!ac_volt_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add AC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID, (void *)&default_ac_divisor); + if (ret != ESP_OK) { + log_e("Failed to add AC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ac_volt_mult_div_set = true; // Set flag to true, so we dont add the attributes again + } + } + // Add the AC Current attributes + else if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT) { + esp_zb_zcl_electrical_measurement_attr_t attr_current = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_current_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_current_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_ID; + switch(phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + // already set + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_current = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; + attr_current_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_B_ID; + attr_current_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_current = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; + attr_current_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_ID; + attr_current_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_current, (void *)&default_ac_measurement); + if (ret != ESP_OK) { + log_e("Failed to add AC current: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_current_min, (void *)&default_ac_min); + if (ret != ESP_OK) { + log_e("Failed to add AC current min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_current_max, (void *)&default_ac_max); + if (ret != ESP_OK) { + log_e("Failed to add AC current max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + if(!ac_current_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add AC current multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID, (void *)&default_ac_divisor); + if (ret != ESP_OK) { + log_e("Failed to add AC current divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ac_current_mult_div_set = true; // Set flag to true, so we dont add the attributes again + } + } + // Add the AC Power attributes + else if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER) { + esp_zb_zcl_electrical_measurement_attr_t attr_power = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_power_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_ID; + esp_zb_zcl_electrical_measurement_attr_t attr_power_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_ID; + + switch(phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + // already set + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_power = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; + attr_power_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_B_ID; + attr_power_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_power = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; + attr_power_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_ID; + attr_power_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power, (void *)&default_ac_measurement); + if (ret != ESP_OK) { + log_e("Failed to add AC power: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power_min, (void *)&default_ac_min); + if (ret != ESP_OK) { + log_e("Failed to add AC power min: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power_max, (void *)&default_ac_max); + if (ret != ESP_OK) { + log_e("Failed to add AC power max: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + if(!ac_power_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (ret != ESP_OK) { + log_e("Failed to add AC power multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID, (void *)&default_ac_divisor); + if (ret != ESP_OK) { + log_e("Failed to add AC power divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ac_power_mult_div_set = true; // Set flag to true, so we dont add the attributes again + } + } + else { //(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) + esp_zb_zcl_electrical_measurement_attr_t attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; + + switch(phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + // already set + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power_factor, (void *)&default_ac_power_factor); + if (ret != ESP_OK) { + log_e("Failed to add AC power factor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + } + return true; +} + +bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t min_value, int32_t max_value) { + uint16_t attr_min_id = 0; + uint16_t attr_max_id = 0; + + // Check min/max values are valid for the measurement type + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + if (min_value < 0 || min_value > UINT16_MAX || max_value < 0 || max_value > UINT16_MAX) { + log_e("AC measurement min/max values must be between 0 and %u (got min=%d, max=%d)", UINT16_MAX, min_value, max_value); + return false; + } + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + if (min_value < INT16_MIN || min_value > INT16_MAX || max_value < INT16_MIN || max_value > INT16_MAX) { + log_e("AC power min/max values must be between %d and %d (got min=%d, max=%d)", INT16_MIN, INT16_MAX, min_value, max_value); + return false; + } + break; + + default: + log_e("Invalid measurement type"); + return false; + } + + [[maybe_unused]] int16_t int16_min_value = (int16_t)min_value; + [[maybe_unused]] int16_t int16_max_value = (int16_t)max_value; + [[maybe_unused]] uint16_t uint16_min_value = (uint16_t)min_value; + [[maybe_unused]] uint16_t uint16_max_value = (uint16_t)max_value; + + //TODO: Log info about min and max values for different measurement types + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_B_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_B_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_B_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_ID; + attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_ID; + break; + default: + log_e("Invalid phase type"); + return false; + } + break; + + default: + log_e("Invalid measurement type"); + return false; + } + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + esp_err_t ret = ESP_OK; + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_min_id, (void *)&min_value); + 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(electrical_measurement_cluster, attr_max_id, (void *)&max_value); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeElectricalMeasurement::setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, uint16_t multiplier, uint16_t divisor) { + uint16_t attr_multiplier = 0; + uint16_t attr_divisor = 0; + + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID; + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID; + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID; + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID; + attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID; + break; + default: + log_e("Invalid measurement type"); + return false; + } + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + esp_err_t ret = ESP_OK; + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_multiplier, (void *)&multiplier); + if (ret != ESP_OK) { + log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_divisor, (void *)&divisor); + if (ret != ESP_OK) { + log_e("Failed to set divisor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeElectricalMeasurement::setACPowerFactor(ZIGBEE_AC_PHASE_TYPE phase_type, int8_t power_factor) { + uint16_t attr_id = 0; + + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + + esp_zb_attribute_list_t *electrical_measurement_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + esp_err_t ret = ESP_OK; + ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_id, (void *)&power_factor); + if (ret != ESP_OK) { + log_e("Failed to set power factor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} +bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t value) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + uint16_t attr_id = 0; + + // Check value is valid for the measurement type + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + if (value < 0 || value > UINT16_MAX) { + log_e("AC measurement value must be between 0 and %u (got %d)", UINT16_MAX, value); + return false; + } + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + if (value < INT16_MIN || value > INT16_MAX) { + log_e("AC power value must be between %d and %d (got %d)", INT16_MIN, INT16_MAX, value); + return false; + } + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: + if (value < -100 || value > 100) { + log_e("AC power factor value must be between -100 and 100 (got %d)", value); + return false; + } + break; + + default: + log_e("Invalid measurement type"); + return false; + } + // Convert value to appropriate type based on measurement type + uint16_t uint16_value = (uint16_t)value; + int16_t int16_value = (int16_t)value; + int8_t int8_value = (int8_t)value; + + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + // Use uint16_t for voltage + log_v("Updating AC voltage measurement value..."); + log_d("Setting AC voltage to %u", uint16_value); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, + ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + esp_zb_lock_release(); + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + // Use uint16_t for current + log_v("Updating AC current measurement value..."); + log_d("Setting AC current to %u", uint16_value); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, + ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + esp_zb_lock_release(); + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + // Use int16_t for power + log_v("Updating AC power measurement value..."); + log_d("Setting AC power to %d", int16_value); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, + ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int16_value, false); + esp_zb_lock_release(); + break; + + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; + // Use uint16_t for frequency + log_v("Updating AC frequency measurement value..."); + log_d("Setting AC frequency to %u", uint16_value); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, + ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + esp_zb_lock_release(); + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + // Use int8_t for power factor + log_v("Updating AC power factor measurement value..."); + log_d("Setting AC power factor to %d", int8_value); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, + ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int8_value, false); + esp_zb_lock_release(); + break; + default: + log_e("Invalid measurement type"); + return false; + } + + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set AC measurement: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeElectricalMeasurement::setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta) { + uint16_t attr_id = 0; + + // Convert value to appropriate type based on measurement type + uint16_t uint16_delta = (uint16_t)delta; + int16_t int16_delta = (int16_t)delta; + + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: + log_e("Power factor attribute reporting not supported by zigbee specification"); + return false; + default: + log_e("Invalid measurement type"); + return false; + } + + 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; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = attr_id; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER) { + reporting_info.u.send_info.delta.s16 = int16_delta; + } else { + reporting_info.u.send_info.delta.u16 = uint16_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_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; +} + +bool ZigbeeElectricalMeasurement::reportAC(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type) { + uint16_t attr_id = 0; + + switch (measurement_type) { + case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: + switch (phase_type) { + case ZIGBEE_AC_PHASE_TYPE_A: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_B: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_C: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; + break; + case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: + default: + log_e("Invalid phase type"); + return false; + } + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: + attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; + break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: + log_e("Power factor attribute reporting not supported by zigbee specification"); + return false; + default: + log_e("Invalid measurement type"); + return false; + } + /* 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; + report_attr_cmd.attributeID = attr_id; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + 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 AC report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("AC report sent"); + return true; +} + + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h new file mode 100644 index 00000000000..7bd7d4aa44d --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h @@ -0,0 +1,104 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_ELECTRICAL_MEASUREMENT_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, \ + }, \ + .electrical_measurement_cfg = \ + { \ + .measured_type = 0x00, \ + }, \ + } +// clang-format on + +enum ZIGBEE_DC_MEASUREMENT_TYPE { + ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE = 0x0001, + ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT = 0x0002, + ZIGBEE_DC_MEASUREMENT_TYPE_POWER = 0x0003, +}; + +enum ZIGBEE_AC_MEASUREMENT_TYPE { + ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE = 0x0001, + ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT = 0x0002, + ZIGBEE_AC_MEASUREMENT_TYPE_POWER = 0x0003, + ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR = 0x0004, + ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY = 0x0005, +}; + +enum ZIGBEE_AC_PHASE_TYPE { + ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC = 0x0000, + ZIGBEE_AC_PHASE_TYPE_A = 0x0001, + ZIGBEE_AC_PHASE_TYPE_B = 0x0002, + ZIGBEE_AC_PHASE_TYPE_C = 0x0003, +}; + +typedef struct zigbee_electrical_measurement_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_electrical_meas_cluster_cfg_t electrical_measurement_cfg; +} zigbee_electrical_measurement_cfg_t; + +class ZigbeeElectricalMeasurement : public ZigbeeEP { +public: + ZigbeeElectricalMeasurement(uint8_t endpoint); + ~ZigbeeElectricalMeasurement() {} + + /** + * @brief DC measurement methods + */ + // Add a DC measurement type + bool addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type); + // Set the DC measurement value for the given measurement type + bool setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, int16_t value); + // Set the DC min and max value for the given measurement type + bool setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, int16_t min, int16_t max); + // Set the DC multiplier and divisor for the given measurement type + bool setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, uint16_t multiplier, uint16_t divisor); + // Set the DC reporting interval for the given measurement type in seconds and delta (measurement change) + bool setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, uint16_t min_interval, uint16_t max_interval, int16_t delta); + // Report the DC measurement value for the given measurement type + bool reportDC(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type); + + /** + * @brief AC measurement methods + */ + // Add an AC measurement type for selected phase type + bool addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type); + // Set the AC measurement value for the given measurement type and phase type (uint16_t for voltage, current and frequency, int32_t for power) + bool setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t value); + // Set the AC min and max value for the given measurement type and phase type (uint16_t for voltage, current and frequency, int32_t for power) + bool setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t min, int32_t max); + // Set the AC multiplier and divisor for the given measurement type (common for all phases) + bool setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, uint16_t multiplier, uint16_t divisor); + // Set the AC power factor for the given phase type (-100 to 100 %) + bool setACPowerFactor(ZIGBEE_AC_PHASE_TYPE phase_type, int8_t power_factor); + // Set the AC reporting interval for the given measurement type and phase type in seconds and delta (measurement change - uint16_t for voltage, current and frequency, int32_t for power) + bool setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta); + // Report the AC measurement value for the given measurement type and phase type + bool reportAC(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type); + +private: + uint32_t measure_type = 0x0000; + bool ac_volt_mult_div_set = false; + bool ac_current_mult_div_set = false; + bool ac_power_mult_div_set = false; +}; + +#endif // CONFIG_ZB_ENABLED From 80fda009f12303f91439ddea69ccc32a2c11a39f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 13:40:55 +0000 Subject: [PATCH 2/4] ci(pre-commit): Apply automatic fixes --- .../Zigbee_Electrical_AC_Sensor.ino | 52 +- ...Zigbee_Electrical_AC_Sensor_MultiPhase.ino | 48 +- .../Zigbee_Electrical_DC_Sensor.ino | 26 +- .../src/ep/ZigbeeElectricalMeasurement.cpp | 531 ++++++++---------- .../src/ep/ZigbeeElectricalMeasurement.h | 5 +- 5 files changed, 295 insertions(+), 367 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino index a970d91e301..5650a0f4878 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino @@ -63,22 +63,24 @@ void setup() { zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR, ZIGBEE_AC_PHASE_TYPE_A); - zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); // frequency is not phase specific (shared) + zbElectricalMeasurement.addACMeasurement( + ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC + ); // frequency is not phase specific (shared) // Optional: set Multiplier/Divisor for the measurements - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) // Optional: set Min/max values for the measurements - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz // Optional: set power factor for the measurements - zbElectricalMeasurement.setACPowerFactor(ZIGBEE_AC_PHASE_TYPE_A, 98); // 100 = 1.00, 0 = 0.00, -100 = -1.00 + zbElectricalMeasurement.setACPowerFactor(ZIGBEE_AC_PHASE_TYPE_A, 98); // 100 = 1.00, 0 = 0.00, -100 = -1.00 // Add endpoints to Zigbee Core Zigbee.addEndpoint(&zbElectricalMeasurement); @@ -100,10 +102,18 @@ void setup() { Serial.println("Connected"); // Optional: Add reporting for AC measurements (this is overriden by HomeAssistant ZHA if used as a Zigbee coordinator) - zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1V) - zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 100); // report every 30 seconds if value changes by 10 (0.1A) - zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10); // report every 30 seconds if value changes by 10 (1W) - zbElectricalMeasurement.setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 30, 100); // report every 30 seconds if value changes by 100 (0.1Hz) + zbElectricalMeasurement.setACReporting( + ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10 + ); // report every 30 seconds if value changes by 10 (0.1V) + zbElectricalMeasurement.setACReporting( + ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 100 + ); // report every 30 seconds if value changes by 10 (0.1A) + zbElectricalMeasurement.setACReporting( + ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10 + ); // report every 30 seconds if value changes by 10 (1W) + zbElectricalMeasurement.setACReporting( + ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 30, 100 + ); // report every 30 seconds if value changes by 100 (0.1Hz) } void loop() { @@ -111,11 +121,11 @@ void loop() { static uint8_t randomizer = 0; // Read ADC value as current to demonstrate the measurements and update the electrical measurement values every 2s - if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s - uint16_t voltage = 23000 + randomizer; // 230.00 V - uint16_t current = analogReadMilliVolts(analogPin); // demonstrates 0-3.3A - int16_t power = ((voltage/100) * (current/1000) * 10); //calculate power in W - uint16_t frequency = 50135; // 50.000 Hz + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + uint16_t voltage = 23000 + randomizer; // 230.00 V + uint16_t current = analogReadMilliVolts(analogPin); // demonstrates 0-3.3A + int16_t power = ((voltage / 100) * (current / 1000) * 10); //calculate power in W + uint16_t frequency = 50135; // 50.000 Hz Serial.printf("Updating AC voltage to %d (0.01V), current to %d (mA), power to %d (0.1W), frequency to %d (mHz)\r\n", voltage, current, power, frequency); // Update the measurements @@ -124,13 +134,13 @@ void loop() { zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, power); zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, frequency); - // Report the measurements + // Report the measurements zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A); zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A); zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A); zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); - randomizer+=10; + randomizer += 10; } // Checking button for factory reset and reporting diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino index 34745b5f353..e219113468e 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/Zigbee_Electrical_AC_Sensor_MultiPhase.ino @@ -77,28 +77,30 @@ void setup() { zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C); zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C); - zbElectricalMeasurement.addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); // frequency is not phase specific (shared) + zbElectricalMeasurement.addACMeasurement( + ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC + ); // frequency is not phase specific (shared) // Recommended: set Multiplier/Divisor for the measurements (common for all phases) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) - zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, 1, 100); // 1/100 = 0.01V (1 unit of measurement = 0.01V = 10mV) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, 1, 10); // 1/10 = 0.1W (1 unit of measurement = 0.1W = 100mW) + zbElectricalMeasurement.setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, 1, 1000); // 1/1000 = 0.001Hz (1 unit of measurement = 0.001Hz = 1mHz) // Optional: set Min/max values for the measurements - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_A, 0, 32000); // 0-3200.0W - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B, 0, 30000); // 0-300.00V - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B, 0, 10000); // 0-10.000A - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B, 0, 32000); // 0-3200.0W + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_B, 0, 32000); // 0-3200.0W - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C, 0, 30000); // 0-300.00V - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C, 0, 10000); // 0-10.000A - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C, 0, 32000); // 0-3200.0W + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C, 0, 30000); // 0-300.00V + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C, 0, 10000); // 0-10.000A + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_POWER, ZIGBEE_AC_PHASE_TYPE_C, 0, 32000); // 0-3200.0W - zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz + zbElectricalMeasurement.setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC, 0, 65000); // 0-65.000Hz // Add endpoints to Zigbee Core Zigbee.addEndpoint(&zbElectricalMeasurement); @@ -124,11 +126,11 @@ void loop() { static uint32_t timeCounter = 0; static uint8_t randomizer = 0; // Read ADC value and update the analog value every 2s - if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s - uint16_t voltage = 23000 + randomizer; // 230.00 V - uint16_t current = analogReadMilliVolts(analogPin); // demonstrates approx 0-3.3A - int16_t power = ((voltage/100) * (current/1000) * 10); //calculate power in W - uint16_t frequency = 50135; // 50.000 Hz + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + uint16_t voltage = 23000 + randomizer; // 230.00 V + uint16_t current = analogReadMilliVolts(analogPin); // demonstrates approx 0-3.3A + int16_t power = ((voltage / 100) * (current / 1000) * 10); //calculate power in W + uint16_t frequency = 50135; // 50.000 Hz Serial.printf("Updating AC voltage to %d (0.01V), current to %d (mA), power to %d (0.1W), frequency to %d (mHz)\r\n", voltage, current, power, frequency); zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, voltage); zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_A, current); @@ -137,7 +139,7 @@ void loop() { // Phase B demonstrates phase shift current += 500; voltage += 500; - power = ((voltage/100) * (current/1000) * 10); //calculate power in W + power = ((voltage / 100) * (current / 1000) * 10); //calculate power in W zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_B, voltage); zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_B, current); @@ -146,7 +148,7 @@ void loop() { // Phase C demonstrates phase shift current += 500; voltage += 500; - power = ((voltage/100) * (current/1000) * 10); //calculate power in W + power = ((voltage / 100) * (current / 1000) * 10); //calculate power in W zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_C, voltage); zbElectricalMeasurement.setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT, ZIGBEE_AC_PHASE_TYPE_C, current); @@ -168,7 +170,7 @@ void loop() { zbElectricalMeasurement.reportAC(ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY, ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC); - randomizer+=10; + randomizer += 10; } // Checking button for factory reset and reporting diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino index 1c75169d691..cd7c31a2912 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino @@ -14,13 +14,13 @@ /** * @brief This example demonstrates a Zigbee DC electrical measurement sensor. - * + * * The example shows how to use the Zigbee library to create an end device that measures * DC voltage, current and power using the Electrical Measurement cluster. - * + * * The device reports: * - DC voltage in millivolts (0-5000mV) - * - DC current in milliamps (0-1000mA) + * - DC current in milliamps (0-1000mA) * - DC power in milliwatts (0-5000mW) * * Proper Zigbee mode must be selected in Tools->Zigbee mode @@ -64,14 +64,14 @@ void setup() { zbElectricalMeasurement.addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_POWER); // // Optional: set Min/max values for the measurements - zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 5000); // 0-5.000V - zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 1000); // 0-1.000A - zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 5000); // 0-5.000W + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 5000); // 0-5.000V + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 1000); // 0-1.000A + zbElectricalMeasurement.setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 5000); // 0-5.000W // // Optional: set Multiplier/Divisor for the measurements - zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 1, 1000); // 1/1000 = 0.001V (1 unit of measurement = 0.001V = 1mV) - zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) - zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 1, 1000); // 1/1000 = 0.001W (1 unit of measurement = 0.001W = 1mW) + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 1, 1000); // 1/1000 = 0.001V (1 unit of measurement = 0.001V = 1mV) + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 1, 1000); // 1/1000 = 0.001A (1 unit of measurement = 0.001A = 1mA) + zbElectricalMeasurement.setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 1, 1000); // 1/1000 = 0.001W (1 unit of measurement = 0.001W = 1mW) // Add endpoints to Zigbee Core Zigbee.addEndpoint(&zbElectricalMeasurement); @@ -95,7 +95,7 @@ void setup() { // Optional: Add reporting for DC measurements (this is overriden by HomeAssistant ZHA if connected to its network) zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1V) zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1A) - zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1W) + zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1W) } void loop() { @@ -104,8 +104,8 @@ void loop() { // Read ADC value and update the analog value every 2s if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s int16_t voltage_mv = (int16_t)(analogReadMilliVolts(analogPin)); - int16_t current_ma = randomizer; //0-255mA - int16_t power_mw = voltage_mv * current_ma / 1000; //calculate power in mW + int16_t current_ma = randomizer; //0-255mA + int16_t power_mw = voltage_mv * current_ma / 1000; //calculate power in mW Serial.printf("Updating DC voltage to %d mV, current to %d mA, power to %d mW\r\n", voltage_mv, current_ma, power_mw); zbElectricalMeasurement.setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, voltage_mv); zbElectricalMeasurement.setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, current_ma); @@ -115,7 +115,7 @@ void loop() { zbElectricalMeasurement.reportDC(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT); zbElectricalMeasurement.reportDC(ZIGBEE_DC_MEASUREMENT_TYPE_POWER); - randomizer+=10; + randomizer += 10; } // Checking button for factory reset and reporting diff --git a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp index 63716c6a8dd..8fa456c967a 100644 --- a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp @@ -11,7 +11,9 @@ esp_zb_cluster_list_t *zigbee_electrical_measurement_clusters_create(zigbee_elec 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); - esp_zb_cluster_list_add_electrical_meas_cluster(cluster_list, esp_zb_electrical_meas_cluster_create(electrical_measurement_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_electrical_meas_cluster( + cluster_list, esp_zb_electrical_meas_cluster_create(electrical_measurement_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE + ); return cluster_list; } @@ -22,7 +24,9 @@ ZigbeeElectricalMeasurement::ZigbeeElectricalMeasurement(uint8_t endpoint) : Zig zigbee_electrical_measurement_cfg_t electrical_measurement_cfg = ZIGBEE_DEFAULT_ELECTRICAL_MEASUREMENT_CONFIG(); _cluster_list = zigbee_electrical_measurement_clusters_create(&electrical_measurement_cfg); - _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_METER_INTERFACE_DEVICE_ID, .app_device_version = 0}; + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_METER_INTERFACE_DEVICE_ID, .app_device_version = 0 + }; } /* DC MEASUREMENT */ @@ -44,64 +48,79 @@ bool ZigbeeElectricalMeasurement::addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE me esp_err_t ret = ESP_OK; // Add the DC Voltage attributes if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE) { - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID, (void *)&default_measurement); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID, (void *)&default_measurement + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID, (void *)&default_min); + ret = + esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID, (void *)&default_min); if (ret != ESP_OK) { log_e("Failed to add DC voltage min: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID, (void *)&default_max); + ret = + esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID, (void *)&default_max); if (ret != ESP_OK) { log_e("Failed to add DC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_ID, (void *)&default_multiplier); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_ID, (void *)&default_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_ID, (void *)&default_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_ID, (void *)&default_divisor + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { // Add the DC Current attributes - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID, (void *)&default_measurement); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID, (void *)&default_measurement + ); if (ret != ESP_OK) { log_e("Failed to add DC current: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID, (void *)&default_min); + ret = + esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID, (void *)&default_min); if (ret != ESP_OK) { log_e("Failed to add DC current min: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID, (void *)&default_max); + ret = + esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID, (void *)&default_max); if (ret != ESP_OK) { log_e("Failed to add DC current max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID, (void *)&default_multiplier); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID, (void *)&default_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add DC current multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID, (void *)&default_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID, (void *)&default_divisor + ); if (ret != ESP_OK) { log_e("Failed to add DC current divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - } - else { //(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) + } else { //(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) // Add the DC Power attributes - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID, (void *)&default_measurement); + ret = + esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID, (void *)&default_measurement); if (ret != ESP_OK) { log_e("Failed to add DC power: 0x%x: %s", ret, esp_err_to_name(ret)); return false; @@ -116,12 +135,16 @@ bool ZigbeeElectricalMeasurement::addDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE me log_e("Failed to add DC power max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID, (void *)&default_multiplier); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID, (void *)&default_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add DC power multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID, (void *)&default_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID, (void *)&default_divisor + ); if (ret != ESP_OK) { log_e("Failed to add DC power divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; @@ -136,19 +159,18 @@ bool ZigbeeElectricalMeasurement::setDCMinMaxValue(ZIGBEE_DC_MEASUREMENT_TYPE me esp_zb_zcl_electrical_measurement_attr_t attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID; esp_zb_zcl_electrical_measurement_attr_t attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID; - if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID; attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID; - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { attr_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MIN_ID; attr_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MAX_ID; } esp_err_t ret = ESP_OK; ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_min, (void *)&min); if (ret != ESP_OK) { - log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; } ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_max, (void *)&max); if (ret != ESP_OK) { @@ -168,8 +190,7 @@ bool ZigbeeElectricalMeasurement::setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_T if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID; attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID; - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID; attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID; } @@ -177,8 +198,8 @@ bool ZigbeeElectricalMeasurement::setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_T esp_err_t ret = ESP_OK; ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_multiplier, (void *)&multiplier); if (ret != ESP_OK) { - log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; + log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; } ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_divisor, (void *)&divisor); if (ret != ESP_OK) { @@ -190,13 +211,12 @@ bool ZigbeeElectricalMeasurement::setDCMultiplierDivisor(ZIGBEE_DC_MEASUREMENT_T bool ZigbeeElectricalMeasurement::setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type, uint16_t min_interval, uint16_t max_interval, int16_t delta) { uint16_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; - if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; } - + 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; @@ -225,10 +245,9 @@ bool ZigbeeElectricalMeasurement::setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE me esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; esp_zb_zcl_electrical_measurement_attr_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; - if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; } @@ -236,9 +255,7 @@ bool ZigbeeElectricalMeasurement::setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE me /* Update DC sensor measured value */ log_d("Setting DC measurement to %d", measurement); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val( - _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &measurement, false - ); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &measurement, false); esp_zb_lock_release(); if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { log_e("Failed to set DC measurement: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); @@ -249,10 +266,9 @@ bool ZigbeeElectricalMeasurement::setDCMeasurement(ZIGBEE_DC_MEASUREMENT_TYPE me bool ZigbeeElectricalMeasurement::reportDC(ZIGBEE_DC_MEASUREMENT_TYPE measurement_type) { uint16_t attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID; - if(measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { + if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID; - } - else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { + } else if (measurement_type == ZIGBEE_DC_MEASUREMENT_TYPE_POWER) { attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_ID; } /* Send report attributes command */ @@ -281,66 +297,77 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me esp_zb_attribute_list_t *electrical_measurement_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - switch(phase_type) { + switch (phase_type) { case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: // Non phase specific dont need any bit set break; - case ZIGBEE_AC_PHASE_TYPE_A: - measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_A_MEASUREMENT; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_B_MEASUREMENT; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_C_MEASUREMENT; - break; - default: - log_e("Invalid phase type"); - break; + case ZIGBEE_AC_PHASE_TYPE_A: measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_A_MEASUREMENT; break; + case ZIGBEE_AC_PHASE_TYPE_B: measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_B_MEASUREMENT; break; + case ZIGBEE_AC_PHASE_TYPE_C: measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_C_MEASUREMENT; break; + default: log_e("Invalid phase type"); break; } // Set Active measurement bit for active power and power factor, otherwise no bit needed for voltage, current - if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER || measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) { - measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_MEASUREMENT; // Active power is used + if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER || measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) { + measure_type |= ESP_ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_MEASUREMENT; // Active power is used } // Update the measurement type attribute esp_zb_cluster_update_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID, &measure_type); // Default values for AC measurements - [[maybe_unused]] int16_t default_ac_power_min = -32767; - [[maybe_unused]] int16_t default_ac_power_max = 32767; - [[maybe_unused]] int16_t default_ac_power_measurement = 0; - [[maybe_unused]] uint16_t default_ac_min = 0x0000; - [[maybe_unused]] uint16_t default_ac_max = 0xffff; - [[maybe_unused]] uint16_t default_ac_measurement = 0x0000; - [[maybe_unused]] uint16_t default_ac_multiplier = 1; - [[maybe_unused]] uint16_t default_ac_divisor = 1; - [[maybe_unused]] int8_t default_ac_power_factor = 100; + [[maybe_unused]] + int16_t default_ac_power_min = -32767; + [[maybe_unused]] + int16_t default_ac_power_max = 32767; + [[maybe_unused]] + int16_t default_ac_power_measurement = 0; + [[maybe_unused]] + uint16_t default_ac_min = 0x0000; + [[maybe_unused]] + uint16_t default_ac_max = 0xffff; + [[maybe_unused]] + uint16_t default_ac_measurement = 0x0000; + [[maybe_unused]] + uint16_t default_ac_multiplier = 1; + [[maybe_unused]] + uint16_t default_ac_divisor = 1; + [[maybe_unused]] + int8_t default_ac_power_factor = 100; esp_err_t ret = ESP_OK; // AC Frequency - if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY) { // No phase specific - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID, (void *)&default_ac_measurement); + if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY) { // No phase specific + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID, (void *)&default_ac_measurement + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MIN_ID, (void *)&default_ac_min); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MIN_ID, (void *)&default_ac_min + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage min: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MAX_ID, (void *)&default_ac_max); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MAX_ID, (void *)&default_ac_max + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID, (void *)&default_ac_multiplier); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID, (void *)&default_ac_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID, (void *)&default_ac_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID, (void *)&default_ac_divisor + ); if (ret != ESP_OK) { log_e("Failed to add DC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; @@ -352,7 +379,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me esp_zb_zcl_electrical_measurement_attr_t attr_voltage = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; esp_zb_zcl_electrical_measurement_attr_t attr_voltage_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_ID; esp_zb_zcl_electrical_measurement_attr_t attr_voltage_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_ID; - switch(phase_type) { + switch (phase_type) { case ZIGBEE_AC_PHASE_TYPE_A: // already set break; @@ -366,9 +393,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me attr_voltage_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_ID; attr_voltage_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_voltage, (void *)&default_ac_measurement); if (ret != ESP_OK) { @@ -385,18 +410,22 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me log_e("Failed to add AC voltage max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - if(!ac_volt_mult_div_set) { - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (!ac_volt_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID, (void *)&default_ac_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add AC voltage multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID, (void *)&default_ac_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID, (void *)&default_ac_divisor + ); if (ret != ESP_OK) { log_e("Failed to add AC voltage divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ac_volt_mult_div_set = true; // Set flag to true, so we dont add the attributes again + ac_volt_mult_div_set = true; // Set flag to true, so we dont add the attributes again } } // Add the AC Current attributes @@ -404,7 +433,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me esp_zb_zcl_electrical_measurement_attr_t attr_current = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; esp_zb_zcl_electrical_measurement_attr_t attr_current_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_ID; esp_zb_zcl_electrical_measurement_attr_t attr_current_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_ID; - switch(phase_type) { + switch (phase_type) { case ZIGBEE_AC_PHASE_TYPE_A: // already set break; @@ -418,9 +447,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me attr_current_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_ID; attr_current_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_current, (void *)&default_ac_measurement); if (ret != ESP_OK) { @@ -437,18 +464,22 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me log_e("Failed to add AC current max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - if(!ac_current_mult_div_set) { - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (!ac_current_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID, (void *)&default_ac_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add AC current multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID, (void *)&default_ac_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID, (void *)&default_ac_divisor + ); if (ret != ESP_OK) { log_e("Failed to add AC current divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ac_current_mult_div_set = true; // Set flag to true, so we dont add the attributes again + ac_current_mult_div_set = true; // Set flag to true, so we dont add the attributes again } } // Add the AC Power attributes @@ -457,7 +488,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me esp_zb_zcl_electrical_measurement_attr_t attr_power_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_ID; esp_zb_zcl_electrical_measurement_attr_t attr_power_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_ID; - switch(phase_type) { + switch (phase_type) { case ZIGBEE_AC_PHASE_TYPE_A: // already set break; @@ -471,9 +502,7 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me attr_power_min = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_ID; attr_power_max = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power, (void *)&default_ac_measurement); if (ret != ESP_OK) { @@ -490,36 +519,33 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me log_e("Failed to add AC power max: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - if(!ac_power_mult_div_set) { - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID, (void *)&default_ac_multiplier); + if (!ac_power_mult_div_set) { + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID, (void *)&default_ac_multiplier + ); if (ret != ESP_OK) { log_e("Failed to add AC power multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID, (void *)&default_ac_divisor); + ret = esp_zb_electrical_meas_cluster_add_attr( + electrical_measurement_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID, (void *)&default_ac_divisor + ); if (ret != ESP_OK) { log_e("Failed to add AC power divisor: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } - ac_power_mult_div_set = true; // Set flag to true, so we dont add the attributes again + ac_power_mult_div_set = true; // Set flag to true, so we dont add the attributes again } - } - else { //(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) + } else { //(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR) esp_zb_zcl_electrical_measurement_attr_t attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; - switch(phase_type) { + switch (phase_type) { case ZIGBEE_AC_PHASE_TYPE_A: // already set break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; - break; - default: - log_e("Invalid phase type"); - return false; + case ZIGBEE_AC_PHASE_TYPE_B: attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_power_factor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; break; + default: log_e("Invalid phase type"); return false; } ret = esp_zb_electrical_meas_cluster_add_attr(electrical_measurement_cluster, attr_power_factor, (void *)&default_ac_power_factor); if (ret != ESP_OK) { @@ -530,14 +556,16 @@ bool ZigbeeElectricalMeasurement::addACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me return true; } -bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t min_value, int32_t max_value) { +bool ZigbeeElectricalMeasurement::setACMinMaxValue( + ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, int32_t min_value, int32_t max_value +) { uint16_t attr_min_id = 0; uint16_t attr_max_id = 0; // Check min/max values are valid for the measurement type switch (measurement_type) { case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: - case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: if (min_value < 0 || min_value > UINT16_MAX || max_value < 0 || max_value > UINT16_MAX) { log_e("AC measurement min/max values must be between 0 and %u (got min=%d, max=%d)", UINT16_MAX, min_value, max_value); @@ -552,15 +580,17 @@ bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE me } break; - default: - log_e("Invalid measurement type"); - return false; + default: log_e("Invalid measurement type"); return false; } - [[maybe_unused]] int16_t int16_min_value = (int16_t)min_value; - [[maybe_unused]] int16_t int16_max_value = (int16_t)max_value; - [[maybe_unused]] uint16_t uint16_min_value = (uint16_t)min_value; - [[maybe_unused]] uint16_t uint16_max_value = (uint16_t)max_value; + [[maybe_unused]] + int16_t int16_min_value = (int16_t)min_value; + [[maybe_unused]] + int16_t int16_max_value = (int16_t)max_value; + [[maybe_unused]] + uint16_t uint16_min_value = (uint16_t)min_value; + [[maybe_unused]] + uint16_t uint16_max_value = (uint16_t)max_value; //TODO: Log info about min and max values for different measurement types switch (measurement_type) { @@ -578,9 +608,7 @@ bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE me attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_ID; attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; @@ -598,9 +626,7 @@ bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE me attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_ID; attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; @@ -618,15 +644,11 @@ bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE me attr_min_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_ID; attr_max_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_ID; break; - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; - default: - log_e("Invalid measurement type"); - return false; + default: log_e("Invalid measurement type"); return false; } esp_zb_attribute_list_t *electrical_measurement_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); @@ -634,8 +656,8 @@ bool ZigbeeElectricalMeasurement::setACMinMaxValue(ZIGBEE_AC_MEASUREMENT_TYPE me esp_err_t ret = ESP_OK; ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_min_id, (void *)&min_value); if (ret != ESP_OK) { - log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; } ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_max_id, (void *)&max_value); if (ret != ESP_OK) { @@ -666,9 +688,7 @@ bool ZigbeeElectricalMeasurement::setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_T attr_multiplier = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID; attr_divisor = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID; break; - default: - log_e("Invalid measurement type"); - return false; + default: log_e("Invalid measurement type"); return false; } esp_zb_attribute_list_t *electrical_measurement_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); @@ -676,8 +696,8 @@ bool ZigbeeElectricalMeasurement::setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_T esp_err_t ret = ESP_OK; ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_multiplier, (void *)&multiplier); if (ret != ESP_OK) { - log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; + log_e("Failed to set multiplier: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; } ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_divisor, (void *)&divisor); if (ret != ESP_OK) { @@ -691,19 +711,11 @@ bool ZigbeeElectricalMeasurement::setACPowerFactor(ZIGBEE_AC_PHASE_TYPE phase_ty uint16_t attr_id = 0; switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } esp_zb_attribute_list_t *electrical_measurement_cluster = @@ -712,8 +724,8 @@ bool ZigbeeElectricalMeasurement::setACPowerFactor(ZIGBEE_AC_PHASE_TYPE phase_ty esp_err_t ret = ESP_OK; ret = esp_zb_cluster_update_attr(electrical_measurement_cluster, attr_id, (void *)&power_factor); if (ret != ESP_OK) { - log_e("Failed to set power factor: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; + log_e("Failed to set power factor: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; } return true; } @@ -724,7 +736,7 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me // Check value is valid for the measurement type switch (measurement_type) { case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: - case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: + case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: if (value < 0 || value > UINT16_MAX) { log_e("AC measurement value must be between 0 and %u (got %d)", UINT16_MAX, value); @@ -738,7 +750,7 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me return false; } break; - + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: if (value < -100 || value > 100) { log_e("AC power factor value must be between -100 and 100 (got %d)", value); @@ -746,9 +758,7 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me } break; - default: - log_e("Invalid measurement type"); - return false; + default: log_e("Invalid measurement type"); return false; } // Convert value to appropriate type based on measurement type uint16_t uint16_value = (uint16_t)value; @@ -758,76 +768,51 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me switch (measurement_type) { case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } // Use uint16_t for voltage log_v("Updating AC voltage measurement value..."); log_d("Setting AC voltage to %u", uint16_value); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + ret = + esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); esp_zb_lock_release(); break; case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } // Use uint16_t for current log_v("Updating AC current measurement value..."); log_d("Setting AC current to %u", uint16_value); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + ret = + esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); esp_zb_lock_release(); break; case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } // Use int16_t for power log_v("Updating AC power measurement value..."); log_d("Setting AC power to %d", int16_value); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int16_value, false); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int16_value, false); esp_zb_lock_release(); break; @@ -837,37 +822,26 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me log_v("Updating AC frequency measurement value..."); log_d("Setting AC frequency to %u", uint16_value); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); + ret = + esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &uint16_value, false); esp_zb_lock_release(); break; case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } // Use int8_t for power factor log_v("Updating AC power factor measurement value..."); log_d("Setting AC power factor to %d", int8_value); esp_zb_lock_acquire(portMAX_DELAY); - ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int8_value, false); + ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id, &int8_value, false); esp_zb_lock_release(); break; - default: - log_e("Invalid measurement type"); - return false; + default: log_e("Invalid measurement type"); return false; } if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { @@ -877,7 +851,9 @@ bool ZigbeeElectricalMeasurement::setACMeasurement(ZIGBEE_AC_MEASUREMENT_TYPE me return true; } -bool ZigbeeElectricalMeasurement::setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta) { +bool ZigbeeElectricalMeasurement::setACReporting( + ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta +) { uint16_t attr_id = 0; // Convert value to appropriate type based on measurement type @@ -887,64 +863,34 @@ bool ZigbeeElectricalMeasurement::setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE meas switch (measurement_type) { case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; - case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; - break; - case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: - log_e("Power factor attribute reporting not supported by zigbee specification"); - return false; - default: - log_e("Invalid measurement type"); - return false; + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: log_e("Power factor attribute reporting not supported by zigbee specification"); return false; + default: log_e("Invalid measurement type"); return false; } esp_zb_zcl_reporting_info_t reporting_info; @@ -958,7 +904,7 @@ bool ZigbeeElectricalMeasurement::setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE meas reporting_info.u.send_info.max_interval = max_interval; reporting_info.u.send_info.def_min_interval = min_interval; reporting_info.u.send_info.def_max_interval = max_interval; - if(measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER) { + if (measurement_type == ZIGBEE_AC_MEASUREMENT_TYPE_POWER) { reporting_info.u.send_info.delta.s16 = int16_delta; } else { reporting_info.u.send_info.delta.u16 = uint16_delta; @@ -981,64 +927,34 @@ bool ZigbeeElectricalMeasurement::reportAC(ZIGBEE_AC_MEASUREMENT_TYPE measuremen switch (measurement_type) { case ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; case ZIGBEE_AC_MEASUREMENT_TYPE_CURRENT: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; case ZIGBEE_AC_MEASUREMENT_TYPE_POWER: switch (phase_type) { - case ZIGBEE_AC_PHASE_TYPE_A: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_B: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; - break; - case ZIGBEE_AC_PHASE_TYPE_C: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; - break; + case ZIGBEE_AC_PHASE_TYPE_A: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID; break; + case ZIGBEE_AC_PHASE_TYPE_B: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID; break; + case ZIGBEE_AC_PHASE_TYPE_C: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID; break; case ZIGBEE_AC_PHASE_TYPE_NON_SPECIFIC: - default: - log_e("Invalid phase type"); - return false; + default: log_e("Invalid phase type"); return false; } break; - case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: - attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; - break; - case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: - log_e("Power factor attribute reporting not supported by zigbee specification"); - return false; - default: - log_e("Invalid measurement type"); - return false; + case ZIGBEE_AC_MEASUREMENT_TYPE_FREQUENCY: attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID; break; + case ZIGBEE_AC_MEASUREMENT_TYPE_POWER_FACTOR: log_e("Power factor attribute reporting not supported by zigbee specification"); return false; + default: log_e("Invalid measurement type"); return false; } /* Send report attributes command */ esp_zb_zcl_report_attr_cmd_t report_attr_cmd; @@ -1060,5 +976,4 @@ bool ZigbeeElectricalMeasurement::reportAC(ZIGBEE_AC_MEASUREMENT_TYPE measuremen return true; } - #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h index 7bd7d4aa44d..74d4a718fe2 100644 --- a/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h +++ b/libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.h @@ -89,8 +89,9 @@ class ZigbeeElectricalMeasurement : public ZigbeeEP { bool setACMultiplierDivisor(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, uint16_t multiplier, uint16_t divisor); // Set the AC power factor for the given phase type (-100 to 100 %) bool setACPowerFactor(ZIGBEE_AC_PHASE_TYPE phase_type, int8_t power_factor); - // Set the AC reporting interval for the given measurement type and phase type in seconds and delta (measurement change - uint16_t for voltage, current and frequency, int32_t for power) - bool setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta); + // Set the AC reporting interval for the given measurement type and phase type in seconds and delta (measurement change - uint16_t for voltage, current and frequency, int32_t for power) + bool + setACReporting(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type, uint16_t min_interval, uint16_t max_interval, int32_t delta); // Report the AC measurement value for the given measurement type and phase type bool reportAC(ZIGBEE_AC_MEASUREMENT_TYPE measurement_type, ZIGBEE_AC_PHASE_TYPE phase_type); From 5b03d614d1e35ab373577602595c6938db9a3a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 23 May 2025 15:47:03 +0200 Subject: [PATCH 3/4] ci(): fix precommit codespell --- .../Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino | 2 +- .../Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino index 5650a0f4878..9e8656119d6 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/Zigbee_Electrical_AC_Sensor.ino @@ -101,7 +101,7 @@ void setup() { } Serial.println("Connected"); - // Optional: Add reporting for AC measurements (this is overriden by HomeAssistant ZHA if used as a Zigbee coordinator) + // Optional: Add reporting for AC measurements (this is overridden by HomeAssistant ZHA if used as a Zigbee coordinator) zbElectricalMeasurement.setACReporting( ZIGBEE_AC_MEASUREMENT_TYPE_VOLTAGE, ZIGBEE_AC_PHASE_TYPE_A, 0, 30, 10 ); // report every 30 seconds if value changes by 10 (0.1V) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino index cd7c31a2912..4324a7b3ce5 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/Zigbee_Electrical_DC_Sensor.ino @@ -92,7 +92,7 @@ void setup() { } Serial.println("Connected"); - // Optional: Add reporting for DC measurements (this is overriden by HomeAssistant ZHA if connected to its network) + // Optional: Add reporting for DC measurements (this is overridden by HomeAssistant ZHA if connected to its network) zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_VOLTAGE, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1V) zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_CURRENT, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1A) zbElectricalMeasurement.setDCReporting(ZIGBEE_DC_MEASUREMENT_TYPE_POWER, 0, 30, 10); // report every 30 seconds if value changes by 10 (0.1W) From b50d3fb21fd5116a15b981d598da31fd17a6d16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 23 May 2025 15:54:24 +0200 Subject: [PATCH 4/4] ci(pre-commit): Add spaces between numbers and units --- .../Zigbee_Electrical_AC_Sensor/README.md | 16 ++++++++-------- .../README.md | 16 ++++++++-------- .../Zigbee_Electrical_DC_Sensor/README.md | 12 ++++++------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md index d8f2c6b2743..fe032049c90 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor/README.md @@ -12,20 +12,20 @@ Currently, this example supports the following targets. ## AC Electrical Measurement Functions * After this board first starts up, it would be configured locally to report AC electrical measurements: - - AC voltage in volts (0-300.00V) - - AC current in amps (0-10.000A) - - AC power in watts (0-3200.0W) - - AC frequency in hertz (0-65.000Hz) + - AC voltage in volts (0-300.00 V) + - AC current in amps (0-10.000 A) + - AC power in watts (0-3200.0 W) + - AC frequency in hertz (0-65.000 Hz) * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. * The device reports measurements every 2 seconds with simulated values. ## Measurement Precision The example demonstrates how to set up proper measurement precision using multiplier and divisor values: - * Voltage: 1/100 = 0.01V (1 unit = 10mV) - * Current: 1/1000 = 0.001A (1 unit = 1mA) - * Power: 1/10 = 0.1W (1 unit = 100mW) - * Frequency: 1/1000 = 0.001Hz (1 unit = 1mHz) + * Voltage: 1/100 = 0.01 V (1 unit = 10 mV) + * Current: 1/1000 = 0.001 A (1 unit = 1 mA) + * Power: 1/10 = 0.1 W (1 unit = 100 mW) + * Frequency: 1/1000 = 0.001 Hz (1 unit = 1 mHz) These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network. diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md index bc6b2e1a5d7..3714a05fa4f 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md +++ b/libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase/README.md @@ -12,20 +12,20 @@ Currently, this example supports the following targets. ## AC Electrical Measurement Functions * After this board first starts up, it would be configured locally to report AC electrical measurements: - - AC voltage in volts (0-300.00V) for each phase (A, B, C) - - AC current in amps (0-10.000A) for each phase (A, B, C) - - AC power in watts (0-3200.0W) for each phase (A, B, C) - - AC frequency in hertz (0-65.000Hz) shared across all phases + - AC voltage in volts (0-300.00 V) for each phase (A, B, C) + - AC current in amps (0-10.000 A) for each phase (A, B, C) + - AC power in watts (0-3200.0 W) for each phase (A, B, C) + - AC frequency in hertz (0-65.000 Hz) shared across all phases * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. * The device reports measurements every 2 seconds with simulated values. ## Measurement Precision The example demonstrates how to set up proper measurement precision using multiplier and divisor values: - * Voltage: 1/100 = 0.01V (1 unit = 10mV) - * Current: 1/1000 = 0.001A (1 unit = 1mA) - * Power: 1/10 = 0.1W (1 unit = 100mW) - * Frequency: 1/1000 = 0.001Hz (1 unit = 1mHz) + * Voltage: 1/100 = 0.01 V (1 unit = 10 mV) + * Current: 1/1000 = 0.001 A (1 unit = 1 mA) + * Power: 1/10 = 0.1 W (1 unit = 100 mW) + * Frequency: 1/1000 = 0.001 Hz (1 unit = 1 mHz) These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network. diff --git a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md index fae9565ecec..e8922fc1a79 100644 --- a/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md +++ b/libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor/README.md @@ -12,18 +12,18 @@ Currently, this example supports the following targets. ## DC Electrical Measurement Functions * After this board first starts up, it would be configured locally to report DC electrical measurements: - - DC voltage in millivolts (0-5000mV) - - DC current in milliamps (0-1000mA) - - DC power in milliwatts (0-5000mW) + - DC voltage in millivolts (0-5000 mV) + - DC current in milliamps (0-1000 mA) + - DC power in milliwatts (0-5000 mW) * Holding the button (BOOT) for more than 3 seconds will trigger a factory reset of the device. * The device reports measurements every 30 seconds if the value changes by more than the configured delta. ## Measurement Precision The example demonstrates how to set up proper measurement precision using multiplier and divisor values: - * Voltage: 1/1000 = 0.001V (1 unit = 1mV) - * Current: 1/1000 = 0.001A (1 unit = 1mA) - * Power: 1/1000 = 0.001W (1 unit = 1mW) + * Voltage: 1/1000 = 0.001 V (1 unit = 1 mV) + * Current: 1/1000 = 0.001 A (1 unit = 1 mA) + * Power: 1/1000 = 0.001 W (1 unit = 1 mW) These settings ensure accurate reporting of measurements with proper decimal precision in the Zigbee network.