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

Add support for Inovelli VTM31-SN Dimmer Switch #1754

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions drivers/SmartThings/matter-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ matterManufacturer:
vendorId: 0x1372
productId: 0x0002
deviceProfileName: switch-4
# Inovelli
- id: "4961/1"
deviceLabel: Inovelli Dimmer Switch
vendorId: 0x1361
productId: 0x0001
deviceProfileName: inovelli-vtm31-sn
#Legrand
- id: "4129/3"
deviceLabel: Smart Lights Smart Plug
Expand Down
127 changes: 127 additions & 0 deletions drivers/SmartThings/matter-switch/profiles/inovelli-vtm31-sn.yml
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
26 changes: 25 additions & 1 deletion drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ 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 detect_matter_thing

local CUMULATIVE_REPORTS_NOT_SUPPORTED = "__cumulative_reports_not_supported"
Expand Down Expand Up @@ -500,6 +504,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})
Expand Down Expand Up @@ -571,6 +585,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
Copy link
Contributor

Choose a reason for hiding this comment

The 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 init event in the inovelli sub driver. This way we can try to keep the base driver as generic as possible (although there are already exceptions to this).

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 configure_buttons function to its own file so that it can be shared between the base and sub driver, similar to what is done with the embedded-cluster-utils module.

-- 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"
Expand Down Expand Up @@ -1292,8 +1315,9 @@ local matter_driver_template = {
capabilities.battery
},
sub_drivers = {
require("aqara-cube"),
require("eve-energy"),
require("aqara-cube")
require("inovelli-vtm31-sn")
}
}

Expand Down
81 changes: 81 additions & 0 deletions drivers/SmartThings/matter-switch/src/inovelli-vtm31-sn/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
-- 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.matter.clusters"
local data_types = require "st.matter.data_types"
local device_lib = require "st.device"
local log = require "log"

local INOVELLI_VTM31_SN_FINGERPRINT = { vendor_id = 0x1361, product_id = 0x0001 }

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 is_inovelli_vtm31_sn = function(device)
if device.manufacturer_info.vendor_id == INOVELLI_VTM31_SN_FINGERPRINT.vendor_id and
device.manufacturer_info.product_id == INOVELLI_VTM31_SN_FINGERPRINT.product_id then
log.info("Using sub driver")
return true
end
return false
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 function info_changed(device, args)
if device.network_type == device_lib.NETWORK_TYPE_CHILD then
return
end
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)
device:send(req)
end
end
end
end

local inovelli_vtm31_sn_handler = {
NAME = "inovelli vzm31-sn handler",
lifecycle_handlers = {
infoChanged = info_changed
},
can_handle = is_inovelli_vtm31_sn
}

return inovelli_vtm31_sn_handler
Loading