Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requset to add a fingerprints for Kichler Zigbee fan light #1278

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

seungkwan-choi
Copy link
Contributor

@seungkwan-choi seungkwan-choi commented Mar 19, 2024

This is new project for Kichler.
It's a Zigbee fan and the model no. is KICHLER-FANLIGHT-Z-301.
I want to add Kichler to the fingerprints of a Zigbee fan.
The function of the option has been added to the fan light
Please review it.

Add fingerprints for KICHLER
Create Profiles for kichler-fan-light
Add update init for Kichler
Add update configurations for Kichler
Add create init for Kichler fan light
Add create test kichler fan light
@seungkwan-choi seungkwan-choi changed the title Requset to add a fingerpirnts for Kichler Zigbee fan light Requset to add a fingerprints for Kichler Zigbee fan light Mar 19, 2024
Copy link

Duplicate profile check: Passed - no duplicate profiles detected.

Copy link

Copy link

github-actions bot commented Mar 19, 2024

Test Results

   56 files    363 suites   0s ⏱️
1 757 tests 1 757 ✅ 0 💤 0 ❌
3 049 runs  3 049 ✅ 0 💤 0 ❌

Results for commit 584c4a9.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Mar 19, 2024

File Coverage
All files 97%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-fan/src/fan-light/init.lua 95%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-fan/src/configurations.lua 97%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-fan/src/kichler-fan-light/init.lua 97%

Minimum allowed coverage is 90%

Generated by 🐒 cobertura-action against 584c4a9

Comment on lines 35 to 36
local last_level = device:get_field('LAST_DIM_LEVEL') or 100
local level = math.floor((last_level/100.0) * 254 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these should be moved inside the if statement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change it.


-- CAPABILITY HANDLERS
local function on_handler(driver, device, command)
local last_level = device:get_field('LAST_DIM_LEVEL') or 100
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as far as I can tell, you maintain the level value even when receiving an off report. Unless the device separately reports a 0 level when turning off, you should be able to use device:get_latest_state instead of setting an additional field here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When i apply the code that was guided to me, if i turn on the light after turning it off, i can't retrieve the last value (off), and instead retrieve the off state. so, I will continue to use the set/get_field as you are now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

were you getting the latest value of the switch capability or the switchLevel capability?

device:get_latest_state("main", capabilities.switchLevel.ID, capabilities.switchLevel.level.NAME)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of the switchlevel is because it is synchronized with the main switch.
The proposed get_lastest_state maintains "off" if you turn it on after turning it off, as the last state value is "off".
Therefore, we intend to use set/get field instead of using get_lastest_state.

Comment on lines +63 to +65
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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the intent behind these two level events from the same component here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to use the Trim function. This trim is used to limit the minimum value of dimming.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the point of the trim function, but it seems like you'd want to only emit the trimmed value, not both the untrimmed and trimmed value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to refresh the value below the trim setting value so that it is not reflected in the UI. If you set it to trim 25% and control it to 10%, it will be 25%.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why send both the 10% event and the 25% event? Wouldn't you want to just send the 25% event?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

24캡처

Set Trim to 25%.
If the user has changed to 10% in the UI, the intention is to express it as 25%.
However, if you adjust 25% and then adjust it to less than that (e.g., 20%), it is to inform you of the event that it has been changed to go back to 25%

@greens
Copy link
Contributor

greens commented Mar 22, 2024

Please work to raise the code coverage to at least 90%

Update init file
Comment on lines 114 to 125
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
local newlevel = math.floor((current_level/100.0) * 254 )
if old_trim < new_trim then
if new_trim >= current_level then
local newlevel = math.floor((new_trim/100.0) * 254 )
end
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified it with the code you suggested

Edit with suggested code
Comment on lines 114 to 123
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
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
else
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
else
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))
end
if old_trim < new_trim then
if new_trim >= current_level then
newlevel = math.floor((new_trim/100.0) * 254 )
end
end
device:send_to_component('light', Level.server.commands.MoveToLevelWithOnOff(device, newlevel, 0))

Copy link
Contributor Author

@seungkwan-choi seungkwan-choi Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it with the code you suggested.

Comment on lines +36 to +47
- name: "trim"
title: "Minimum Dimming Level"
description: "Set the lowest dimming level"
required: false
preferenceType: enumeration
definition:
options:
10 : "10%"
15 : "15%"
20 : "20%"
25 : "25%"
default: 10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In relation to this preference, I'm happy to direct you to this new feature we added, which is the ability to set min/max values for the switch level attribute. You may find that using this is simpler than having to do the trimming yourself.

Here's an example of how to emit this event:

https://github.com/SmartThingsCommunity/SmartThingsEdgeDrivers/pull/1220/files#diff-7ab55ddbc6a9760ea5b6f928abee244c3142c74389743ce05b895b938ad81f10R372

The min/max should be displayed and carried across automations as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is expected that there will be models derived from this model. We will try to use the code you suggested at that time. Thank you.

I changed it with the code you suggested.
Copy link
Contributor

@greens greens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good but could you write a test that verifies the setlevel command after setting the trim above 0?

Similarly a test that checks the events that are sent after the trim is set above the current level of the device?

We prefer to have code coverage over 90% and you're currently at 87%.

@seungkwan-choi
Copy link
Contributor Author

The test code has been modified.

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})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this value doesn't need to persist

it takes more than 10s for the hub to reboot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of using the following code, regardless of the hub, is to prevent sending commands if a command has been sent within 10 seconds. (This is related to protecting the fan driving circuit.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but the persist = true makes the value durable through hub restarts.

Because hub restarts take more than 10s, you do not need to have this flag persist, because it is guaranteed to have been more than 10s since you last sent the write on hub restart. Just keeping it in memory should be enough.

device:send(FanControl.attributes.FanMode:write(device, 6))
device:set_field('FANDIRECTION_SENDTIME', current_fandirection_time, {persist = true})
else
device:set_field('FANDIRECTION_FLAG', flag_direction + 1 , {persist = true})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's unclear what this flag does. you don't use the value except here where you increment it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test code has been modified.

240403 update init file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants