# default_exp raspberrypi_growlight
This is a simple bare-bones webserver run on my raspberry pi to turn my dwarf citrus tree's grow light on at sunrise and off at sunset.
# export
import datetime
import sys
import time
import apscheduler.schedulers.background
import astral
import astral.sun
import pytz
import RPi.GPIO as GPIO
from flask import Flask
# export
PIN_GPIO = 17
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # Broadcom Chip
GPIO.setup(PIN_GPIO, GPIO.OUT) # Output
Test out gpio stuff manually
GPIO.output(PIN_GPIO, True)
GPIO.output(PIN_GPIO, False)
Needed to localize datetime.now()
# export
TIMEZONE = pytz.timezone('US/Eastern')
Set interval in seconds to check schedule
# export
INTERVAL = 1
Growlight on()
will turn on grow light and off()
will turn off grow light
# export
class Growlight:
def on(self):
GPIO.output(PIN_GPIO, True)
def off(self):
GPIO.output(PIN_GPIO, False)
Test to see if growlight turns on and off
growlight = Growlight()
growlight.on()
time.sleep(1)
growlight.off()
Given an input time, Schedule
will return 'ON'
if grow light should be on and 'OFF'
if growlight should be off
# export
class Schedule:
def get_status(T):
return 'OFF'
Sunlight schedule will turn on during sunlight
# export
class SunlightSchedule(Schedule):
def __init__(self, city):
self.city = city
def get_status(self, T):
s = astral.sun.sun(self.city.observer) # Get current status of sun
if s['sunrise'] < T < s['sunset']: return 'ON'
else: return 'OFF'
def __repr__(self):
return f'sunlight schedule for {self.city.name}.'
Make a schedule based on lowell
# export
class LowellSunlightSchedule(SunlightSchedule):
def __init__(self):
super().__init__(city=astral.LocationInfo(name='Lowell',
region='USA',
timezone='Eastern',
latitude=42.640999,
longitude=-71.316711))
Test out schedule
schedule = LowellSunlightSchedule()
schedule
sunlight schedule for Lowell.
T = TIMEZONE.localize(datetime.datetime.now())
schedule.get_status(T)
'ON'
Add some time to see if scheduler works
schedule.get_status(T + datetime.timedelta(hours=10))
'OFF'
Given a Schedule
and a GrowLight
, GrowlightScheduler
will turn on or off the growlight based on the schedule at a given interval
.
# export
class GrowlightScheduler:
def __init__(self, schedule, growlight, interval=INTERVAL):
self.schedule = schedule
self.growlight = growlight
self.interval = interval
self.scheduler = apscheduler.schedulers.background.BackgroundScheduler()
self.scheduler.add_job(self.job, 'interval', seconds=self.interval)
def job(self):
T = TIMEZONE.localize(datetime.datetime.now())
status = self.schedule.get_status(T)
if status == 'ON': self.growlight.on()
elif status == 'OFF': self.growlight.off()
else: raise RuntimeError(f'Unknown status: {status}')
def start(self):
if self.scheduler.running: self.scheduler.resume()
else: self.scheduler.start()
def stop(self):
if self.scheduler.running: self.scheduler.pause()
schedule = LowellSunlightSchedule()
growlight = Growlight()
scheduler_growlight = GrowlightScheduler(schedule, growlight)
scheduler_growlight.start()
scheduler_growlight.stop()
growlight.off()
Create flask app with the following API:
ON
- stops scheduler and turns growlight onOFF
- stops scheduler and turns growlight offSTART
- starts schedulerSTOP
- stops schedulerSTATUS
- returns current status
# export
app = Flask(__name__)
schedule = LowellSunlightSchedule()
growlight = Growlight()
scheduler_growlight = GrowlightScheduler(schedule, growlight)
STATUS = None
# export
def _status():
return f'Growlight status: {STATUS}'
# export
@app.route('/ON/', methods=['GET'])
def ON():
global STATUS
scheduler_growlight.stop()
growlight.on()
STATUS = 'ON'
return _status()
# export
@app.route('/OFF/', methods=['GET'])
def OFF():
global STATUS
scheduler_growlight.stop()
growlight.off()
STATUS = 'OFF'
return _status()
# export
@app.route('/START/', methods=['GET'])
def START():
global STATUS
scheduler_growlight.start()
STATUS = str(scheduler_growlight.schedule)
return _status()
# export
@app.route('/STOP/', methods=['GET'])
def PAUSE():
global STATUS
scheduler_growlight.stop()
STATUS = 'stopped ' + str(scheduler_growlight.schedule)
return _status()
# export
@app.route('/STATUS/', methods=['GET'])
def STATUS():
return _status()
For testing purposes change name
__name__ = '__notebook__'
By default, start grownlight scheduler when server starts up
# export
if __name__ == '__main__':
START()
app.run(host='0.0.0.0', port=8080)
!nbdev_build_lib --fname raspberrypi_growlight.ipynb
Converted raspberrypi_growlight.ipynb.
!jupyter nbconvert --to markdown --output README raspberrypi_growlight.ipynb
[NbConvertApp] Converting notebook raspberrypi_growlight.ipynb to markdown
[NbConvertApp] Writing 6159 bytes to README.md