From 033ded5c8df590a4448fe2d42a67e5f9122c953d Mon Sep 17 00:00:00 2001 From: seungkwan-choi <136560804+seungkwan-choi@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:20:48 +0900 Subject: [PATCH] Add Zigbee fan Add Zigbee fan --- drivers/SmartThings/zigbee-fan/README.md | 2 + drivers/SmartThings/zigbee-fan/config.yml | 6 + .../SmartThings/zigbee-fan/fingerprints.yml | 7 + .../zigbee-fan/profiles/itm-fan-light.yml | 34 ++++ .../zigbee-fan/profiles/switch-level.yml | 12 ++ .../zigbee-fan/src/configurations.lua | 66 +++++++ drivers/SmartThings/zigbee-fan/src/init.lua | 46 +++++ .../zigbee-fan/src/itm-fan-light/init.lua | 168 ++++++++++++++++++ 8 files changed, 341 insertions(+) create mode 100644 drivers/SmartThings/zigbee-fan/README.md create mode 100644 drivers/SmartThings/zigbee-fan/config.yml create mode 100644 drivers/SmartThings/zigbee-fan/fingerprints.yml create mode 100644 drivers/SmartThings/zigbee-fan/profiles/itm-fan-light.yml create mode 100644 drivers/SmartThings/zigbee-fan/profiles/switch-level.yml create mode 100644 drivers/SmartThings/zigbee-fan/src/configurations.lua create mode 100644 drivers/SmartThings/zigbee-fan/src/init.lua create mode 100644 drivers/SmartThings/zigbee-fan/src/itm-fan-light/init.lua diff --git a/drivers/SmartThings/zigbee-fan/README.md b/drivers/SmartThings/zigbee-fan/README.md new file mode 100644 index 0000000000..a90f2734b0 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/README.md @@ -0,0 +1,2 @@ +# EDGE-Driver---Fan-Light +# update code complete \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-fan/config.yml b/drivers/SmartThings/zigbee-fan/config.yml new file mode 100644 index 0000000000..1788de6f73 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/config.yml @@ -0,0 +1,6 @@ +name: 'ITM Fan Light 231201' +packageKey: 'itm-fan-light' +description: 'EDGE Driver, ITM Fan Light' +vendorSupportInformation: +permissions: + zigbee: {} diff --git a/drivers/SmartThings/zigbee-fan/fingerprints.yml b/drivers/SmartThings/zigbee-fan/fingerprints.yml new file mode 100644 index 0000000000..478104c7a6 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/fingerprints.yml @@ -0,0 +1,7 @@ +zigbeeManufacturer: + # FANS + - id: "Samsung/SAMSUNG-ITM-Z-003" + deviceLabel: ITM Fan Light + manufacturer: Samsung Electronics + model: SAMSUNG-ITM-Z-003 + deviceProfileName: itm-fan-light \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-fan/profiles/itm-fan-light.yml b/drivers/SmartThings/zigbee-fan/profiles/itm-fan-light.yml new file mode 100644 index 0000000000..a7df963ac7 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/profiles/itm-fan-light.yml @@ -0,0 +1,34 @@ +name: itm-fan-light +components: + - id: main + label: Fan + capabilities: + - id: switch + version: 1 + - id: fanSpeed + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: Fan + - id: light + label: Light + capabilities: + - id: switch + version: 1 + - id: switchLevel + version: 1 + - id: refresh + version: 1 + categories: + - name: Light +preferences: + - title: "Child Device" + name: childLight2 + description: "Create Child Device : Light" + required: true + preferenceType: boolean + definition: + default: false \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-fan/profiles/switch-level.yml b/drivers/SmartThings/zigbee-fan/profiles/switch-level.yml new file mode 100644 index 0000000000..eba6e2cde4 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/profiles/switch-level.yml @@ -0,0 +1,12 @@ +name: switch-level +components: +- id: main + capabilities: + - id: switch + version: 1 + - id: switchLevel + version: 1 + - id: refresh + version: 1 + categories: + - name: Light \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-fan/src/configurations.lua b/drivers/SmartThings/zigbee-fan/src/configurations.lua new file mode 100644 index 0000000000..752eb83bba --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/src/configurations.lua @@ -0,0 +1,66 @@ +-- Copyright 2022 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 OnOff = clusters.OnOff +local Level = clusters.Level +local FanControl = clusters.FanControl + +local devices = { + ITM_FAN_LIGHT = { + FINGERPRINTS = { + { mfr = "Samsung Electronics", model = "SAMSUNG-ITM-Z-003" }, + }, + CONFIGURATION = { + { + cluster = OnOff.ID, + attribute = OnOff.attributes.OnOff.ID, + minimum_interval = 0, + maximum_interval = 600, + data_type = OnOff.attributes.OnOff.base_type + }, + { + cluster = Level.ID, + attribute = Level.attributes.CurrentLevel.ID, + minimum_interval = 1, + maximum_interval = 600, + data_type = Level.attributes.CurrentLevel.base_type, + reportable_change = 1 + }, + { + cluster = FanControl.ID, + attribute = FanControl.attributes.FanMode.ID, + minimum_interval = 1, + maximum_interval = 600, + data_type = FanControl.attributes.FanMode.base_type + } + } + }, +} + +local configurations = {} + +configurations.get_device_configuration = function(zigbee_device) + for _, device in pairs(devices) do + for _, fingerprint in pairs(device.FINGERPRINTS) do + if zigbee_device:get_manufacturer() == fingerprint.mfr and zigbee_device:get_model() == fingerprint.model then + return device.CONFIGURATION + end + end + end + return nil +end + +return configurations \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-fan/src/init.lua b/drivers/SmartThings/zigbee-fan/src/init.lua new file mode 100644 index 0000000000..ccde518275 --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/src/init.lua @@ -0,0 +1,46 @@ +-- Copyright 2022 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 capabilities = require "st.capabilities" +local ZigbeeDriver = require "st.zigbee" +local defaults = require "st.zigbee.defaults" +local configurationMap = require "configurations" + +local device_init = function(self, device) + local configuration = configurationMap.get_device_configuration(device) + if configuration ~= nil then + for _, attribute in ipairs(configuration) do + device:add_configured_attribute(attribute) + device:add_monitored_attribute(attribute) + end + end +end + +local zigbee_switch_driver_template = { + supported_capabilities = { + capabilities.switch, + capabilities.switchLevel, + capabilities.colorControl, + capabilities.colorTemperature, + capabilities.fanspeed + }, + sub_drivers = { + require("itm-fan-light") + }, + lifecycle_handlers = { + init = device_init + } +} + +zigbee_switch:run() diff --git a/drivers/SmartThings/zigbee-fan/src/itm-fan-light/init.lua b/drivers/SmartThings/zigbee-fan/src/itm-fan-light/init.lua new file mode 100644 index 0000000000..36ad7bc12e --- /dev/null +++ b/drivers/SmartThings/zigbee-fan/src/itm-fan-light/init.lua @@ -0,0 +1,168 @@ +-- Copyright 2023 philh30 +-- +-- 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 st_device = require "st.device" +local clusters = require "st.zigbee.zcl.clusters" +local capabilities = require "st.capabilities" +local FanControl = clusters.FanControl +local Level = clusters.Level +local OnOff = clusters.OnOff + +local IFL_FINGERPRINTS = { + { mfr = "Samsung Electronics", model = "SAMSUNG-ITM-Z-003" }, +} + +local is_ifl = function(opts, driver, device) + for _, fingerprint in ipairs(IFL_FINGERPRINTS) do + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end + end + return false +end + +-- Create child device + +local function add_child(driver,parent,profile,child_type) + local child_metadata = { + type = "EDGE_CHILD", + label = string.format("%s %s", parent.label, child_type), + profile = profile, + parent_device_id = parent.id, + parent_assigned_child_key = child_type, + vendor_provided_label = string.format("%s %s", parent.label, child_type) + } + driver:try_create_device(child_metadata) +end + +local function info_changed(driver, device, event, args) + if (device.preferences or {}).childLight2 then + if not device:get_child_by_parent_assigned_key('light') then + add_child(driver,device,'switch-level','light') + end + end +end + +-- CAPABILITY HANDLERS + +local function on_handler(driver, device, command) + local dev = device + if device.network_type == st_device.NETWORK_TYPE_CHILD then + command.component = 'light' + dev = device:get_parent_device() + end + if command.component == 'light' then + dev:send(OnOff.server.commands.On(dev)) + else + local speed = dev:get_field('LAST_FAN_SPD') or 1 + dev:send(FanControl.attributes.FanMode:write(dev,speed)) + dev:send(FanControl.attributes.FanMode:read(dev,speed)) + end +end + +local function off_handler(driver, device, command) + local dev = device + if device.network_type == st_device.NETWORK_TYPE_CHILD then + command.component = 'light' + dev = device:get_parent_device() + end + if command.component == 'light' then + dev:send(OnOff.server.commands.Off(dev)) + else + dev:send(FanControl.attributes.FanMode:write(dev,FanControl.attributes.FanMode.OFF)) + end + dev:send(FanControl.attributes.FanMode:read(dev,FanControl.attributes.FanMode.OFF)) +end + +local function switch_level_handler(driver, device, command) + local dev = device + if device.network_type == st_device.NETWORK_TYPE_CHILD then + command.component = 'light' + dev = device:get_parent_device() + end + if command.component == 'light' then + local level = math.floor(command.args.level/100.0 * 254) + dev:send(Level.server.commands.MoveToLevelWithOnOff(dev, level, command.args.rate or 0xFFFF)) + end +end + +local function fan_speed_handler(driver, device, command) + device:send(FanControl.attributes.FanMode:write(device,command.args.speed)) + device:send(FanControl.attributes.FanMode:read(device,command.args.speed)) +end + +-- ZIGBEE HANDLERS + +local function zb_fan_control_handler(driver, device, value, zb_rx) + device:emit_event(capabilities.fanSpeed.fanSpeed(value.value)) + local evt = capabilities.switch.switch(value.value > 0 and 'on' or 'off', { visibility = { displayed = false } }) + device:emit_component_event(device.profile.components.main,evt) + if value.value > 0 then + device:set_field('LAST_FAN_SPD', value.value, {persist = true}) + end +end + +local function zb_level_handler(driver, device, value, zb_rx) + local evt = capabilities.switchLevel.level(math.floor((value.value / 254.0 * 100) + 0.5)) + device:emit_component_event(device.profile.components.light,evt) + local child = device:get_child_by_parent_assigned_key('light') + if child ~= nil then + child:emit_event(evt) + end +end + +local function zb_onoff_handler(driver, device, value, zb_rx) + local attr = capabilities.switch.switch + local evt = value.value and attr.on() or attr.off() + device:emit_component_event(device.profile.components.light,evt) + local child = device:get_child_by_parent_assigned_key('light') + if child ~= nil then + child:emit_event(evt) + end +end + +local itm_fan_light = { + NAME = "ITM Fan Light", + zigbee_handlers = { + attr = { + [FanControl.ID] = { + [FanControl.attributes.FanMode.ID] = zb_fan_control_handler + }, + [Level.ID] = { + [Level.attributes.CurrentLevel.ID] = zb_level_handler + }, + [OnOff.ID] = { + [OnOff.attributes.OnOff.ID] = zb_onoff_handler + } + } + }, + capability_handlers = { + [capabilities.switch.ID] = { + [capabilities.switch.commands.on.NAME] = on_handler, + [capabilities.switch.commands.off.NAME] = off_handler, + }, + [capabilities.switchLevel.ID] = { + [capabilities.switchLevel.commands.setLevel.NAME] = switch_level_handler + }, + [capabilities.fanSpeed.ID] = { + [capabilities.fanSpeed.commands.setFanSpeed.NAME] = fan_speed_handler + } + }, + lifecycle_handlers = { + infoChanged = info_changed, + }, + can_handle = is_ifl +} + +return itm_fan_light \ No newline at end of file