Skip to content

Commit

Permalink
update to sleep until next run.
Browse files Browse the repository at this point in the history
consistency in table and column names.
  • Loading branch information
bisla authored Jul 26, 2019
1 parent 3c43e67 commit 5009b29
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 172 deletions.
42 changes: 25 additions & 17 deletions Controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

def log(msg):
now = datetime.now()
print("[{}] {}".format(now.strftime("%w, %-H:%-M"), msg))
print("[{}] {}".format(now.strftime("%a, %H:%M"), msg))

class Controller:
# Here will be the instance stored.
Expand Down Expand Up @@ -93,46 +93,54 @@ def run(self):
log("\nv:{} running through {} zones".format(VERSION, len(self.zones)))
for zone in self.zones:
#log("zone: {}".format(zone.name))

for sched in zone.getActiveSchedule():
sched = zone.getNextSchedule()
if sched: # zone.getActiveSchedule():
delta = sched.getNextRunDatetime() - datetime.now()
_hours = delta.total_seconds()/3600
hours = "{}".format(int(_hours))
_mins = delta.total_seconds()%3600/60
min = "{}".format(int(_mins))
sec = "{}".format(int(delta.total_seconds()%3600%60))
log("next run in {}:{}:{} ".format(hours, min, sec))

# sleep until next run.
time.sleep(delta.total_seconds() - 5)
log("{} found active {}".format(zone.name, sched.toStr()))
# run the zone
runforSeconds = sched.runSeconds
self.startChannel(zone.channel, runforSeconds)
time.sleep(15)
self.startChannel(zone, runforSeconds)


def startChannel(self, ch=0, seconds=500):
a = [0xfe , 0xfd , 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f]
channel = ch
gpio = (Controller.GPIOB, Controller.GPIOA) [ch < 8]
ch -= (8, 0) [ch < 8]
def startChannel(self, zone, seconds=500):
reg_value = [0xfe , 0xfd , 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f]
channel = zone.relay_channel
gpio = (Controller.GPIOB, Controller.GPIOA) [zone.relay_channel < 8]
channel -= (8, 0) [zone.relay_channel < 8]

log("\trunning channel:{} for {} seconds".format(ch, seconds))
log("\trunning zone:{} for {} seconds".format(zone.zoneId, seconds))

if platform.startswith('linux'):
startTime = datetime.now()

self.__bus.write_byte_data(Controller.DEVICE, gpio, a[ch])
self.__bus.write_byte_data(Controller.DEVICE, gpio, reg_value[channel])
time.sleep(seconds)
self.__bus.write_byte_data(Controller.DEVICE, gpio, 0xff)
endTime = datetime.now()
self.addWaterLog(startTime.strftime("%H:%M:%S"),
endTime.strftime("%H:%M:%S"),
channel,
zone.zoneId,
(endTime-startTime).total_seconds())
else:
time.sleep(seconds)


def addWaterLog(self, startTime, endTime, channel, seconds):
query = "insert into waterlog (startTime, channel, endTime, secondsOn) values(?, ?, ?, ?)"
def addWaterLog(self, startTime, endTime, zoneId, seconds):
query = "insert into waterlog (start_ts, zone_id, end_ts, run_seconds) values(?, ?, ?, ?)"

conn = sqlite3.connect('sprinkler.db')

with conn:
curs = conn.cursor()
curs.execute(query, (startTime, channel, endTime, seconds))
curs.execute(query, (startTime, zoneId, endTime, seconds))


'''
Expand Down
96 changes: 71 additions & 25 deletions Zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import json
from sys import platform
import sqlite3
import functools
import calendar
from datetime import timedelta

# from mylib import Zone


# something wierd that calendar takes monday as day 0 but datetime treats sunday as day 0
DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
'''
Generic class that hold the info for Sprinklers
- Zone
Expand All @@ -17,22 +20,14 @@
'''

class Zone:
'''
def __init__(self, name, channel, scheduleDataRaw, isActive=False):
self.name = name
self.channel = channel
self.isActive = isActive
self.scheduleStr = scheduleDataRaw
self.schedules = []
self.parseSchedule()
'''

def __init__(self, name, channel, desc):
""" Represents a zone and it's schedule """

def __init__(self, zoneId, name, relay_channel, desc):
self.name = name
self.channel = channel
self.zoneId = zoneId
self.relay_channel = relay_channel
self.desc = desc
self.schedules = []


'''
def parseSchedule(self):
Expand Down Expand Up @@ -60,6 +55,27 @@ def getActiveSchedule(self):
active.append(i)
return active

def getNextSchedule(self):
# //print("CALLED")
self.schedules.sort()
# # cm = datetime.now().strftime("%w %-H:%-M")
# # d = datetime.strptime(cm, '%w %H:%M')
# sch_d = datetime.strptime("{} {}:{}".format(s.dayOfWeek, s.startHour, s.startMinute), '%w %H:%M')
# sch.append(sch_d)
# sch.sort()

