def removeJob(): caller = request.fullpath[1:] qString = request.query_string.strip() logSys(" /" + caller + " >>" + qString + "<<") try : sched.remove_job(qString) except: logInfo("Job may have been removed already") page = refreshSchedule() return page #.replace('&&language&&', piStrings.getLocale())
def fire_pilight(arg): #--------------------------------- global xP message = arg['message'] info = arg['info'] url = ('http://' + xP.prefs['server'] + ':' + str(xP.prefs['pilightPort']) + message) request = urllib2.Request(url) response = urllib2.urlopen(request) logSys ("url " + url) logInfo ("\n " + "\033[1m" + "pilight control >" + info + "<" + "\033[0m") log2DayFile(False, info)
def log2DayFile(new=False, info='xnewx'): sDay = datetime.now() logF = logFile(sDay.strftime("%A")) logInfo("log2DayFile " + logF) if new == True: try: os.remove(logF) except: pass now = datetime.now() f = open(logF, 'a') f.write(str(now)[0:19] + " : " + info + "\n") f.close()
def jobsRead(cIniFile = 'piSchedule.ini'): if cIniFile == "": cIniFile = 'piSchedule.ini' jobLines = "" try: msg = "read INI Jobs file >> " + cIniFile + "<<" jobLines = jobsReadFile(cIniFile) logSys (msg + "\n" + str(jobLines)) logInfo (msg) except: pass #if fails get 'piSchedule.ini' or initialize it logERR(True) return jobLines
def jobs2Schedule(jobLines): #--------------------------------- ''' lampe2; on lampe2; on,22:50;off,+:10 lampe2; on,+:02; off,+:03:00 * text/comment lampe2; on,+:02;off,+:03:00 lampe2; on,+01:02,sunrise;off,-01:30,sunset;on,~:10,18:00;off,~:15,21:05 ''' global xP #now = datetime.now() #logSys("&& jobs2Schedule xP.switchTime A: " + str(xP.switchTime)) for cJobs in jobLines: cJobs = cJobs.strip() # strip out empty or comment lines if len(cJobs) == 0 or cJobs[0] == '*': continue logInfo ('\n-->>{0}<<'.format(cJobs)) cJob = cJobs.split(";") cJobLen = len(cJob) if cJobLen > 1 : actualDevice = cJob[0].strip().replace("%20", "") now = datetime.now() n = 1 while n < (cJobLen): currentSwitch = cJob[n].strip().replace("%20", "") logInfo("\ncurrentSwitch " + str(currentSwitch)) # inkrement now to ensure to have a 1 sec delta to the previous switchtime now = now + timedelta(hours=0, minutes=0, seconds=n) now, currentJob, xP.switchTime = scheduleSet(now, actualDevice, currentSwitch, xP.switchTime) #logSys ("&& currentJob:" + str(currentJob) + " rNow:" + str(now)) n += 1 #logSys("&& jobs2Schedule xP.switchTime E: " + str(xP.switchTime)) return
def prefsSetup(): #try: global xP, piPortDelta global cVersion cLocale = "EN" if 'locale' in xP.prefs: if xP.prefs['locale'] != '': cLocale = xP.prefs['locale'] geoprefs = piGeoDetails.geoPrefs(xP.prefs) for p in geoprefs: xP.prefs[p] = geoprefs[p] xP.prefs['locale'] = cLocale piStrings.lang = xP.prefs['locale'] if (type(xP.prefs) is dict): pass else: xP.prefs['longitude'] = "" logInfo(" +++ pilight/piSchedule 'prefs': \033[1m " + xS("piSchedule.noGeoCordinates") + "\033[0m") responses = piDiscover.piDiscover("urn:schemas-upnp-org:service:pilight:1"); xP.prefs['server'] = responses[0] xP.prefs['pilightPort'] = responses[1] xP.prefs['pilightVersion'] = responses[2] xP.prefs['ssdp'] = responses[3] if piPortDelta < 2: piPortDelta = 4 cPort = int(xP.prefs['pilightPort'])+ piPortDelta #<<<<<<<<<< port number setting xP.prefs['port'] = cPort prefsSaveJSON(None, None) return (xP.prefs)
def main(): #if len(sys.argv) == 1: # return # Initialized only try: calling = sys.argv[1] except: calling = "-ip" if (calling == "-help"): print (""" --- piGeoDetails Help piGeoDetails returns the geolocation (city, locale code, latitude, longitude) based on the current IP or a given location. Call: piGeoDetails.py [argument] arguments are: -ip uses IP based search -gmaps uses Google Maps, needs location data -help Note: With using IP based search (-ip) and the return string for 'city' is empty, an alternative Google Maps search will run if the 'location' was passed also. """) exit() location = "" if (len(sys.argv) == 3): location = (sys.argv[2]).encode('utf-8') # address="San+Francisco" rv = geoPrefs(calling, location) if rv['status'] != 200: logInfo (json.dumps(rv, sort_keys=True, indent=3).decode('unicode_escape'), color) else: logSys (json.dumps(rv, sort_keys=True, indent=3).decode('unicode_escape'), color) return rv
def main(): global xP, piPortDelta try: logInfo('\n________Started piSchedule (cMain)________') logSys ('\n________Started piSchedule (cMain)________') debug(mode=False) # Bottle debug mode <<<<<<<<<<<<<<<<< xP.switchTime = datetime.now().replace(hour=0,minute=0,second=0,microsecond=0)+ timedelta(hours=24) prefsRead() xP.prefs = prefsSetup() # includes geoDetails, suntime info = logPrefsDetails(xP.prefs) print(info) logInfo(info) if xP.prefs['ssdp'] != "OK": print ("\n ** NO 'ssdp' connection! **") return xP.prefs['ssdp'] if (len(sys.argv) == 2) and sys.argv[1] == "-prefs": return 0 #x= 1/0 # logERR Testing only sched.start() # start the scheduler renewSchedule() # if iniFile is set, load jobList of it # starting bottle with web page app.run(host = xP.prefs['server'], port = xP.prefs['port'], reloader=False) except: logERR(True) logInfo('Finished Main\n') logSys('Finished Main\n')
def piDiscover(service, timeout=2, retries=1): #--------------------------------- global xP try: prefsFile = open(xP.prefsJSONfile, 'r') fPrefs = json.loads(prefsFile.read()) except: fPrefs = {} group = ("239.255.255.250", 1900) message = "\r\n".join([ 'M-SEARCH * HTTP/1.1', 'HOST: {0}:{1}'.format(*group), 'MAN: "ssdp:discover"', 'ST: {st}','MX: 3','','']) responses = {} try: server = str(fPrefs['server']) except: server = "" port = '' error = 'OK' i = 0; for _ in range(retries): i += 1 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('LL', 0, 10000)); sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) sock.sendto(message.format(st=service), group) while True: try: responses[i] = sock.recv(1024); break; except socket.timeout: error = 'timeout' break; except: error = 'no pilight ssdp connections found' break; r = responses.values() if len(r) > 0: locationsrc = re.search('Location:([0-9.]+):(.*)', str(r[0]), re.IGNORECASE) if locationsrc: server = locationsrc.group(1).strip() port = locationsrc.group(2).strip() configFile = '/etc/pilight/config.json' piPrefs = {} try: prefsFile = open(configFile, 'r') piPrefs = json.loads(prefsFile.read()) if 'webserver-http-port' in piPrefs['settings']: port = piPrefs['settings']['webserver-http-port'] if 'webserver-port' in piPrefs['settings']: port = piPrefs['settings']['webserver-port'] except: logERR(True) # will terminate / quiet pilightVersion = str(piPrefs['registry']['pilight']['version']['current']) rv = [server, port, pilightVersion, error] #print (" ** piDiscover pilight (v." + version + ") **\n" # + (str(responses)).replace("\\x00","").replace("\\r\\n","\n")) logInfo (" ** piDiscover pilight " + str(rv), xColor) logSys (" ** piDiscover pilight " + str(rv), xColor) return rv
def close(): caller = request.fullpath[1:] message = request.query_string.strip() logInfo(caller) os.kill(os.getpid(), signal.SIGTERM)
def scheduleSet(onTime, actualDevice, currentSwitch, switchTime): #--------------------------------- ''' lampe2; on,+:02 actualDevice= lampe2; currentSwitch= on,+:02 ''' actualSwitch = currentSwitch.strip().replace("%20", "").split(",") if ('on' in actualSwitch or 'off' in actualSwitch) == False: return xS("piSchedule.noState") # ERROR: no on/off if xP.prefs['pilightVersion'] > '7.0': # for 7.0 Nightly #http://x.x.x.x:xx/control?device=studyfloorlamp&state=on message = "/control?device=" + actualDevice + "&state=" + str(actualSwitch[0]) else: message = '/send?{"action":"control","code":{"device":"' + actualDevice \ + '","state":"' + str(actualSwitch[0]) + '"}}' # piSchedule direct on/off switching if len(actualSwitch) == 1: arg = {} arg['message'] = message info = '{0:12} {1:15}'.format(actualDevice[0:12], currentSwitch.replace(',', ' ')) arg['info'] = info fire_pilight(arg) #sleep(2) # for testing .. delay between directly switching jmsg = [str(onTime)[0:19], actualDevice, currentSwitch] return [onTime, jmsg, switchTime] xTime = onTime deltaTime = "*" # check xTime if valid and process different time options # xTime = '2014-04-17 22:06:00' NEED secs, even if ':00' for nSwitch in actualSwitch: nSwitch = nSwitch.strip() # have dateTime or sunrise or sunset if nSwitch == 'sunrise': xTime = parser.parse(xP.prefs['sunrise']) elif nSwitch == 'sunset': xTime = parser.parse(xP.prefs['sunset']) # --- use deltaTime # '+' add or '-' subtract time value # '~' add or '~-' subtract 'random' time value elif nSwitch[0] == '+' or nSwitch[0] == "-" \ or nSwitch[0] == "~": h = 0 min = 0 sec = 0 random_subtract = False if nSwitch[0:2] == "~-": # subtract random time random_subtract = True delta = nSwitch[2:] else: delta = nSwitch[1:] xDelta = delta.split(":") nDelta = len(xDelta) if nDelta >= 1: h = 0 if xDelta[0] == '' else int(xDelta[0]) if nDelta >= 2: min = 0 if xDelta[1] == '' else int(xDelta[1]) if nDelta == 3: sec = 0 if xDelta[2] == '' else int(xDelta[2]) deltaTime = timedelta(hours=h, minutes=min, seconds=sec) if nSwitch[0] == '+': # # add timedelta logInfo (" delta + : " + nSwitch) xTime = xTime + deltaTime #++++++++ if nSwitch[0] == '-': # # substract timedelta logInfo (" delta - : " + nSwitch) deltaTime = -deltaTime xTime = xTime + deltaTime #++++++++ elif nSwitch[0] == '~': # # add random minutes rMin = h * 60 + min if random_subtract: deltaTime = -timedelta(minutes=random.randrange(rMin)) else: deltaTime = timedelta(minutes=random.randrange(rMin)) logInfo (" random : " + nSwitch + " --> deltaTime : " + str(deltaTime)) xTime = xTime + deltaTime #++++++++ # ... use deltaTime elif nSwitch == 'on' or nSwitch == "off" or nSwitch == "time" : pass else: # check for absolute time not to be 24:00 and any other unknown format try: if (nSwitch == "24:00"): nSwitch = "23:59" xTime = parser.parse(nSwitch) except: nSwitch = 'err:' + str(nSwitch) logInfo(" +++ " + xS("piSchedule.unknownString") + ">>" + nSwitch + "<<") logInfo(" +++++ check nSwitch >>" + str(nSwitch) +"<< xTime >>" + str(xTime) + "<<") xTime = xTime + timedelta(seconds=random.randrange(60)) logInfo (" baseTime + delta : " + str(xTime)[0:19]) # remember 'on' state time wasOnTime = onTime onTime = xTime jmsg = [] # check if xTime is before actual time if (xTime < datetime.now()): logInfo (" +++ SKIP : " + str(xTime)[0:19] + " :: " + currentSwitch.strip() + " +++ " + xS("piSchedule.beforeTime") + " +++") else: logInfo (" ..set Job : " + str(xTime)[0:19] + " :: " + actualDevice + " :: " + currentSwitch) jmsg = [str(xTime)[0:19], actualDevice, currentSwitch] jobName = str(int(time.time() * 1000))[6:] info = ('{0:12} {1:15} '.format(actualDevice[0:12], currentSwitch.replace(',', ' '))) if 'off' in actualSwitch: info = info + " (on: " + str(wasOnTime)[11:16] + ")" cJob = (sched.add_job(fire_pilight, 'date', run_date=str(xTime), args=[{'message':message, 'info':info}], id=jobName)) logSys(" .. Job to be appended to jobs id=jobName " + jobName + "\n " + str(cJob) + "\n"+ str([{'message':message, 'info':info}])) logSys("&& xTime " + str(xTime) + " switchT " + str(switchTime)) if xTime > switchTime: switchTime = xTime return [onTime, jmsg, switchTime]