502 lines
18 KiB
Python
502 lines
18 KiB
Python
import array
|
|
import time
|
|
import thread
|
|
import threading
|
|
import sys
|
|
import os
|
|
sys.path.insert(0, '/WEB/python/simplejson-2.zip')
|
|
import simplejson as json
|
|
import datetime
|
|
from datetime import tzinfo, timedelta
|
|
ZERO = timedelta(0)
|
|
|
|
rootPath = "WEB/python/"
|
|
rootPath2 = "/userfs/WEB/python/"
|
|
|
|
|
|
#<channel_set name="outlet_[00:13:a2:00:40:a0:48:cb]!.switch" value="off"/>
|
|
#that will be sent to the
|
|
|
|
|
|
class schedule:
|
|
|
|
def __init__(self, rci1, getTime, mc):
|
|
self.getTime = getTime
|
|
self.rci = rci1
|
|
self.mc = mc
|
|
|
|
|
|
|
|
print "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
|
print "starting scheduler"
|
|
#load any schedules from pickle file
|
|
#if we can't get it from the web, look for the pickled version
|
|
try:
|
|
#self.schedDict = pickle.load( open( (rootPath + "schJSON.p"), "rb" ) )
|
|
try:
|
|
f = open((rootPath + "schJSON.p"),'r')
|
|
except:
|
|
f = open((rootPath2 + "schJSON.p"),'r')
|
|
data = f.read()
|
|
self.schedDict = json.loads(data)
|
|
print "found pickled dictionary"
|
|
print self.schedDict
|
|
except:
|
|
print "couldn't load schedule file from pickle"
|
|
self.schedDict = {}
|
|
|
|
thread.start_new_thread(self.run, ())
|
|
thread.start_new_thread(self.fileCheckThread, ())
|
|
|
|
|
|
#[{"user":"demo@meshify.com","mac":"000CE373293D","company":"188","payload":{"name":"wipom_[00:0c:e3:73:29:3d:00:21]!.do2","value":"1","expires":"1389369695"},"msgId":4478}]
|
|
#take that object and replace the .d02 (channel name) with the channel name in the scheduler, and the value with the value, then put back into sets
|
|
|
|
#add -> update the list of scheduled events, return in time order
|
|
|
|
#del -> remove the one with the hash that was sent. [hash, hash, hash]
|
|
|
|
def fileCheckThread(self):
|
|
while True:
|
|
try:
|
|
try:
|
|
f = open((rootPath + "schJSON.p"),'r')
|
|
except:
|
|
f = open((rootPath2 + "schJSON.p"),'r')
|
|
data = file.read()
|
|
file.close()
|
|
#!!!!delete the file!!!
|
|
os.remove(rootPath + "schedule.json")
|
|
self.message(data, "sch-add")
|
|
self.initilizeAll()
|
|
except:
|
|
time.sleep(10)
|
|
print "didn't find the json file"
|
|
|
|
|
|
def run(self):
|
|
#sleep for a minute to make sure the core is ready
|
|
time.sleep(30)
|
|
|
|
try:
|
|
t = self.getTime()
|
|
except:
|
|
#try and sleep another minute
|
|
time.sleep(60)
|
|
t = self.getTime()
|
|
|
|
print "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
|
self.initilizeAll()
|
|
print "running schedule core"
|
|
#here we will loop over the json and send on any sets we need to when we need to
|
|
#how to run this once a minute and make sure we dont miss or repeat???
|
|
#since we only support every 5 minutes of time, how about I look at it every 30 seconds and sleep for 120 if I hit an event.
|
|
|
|
|
|
|
|
while True:
|
|
try:
|
|
print "checking schedule"
|
|
|
|
#marker for if we got an event this time:
|
|
didSomethingHappen = False
|
|
|
|
#first grab the time using the gettime function
|
|
utc = UTC()
|
|
|
|
timeObj = datetime.datetime.fromtimestamp(int(self.getTime()), tz=utc)
|
|
DOW = timeObj.weekday()
|
|
min = timeObj.minute
|
|
if min < 10:
|
|
min = "0" + str(min)
|
|
hour = timeObj.hour
|
|
tm = str(hour) + ":" + str(min)
|
|
print "here is our time and day of week:"
|
|
print tm, DOW
|
|
#its less likely that a time will match, so first lets check for hours and minutes that match
|
|
|
|
#now I need to know if the current time "tm" is between 't' and 'et' by looking at 'r' and its value like '5m'
|
|
for device in self.schedDict:
|
|
#mac = self.schedDict[device]['mac']
|
|
#company = self.schedDict[device]['company']
|
|
name = self.schedDict[device]['name']
|
|
|
|
|
|
events = self.schedDict[device]['events']
|
|
#print "here are the events:"
|
|
#print events
|
|
for event in events:
|
|
#print "here is the event"
|
|
event = self.schedDict[device]['events'][event]
|
|
#print event
|
|
|
|
|
|
timeList = self.getTimes(event['t'], event['et'], event['r'])
|
|
print tm
|
|
print timeList
|
|
if tm in timeList:
|
|
print "we have a time match"
|
|
if DOW in event['d'] or str(DOW) in event['d']:
|
|
print "activating schedule event"
|
|
print ("Schedule Set: " + str(event['c']) + " To: " + str(event['v']))
|
|
didSomethingHappen = True
|
|
j = event['set']
|
|
#do the set, then send a message on the log channel that the sceduled event has taken place
|
|
try:
|
|
#this is where we do the set
|
|
#<channel_set name="outlet_[00:13:a2:00:40:a0:48:cb]!.switch" value="off"/>
|
|
obj = json.loads(j)
|
|
|
|
|
|
name = obj["name"]
|
|
value = obj["value"]
|
|
|
|
|
|
setData = """<channel_set name="%s" value="%s"/>""" % (name, str(value))
|
|
|
|
print "66666666666666666666666666666666666666666666666666666666666666666"
|
|
print setData
|
|
|
|
success = self.rci.setFromSched(setData)
|
|
|
|
msg = ""
|
|
if success == 0:
|
|
print "success"
|
|
msg = "Schedule Set: " + str(event['c']) + " To: " + str(event['v'])
|
|
if success == 1:
|
|
print "error 1"
|
|
msg = "Schedule FAILED (internal/driver error) to Set: " + str(event['c']) + " To: " + str(event['v'])
|
|
if success == 2:
|
|
print "error 2"
|
|
msg = "Schedule FAILED (no driver callback) to Set: " + str(event['c']) + " To: " + str(event['v'])
|
|
#if msg != "":
|
|
# self.sendtodb('log', msg, name.split(".")[0])
|
|
except:
|
|
#if one breaks, keep looking
|
|
continue
|
|
|
|
#sleep for 2 minutes if you had an event, this keeps you from calling an event twice, and you can't miss another event, because it wont happen for a least 5 more min
|
|
if didSomethingHappen:
|
|
print "sleeping 2 minutes"
|
|
time.sleep(120)
|
|
else:
|
|
print "sleeping 28 seconds"
|
|
time.sleep(10)
|
|
|
|
|
|
pass
|
|
except Exception,e:
|
|
print e
|
|
time.sleep(28)
|
|
|
|
def sendtodb(self, channel, value, name):
|
|
|
|
if name.endswith("!"):
|
|
pass
|
|
else:
|
|
name = name + "!"
|
|
|
|
#here I need to grab the device manager and look for the device name for the channel set and actually do it here, not returning it to the
|
|
#mistaway driver for the set
|
|
try:
|
|
print "sending to db", channel, value, name
|
|
dm = self.mc.myCore.get_service("device_driver_manager")
|
|
print "worked getting dm"
|
|
newMC = dm.get_driver_object(name)
|
|
print "worked getting the node, now doing the set..."
|
|
print channel
|
|
print value
|
|
print name
|
|
newMC.setProperty(channel, value)
|
|
except:
|
|
|
|
print "didn't work to do the set, the reason would have to be the node is no longer on the network"
|
|
|
|
|
|
def message(self, msg, channel):
|
|
|
|
|
|
#msg = [{'tn':'mc13_[00:13:a2:00:40:ba:8a:4c]!','c':'r','d':['0','1','2','3','4','5','6'],'h':'7d8c','n':'Misting from 8am - 10pm every 5 min','t':'08:00','v':'M','et':'22:00','r':'5m','s':'1'}]
|
|
|
|
if channel != "sch-sync":
|
|
print "adding schedule part 1"
|
|
msg = msg.replace("'", '"')
|
|
value = json.loads(msg)
|
|
fullmsg = value
|
|
|
|
#for digi
|
|
#[{'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]}, {'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]},{'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]}, {'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]} ]
|
|
|
|
|
|
|
|
|
|
|
|
#[{"user":"demo@meshify.com","mac":"000CE373293D","company":"188","payload":{"name":"wipom_[00:0c:e3:73:29:3d:00:21]!.do2","value":"1","expires":"1389369695"},"msgId":4478}]
|
|
|
|
|
|
#example value: [{'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]}, {'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]},{'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]}, {'h':'0123','n':'back to running','c':'start','v': 'On','t': '13:55','d': [0,1,2,3,4,5,6]} ]
|
|
#only single quotes for now can be sent
|
|
# [{
|
|
# 'h':0123, (hash)
|
|
# 'n':'back to running',
|
|
# 'c':'start',
|
|
# 'v': 'On',
|
|
# 't': '13:55',
|
|
# 'd': [0,1,2,3,4,5,6]
|
|
# }]
|
|
#channel can be sch-add or sch-del
|
|
|
|
|
|
#data = msg[0]
|
|
#msgId = str(data['msgId'])
|
|
#user = str(data['user'])
|
|
#mac = str(data['mac'])
|
|
#company = str(data['company'])
|
|
#d = data['payload']
|
|
|
|
#name = wipom_[00:0c:e3:73:29:3d:00:21]!
|
|
|
|
|
|
if channel == "sch-add":
|
|
print "adding schedule part 2"
|
|
#value = value.replace("'", '"')
|
|
#events = json.loads(value)
|
|
events = value
|
|
print events
|
|
|
|
|
|
|
|
#now it has a section for the device, lets start adding the events
|
|
returnStr = ""
|
|
for event in events:
|
|
|
|
name = event['tn'] #wipom_[00:0c:e3:73:29:3d:00:21]!
|
|
|
|
deviceName = name.split('_')[0] #wipom
|
|
|
|
#first see if this device has a key in our main dictionary
|
|
if self.schedDict.has_key(name):
|
|
print "device already in dictionary"
|
|
else:
|
|
#add this device to the dictionary
|
|
print "adding device to dictionary"
|
|
self.schedDict[name] = {'events': {}, 'name':name}
|
|
|
|
try:
|
|
n = event['tn'] + "!." + event['c'] #mc13z_[00:13:a2:00:40:ba:8a:4c]!.r
|
|
|
|
obj = {}
|
|
obj["name"] = n
|
|
obj["value"] = event['v']
|
|
|
|
#set up a dictionary for the event details of this event
|
|
#consiquently this will erase an event with this same hash, but this is ok
|
|
print "here is the new key in the event"
|
|
print event['h']
|
|
self.schedDict[name]['events'][event['h']] = {'set':str(json.dumps(obj)),'tn':event['tn'],'h':event['h'], 'n':event['n'],'c':event['c'],'v':event['v'],'t':event['t'],'d':event['d'],'et':event['et'],'r':event['r']}
|
|
print 'here is the event'
|
|
print self.schedDict[name]['events'][event['h']]
|
|
except:
|
|
returnStr += "Failed Adding: " + str(n) + " , "
|
|
else:
|
|
returnStr += "Success Adding: " + str(n) + " , "
|
|
|
|
#self.sendMsgResp(returnStr)
|
|
print self.schedDict
|
|
|
|
#now send back the updated data to the web
|
|
returnJSON = self.rebuildForDevice(name)
|
|
|
|
|
|
#fullmsg[0]['payload']['name'] = (name + "." + "sch-")
|
|
#fullmsg[0]['payload']['value'] = returnJSON
|
|
|
|
print fullmsg
|
|
|
|
self.sendtodb('sch-', returnJSON, name)
|
|
|
|
|
|
elif channel == "sch-del":
|
|
returnStr = ""
|
|
|
|
print "deleting an event with the ID"
|
|
#in this case the value will be a list of hahses that will be deleted
|
|
|
|
values = value
|
|
print values
|
|
|
|
name = ""
|
|
for name in self.schedDict:
|
|
for val in values:
|
|
try:
|
|
n = self.schedDict[name]['events'][val]['n']
|
|
except:
|
|
continue
|
|
try:
|
|
del self.schedDict[name]['events'][val]
|
|
except:
|
|
returnStr += "Failed Deteting: " + str(n) + " , "
|
|
else:
|
|
returnStr += "Success Deteting: " + str(n) + " , "
|
|
|
|
#self.sendMsgResp(returnStr)
|
|
#now send back the updated data to the web
|
|
returnJSON = self.rebuildForDevice(name)
|
|
|
|
|
|
#fullmsg[0]['payload']['name'] = (name + "." + "sch-")
|
|
#fullmsg[0]['payload']['value'] = returnJSON
|
|
|
|
print fullmsg
|
|
|
|
self.sendtodb('sch-', returnJSON, name)
|
|
|
|
|
|
elif channel == "sch-sync":
|
|
#self.sendMsgResp("Schedule Synced", msgId)
|
|
self.initilizeAll()
|
|
|
|
|
|
#update persistant dictionary
|
|
#pickle.dump( self.schedDict, open( (rootPath + "schJSON.p"), "wb" ) )
|
|
try:
|
|
f = open((rootPath + "schJSON.p"),'r')
|
|
except:
|
|
f = open((rootPath2 + "schJSON.p"),'r')
|
|
f.write(json.dumps(self.schedDict))
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
|
|
#thread.start_new_thread(self.sets, (j,))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sendMsgResp(self, val):
|
|
pass
|
|
#self.mc.setProperty("log", val)
|
|
|
|
|
|
def rebuildForDevice(self, name):
|
|
print "building json for return message"
|
|
newJSON = []
|
|
for event in self.schedDict[name]['events']:
|
|
print event
|
|
print self.schedDict[name]['events'][event]['h'], self.schedDict[name]['events'][event]['n'], self.schedDict[name]['events'][event]['c'], self.schedDict[name]['events'][event]['v'], self.schedDict[name]['events'][event]['t'], self.schedDict[name]['events'][event]['d']
|
|
newJSON.append({'h':self.schedDict[name]['events'][event]['h'],
|
|
'n':self.schedDict[name]['events'][event]['n'],
|
|
'c':self.schedDict[name]['events'][event]['c'],
|
|
'v':self.schedDict[name]['events'][event]['v'],
|
|
't':self.schedDict[name]['events'][event]['t'],
|
|
'd':self.schedDict[name]['events'][event]['d'],
|
|
'tn':self.schedDict[name]['events'][event]['tn'],
|
|
'r':self.schedDict[name]['events'][event]['r'],
|
|
'et':self.schedDict[name]['events'][event]['et'],
|
|
})
|
|
data = str(json.dumps(newJSON))
|
|
print "here is the device JSON"
|
|
print data
|
|
return data
|
|
|
|
|
|
def initilizeAll(self):
|
|
try:
|
|
#check the schedule.json file for anything added to the schedule
|
|
#this file is only giving me new data
|
|
|
|
|
|
#here I want to send all of the current schedules for all devices on startup, this could use a lot of data maybe
|
|
print "updating everything on startup"
|
|
for name in self.schedDict:
|
|
#mac = self.schedDict[name]['mac']
|
|
#company = self.schedDict[name]['company']
|
|
name = self.schedDict[name]['name']
|
|
msg = self.rebuildForDevice(name)
|
|
self.sendtodb('sch-', msg, name)
|
|
upld = self.mc.myCore.get_service("presentation_manager")
|
|
upload = upld.driver_get("Uploader")
|
|
upload.upload_data()
|
|
|
|
except:
|
|
pass
|
|
|
|
def getTimes(self, start, end, inc):
|
|
|
|
myList = []
|
|
currentTime = 0
|
|
myList.append(start)
|
|
|
|
if inc == 0 or inc == None or inc == "0":
|
|
inc = None
|
|
|
|
if inc is not None:
|
|
#hInc = hour increment
|
|
#mInc = minute increment
|
|
if inc.endswith("m"):
|
|
inc = inc[:-1]
|
|
mInc = int(inc)
|
|
hInc = 0
|
|
elif inc.endswith("h"):
|
|
mInc = 0
|
|
inc = inc[:-1]
|
|
hInc = int(inc)
|
|
|
|
while currentTime <= int(end.replace(":", "")):
|
|
sH = int(start.split(":")[0])
|
|
sM = int(start.split(":")[1])
|
|
|
|
|
|
sH += hInc
|
|
sM += mInc
|
|
|
|
if sM > 59:
|
|
hours, minutes = divmod(sM, 60)
|
|
sM = minutes
|
|
sH += hours
|
|
|
|
#new time
|
|
if sM < 10:
|
|
sM = "0" + str(sM)
|
|
else:
|
|
sM = str(sM)
|
|
|
|
|
|
sH = str(sH)
|
|
|
|
newTime = sH + ":" + sM
|
|
|
|
|
|
|
|
|
|
newTime = sH + ":" + sM
|
|
|
|
currentTime = int(newTime.replace(":", ""))
|
|
start = newTime
|
|
#print "new time:"
|
|
#print currentTime
|
|
if currentTime <= int(end.replace(":", "")):
|
|
#the time fits in the window, so add it!!
|
|
myList.append(newTime)
|
|
|
|
|
|
return myList
|
|
|
|
|
|
class UTC(tzinfo):
|
|
"""UTC"""
|
|
def utcoffset(self, dt):
|
|
return ZERO
|
|
def tzname(self, dt):
|
|
return "UTC"
|
|
def dst(self, dt):
|
|
return ZERO
|
|
|
|
utc = UTC() |