diff --git a/chch-power.py b/chch-power.py index dd74d28..b4bf87c 100644 --- a/chch-power.py +++ b/chch-power.py @@ -3,16 +3,32 @@ import pifacecommon.mcp23s17 import time from subprocess import call import sys -import os button_count = 2 longpress_delay = 0.4 -verylongpress_delay = 2 shortpress_count_max_delay = 0.5 -inter_press_max_delay = 1.5 -pin_last_rise_date = [0]*button_count -pin_last_shortpress = [0]*button_count -pin_shortpress_count = [0]*button_count +inter_press_max_delay = 0.5 + +pin = { + 0: { + 'shortpress': { + 'count': 0, + 'last_unpress': 0 + }, + 'last_unpress': 0, + 'last_press': 0, + 'sched_time': 0 + }, + 1: { + 'shortpress': { + 'count': 0, + 'last_unpress': 0 + }, + 'last_unpress': 0, + 'last_press': 0, + 'sched_time': 0 + } +} # dirty workaround to disable reset of output pins def init_board_no_power_off(self): @@ -50,64 +66,81 @@ def chch_status_output(pfd): f.truncate(0) f.write(status) except OSError: - sys.stderr("Can not write to status file\n") + sys.stderr.write("Can not write to status file\n") + +def exec_chch_button_cmd(event): + c_pin = pin[event.pin_num] + print({'event':{'pin':event.pin_num,'at':c_pin['last_unpress'],'state':'executing'}}) + count = c_pin['shortpress']['count'] + # a longpress happend + if c_pin['last_unpress'] > c_pin['shortpress']['last_unpress']: + # '-' all off + if count == 0: + for i in range(button_count): + event.chip.output_pins[i].turn_off() + # '. -' all on + elif count == 1: + for i in range(button_count): + event.chip.output_pins[i].turn_on() + else: + sys.stderr.write("No mode with " + str(count) + " short press and a long press\n") + else: + # '.' toggle current room + if count == 1: + event.chip.output_pins[event.pin_num].toggle() + # '. .' room specific function + elif count == 2: + if event.pin_num == 0: + call(["/home/automation/chch-power/light.sh"]) + else: + sys.stderr.write("No room specific function for room " + str(event.pin_num) + "\n") + else: + sys.stderr.write("No mode with " + str(count) + " short press at pin " + str(event.pin_num) + "\n") + chch_status_output(event.chip) + # cleanup + c_pin['last_unpress'] = 0 + c_pin['last_press'] = 0 + c_pin['shortpress']['count'] = 0 + +# count the number of short press +def switch_shortpressed(event): + c_pin = pin[event.pin_num] + if c_pin['shortpress']['count'] == 0: + c_pin['shortpress']['last_unpress'] = c_pin['last_unpress'] + # determine delay between last rise of the switch and current rise + shortpress_delay = c_pin['last_unpress'] - c_pin['shortpress']['last_unpress'] + if shortpress_delay > shortpress_count_max_delay: + c_pin['shortpress']['count'] = 1 + else: + c_pin['shortpress']['count'] += 1 + c_pin['shortpress']['last_unpress'] = c_pin['last_unpress'] + print({'shortpress':{'delay':shortpress_delay,'count':c_pin['shortpress']['count']}}) def switch_pressed(event): - pin_last_rise_date[event.pin_num] = 0 + c_pin = pin[event.pin_num] + # debouncing + c_pin['last_press'] = 0 time.sleep(0.02) - if event.chip.input_pins[event.pin_num].value != 0: - pin_last_rise_date[event.pin_num] = time.time() + if event.chip.input_pins[event.pin_num].value == 0: + return + # remove scheduled event + c_pin['sched_time'] = 0 + c_pin['last_press'] = time.time() def switch_unpressed(event): - if pin_last_rise_date[event.pin_num] != 0: - press_time = time.time() - pin_last_rise_date[event.pin_num] - if press_time < longpress_delay: - switch_shortpressed(event) - elif longpress_delay <= press_time and press_time < verylongpress_delay: - switch_longpressed(event) - else: - switch_verylongpressed(event) - pin_last_rise_date[event.pin_num] = 0 - -# toggle current room's power with a short and a long press -# call a script with two short and a long press -def switch_longpressed(event): - shortpress_delay = pin_last_rise_date[event.pin_num] - pin_last_shortpress[event.pin_num] - if shortpress_delay > inter_press_max_delay: - pin_shortpress_count[event.pin_num] = 0 - elif pin_shortpress_count[event.pin_num] == 1: - event.chip.output_pins[event.pin_num].toggle() - elif pin_shortpress_count[event.pin_num] == 2: - if event.pin_num == 0: - call(["/home/automation/chch-power/light.sh"]) - chch_status_output(event.chip) - -# switch all power off with a very long press -# switch all power on with a short and a very long press -def switch_verylongpressed(event): - shortpress_delay = pin_last_rise_date[event.pin_num] - pin_last_shortpress[event.pin_num] - if shortpress_delay > inter_press_max_delay: - pin_shortpress_count[event.pin_num] = 0 - for i in range(button_count): - event.chip.output_pins[i].turn_off() - elif pin_shortpress_count[event.pin_num] == 1: - for i in range(button_count): - event.chip.output_pins[i].turn_on() - chch_status_output(event.chip) - -def switch_shortpressed(event): - now = time.time() - if pin_shortpress_count[event.pin_num] == 0: - pin_last_shortpress[event.pin_num] = now - shortpress_delay = now - pin_last_shortpress[event.pin_num] - print(shortpress_delay) - if shortpress_delay > shortpress_count_max_delay: - pin_shortpress_count[event.pin_num] = 1 + c_pin = pin[event.pin_num] + if c_pin['last_press'] == 0: + return + c_pin['last_unpress'] = time.time() + press_time = c_pin['last_unpress'] - c_pin['last_press'] + if press_time < longpress_delay: + # parse data inter_press_max_delay seconds after no event + c_pin['sched_time'] = c_pin['last_unpress'] + inter_press_max_delay + print({'event':{'pin':event.pin_num,'at':c_pin['last_unpress'],'in':inter_press_max_delay,'state':'scheduled'}}) + switch_shortpressed(event) else: - pin_shortpress_count[event.pin_num] += 1 - pin_last_shortpress[event.pin_num] = now - chch_status_output(event.chip) - print(["count:", pin_shortpress_count[event.pin_num]]) + c_pin['sched_time'] = 0 + exec_chch_button_cmd(event) if __name__ == "__main__": listener = pifacedigitalio.InputEventListener() @@ -116,3 +149,11 @@ if __name__ == "__main__": listener.register(i, pifacedigitalio.IODIR_OFF, switch_unpressed) listener.activate() chch_status_output(listener.chip) + while True: + for i in range(button_count): + c_pin = pin[i] + if time.time() > c_pin['sched_time'] and c_pin['sched_time'] != 0: + c_pin['sched_time'] = 0 + setattr(listener, 'pin_num', i) + exec_chch_button_cmd(listener) + time.sleep(0.001)