Files
smart-home/garage/garage.py
T

168 lines
5.9 KiB
Python

import RPi.GPIO as GPIO
import logging
import logging.handlers as handlers
import time
from threading import Thread
import cherrypy # https://docs.cherrypy.org/en/latest/tutorials.html#tutorial-1-a-basic-web-application
import requests, json
cherrypy.config.update({
'server.socket_host' : '192.168.178.49',
'server.socket_port' : 8081,
})
logger = logging.getLogger('Rotating Log')
logger.setLevel(logging.INFO)
logHandler = handlers.RotatingFileHandler('garage.log', maxBytes=1000000, backupCount=2)
logHandler.setLevel(logging.INFO)
logHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s - %(message)s', '%Y-%m-%d %H:%M:%S'))
logger.addHandler(logHandler)
PIN_GARAGE_BUTTON = 23
PIN_GATE_BUTTON = 24
PIN_GARAGE = 21
PIN_GATE = 26
PIN_LED = 11
PIN_DOOR_OPEN = 6
PIN_DOOR_CLOSED = 13
PIN_SENSOR_GATE= 19
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_GARAGE_BUTTON, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(PIN_GATE_BUTTON, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(PIN_GARAGE, GPIO.OUT)
GPIO.setup(PIN_GATE, GPIO.OUT)
GPIO.setup(PIN_LED, GPIO.OUT)
GPIO.setup(PIN_DOOR_OPEN, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(PIN_DOOR_CLOSED, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(PIN_SENSOR_GATE, GPIO.IN, GPIO.PUD_UP)
# move robomower into safe zone
def mower_safety():
try:
#response = requests.get("http://192.168.178.54/json?user=lewe&pass=nFdcX3sMD115WAap&cmd=status")
jsonstr = '{"name": "Rasi", "id": "C7697E", "status": {"status": 17, "distance": 0, "stopped": false, "duration": 4290, "mode": 2, "battery": 100, "hours": 90}, "timer": {"status": 0}, "wlan": {"signal": -86}, "health": {"temperature": 23, "humidity": 25}, "clock": {"date": "2021-05-13", "time": "14:23:27", "unix": 1620915807}, "successful": true}'
except requests.exceptions.RequestException as e:
#raise SystemExit(e)
logger.warning("couldn't reach mower")
return None
#status = json.loads(response.text)
status = json.loads(jsonstr)
logger.info(status["status"]["status"])
if (status["status"]["status"] in [2, 3, 5]):
logger.info("mower, run for your life")
else:
logger.info("lock mower in garage")
# robomower back to auto mode after gate has been closed
def mower_auto():
logger.info("set mower back to auto mode")
try:
response = requests.get("http://192.168.178.54/json?cmd=mode&mode=auto&user=lewe&pass=nFdcX3sMD115WAap&cmd=status")
except requests.exceptions.RequestException as e:
logger.warning("couldn't reach mower")
return None
def garage_button(channel):
time.sleep(0.01) # el cheapo relay module creates lots of interference, so we check again after a waiting period (see https://electronics.stackexchange.com/a/361793/253533)
if channel == 0 or GPIO.input(PIN_GARAGE_BUTTON) == False:
logger.info("trigger motor")
GPIO.output(PIN_GARAGE, GPIO.LOW)
GPIO.output(PIN_LED, GPIO.HIGH)
time.sleep(0.4)
GPIO.output(PIN_GARAGE, GPIO.HIGH)
GPIO.output(PIN_LED, GPIO.LOW)
else:
logger.info("flare (motor button)")
def gate_button(channel):
time.sleep(0.01)
if channel == 0 or GPIO.input(PIN_GATE_BUTTON) == False:
logger.info("trigger remote")
GPIO.output(PIN_GATE, GPIO.HIGH)
GPIO.output(PIN_LED, GPIO.HIGH)
time.sleep(0.4)
GPIO.output(PIN_GATE, GPIO.LOW)
GPIO.output(PIN_LED, GPIO.LOW)
if GPIO.input(PIN_SENSOR_GATE) == 0:
mower_auto()
else:
mower_safety()
else:
logger.info("flare (remote button)")
GPIO.add_event_detect(PIN_GARAGE_BUTTON, GPIO.FALLING, callback=garage_button, bouncetime=250)
GPIO.add_event_detect(PIN_GATE_BUTTON, GPIO.FALLING, callback=gate_button, bouncetime=250)
GPIO.output(PIN_GARAGE, GPIO.HIGH)
GPIO.output(PIN_GATE, GPIO.LOW)
GPIO.output(PIN_LED, GPIO.LOW)
class GarageService(object):
@cherrypy.expose
def index(self):
return "Hello World!"
# deprecated
@cherrypy.expose
def motor(self):
Thread(target=garage_button,args=[0]).start()
return "trigger garage door"
# deprecated
@cherrypy.expose
def remote(self):
Thread(target=gate_button,args=[0]).start()
return "trigger gate"
@cherrypy.expose
def garage(self, action=None):
if (action == "open" and GPIO.input(PIN_DOOR_CLOSED) and not GPIO.input(PIN_DOOR_OPEN)):
Thread(target=garage_button,args=[0]).start()
return '{ "action": "open" }'
elif (action == "close" and GPIO.input(PIN_DOOR_OPEN) and not GPIO.input(PIN_DOOR_CLOSED)):
Thread(target=garage_button,args=[0]).start()
return '{ "action": "close" }'
if (GPIO.input(PIN_DOOR_OPEN) and not GPIO.input(PIN_DOOR_CLOSED)):
status = "true"
else:
status = "false"
return '{ "status": "' + status + '" }'
@cherrypy.expose
def gate(self, action=None):
if (action == "open" and not GPIO.input(PIN_SENSOR_GATE)):
Thread(target=gate_button,args=[0]).start()
return '{ "action": "open" }'
elif (action == "close" and GPIO.input(PIN_SENSOR_GATE)):
Thread(target=gate_button,args=[0]).start()
return '{ "action": "close" }'
if GPIO.input(PIN_SENSOR_GATE) == 0:
status = "false"
else:
status = "true"
return '{ "status": "' + status + '" }'
@cherrypy.expose
def all(self):
Thread(target=garage_button,args=[0]).start()
Thread(target=gate_button,args=[0]).start()
return "trigger all"
@cherrypy.expose
def status(self):
return '{ "open": ' + str(GPIO.input(PIN_DOOR_OPEN)) + ', "closed": ' + str(GPIO.input(PIN_DOOR_CLOSED)) + ', "gate": ' + str(GPIO.input(PIN_SENSOR_GATE)) + ' }'
cherrypy.quickstart(GarageService())
logger.info('Shutdown')
logger.info('Reset GPIO configuration and close')
GPIO.cleanup()