class Scheduler(object): def __init__(self, config): self._debug = config['debug'] self._interval = config.get('interval', 10) self._sched = Sched() def add(self, func, args, tag): if self._sched is None: raise SchedulerException('required to create scheduler') self._sched.every(self._interval).seconds.do(func, args=args).tag(tag) def run(self): if self._sched is None: raise SchedulerException('required to create scheduler') self._sched.run_pending() def stop(self, tag=None): if self._sched is None: raise SchedulerException('required to create scheduler') self._sched.clear(tag)
class CapSaveRecognTask(AbstractTask): def __init__(self, uuid): super().__init__("capcam") self.cam_uuid = uuid self.success_interval = camctl.get_one(self.cam_uuid).interval self.schedule = Scheduler() def run(self): self.schedule.clear() self.schedule.every(self.success_interval).seconds.do(self.run_threaded, self.__run) while not self.stopped: try: self.schedule.run_pending() time.sleep(1) except Exception as err: logging.error("task(%s@%s) failed, %s", self.name, self.cam_uuid, str(err)) time.sleep(self.fail_interval) def __run(self): try: cam = camctl.get_one(self.cam_uuid) if clkctl.check_period_filter(cam.detection_cycle.get('detection_period'), cam.detection_cycle.get('detection_time')): if_sto_img = camctl.if_sto_img(cam) saved_path, if_sto_db = bktctl.save(cam.frame(), self.cam_uuid, if_sto_img) function_list = rcgctl.period_function_filter(cam) model_list = rcgctl.ai_pointer_filter(function_list) logging.info(model_list) if len(model_list): logging.info("task(%s@%s): start ai recognize, function is : %s, model is : %s", self.name, self.cam_uuid, str(function_list), str(model_list)) rcgctl.recognize(saved_path, self.cam_uuid, function_list, model_list) logging.info("task(%s@%s): succ and next in: %s", self.name, self.cam_uuid, cam.interval) else: logging.info("task(%s@%s): not in ai recognize cycle", self.name, self.cam_uuid) if not if_sto_db: bktctl.delete(saved_path) if cam.interval != self.success_interval: self.success_interval = cam.interval self.schedule.clear() self.schedule.every(self.success_interval).seconds.do(self.run_threaded, self.__run) except Exception as err: logging.error("task(%s) failed", self.name) logging.exception(err) logging.info("task(%s@%s): fail and next in: %s", self.name, self.cam_uuid, self.fail_interval) self.success_interval = self.fail_interval self.schedule.clear() self.schedule.every(self.fail_interval).seconds.do(self.run_threaded, self.__run) def run_threaded(self, func): job_thread = threading.Thread(target=func) job_thread.start()
class LocalController(Thread): def __init__(self): Thread.__init__(self, name='Local Timer') self.__stop = Event() self.__days, self.__start_time = parse_config() self.__scheduler = Scheduler() def stop(self): if not self.__stop.is_set(): self.__stop.set() self.join() def next_run(self): return self.__scheduler.next_run def __run_cycle(self): state.run_zone_action((ZoneAction.RUN_CYCLE, 0)) def __schedule_job(self): self.__scheduler.clear() if in_production(): for day in self.__days: job = Job(1, self.__scheduler) job.start_day = day.name.lower() job.unit = 'weeks' job.at(self.__start_time.strftime("%H:%M")).do( self.__run_cycle) else: self.__scheduler.every(3).minutes.do(self.__run_cycle) logging.info('Next run scheduled for {0}.'.format( self.__scheduler.next_run)) def control_mode_changed(self): mode = state.active_controller_mode() if mode is not ControllerMode.LOCAL: self.__scheduler.clear() elif mode is ControllerMode.LOCAL: self.__schedule_job() def run(self): logging.info('Local cycle run controller started.') self.__schedule_job() while not self.__stop.is_set(): if state.active_controller_mode() is ControllerMode.LOCAL: self.__scheduler.run_pending() sleep(1) self.__scheduler.clear() logging.info('Local cycle run controller stopped.')
class Lunchy(object): ''' A docstring documenting this bot. ''' JOBSFILE = 'jobs.p' def initialize(self, bot_handler): self.load_jobs(bot_handler) def __init__(self): self.schedule = Scheduler() self.cease_continuous_run = self.run_continously() def load_jobs(self, bot_handler): if os.path.isfile(self.JOBSFILE): with open('jobs.p', 'rb') as f: jobs = pickle.load(f) # jobs = bot_handler.storage.get('jobs') for (t, id) in jobs: self.schedule.every().day.at(t).do( lambda: bot_handler.send_message(dict( type=id[0], # can be 'stream' or 'private' to=id[1], # either the stream name or user's email subject=id[2], # message subject content=self.menu(), # content of the sent message )) if datetime.datetime.today().weekday() < 5 else False).tag(id) print("Job file loaded!") def save_jobs(self, bot_handler): l = [(j.at_time.strftime('%H:%M'), list(j.tags)[0]) for j in self.schedule.jobs] # bot_handler.storage.put('jobs', l) pickle.dump(l, open(self.JOBSFILE, "wb")) def run_continously(self, interval=1): cease_continuous_run = threading.Event() class ScheduleThread(threading.Thread): @classmethod def run(cls): while not cease_continuous_run.is_set(): self.schedule.run_pending() time.sleep(interval) continuous_thread = ScheduleThread() continuous_thread.start() return cease_continuous_run def tag(self): lst = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'] return lst[datetime.datetime.today().weekday()] def wiatshaus(self): print('Parsing wiener-wiazhaus.at') page = requests.get('https://www.wiener-wiazhaus.com/mittag') soup = BeautifulSoup(page.text, 'html.parser') elem = soup.find("a", string="MITTAGSMENÜS.PDF") pdf = requests.get(elem.attrs['href']) txt = pdfparser(pdf.content) soup = BeautifulSoup(txt, 'html.parser') elem = soup.find("span",string=self.tag()) if not elem: return [] start = elem.find_next("span",style=re.compile('.*position:absolute.*')) body = start.next items = [ re.findall('I\. (.+?)II\. ', body), re.findall('II\. (.+?)III\. ', body), re.findall('III\.(.+)', body) ] def clean(i): if len(i) > 0: return i[0].strip() return None price = clean(re.findall('([0-9,]+)\s*€',txt)) or '..€' return ['{} - *€{}*'.format(t, price) for t in [clean(i) for i in items] if t is not None] def salonwichtig(self): print('Parsing facebook.com/salonwichtig') page = requests.get('https://www.facebook.com/salonwichtig') soup = BeautifulSoup(page.text, 'html.parser') timestamp = soup.find_all("span", attrs={"class": "timestampContent"}) last = [t for t in timestamp if re.match('\d+ Std', t.text)] if last: p = last[0].find_parent("div", attrs={"class": None}).find_parent("div", attrs={"class": None}) pars = p.find_all('p') all = '' for p in pars: all += p.text lines = all.split('#') if len(lines) >= 2: return lines[2:-1] else: return lines else: return [] def teigware(self): print('Parsing teigware.at') page = requests.get('http://www.teigware.at/') soup = BeautifulSoup(page.text, 'html.parser') elem = soup.find("table", attrs={"cellpadding": "8"}) text = [] def clean(s): return ' '.join(s.split()) for r in elem.find_all('tr'): row = [c.text.strip() for c in r.find_all('td') if c.text.strip()] if re.search(self.tag(), row[0], flags=re.IGNORECASE): if row[1].isupper(): text = ['Geschlossen'] break text.append('{} - *{}*'.format(clean(row[1]), '€5,80')) text.append('{} - *{}*'.format(clean(row[2]), '€6,80')) return text def feinessen(self): print('Parsing feinessen.at') page = requests.get('http://www.feinessen.at/') soup = BeautifulSoup(page.text, 'html.parser') elem = soup.find("div", attrs={"id": "vbid-424badbc-rraljy31"}) text = [] # create separated list of items on page def br_list(node): list = [] current = '' for c in node.find_all(): if c.name == 'p': list.append(current) current = '' elif type(c.next) == NavigableString: if c.string and c.string.startswith('__'): list.append(current) list.append('__') current = '' else: current += str(c.string) if c.find_parent(name='h3'): list.append(current) current = '' list.append(current) return list list = [l for l in br_list(elem) if l is not ''] for i, e in enumerate(list): if re.search(self.tag(), e, flags=re.IGNORECASE) or re.search('WOCHENGERICHTE', e): if list[i+2] is not '__': text.append('{} - *{}*'.format(list[i + 1], list[i + 2].replace(' ', ''))) else: text.append(list[i+1]) return text def set_reminder(self, message, bot_handler): global reminder t = re.match('set reminder (.*)', message['content']).group(1) if message['type'] == 'private': id = (message['type'], message['sender_email'], message['subject']) else: id = (message['type'], message['display_recipient'], message['subject']) if t == 'off': self.schedule.clear(id) msg = 'Reminder cleared' self.save_jobs(bot_handler) elif t and time.strptime(t, '%H:%M'): self.schedule.clear(id) self.schedule.every().day.at(t).do( lambda: bot_handler.send_message(dict( type=id[0], # can be 'stream' or 'private' to=id[1], # either the stream name or user's email subject=id[2], # message subject content=self.menu(), # content of the sent message )) if datetime.datetime.today().weekday() < 5 else False).tag(id) msg = 'Reminder set to {}'.format(t) self.save_jobs(bot_handler) else: msg = 'Wrong format. Example "set reminder 11:50' bot_handler.send_reply( message, msg, ) def list_reminder(self, message, bot_handler): msg = 'No reminder set' if message['type'] == 'private': id = (message['type'], message['sender_email'], message['subject']) else: id = (message['type'], message['display_recipient'], message['subject']) if message['content'].endswith('all'): reminder = ['{} for streams {}'.format(j.at_time.strftime('%H:%M'), list(j.tags)[0]) for j in self.schedule.jobs] if reminder: msg = '\n'.join(reminder) else: reminder = ['{}'.format(j.at_time.strftime('%H:%M')) for j in self.schedule.jobs if id in j.tags] if reminder: msg = 'Reminder set to {}'.format( '\n'.join(reminder)) bot_handler.send_reply( message, msg, ) def menu(self): msg = "**{}'s lunch menu**\n\n".format(self.tag()) msg += "**Teigware:**\n" + "\n".join(self.teigware()) + '\n\n' msg += "**Feinessen:**\n" + "\n".join(self.feinessen()) + '\n\n' # msg += "**Salon Wichtig:**\n" + "\n".join(self.salonwichtig()) + '\n\n' msg += "**Wiener Wiazhaus:**\n" + "\n".join(self.wiatshaus()) + '\n' print(msg) return msg def usage(self): msg = "**Hi, I'm lunchy. How can I help you?**\n\n" msg += "*Usage:*\n" msg += "`menu` gives you today's lunch menu right away\n" msg += "`set reminder <hours>:<min>` sets a daily reminder for the current stream\n" msg += "`list reminder` lists reminders for the current stream\n" msg += "`list reminder all` lists reminders in all streams" return msg def handle_message(self, message, bot_handler): if message['content'].startswith('menu'): bot_handler.send_reply( message, self.menu(), ) elif message['content'].startswith('reminder'): self.schedule.every(5).seconds.do( lambda: bot_handler.send_reply( message, self.menu(), )) elif message['content'].startswith('set reminder'): self.set_reminder(message, bot_handler) elif message['content'].startswith('load jobs'): self.load_jobs(bot_handler) elif message['content'].startswith('list reminder'): self.list_reminder(message, bot_handler) else: bot_handler.send_reply( message, self.usage(), ) print('message recieved')
class MqttScheduler: schedulePath = 'schedule.json' def __init__(self): self.prevModified = 0 self.lastModified = 0 self.mqttclient = mqtt.Client() self.initMqtt() self.ss = Scheduler() def loop(self): while True: self.checkModified() self.ss.run_pending() time.sleep(1) def checkModified(self): self.lastModified = os.path.getmtime(MqttScheduler.schedulePath) if self.lastModified != self.prevModified: print('modified') print(self.lastModified) self.loadTasks() self.prevModified = self.lastModified def initMqtt(self): with open('private.json', 'r') as f: private = json.load(f) self.mqttclient.username_pw_set(private['mqtt_login'], private['mqtt_password']) self.mqttclient.connect(private['mqtt_host'], private['mqtt_port'], 60) self.mqttclient.loop_start() @staticmethod def getSchedule(): with open(MqttScheduler.schedulePath, 'r') as f: tasks_json = json.load(f) return tasks_json @staticmethod def delTask(tag): tasklist = MqttScheduler.getSchedule() tasklist.pop(tag, None) MqttScheduler.saveSchedule(tasklist) @staticmethod def saveSchedule(tasks_json): with open(MqttScheduler.schedulePath, 'w') as f: json.dump(tasks_json, f) @staticmethod def addTask(name, value): tasks_json = MqttScheduler.getSchedule() tasks_json[name] = value MqttScheduler.saveSchedule(tasks_json) def loadTasks(self): tasklist = MqttScheduler.getSchedule() print('tasklist', tasklist) self.ss.clear() for task in tasklist: self.processTask(task, tasklist[task]) def mqttpost(self, topic, msg): self.mqttclient.publish(topic, msg) conf.update_config(topic, json.loads(msg)) def mqttpostWorkday(self, topic, msg): weekno = datetime.datetime.today().weekday() if datetime.datetime.today().weekday() < 5: self.mqttpost(topic, msg) def mqttpostWeekend(self, topic, msg): if datetime.datetime.today().weekday() >= 5: self.mqttpost(topic, msg) def processTask(self, tag, schedobj): if schedobj['type'] == 'daily': self.ss.every().day.at(schedobj['time']).do( self.mqttpost, schedobj['topic'], schedobj['msg']) elif schedobj['type'] == 'workday': self.ss.every().day.at(schedobj['time']).do( self.mqttpostWorkday, schedobj['topic'], schedobj['msg']) elif schedobj['type'] == 'weekend': self.ss.every().day.at(schedobj['time']).do( self.mqttpostWeekend, schedobj['topic'], schedobj['msg']) elif schedobj['type'] == 'hour': self.ss.every().hour.do(self.mqttpost, schedobj['topic'], schedobj['msg']) elif schedobj['type'] == 'minute': self.ss.every().minute.do(self.mqttpost, schedobj['topic'], schedobj['msg']) elif schedobj['type'] == 'second': self.ss.every().second.do(self.mqttpost, schedobj['topic'], schedobj['msg'])