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..fab380ce6f 100644 --- a/drivers/SmartThings/zigbee-power-meter/fingerprints.yml +++ b/drivers/SmartThings/zigbee-power-meter/fingerprints.yml @@ -28,6 +28,11 @@ 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: ct-clamp zigbeeGeneric: - id: "genericMeter" deviceLabel: Zigbee Meter @@ -35,3 +40,24 @@ zigbeeGeneric: server: - 0x0702 #Simple Metering deviceProfileName: power-meter + - id: "ChameleonCTClamp" + deviceLabel: Zigbee CT + deviceIdentifiers: + - 0x000D + zigbeeProfiles: + - 0x0104 + clusters: + server: + - 0x0000 #Basic + - 0x0001 #Power Configuration + - 0x0002 #Device Temperature Configuration + - 0x0003 #Identify + - 0x0019 #Over the Air Bootloading + - 0x0020 #Poll Control + - 0x0702 #Simple Metering + - 0x0B04 #Electrical Measurement + client: + - 0x0003 #Identify + deviceProfileName: ct-clamp + + diff --git a/drivers/SmartThings/zigbee-power-meter/profiles/ct-clamp.yml b/drivers/SmartThings/zigbee-power-meter/profiles/ct-clamp.yml new file mode 100644 index 0000000000..e5ad44c8f3 --- /dev/null +++ b/drivers/SmartThings/zigbee-power-meter/profiles/ct-clamp.yml @@ -0,0 +1,19 @@ +name: ct-clamp +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..e6245af14f --- /dev/null +++ b/drivers/SmartThings/zigbee-power-meter/src/chameleon/init.lua @@ -0,0 +1,98 @@ +local clusters = require "st.zigbee.zcl.clusters" +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local capabilities = require "st.capabilities" +local log = require "log" + +local TemperatureMeasurement = clusters.DeviceTemperatureConfiguration +local PowerConfiguration = clusters.PowerConfiguration + +local ZIGBEE_FINGERPRINT = { + {model = "CT101xxxx" } +} + +-- temperature: 0.5C, battery level remaining: 1% +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 + + local batt_level = device:get_latest_state("main", capabilities.battery.ID, capabilities.battery.battery.NAME) or nil + if batt_level == nil then + device:emit_event(capabilities.battery.battery.normal()) + 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..016f1e7e42 100644 --- a/drivers/SmartThings/zigbee-power-meter/src/init.lua +++ b/drivers/SmartThings/zigbee-power-meter/src/init.lua @@ -67,6 +67,7 @@ local zigbee_power_meter_driver_template = { require("ezex"), require("frient"), require("shinasystems"), + require("chameleon"), }, lifecycle_handlers = { init = configurations.power_reconfig_wrapper(device_init),