-
Notifications
You must be signed in to change notification settings - Fork 464
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
Add support for Inovelli VTM31-SN Dimmer Switch #1754
base: main
Are you sure you want to change the base?
Changes from 2 commits
ce551e2
435c7d5
2e8b4b5
a3a79ab
f48add6
cce231f
3405324
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
name: inovelli-vtm31-sn | ||
components: | ||
- id: main | ||
capabilities: | ||
- id: switch | ||
version: 1 | ||
- id: switchLevel | ||
version: 1 | ||
- id: refresh | ||
version: 1 | ||
- id: configuration | ||
version: 1 | ||
- id: firmwareUpdate | ||
version: 1 | ||
categories: | ||
- name: Switch | ||
- id: button1 | ||
label: Up Button | ||
capabilities: | ||
- id: button | ||
version: 1 | ||
categories: | ||
- name: RemoteController | ||
- id: button2 | ||
label: Down Button | ||
capabilities: | ||
- id: button | ||
version: 1 | ||
categories: | ||
- name: RemoteController | ||
- id: button3 | ||
label: Config Button | ||
capabilities: | ||
- id: button | ||
version: 1 | ||
categories: | ||
- name: RemoteController | ||
preferences: | ||
- name: "switchMode" | ||
title: "1. Switch Mode" | ||
description: "Use as a Dimmer or an On/Off switch" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "On/Off + Single (default)" | ||
"1": "On/OFf + Dumb" | ||
"2": "On/Off + Aux" | ||
"3": "On/OFf + Full Wave" | ||
"4": "Dimmer + Single" | ||
"5": "Dimmer + Dumb" | ||
"6": "Dimmer + Aux" | ||
default: 0 | ||
- name: "smartBulbMode" | ||
title: "2. Smart Bulb Mode" | ||
description: "For use with Smart Bulbs that need constant power and are controlled via commands rather than power. Smart Bulb Mode does not work in Sumb 3-Way Switch mode" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "Disabled (default)" | ||
"1": "Smart Bulb Mode" | ||
default: 0 | ||
- name: "dimmingEdge" | ||
title: "3. Dimming Edge" | ||
description: "Change dimming type to leading edge (default) or trailing edge for better bulb compatibility" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "Leading (default)" | ||
"1": "Trailing" | ||
default: 0 | ||
- name: "dimmingSpeed" | ||
title: "4. Dimming Speed" | ||
description: "This changes the speed that the light dims. A setting of '0' turns the light immediately on. Increasing the value slows down the transition speed. Default=25 (2500ms or 2.5s)" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "Instant" | ||
"1": "500ms" | ||
"2": "800ms" | ||
"3": "1s" | ||
"4": "1.5s" | ||
"5": "2s" | ||
"6": "2.5s (default)" | ||
"7": "3s" | ||
"8": "3.5s" | ||
"9": "4s" | ||
"10": "5s" | ||
"11": "6s" | ||
"12": "7s" | ||
"13": "8s" | ||
"14": "10s" | ||
default: 6 | ||
- name: "relayClick" | ||
title: "5. Relay Click" | ||
description: "Audible Click in On/Off mode" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "Enabled (default)" | ||
"1": "Disabled" | ||
default: 0 | ||
- name: "ledIndicatorColor" | ||
title: "6. LED Indicator Color (w/On)" | ||
description: "Set the color of the Full LED Indicator when the load is on" | ||
required: false | ||
preferenceType: enumeration | ||
definition: | ||
options: | ||
"0": "Red" | ||
"1": "Orange" | ||
"2": "Lemon" | ||
"3": "Lime" | ||
"4": "Green" | ||
"5": "Teal" | ||
"6": "Cyan" | ||
"7": "Aqua" | ||
"8": "Blue (default)" | ||
"9": "Violet" | ||
"10": "Magenta" | ||
"11": "Pink" | ||
"12": "White" | ||
default: 8 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ local MatterDriver = require "st.matter.driver" | |
local lua_socket = require "socket" | ||
local utils = require "st.utils" | ||
local device_lib = require "st.device" | ||
local data_types = require "st.matter.data_types" | ||
|
||
local MOST_RECENT_TEMP = "mostRecentTemp" | ||
local RECEIVED_X = "receivedX" | ||
|
@@ -154,6 +155,21 @@ local child_device_profile_overrides = { | |
{ vendor_id = 0x1321, product_id = 0x000D, child_profile = "switch-binary" }, | ||
} | ||
|
||
local fingerprint_profile_overrides = { | ||
{ vendor_id = 0x1361, product_id = 0x0001 }, -- Inovelli VTM31-SN | ||
} | ||
|
||
local LATEST_CLOCK_SET_TIMESTAMP = "latest_clock_set_timestamp" | ||
|
||
local preference_map_inovelli_vtm31sn = { | ||
switchMode = {parameter_number = 1, size = data_types.Uint8}, | ||
smartBulbMode = {parameter_number = 2, size = data_types.Uint8}, | ||
dimmingEdge = {parameter_number = 3, size = data_types.Uint8}, | ||
dimmingSpeed = {parameter_number = 4, size = data_types.Uint8}, | ||
relayClick = {parameter_number = 5, size = data_types.Uint8}, | ||
ledIndicatorColor = {parameter_number = 6, size = data_types.Uint8}, | ||
} | ||
|
||
local detect_matter_thing | ||
|
||
local CUMULATIVE_REPORTS_NOT_SUPPORTED = "__cumulative_reports_not_supported" | ||
|
@@ -248,6 +264,14 @@ local function set_poll_report_timer_and_schedule(device, is_cumulative_report) | |
end | ||
end | ||
|
||
local preferences_to_numeric_value = function(new_value) | ||
local numeric = tonumber(new_value) | ||
if numeric == nil then -- in case the value is Boolean | ||
numeric = new_value and 1 or 0 | ||
end | ||
return numeric | ||
end | ||
|
||
local START_BUTTON_PRESS = "__start_button_press" | ||
local TIMEOUT_THRESHOLD = 10 --arbitrary timeout | ||
local HELD_THRESHOLD = 1 | ||
|
@@ -499,6 +523,16 @@ local function find_child(parent, ep_id) | |
return parent:get_child_by_parent_assigned_key(string.format("%d", ep_id)) | ||
end | ||
|
||
local function check_fingerprint_profile_overrides(device) | ||
for _, fingerprint in ipairs(fingerprint_profile_overrides) do | ||
if device.manufacturer_info.vendor_id == fingerprint.vendor_id and | ||
device.manufacturer_info.product_id == fingerprint.product_id then | ||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
local function initialize_switch(driver, device) | ||
local switch_eps = device:get_endpoints(clusters.OnOff.ID) | ||
local button_eps = device:get_endpoints(clusters.Switch.ID, {feature_bitmap=clusters.Switch.types.SwitchFeature.MOMENTARY_SWITCH}) | ||
|
@@ -570,6 +604,15 @@ local function initialize_switch(driver, device) | |
device:set_field(COMPONENT_TO_ENDPOINT_MAP_BUTTON, component_map, {persist = true}) | ||
end | ||
|
||
-- If there is a custom static profile for the device, configure buttons if needed and | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the inovelli switch already has a sub driver, I would say we should remove this override from the main driver and just add the special handling for the So, I would just copy whatever functionality is needed from the base driver and then put it in the sub driver for the init function, and then trim whatever is not needed. Better yet, you could move the |
||
-- then return to prevent profile from being updated. | ||
if check_fingerprint_profile_overrides(device) then | ||
if #button_eps > 0 then | ||
configure_buttons(device) | ||
end | ||
return | ||
end | ||
|
||
if #button_eps > 0 and is_supported_combination_button_switch_device_type(device, main_endpoint) then | ||
if #button_eps == 1 then | ||
profile_name = "light-level-button" | ||
|
@@ -1114,6 +1157,30 @@ local function info_changed(driver, device, event, args) | |
device:set_field(DEFERRED_CONFIGURE, nil) | ||
end | ||
end | ||
|
||
if not device.preferences or device.network_type == device_lib.NETWORK_TYPE_CHILD then | ||
return | ||
end | ||
|
||
if device.manufacturer_info.vendor_id == fingerprint_profile_overrides[1].vendor_id and | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is somewhat confusing and I think it could use some comments or documentation somewhere since there is some device specific knowledge here. For example, why is the time diff here and what is the significance of the values? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this code is used to prevent preferences from being changed faster than every two seconds. This was the same way that Inovelli implemented this for the zigbee driver, so it could be a device limitation. I will add some comments to make things a little more clear. |
||
device.manufacturer_info.product_id == fingerprint_profile_overrides[1].product_id then | ||
local time_diff = 3 | ||
local last_clock_set_time = device:get_field(LATEST_CLOCK_SET_TIMESTAMP) | ||
if last_clock_set_time ~= nil then | ||
time_diff = os.difftime(os.time(), last_clock_set_time) | ||
end | ||
device:set_field(LATEST_CLOCK_SET_TIMESTAMP, os.time(), {persist = true}) | ||
if time_diff > 2 then | ||
local preferences = preference_map_inovelli_vtm31sn | ||
for id, value in pairs(device.preferences) do | ||
if args.old_st_store.preferences[id] ~= value and preferences and preferences[id] then | ||
local new_parameter_value = preferences_to_numeric_value(device.preferences[id]) | ||
local req = clusters.ModeSelect.server.commands.ChangeToMode(device, preferences[id].parameter_number, new_parameter_value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the mode cluster is going to be used here, this would be the first use of it in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like ModeSelect has been been in the spec since matter 1.0. Is there a way to check when it was first added to the lua libs? |
||
device:send(req) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
local function device_added(driver, device) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make sense to move preferences that are specific to a certain device to a sub driver if we are able to. Or these configs could be moved to their own file at least to keep it separate from the base driver where we should try to handle things as generically as possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the inovelli-specific handling to a subdriver in 2e8b4b5