Skip to content

Commit

Permalink
Added support for the Philips Hue Smart Button
Browse files Browse the repository at this point in the history
Philips Hue Smart Button is exposed as a 'button' service in addition to
including the 'device_power' service. Development and inclusion of this
device driver was modelled after the 4-button-remote device driver
  • Loading branch information
kiera-robinson-st2 authored and dljsjr committed May 3, 2024
1 parent 002d9cb commit 2ace2f2
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 12 deletions.
12 changes: 12 additions & 0 deletions drivers/SmartThings/philips-hue/profiles/hue-smart-button.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: HueSmartButton
components:
- id: main
capabilities:
- id: button
version: 1
- id: battery
version: 1
- id: refresh
version: 1
categories:
- name: RemoteController
8 changes: 7 additions & 1 deletion drivers/SmartThings/philips-hue/src/disco/button.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,16 @@ function M.handle_discovered_device(
)
return
end

local button_profile_ref = ""
if button_description.num_buttons == 4 then
-- For Philips Hue Smart Button device which contains only 1 button
if button_description.num_buttons == 1 then
button_profile_ref = "HueSmartButton"
-- For Philips Hue Dimmer Remote which contains 4 buttons
elseif button_description.num_buttons == 4 then
button_profile_ref = "4-button-remote"
end

local bridge_device = driver:get_device_by_dni(bridge_id) or {}
local st_metadata = {
type = "EDGE_CHILD",
Expand Down
6 changes: 5 additions & 1 deletion drivers/SmartThings/philips-hue/src/disco/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ local DOMAIN = "local"
---@field public api_keys table<string,string>
---@field public disco_api_instances table<string,PhilipsHueApi>
---@field public device_state_disco_cache table<string,table<string,any>>
---@field public ServiceType string
---@field public Domain string
---@field public discovery_active boolean
local HueDiscovery = {
api_keys = {},
disco_api_instances = {},
Expand Down Expand Up @@ -266,7 +269,8 @@ function HueDiscovery.search_bridge_for_supported_devices(driver, bridge_id, api
local device_is_joined_to_bridge = {}
for _, device_data in ipairs(devices.data or {}) do
local primary_device_service
for _, svc_info in ipairs(device_data.services or {}) do
for _,
svc_info in ipairs(device_data.services or {}) do
if is_device_service_supported(svc_info) then
driver.services_for_device_rid[device_data.id] = driver.services_for_device_rid[device_data.id] or {}
driver.services_for_device_rid[device_data.id][svc_info.rid] = svc_info.rtype
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function ButtonLifecycleHandlers.added(driver, device, parent_device_id, resourc
button_rid_to_index_map[button_info.id] = 1
end

if button_info.num_buttons and button_info.num_buttons > 1 then
if button_info.num_buttons then
for var = 1, button_info.num_buttons do
local button_key = string.format("button%s", var)
local button_id_key = string.format("%s_id", button_key)
Expand Down Expand Up @@ -149,14 +149,12 @@ function ButtonLifecycleHandlers.init(driver, device)
end
end
local svc_rids_for_device = driver.services_for_device_rid[hue_device_id] or {}
if button_info and
(button_info.num_buttons == nil or button_info.num_buttons == 1) and
not svc_rids_for_device[button_info.id]
if button_info and button_info.num_buttons == nil and not svc_rids_for_device[button_info.id]
then
svc_rids_for_device[button_info.id] = HueDeviceTypes.BUTTON
end

if button_info and button_info.num_buttons and button_info.num_buttons > 1 then
if button_info and button_info.num_buttons then
for var = 1, (button_info.num_buttons or 1) do
local button_id_key = string.format("button%s_id", var)
local button_id = button_info[button_id_key]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,5 @@ device_type_refresh_handlers_map[HueDeviceTypes.BUTTON] = RefreshHandlers.do_ref
device_type_refresh_handlers_map[HueDeviceTypes.CONTACT] = RefreshHandlers.do_refresh_contact_sensor
device_type_refresh_handlers_map[HueDeviceTypes.LIGHT] = RefreshHandlers.do_refresh_light
device_type_refresh_handlers_map[HueDeviceTypes.MOTION] = RefreshHandlers.do_refresh_motion_sensor

return RefreshHandlers
3 changes: 2 additions & 1 deletion drivers/SmartThings/philips-hue/src/hue_device_types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ local HueDeviceTypes = {
}

local SupportedNumberOfButtons = {
[4] = true
[1] = true, -- For Philips Hue Smart Button device which contains only 1 button
[4] = true, -- For Philips Hue Dimmer Remote which contains 4 buttons
}

local PrimaryDeviceTypes = {
Expand Down
8 changes: 4 additions & 4 deletions drivers/SmartThings/philips-hue/src/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ function utils.safe_wrap_handler(handler)
end
end

function utils.kelvin_to_mirek(kelvin) return 1000000 / kelvin end

function utils.mirek_to_kelvin(mirek) return 1000000 / mirek end

-- TODO: The Hue API itself doesn't have events for multipresses, however, it will
-- emit batched "short release" eventsource on the SSE stream if they're close together.
-- Right now the SSE stream handling is a relatively dumb pass-through that doesn't inspect
Expand All @@ -67,10 +71,6 @@ function utils.get_supported_button_values(event_values)
return values
end

function utils.kelvin_to_mirek(kelvin) return 1000000 / kelvin end

function utils.mirek_to_kelvin(mirek) return 1000000 / mirek end

function utils.str_starts_with(str, start)
return str:sub(1, #start) == start
end
Expand Down

0 comments on commit 2ace2f2

Please sign in to comment.