I’m a big fan of the addon AppDaemon and started writing a simple python script to add double click option. Below is the skeleton of what I have so far. Not a lot of error checking and the way it is now any switch could call this routine.
I wanted to add a hue dimmer switch residing on my Hue hub to my Hubitat environment which has been made possible with the great work done by @khvej8 and others. The script below adds double click. In the function wait4Click the time.sleep() number is what I found to work best. It may be reduced a bit more but too much and the double click wont work unless you have really fast fingers.
import appdaemon.plugins.hass.hassapi as hass
import requests, time, datetime, _thread
HUBITAT_BTN_DEVICE = "1812"
HUBITAT_MAKER_ID = "737"
dClicked = False
timeBetween = 0
# ========================================================================================================
def sendData(msg):
try:
requests.get('http://192.168.1.129/apps/api/' + HUBITAT_MAKER_ID + '/devices/' + msg + '?access_token=your-secret-hubitat-access-token')
return True
except:
print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S") + ' sendData-ERROR: Sending: ' + msg)
return False
# ========================================================================================================
def wait4Click(self,threadName,subType):
time.sleep(1.1)
if dClicked == True:
print("======================== Button %s was DOUBLE clicked ==========================" % subType)
## self.call_service("shell_command/maker", message=HUBITAT_BTN_DEVICE + "/doubleTap/" + subType) # alternative. No idea which method is better
sendData(HUBITAT_BTN_DEVICE + "/doubleTap/" + subType)
else:
print("======================== Button %s was SINGLE clicked ==========================" % subType)
## self.call_service("shell_command/maker", message=HUBITAT_BTN_DEVICE + "/push/" + subType)
sendData(HUBITAT_BTN_DEVICE + "/push/" + subType)
#==========================================================================================================
#==========================================================================================================
class doubleTapEvents(hass.Hass):
def initialize(self):
self.log("Initializing...")
self.listen_event(self.doubletap_event, "hue_event" )
def doubletap_event(self, entity, attribute, old):
global timeBetween,dClicked
typ = str(attribute["type"])
if typ == "initial_press": # some of the other types are short_release, long_release,long_press, long_release, more.....
subType = str(attribute["subtype"])
x = time.time()
timeBetween = x - timeBetween
if timeBetween < 2:
dClicked = True
timeBetween = 0
else:
dClicked = False
_thread.start_new_thread(wait4Click, (self,"Thread-1",subType, ))
timeBetween = x
@khvej8 not sure if this is only valid for my case, but I guess the hue_event structure changed. When I listen to a hue_event, I no longer receive information regarding the type and subtype. In the code below, you can see, that a variable called “event” with a numerical value is given. This number corresponds to the different button presses. (e.g. 20 = short top left Button press). Since the Choose functions in the blueprint refers to no longer exisiting variables, the condition statements need to be adjusted. Am I the only one dealing with that or did the structure really changed?
Alright, this is on my end then. I am not using the official friends of hue devices. There is another version, which uses the green power protocol from a company called „LED trading“ and it can be connected to the power outlet directly. But the interesting part is, that the hue bridge can’t tell the difference and they function completely normal.
Just one question: from which company did you buy your FoH switches? Maybe it makes a difference which vendor you choose in the setup process.
Not entirely sure about the product, it is integrated into a 3D printed battery powered switch from danish company called “Lab3D”. They produce this, no matter which “friends of hue” switch I chose during setup.
I have previously tried other versions, they behaved the same. Reason Im not using those today is they were of poor quality, hence stopped working due to mechanical problems.
If you send me the “codes pr switch” and check the “long press code/codes”, then I believe I can easily change the blueprint.
I have ha running through a virtual machine on a nas.
I have fed the philips hue via the philips hue bridge to ha.
And now I would like to program the foh switch via ha.
I’m just stuck on how best to do this.
I managed to make the blueprint.
Only I don’t understand how I have to proceed now to be able to activate multiple scenes in succession.
1st press welcome.
2nd press eat.
3rd press bright light.
etc.
Can I now also set via ha to adjust the light strength by holding the button.
You can easily create several actions for each button/press, just create them in the blueprint. If you need a delay, then use the delay service. The service calls are the normal once, which can be used in all automations.
For dim up or dim down, you can use the “repeate”, and set an action to increate or decrease light. It will trigger app 2 times a second.
With HA version 2023.08 the Hue integration includes button entities. Hence, I have created a new version of the blueprint. It solves a number of issues
Buttons can be chosen directly in the blueprint. No need for finding the device number
Possiblity to chose multible buttons for each action. Solves the issue with 2 or more switches in a room. Just select the buttons from each and they will get the same actions
No need for creating the helper any more:-)
Here we go
blueprint:
name: Hue, Friends Of Hue switch, 4 button, all functions
description: >
HA version 2023.08 or newer
Works with all functions
Correct the problem of "short release" triggered on the same time as "long release"
If multible switches needing the same functionality, select multible
domain: automation
input:
hue-switch-button1:
name: "Hue Switch button 1"
description: "Upper Left"
selector:
entity:
device_class: button
multiple: true
hue-switch-button2:
name: "Hue Switch button 2"
description: "Lower Left"
selector:
entity:
device_class: button
multiple: true
hue-switch-button3:
name: "Hue Switch button 3"
description: "Upper Right"
selector:
entity:
device_class: button
multiple: true
hue-switch-button4:
name: "Hue Switch button 4"
description: "Lower Right"
selector:
entity:
device_class: button
multiple: true
button_1_short_release:
name: Short Release 1
description: Action to run on button upper-left short release
default: []
selector:
action: {}
button_2_short_release:
name: Short Release 2
description: Action to run on button lower-left short release
default: []
selector:
action: {}
button_3_short_release:
name: Short Release 3
description: Action to run on button upper-right short release
default: []
selector:
action: {}
button_4_short_release:
name: Short Release 4
description: Action to run on button lower-right short release
default: []
selector:
action: {}
button_1_long_release:
name: Long Release 1
description: Action to run on button upper-left long release
default: []
selector:
action: {}
button_2_long_release:
name: Long Release 2
description: Action to run on button lower-left long release
default: []
selector:
action: {}
button_3_long_release:
name: Long Release 3
description: Action to run on button upper-right long release
default: []
selector:
action: {}
button_4_long_release:
name: Long Release 4
description: Action to run on button lower-right long release
default: []
selector:
action: {}
button_1_press:
name: Press 1
description: Action to run on button upper-left initial press
default: []
selector:
action: {}
button_2_press:
name: Press 2
description: Action to run on button lower-left initial press
default: []
selector:
action: {}
button_3_press:
name: Press 3
description: Action to run on button upper-right initial press
default: []
selector:
action: {}
button_4_press:
name: Press 4
description: Action to run on button lower-right initial press
default: []
selector:
action: {}
button_1_repeat:
name: Repeat 1
description: Action to run on button upper-left repeat
default: []
selector:
action: {}
button_2_repeat:
name: Repeat 2
description: Action to run on button lower-left repeat
default: []
selector:
action: {}
button_3_repeat:
name: Repeat 3
description: Action to run on button upper-right repeat
default: []
selector:
action: {}
button_4_repeat:
name: Repeat 4
description: Action to run on button lower-right repeat
default: []
selector:
action: {}
mode: queued
max: 10
trigger:
- platform: state
entity_id: !input 'hue-switch-button1'
id: B1
- platform: state
entity_id: !input 'hue-switch-button2'
id: B2
- platform: state
entity_id: !input 'hue-switch-button3'
id: B3
- platform: state
entity_id: !input 'hue-switch-button4'
id: B4
action:
- variables:
switch_to_state: '{{ trigger.to_state.attributes.event_type }}'
switch_from_state: '{{ trigger.from_state.attributes.event_type }}'
switch_id: '{{ trigger.id }}'
# switch_from_ID: '{{ trigger.entity_id }}'
- choose:
- conditions: '{{ switch_to_state == ''initial_press'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_press'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_press'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_press'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_press'
- conditions: '{{ switch_to_state == ''repeat'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_repeat'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_repeat'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_repeat'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_repeat'
- conditions: '{{ switch_to_state == ''long_release'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_long_release'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_long_release'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_long_release'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_long_release'
- conditions: '{{ switch_to_state == ''short_release'' }}'
sequence:
- choose:
- conditions: '{{ switch_from_state == ''initial_press'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_short_release'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_short_release'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_short_release'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_short_release'
EDIT: Small typo, resulting in long_release not triggering correctly. Works now
I’ve added the possibility to define double click actions. There is an additional input, which is an input number and defines the maximal time between to button presses to be evaluated as double click.
blueprint:
name: Hue, Friends Of Hue switch, 4 button, all functions
description: >
HA version 2023.08 or newer
Works with all functions
Correct the problem of "short release" triggered on the same time as "long release"
If multible switches needing the same functionality, select multible
domain: automation
input:
hue-double-press-time:
name: "Double press time span"
description: "Maximal time between two button presses to count as double press"
selector:
entity:
domain: input_number
hue-switch-button1:
name: "Hue Switch button 1"
description: "Upper Left"
selector:
entity:
device_class: button
multiple: true
hue-switch-button2:
name: "Hue Switch button 2"
description: "Lower Left"
selector:
entity:
device_class: button
multiple: true
hue-switch-button3:
name: "Hue Switch button 3"
description: "Upper Right"
selector:
entity:
device_class: button
multiple: true
hue-switch-button4:
name: "Hue Switch button 4"
description: "Lower Right"
selector:
entity:
device_class: button
multiple: true
button_1_short_release:
name: Short Release 1
description: Action to run on button upper-left short release
default: []
selector:
action: {}
button_2_short_release:
name: Short Release 2
description: Action to run on button lower-left short release
default: []
selector:
action: {}
button_3_short_release:
name: Short Release 3
description: Action to run on button upper-right short release
default: []
selector:
action: {}
button_4_short_release:
name: Short Release 4
description: Action to run on button lower-right short release
default: []
selector:
action: {}
button_1_long_release:
name: Long Release 1
description: Action to run on button upper-left long release
default: []
selector:
action: {}
button_2_long_release:
name: Long Release 2
description: Action to run on button lower-left long release
default: []
selector:
action: {}
button_3_long_release:
name: Long Release 3
description: Action to run on button upper-right long release
default: []
selector:
action: {}
button_4_long_release:
name: Long Release 4
description: Action to run on button lower-right long release
default: []
selector:
action: {}
button_1_press:
name: Press 1
description: Action to run on button upper-left initial press
default: []
selector:
action: {}
button_2_press:
name: Press 2
description: Action to run on button lower-left initial press
default: []
selector:
action: {}
button_3_press:
name: Press 3
description: Action to run on button upper-right initial press
default: []
selector:
action: {}
button_4_press:
name: Press 4
description: Action to run on button lower-right initial press
default: []
selector:
action: {}
button_1_double_press:
name: Double Press 1
description: Action to run on button upper-left initial double press
default: []
selector:
action: {}
button_2_double_press:
name: Double Press 2
description: Action to run on button lower-left initial double press
default: []
selector:
action: {}
button_3_double_press:
name: Double Press 3
description: Action to run on button upper-right initial double press
default: []
selector:
action: {}
button_4_double_press:
name: Double Press 4
description: Action to run on button lower-right initial double press
default: []
selector:
action: {}
button_1_repeat:
name: Repeat 1
description: Action to run on button upper-left repeat
default: []
selector:
action: {}
button_2_repeat:
name: Repeat 2
description: Action to run on button lower-left repeat
default: []
selector:
action: {}
button_3_repeat:
name: Repeat 3
description: Action to run on button upper-right repeat
default: []
selector:
action: {}
button_4_repeat:
name: Repeat 4
description: Action to run on button lower-right repeat
default: []
selector:
action: {}
mode: queued
max: 10
trigger:
- platform: state
entity_id: !input 'hue-switch-button1'
id: B1
- platform: state
entity_id: !input 'hue-switch-button2'
id: B2
- platform: state
entity_id: !input 'hue-switch-button3'
id: B3
- platform: state
entity_id: !input 'hue-switch-button4'
id: B4
action:
- variables:
switch_to_state: '{{ trigger.to_state.attributes.event_type }}'
switch_from_state: '{{ trigger.from_state.attributes.event_type }}'
switch_id: '{{ trigger.id }}'
hue_double_press_seconds: !input 'hue-double-press-time'
# switch_from_ID: '{{ trigger.entity_id }}'
- choose:
- conditions: '{{ switch_to_state == ''initial_press'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence:
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_1_press'
- wait_for_trigger:
- platform: state
entity_id: !input 'hue-switch-button1'
timeout:
seconds: "{{ states('hue_double_press_time') | int }}"
continue_on_timeout: false
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_1_double_press'
- conditions: '{{ switch_id == ''B2'' }}'
sequence:
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_2_press'
- wait_for_trigger:
- platform: state
entity_id: !input 'hue-switch-button2'
timeout:
seconds: 2
continue_on_timeout: false
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_2_double_press'
- conditions: '{{ switch_id == ''B3'' }}'
sequence:
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_3_press'
- wait_for_trigger:
- platform: state
entity_id: !input 'hue-switch-button3'
timeout:
seconds: 2
continue_on_timeout: false
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_3_double_press'
- conditions: '{{ switch_id == ''B4'' }}'
sequence:
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_4_press'
- wait_for_trigger:
- platform: state
entity_id: !input 'hue-switch-button4'
timeout:
seconds: 2
continue_on_timeout: false
- if: { condition: template, value_template: "{{ true }}" }
then: !input 'button_4_double_press'
- conditions: '{{ switch_to_state == ''repeat'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_repeat'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_repeat'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_repeat'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_repeat'
- conditions: '{{ switch_to_state == ''long_release'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_long_release'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_long_release'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_long_release'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_long_release'
- conditions: '{{ switch_to_state == ''short_release'' }}'
sequence:
- choose:
- conditions: '{{ switch_from_state == ''initial_press'' }}'
sequence:
- choose:
- conditions: '{{ switch_id == ''B1'' }}'
sequence: !input 'button_1_short_release'
- conditions: '{{ switch_id == ''B2'' }}'
sequence: !input 'button_2_short_release'
- conditions: '{{ switch_id == ''B3'' }}'
sequence: !input 'button_3_short_release'
- conditions: '{{ switch_id == ''B4'' }}'
sequence: !input 'button_4_short_release'
However, if there is a normal short press on the switch, the sequence will always preform the initial press, the short release and the double press. The double press, as It waits for a state trigger, which be the “short-release” and then performs the “double press” actions, along with the 2 other actions.
The idea is good and I might look into implementing a double press when I get some time during a rainy day.