# import pifacedigitalio import pifacecommon.mcp23s17 import time from subprocess import call import sys button_count = 2 longpress_delay = 0.6 # minimum time in s for a long press inter_press_max_delay = 0.8 # maximum time in s between two presses button_debounce_wait = 0.08 # time in s befor signal stabilizes 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): ioconfig = ( pifacecommon.mcp23s17.BANK_OFF | pifacecommon.mcp23s17.INT_MIRROR_OFF | pifacecommon.mcp23s17.SEQOP_OFF | pifacecommon.mcp23s17.DISSLW_OFF | pifacecommon.mcp23s17.HAEN_ON | pifacecommon.mcp23s17.ODR_OFF | pifacecommon.mcp23s17.INTPOL_LOW ) self.iocon.value = ioconfig if self.iocon.value != ioconfig: raise pifacedigitalio.NoPiFaceDigitalDetectedError( "No PiFace Digital board detected (hardware_addr={h}, " "bus={b}, chip_select={c}).".format( h=self.hardware_addr, b=self.bus, c=self.chip_select)) else: self.iodira.value = 0 # GPIOA as outputs self.iodirb.value = 0xFF # GPIOB as inputs self.gppub.value = 0xFF # input pullups on self.enable_interrupts() setattr(pifacedigitalio.PiFaceDigital, 'init_board', init_board_no_power_off) def chch_status_output(pfd): # update status file f = open("/tmp/status", 'w') status = "geschlossen" for i in range(button_count): if pfd.output_pins[i].value != 0: status = "geƶffnet" break try: f.truncate(0) f.write(status) except OSError: sys.stderr.write("Can not write to status file\n") # start / stop lounge VM if pfd.output_pins[0].value != 0: try: call(["/home/automation/proxmox-api-bash/vm_control.sh","chch","lounge","pve","310","start"]) except: sys.stderr.write("Could not start lounge VM\n") else: try: call(["/home/automation/proxmox-api-bash/vm_control.sh","chch","lounge","pve","310","shutdown"]) except: sys.stderr.write("Could not start lounge VM\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: # '.' room specific function if count == 1: if event.pin_num == 0: call(["/home/automation/chch-power/light.sh","1"]) elif event.pin_num == 1: call(["/home/automation/chch-power/light.sh","2"]) else: sys.stderr.write("No room specific function for room " + str(event.pin_num) + "\n") # '. .' toggle current room elif count == 2: event.chip.output_pins[event.pin_num].toggle() 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 > inter_press_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): event_time = time.time() c_pin = pin[event.pin_num] # debouncing c_pin['last_press'] = 0 time.sleep(button_debounce_wait) if event.chip.input_pins[event.pin_num].value == 0: return # remove scheduled event c_pin['sched_time'] = 0 c_pin['last_press'] = event_time def switch_unpressed(event): event_time = time.time() c_pin = pin[event.pin_num] if c_pin['last_press'] == 0: return c_pin['last_unpress'] = event_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: c_pin['sched_time'] = 0 exec_chch_button_cmd(event) if __name__ == "__main__": listener = pifacedigitalio.InputEventListener() for i in range(button_count): listener.register(i, pifacedigitalio.IODIR_ON, switch_pressed) 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.01)