Skip to content

Commit

Permalink
Create init.lua
Browse files Browse the repository at this point in the history
Add create init for Kichler fan light
  • Loading branch information
seungkwan-choi authored Mar 19, 2024
1 parent 80b525a commit 54b7e0b
Showing 1 changed file with 187 additions and 0 deletions.
187 changes: 187 additions & 0 deletions drivers/SmartThings/zigbee-fan/src/kichler-fan-light/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
-- Copyright 2024 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 FanControl = clusters.FanControl
local Level = clusters.Level
local OnOff = clusters.OnOff

local FINGERPRINTS = {
{ mfr = "KICHLER", model = "KICHLER-FANLIGHT-Z-301" },
}

local function can_handle_itm_fanlight(opts, driver, device)
for _, fingerprint in ipairs(FINGERPRINTS) do
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then
return true
end
end
return false
end

-- CAPABILITY HANDLERS
local function on_handler(driver, device, command)
local last_level = device:get_field('LAST_DIM_LEVEL') or 100
local level = math.floor((last_level/100.0) * 254 )
if command.component == 'light' then
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, level, command.args.rate or 0xFFFF))
device:set_field('LAST_DIM_LEVEL', last_level, {persist = true})
else
local speed = device:get_field('LAST_FAN_SPD') or 1
device:send(FanControl.attributes.FanMode:write(device, speed))
end
device:send(FanControl.attributes.FanMode:read(device))
end

local function off_handler(driver, device, command)
if command.component == 'light' then
local last_level = device:get_field('LAST_DIM_LEVEL') or 100
--local level = math.floor((last_level/100.0) * 254 )
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, 0, command.args.rate or 0xFFFF))
device:set_field('LAST_DIM_LEVEL', last_level, {persist = true})
else
device:send(FanControl.attributes.FanMode:write(device, FanControl.attributes.FanMode.OFF))
end
device:send(FanControl.attributes.FanMode:read(device))
end

local function switch_level_handler(driver, device, command)
local trim_level = tonumber(device.preferences.trim) or 10
if command.args.level <= trim_level and command.args.level >= 1 then
local level = math.floor((trim_level/100.0) * 254 )
device:emit_component_event(device.profile.components.light, capabilities.switchLevel.level(command.args.level))
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, level, command.args.rate or 0xFFFF))
device:emit_component_event(device.profile.components.light, capabilities.switchLevel.level(trim_level))
device:set_field('LAST_DIM_LEVEL', trim_level, {persist = true})
elseif command.args.level < 1 then
local level = 0
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, level, command.args.rate or 0xFFFF))
else
local level = math.floor((command.args.level/100.0) * 254 )
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, level, command.args.rate or 0xFFFF))
device:set_field('LAST_DIM_LEVEL', command.args.level, {persist = true})
end
end

local function fan_speed_handler(driver, device, command)
if command.args.speed < 4 then
device:send(FanControl.attributes.FanMode:write(device, command.args.speed))
device:send(FanControl.attributes.FanMode:read(device))
end
end

-- ZIGBEE HANDLERS
local function zb_fan_control_handler(driver, device, value, zb_rx)
if value.value < 4 then
device:emit_event(capabilities.fanSpeed.fanSpeed(value.value))
local evt = capabilities.switch.switch(value.value > 0 and 'on' or 'off', { visibility = { displayed = true } })
device:emit_component_event(device.profile.components.main, evt)
device:emit_component_event(device.profile.components.main, capabilities.fanSpeed.fanSpeed(value.value))
if value.value > 0 then
device:set_field('LAST_FAN_SPD', value.value, {persist = true})
end
end
end

local function zb_level_handler(driver, device, value, zb_rx)
local evt = capabilities.switchLevel.level(math.floor(0.5 + (value.value / 254.0) * 100))
device:emit_component_event(device.profile.components.light, evt)
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)
end

local function info_changed(driver, device, event, args)
if device.preferences ~= nil then
local current_level = device:get_latest_state('light', capabilities.switchLevel.ID, capabilities.switchLevel.level.NAME)
local new_trim = tonumber(device.preferences.trim)
local old_trim = tonumber(args.old_st_store.preferences.trim)
if args.old_st_store.preferences.trim ~= device.preferences.trim then
if old_trim < new_trim then
if new_trim >= current_level then
local newlevel = math.floor((new_trim/100.0) * 254 )
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
else
local newlevel = math.floor((current_level/100.0) * 254 )
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
else
local newlevel = math.floor((current_level/100.0) * 254 )
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
end
if device.preferences.breezemode ~= args.old_st_store.preferences.breezemode then
local speed = device:get_field('LAST_FAN_SPD') or 1
local breeze_flag = tonumber(device.preferences.breezemode)
if breeze_flag == 0 then
device:send(FanControl.attributes.FanMode:write(device, 5))
device:send(FanControl.attributes.FanMode:write(device, speed))
elseif breeze_flag == 1 then
device:send(FanControl.attributes.FanMode:write(device, 4))
end
end
if device.preferences.fandirection ~= args.old_st_store.preferences.fandirection then
local flag_direction = device:get_field('FANDIRECTION_FLAG') or 0
local send_fandirection_time = device:get_field('FANDIRECTION_SENDTIME') or 0
local current_fandirection_time = os.time()
local time_difference = os.difftime(current_fandirection_time, send_fandirection_time) or 0
if time_difference >= 10 or send_fandirection_time == 0 then
device:send(FanControl.attributes.FanMode:write(device, 6))
device:set_field('FANDIRECTION_SENDTIME', current_fandirection_time, {persist = true})
else
--device.thread:call_with_delay(10 - time_difference,
-- function(d) device:send(FanControl.attributes.FanMode:write(device, 6)) end)
device:set_field('FANDIRECTION_FLAG', flag_direction + 1 , {persist = true})
end
end
end
end

local kichler_fan_light = {
NAME = "KICHLER 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 = can_handle_itm_fanlight
}

return kichler_fan_light

0 comments on commit 54b7e0b

Please sign in to comment.