diff --git a/.gitignore b/.gitignore index c5bbdc6f99..cfd9fe533f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ lua_libs-api_* tools/test_output/* tools/coverage_output/* .DS_Store -.venv/ +.venv/ \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-power-meter/fingerprints.yml b/drivers/SmartThings/zigbee-power-meter/fingerprints.yml index 37cf9df678..7807961214 100644 --- a/drivers/SmartThings/zigbee-power-meter/fingerprints.yml +++ b/drivers/SmartThings/zigbee-power-meter/fingerprints.yml @@ -28,10 +28,15 @@ zigbeeManufacturer: manufacturer: ShinaSystem model: "PMM-300Z3" deviceProfileName: power-meter-consumption-report-sihas + - id: Chameleon/CT101xxxx + deviceLabel: Chameleon CT Clamp + manufacturer: Chameleon Technology + model: CT101xxxx + deviceProfileName: power-energy-battery-temperature zigbeeGeneric: - id: "genericMeter" deviceLabel: Zigbee Meter clusters: server: - 0x0702 #Simple Metering - deviceProfileName: power-meter + deviceProfileName: power-meter \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-power-meter/profiles/power-energy-battery-temperature.yml b/drivers/SmartThings/zigbee-power-meter/profiles/power-energy-battery-temperature.yml new file mode 100644 index 0000000000..a47aef0114 --- /dev/null +++ b/drivers/SmartThings/zigbee-power-meter/profiles/power-energy-battery-temperature.yml @@ -0,0 +1,19 @@ +name: power-energy-battery-temperature +components: +- id: main + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + - id: battery + version: 1 + - id: temperatureMeasurement + version: 1 + categories: + - name: CurbPowerMeter + diff --git a/drivers/SmartThings/zigbee-power-meter/src/chameleon/init.lua b/drivers/SmartThings/zigbee-power-meter/src/chameleon/init.lua new file mode 100644 index 0000000000..e527936146 --- /dev/null +++ b/drivers/SmartThings/zigbee-power-meter/src/chameleon/init.lua @@ -0,0 +1,104 @@ +-- Copyright 2025 SmartThings +-- +-- 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. + +local clusters = require "st.zigbee.zcl.clusters" +local capabilities = require "st.capabilities" +local log = require "log" + +local TemperatureMeasurement = clusters.DeviceTemperatureConfiguration +local PowerConfiguration = clusters.PowerConfiguration + +local ZIGBEE_FINGERPRINT = { + {model = "CT101xxxx" } +} + +local configuration = { + { + cluster = TemperatureMeasurement.ID, + attribute = TemperatureMeasurement.attributes.CurrentTemperature.ID, + minimum_interval = 30, + maximum_interval = 3600, + data_type = TemperatureMeasurement.attributes.CurrentTemperature.base_type, + reportable_change = 1 + }, + { + cluster = PowerConfiguration.ID, + attribute = PowerConfiguration.attributes.BatteryPercentageRemaining.ID, + minimum_interval = 30, + maximum_interval = 3600, + data_type = PowerConfiguration.attributes.BatteryPercentageRemaining.base_type, + reportable_change = 2 + } +} + +local is_chameleon_ct_clamp = function(opts, driver, device) + for _, fingerprint in ipairs(ZIGBEE_FINGERPRINT) do + if device:get_model() == fingerprint.model then + return true + end + end + return false +end + +local function battery_level_handler(driver, device, value, _zb_rx) + if type(value.value) == "number" then + local number = value.value/2 + local integer_result = math.floor(number) + device:emit_event(capabilities.battery.battery(integer_result)) + else + log.error("Invalid battery level value received: " .. tostring(value.value)) + end +end + +local function temperature_handler(driver, device, value, _zb_rx) + if type(value.value) == "number" then + device:emit_event(capabilities.temperatureMeasurement.temperature({ value = value.value, unit = "C" })) + else + log.error("Invalid temperature value received: " .. tostring(value.value)) + end +end + +local function device_init(driver, device) + if configuration ~= nil then + for _, attribute in ipairs(configuration) do + device:add_configured_attribute(attribute) + end + end +end + +local function added_handler(self, device) + device:emit_event(capabilities.temperatureMeasurement.temperature({ value = 0, unit = "C" })) + device:emit_event(capabilities.battery.battery({value = 0, unit = "%" })) +end + +local ct_clamp_battery_temperature_handler = { + NAME = "ct_clamp_battery_temperature_handler", + zigbee_handlers = { + attr = { + --[PowerConfiguration.ID] = { + -- [PowerConfiguration.attributes.BatteryPercentageRemaining.ID] = battery_level_handler + --}, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.CurrentTemperature.ID] = temperature_handler + } + } + }, + lifecycle_handlers = { + init = device_init, + added = added_handler + }, + can_handle = is_chameleon_ct_clamp +} + +return ct_clamp_battery_temperature_handler diff --git a/drivers/SmartThings/zigbee-power-meter/src/init.lua b/drivers/SmartThings/zigbee-power-meter/src/init.lua index ae98baca8b..0df18636d6 100644 --- a/drivers/SmartThings/zigbee-power-meter/src/init.lua +++ b/drivers/SmartThings/zigbee-power-meter/src/init.lua @@ -51,6 +51,7 @@ local zigbee_power_meter_driver_template = { capabilities.powerMeter, capabilities.energyMeter, capabilities.powerConsumptionReport, + capabilities.battery, }, zigbee_handlers = { global = { @@ -67,6 +68,7 @@ local zigbee_power_meter_driver_template = { require("ezex"), require("frient"), require("shinasystems"), + require("chameleon"), }, lifecycle_handlers = { init = configurations.power_reconfig_wrapper(device_init),