Strange Problem Touch phat on Raspberry zerow

I try to use the touch phat to build a Switch for my HUE System. Each button is connected to one bulb and the LED Shows the state of the bulb. Press the button once Switches the bulb on and the led will be on. Press the button the next time and the bulb is off as well as the led.

That works fine, if I do not use the same button twice without using another button in between. If I use the same button twice the led will Switch off but ot the bulb and it seems as if the Event procedure ist not called. If I press the button a third time, the led will go on for a short time and then the bulb and the led Switch off.

Here is my Code wich might be faulty But I cant find an error.
Any help is appreciated.

Holger

#!/usr/bin/env python

import signal
import time

import touchphat
from phue import Bridge
b = Bridge('192.168.3.141',HueCode)
dict = {'A': 'Stripflur', 'B': 'Fenster', 'C': 'Aussenlicht',"D":'Holger','Back':'Sportraum','Enter':'Kellerhals'}

for pad in ['Back','A','B','C','D','Enter']:
    touchphat.set_led(pad, True)
    time.sleep(0.1)
    touchphat.set_led(pad, False)
    time.sleep(0.1)

for pad in ['Back','A','B','C','D','Enter']:
    l = b.get_light_objects(mode='name')[dict[pad]]
    if l.on:
        touchphat.led_on(pad)
touchphat.auto_led = False	

def doEvent(pad):
	#print(".")
	touchphat.auto_led = False	
	light = dict[pad]
	l = b.get_light_objects(mode='name')[light]
	print(pad,dict[pad],l.on)
	if (l.on):
		touchphat.led_off(pad)
		time.sleep(0.1)
		l.on = False
	else:
		touchphat.led_on(pad)
		time.sleep(0.1)
		l.on = True
		l.brightness = 255
	touchphat.auto_led = False	
	# touchphat.set_led(pad, l.on)
	# time.sleep(0.1)

@touchphat.on_touch(['Back','A','B','C','D','Enter'])
def handle_touch(event):
	doEvent(event.name)
	
try:
	signal.pause()
except KeyboardInterrupt:
	touchphat.all_off()
except:
	print("Error")

One error that I can spot is that you’ve called your dictionary dict. dict is a reserved variable name in Python (for dictionaries), so you’ll actually have overridden the built-in dictionary method with the one that you defined.

Try renaming it my_dict or something. I’m not sure that what you’ve done will have caused any other problems, but try changing it then re-running the code.

Thanks Sandy,

I changed the dict to theDictionary. As expected, that did not change the behaviour.
The example from pimoroni works without problems.
It seems to be a timing problem, or something like that.

Holger

You should pretty much never use time.sleep() in an event-handler, if you need to perform actions in sequence with a delay in between then this should either be part of your main loop, or you should set/clear timers to trigger them.

Putting a time.sleep() into a handler, specially one with a value as high as one tenth of a second, has the potential to cause a race condition between multiple handler instances. This means one handler could still be running while another one fires, and then their behaviours might become mixed up.

A better approach would be to minimise what your event handlers do- they should ideally do nothing but change a variable- and put your light on/off logic into a main loop.

You should create something like a led_states dict to keep track of the state you want each LED to be in (True/False on/off) and only toggle those values in your event handler.

Then in your main loop, check this dict and adjust the state of your LEDs accordingly.

Thanks to gadgetoid. That solved the Problem. I thought, taht would not be a Problem, because I press the Buttons myself and in relatively big time distances. But it did matter.

Here my actual Code

#!/usr/bin/env python

import signal
import time
import threading
import Queue
import sys

import touchphat
from phue import Bridge
b = Bridge('192.168.3.141',"HueCode")
theDictionary = {'A': 'Stripflur', 'B': 'Fenster', 'C': 'Aussenlicht',"D":'Holger','Back':'Sportraum','Enter':'Kellerhals'}


for pad in ['Back','A','B','C','D','Enter']:
    l = b.get_light_objects(mode='name')[theDictionary[pad]]
    if l.on:
        touchphat.led_on(pad)
touchphat.auto_led = False	
q = Queue.Queue()

def doEvent(pad):
	light = theDictionary[pad]
	l = b.get_light_objects(mode='name')[light]
	if (l.on):
		touchphat.led_off(pad)
		l.on = False
	else:
		touchphat.led_on(pad)
		l.on = True
		l.brightness = 255

@touchphat.on_touch(['Back','A','B','C','D','Enter'])
def handle_touch(event):
	q.put(event.name)

def checkit():
	while not q.empty():
		t = q.get()
		doEvent(t)
		print(t)
	# check if bulbs are changed from outside
	for pad in ['Back','A','B','C','D','Enter']:
		l = b.get_light_objects(mode='name')[theDictionary[pad]]
		if l.on:
			touchphat.led_on(pad)
	threading.Timer(1.0, checkit).start()
		
try:
	checkit()
	signal.pause()
except KeyboardInterrupt:
	touchphat.all_off()
	sys.exit(0)
except:
	print("Error")