chch-power/chch-power.py

177 lines
6.1 KiB
Python

#
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)