for a in self.schedules:
if a.getNextRunDatetime() >= datetime.now():
# print("Zone {} to run at {}".format(self.zoneId, a.toStr()))
return a
return None

def getSchedules(self):
print("\nZone:{} on relay:{}, desc:{}".format(self.zoneId, self.relay_channel, self.desc))
for s in self.schedules:
print("\t On {}, start at {:02d}:{:02d} for {} secs".format(DAYS[s.dayOfWeek], s.startHour, s.startMinute, s.runSeconds))


@staticmethod
def fromJson(data):
print("fromJSON: {}".format(data['schedule']))
Expand All @@ -72,35 +88,62 @@ def fromJson(data):
@staticmethod
def fromDB():
zones = []
query = "select day, startHour, startMinute, runForSeconds from schedule where zoneid=:zoneid"
query = "select day, start_hour, start_minute, run_seconds from schedule where zone_id=:zoneid"

conn = sqlite3.connect('sprinkler.db')

with conn:

curs = conn.cursor()

for row in curs.execute("select id, name, channel, desc from zone"):
#print("{}, {}, {}, {}".format(row[0], row[1], row[2], row[3]))
for row in curs.execute("select zone_id, name, relay_channel, desc from zone"):
print("\nZone:{} on relay:{}, desc:{}".format(row[0], row[2], row[3]))

_zone = Zone(row[1], row[2], row[3])
_zone = Zone(zoneId=row[0], name=row[1], relay_channel=row[2], desc=row[3])
cursor2 = conn.cursor()
for sch in cursor2.execute(query, {"zoneid": row[0]}):
_schd = Schedule(sch[0], sch[1], sch[2], sch[3])
print("\t On {}, start at {:02d}:{:02d} for {} secs".format(DAYS[sch[0]], sch[1], sch[2], sch[3]))
_schd = Schedule(zoneId=row[0],
dayOfWeek=sch[0], startHour=sch[1],
startMin=sch[2], runSecs=sch[3])
_zone.addSchedule(_schd)
zones.append(_zone)
return zones

@functools.total_ordering
class Schedule:
def __init__(self, dayOfWeek, startHour, startMin, runSecs):
def __init__(self, zoneId, dayOfWeek, startHour, startMin, runSecs):
self.dayOfWeek = dayOfWeek
self.zoneId = zoneId
self.startHour = startHour
self.startMinute = startMin
self.runSeconds = runSecs
self.scheduleStr = "{} {}:{}"
self.scheduleStr = self.scheduleStr.format(self.dayOfWeek, self.startHour, self.startMinute)
print("Schedule {}".format(self.scheduleStr))
# print("Schedule {}".format(self.scheduleStr))
# self.sch_dt = datetime.strptime("{} {}:{}".format(s.dayOfWeek, s.startHour, s.startMinute), '%w %H:%M')

def __lt__(self, other):
return self.getNextRunDatetime() < other.getNextRunDatetime()

def getNextRunDatetime(self):
""" returns the schedule as a datetime object.
*Note* since the schedule only contains day of the week and hour and minute. The object returned year is set to 1900.
"""
now = datetime.now()
currentDay = now.strftime("%w")
currentHour = now.strftime("%-H")
currentMin = now.strftime("%-M")

delta = timedelta(days=int(currentDay), hours=int(currentHour), minutes=int(currentMin))
#gets to start of week
baseline = now - delta

# to base line add the schedule time.
# print("baseline:{}".format(ddd.strftime("%a %d-%b-%Y-%H:%M")))
return baseline + timedelta(days=int(self.dayOfWeek), hours=int(self.startHour), minutes=int(self.startMinute))

# return datetime.strptime("{} {}:{}".format(self.dayOfWeek, self.startHour, self.startMinute), '%d-%b-%Y %w %H:%M')

def isCurrent(self):
cTimeStr = "{} {}:{}"
Expand All @@ -114,6 +157,9 @@ def isCurrent(self):
return cTimeStr == self.scheduleStr

def toStr(self):
return "Day:{}, Hour:{}, Min:{}, RunFor:{}".format(self.dayOfWeek, self.startHour,
self.startMinute, self.runSeconds)
_d = self.getNextRunDatetime()
_d = _d + timedelta(seconds=self.runSeconds)
# print("date time : {}, {}, {}".format(_d, _))
return "Zone {}, to run on {}, at {:02d}:{:02d} until {}:{} for {} secs".format(self.zoneId, DAYS[self.dayOfWeek],
self.startHour, self.startMinute, _d.strftime("%H"), _d.strftime("%M"), self.runSeconds)

Loading

0 comments on commit 5009b29

Please sign in to comment.