def test3():
    """定时执行任务,暂停,恢复"""
    start_time = time.time()
    scheduler = BackgroundScheduler()
    scheduler.add_job(
        my_job, 'interval', args=('123', ), seconds=1,
        id='my_job_id')  # 每隔1秒执行一次my_job函数,args为函数my_job的输入参数;id:可省略;
    scheduler.start()  # 程序运行到这里,任务没有运行完也会往后执行,既执行后面的任务,又执行这个任务。
    print('运行到了这里1')
    while (scheduler.state):
        if time.time() - start_time > 5:
            print('暂停作业')
            scheduler.pause()  # 暂停作业:
            break
    print('恢复作业')
    if time.time() - start_time > 5:
        scheduler.resume()  #
    time.sleep(4)
    print('当前任务列表:{}'.format(
        scheduler.get_jobs()))  # 获得调度作业的列表,可以使用 get_jobs() 来完成,它会返回所有的job实例
    scheduler.get_job('my_job_id')  # 获取id为my_job_id的作业实例

    scheduler.print_jobs()  # 输出所有格式化的作业列表。

    print('移除作业')
    # scheduler.remove_job('my_job_id') # 移除id为my_job_id的作业
    scheduler.remove_all_jobs()  # 移除所有的作业
Exemple #2
0
class Camera:
    def __init__(self, queue_len=10):
        #初始化对象
        self.q_edit = Queue(maxsize=queue_len)
        self.q_show = Queue(maxsize=queue_len)
        self.camera = cv2.VideoCapture(0)
        self.classifier = Detector()
        self.sch = BackgroundScheduler()
        self.sch.add_job(self.work_once, 'interval', seconds=0.5)

    def work_once(self):
        try:
            if self.camera.isOpened():
                ok, img = self.camera.read()
                if not ok:
                    print('camera cannot be read!')
                    exit(2)
                face_edit, face_show = self.classifier.get_face_by_array(img)
                if face_edit is None:
                    return None
                if self.q_edit.full():
                    self.q_edit.get()
                    self.q_show.get()
                self.q_edit.put(face_edit)
                self.q_show.put(face_show)
            else:
                print('camera cannot open!')
                exit(3)
        except Exception as e:
            print(e)
            pass

    #让相机开始工作
    def start(self):
        self.sch.start()

    def pause(self):
        self.sch.pause()

    def resume(self):
        self.sch.resume()

    def end(self):
        self.sch.shutdown()
        self.camera.release()
        cv2.destroyAllWindows()

    def get_image(self):
        #从队列弹出图片
        #如果队列为空,则返回None
        if self.q_edit.empty():
            return [None, None]
        #否则返回队首的已经处理过的面部图片的文件名
        else:
            rst = [self.q_edit.get(), self.q_show.get()]
            return rst

    def clear(self):
        self.q_edit.queue.clear()
        self.q_show.queue.clear()
Exemple #3
0
class SerialReader:
    scheduler = None
    job = None

    def __init__(self, serial, callback, interval=0.1):
        self.active = True
        self.interval = interval
        self.serial = serial
        self.data = None
        self.callback = callback

    def start(self):
        self.scheduler = BackgroundScheduler()
        self.job = self.scheduler.add_job(self.test,
                                          'interval',
                                          seconds=self.interval)
        self.scheduler.start()

    def pause(self):
        self.scheduler.pause()

    def resume(self):
        self.scheduler.resume()

    def test(self):
        n_in = self.serial.in_waiting
        if n_in > 0:
            self.data = self.serial.read()
            if self.data is not None and len(self.data) > 0:
                self.callback(self.data)

    def stop(self):
        self.scheduler.remove_all_jobs()
        self.scheduler.shutdown()
class GatedScraper:
    def __init__(self, cookie, uid, interval=15):
        if (cookie == None):
            raise Exception('Cookie is required to be set')

        if (uid == None):
            raise Exception('Tadpoles UID is required to be set')

        self.cookie = cookie
        self.uid = uid
        self.requests = []

        self.sched = BackgroundScheduler()
        self.sched.start()
        self.sched.add_job(self.fire_job,
                           'interval',
                           seconds=interval,
                           jitter=5)

    def fire_job(self):
        if (len(self.requests) == 0):
            return

        currentItem = self.requests.pop(0)

        if currentItem['url'] == None:
            currentItem['callback'](None, currentItem['params'])
            return

        curReq = urllib.request.Request(currentItem['url'])
        curReq.add_header('cookie', self.cookie)
        curReq.add_header('x-tadpoles-uid', self.uid)
        resp = urllib.request.urlopen(curReq)
        if (resp.getcode() >= 500):
            self.requests.insert(0, currentItem)
            self.sched.pause()
            time.sleep(10)
            self.sched.resume()
        else:
            currentItem['callback'](resp, currentItem['params'])

    def add_job(self, url, callback, **params):
        to_append = {}
        to_append['url'] = url
        to_append['callback'] = callback
        to_append['params'] = params
        self.requests.append(to_append)

    def pause(self):
        self.sched.pause()

    def start(self):
        self.sched.start()
Exemple #5
0
class Scheduler(object):
    def __init__(self):
        self._scheduler = BackgroundScheduler(executors=executors,
                                              job_defaults=job_defaults)
        self._scheduler.add_jobstore('redis',
                                     jobs_key='crontpy.jobs',
                                     run_times_key='crontpy.run_times')

    @property
    def running(self):
        return self._scheduler.running

    def start(self):
        self._scheduler.start()

    def shutdown(self, wait=True):
        self._scheduler.shutdown(wait)

    def pause(self):
        self._scheduler.pause()

    def resume(self):
        self._scheduler.resume()

    def get_jobs(self):
        return self._scheduler.get_jobs()

    def get_job(self, jid):
        return self._scheduler.get_job(job_id=jid)

    def run_job(self, jid):
        job = self.get_job(jid)
        if not job:
            raise Exception('job id:{0} not found'.format(jid))
        job.func(*job.args, **job.kwargs)

    def resume_job(self, jid):
        self._scheduler.resume_job(job_id=jid)

    def pause_job(self, jid):
        self._scheduler.pause_job(job_id=jid)

    def modify_job(self, jid, **changes):
        return self._scheduler.modify_job(job_id=jid, **changes)

    def delete_job(self, jid):
        self._scheduler.remove_job(job_id=jid)
def test2():
    """定时执行任务,暂停,恢复"""
    start_time = time.time()
    scheduler = BackgroundScheduler(daemonic = False) # daemonic = False,
    scheduler.add_job(my_job, 'interval', args=('123',),seconds=1, id='my_job_id') # 每隔1秒执行一次my_job函数,args为函数my_job的输入参数;id:可省略;
    scheduler.start() # 程序运行到这里,任务没有运行完也会往后执行,既执行后面的任务,又执行这个任务。
    print('运行到了这里1')
    while (scheduler.state):
        if time.time() - start_time >5:
            print('暂停作业')
            scheduler.pause() # 暂停作业:
            break
    print('恢复作业')
    if time.time() - start_time >5:
        scheduler.resume() # 恢复作业
    time.sleep(4)
    print('再次暂停作业')
Exemple #7
0
def begin():
    scheduler = BackgroundScheduler()
    scheduler.add_job(update, 'interval', minutes=1)
    scheduler.add_job(update_aroon, 'interval', minutes=1)
    scheduler.add_job(update_atr, 'interval', minutes=1)
    scheduler.add_job(update_chaikin, 'interval', minutes=1)
    scheduler.add_job(update_sma, 'interval', minutes=1)
    scheduler.add_job(update_ssl, 'interval', minutes=1)
    scheduler.start()

    date = datetime.now()
    if date.isocalendar()[2] == 5 and date.hour >= 13:
        print("closed")
        scheduler.pause()
    if date.isocalendar()[2] == 7 and date.hour >= 14:
        print("open")
        scheduler.resume()
Exemple #8
0
class Repeat:
    def __init__(self, toDo, repeatTime):
        self.isQuit = False
        self.scheduler = BackgroundScheduler()
        self.job = None
        self.i = 1
        self.addJob(toDo, repeatTime)

    def addJob(self, toDo, repeatTime=1800):
        print("Job added every " + str(repeatTime))
        self.job = self.scheduler.add_job(toDo,
                                          'interval',
                                          seconds=repeatTime,
                                          max_instances=3)

    def startJobs(self):
        print("Started job")
        self.scheduler.start()

    def quitJob(self):
        self.scheduler.remove_all_jobs()
        self.scheduler.shutdown(wait=False)

    def sayHi(self):
        print("Hi")
        self.i += 1
        if self.i == 3:
            self.pauseJob()
            self.resumeJob()

    def resumeJob(self):
        self.scheduler.resume()

    def pauseJob(self):
        self.scheduler.pause()
        print("paused")


#   ------------------        usage:          ----------------------
# s = Repeat()

# try:
#    s.startJobs()
# except (KeyboardInterrupt, SystemExit):
#    s.quitJob()
Exemple #9
0
class Routine:
    def __init__(self,
                 config,
                 routine_id,
                 desc,
                 num_cmd,
                 cmd_list=[],
                 crontab_list=[]):
        self.main_conf = config
        self.num_cmd = num_cmd
        self.routine_id = routine_id
        self.cmd_list, self.crontab_list = cmd_list, crontab_list
        self.sched = BackgroundScheduler()
        for i in range(len(cmd_list)):
            self.sched.add_job(self.sendCommand,
                               CronTrigger.from_crontab(crontab_list[i]),
                               kwargs={'cmd': cmd_list[i]})

    def sendCommand(self, cmd):
        logger.info("Routine #" + str(self.routine_id + 1) +
                    ": sending command " + cmd)
        address = "http://localhost/cgi-bin/picmd"
        try:
            r = requests.post(address, data={'code': cmd})
        except:
            return -1
        finally:
            return 1

    def run(self):
        global routine_status
        self.sched.start()
        status = 1
        while True:
            if routine_status[self.routine_id] == 0 and status == 1:
                self.sched.pause()
                logger.info("Routine #" + str(self.routine_id + 1) + " paused")
                status = 0
            elif routine_status[self.routine_id] == 1 and status == 0:
                self.sched.resume()
                logger.info("Routine #" + str(self.routine_id + 1) +
                            " resumed")
                status = 1
            time.sleep(10)
def test2():
    """定时执行任务,暂停,恢复"""
    start_time = time.time()
    scheduler = BackgroundScheduler(daemonic=False)  # daemonic = False,
    scheduler.add_job(
        my_job, 'interval', args=('123', ), seconds=1,
        id='my_job_id')  # 每隔1秒执行一次my_job函数,args为函数my_job的输入参数;id:可省略;
    scheduler.start()  # 程序运行到这里,任务没有运行完也会往后执行,既执行后面的任务,又执行这个任务。
    print('运行到了这里1')
    while (scheduler.state):
        if time.time() - start_time > 5:
            print('暂停作业')
            scheduler.pause()  # 暂停作业:
            break
    print('恢复作业')
    if time.time() - start_time > 5:
        scheduler.resume()  # 恢复作业
    time.sleep(4)
    print('再次暂停作业')
def test3():
    """定时执行任务,暂停,恢复"""
    start_time = time.time()
    scheduler = BackgroundScheduler()
    scheduler.add_job(my_job, 'interval', args=('123',),seconds=1, id='my_job_id') # 每隔1秒执行一次my_job函数,args为函数my_job的输入参数;id:可省略;
    scheduler.start() # 程序运行到这里,任务没有运行完也会往后执行,既执行后面的任务,又执行这个任务。
    print('运行到了这里1')
    while (scheduler.state):
        if time.time() - start_time >5:
            print('暂停作业')
            scheduler.pause() # 暂停作业:
            break
    print('恢复作业')
    if time.time() - start_time >5:
        scheduler.resume() # 
    time.sleep(4)
    print('当前任务列表:{}'.format(scheduler.get_jobs())) # 获得调度作业的列表,可以使用 get_jobs() 来完成,它会返回所有的job实例
    scheduler.get_job('my_job_id') # 获取id为my_job_id的作业实例
    
    scheduler.print_jobs() # 输出所有格式化的作业列表。
    
    print('移除作业')
    # scheduler.remove_job('my_job_id') # 移除id为my_job_id的作业
    scheduler.remove_all_jobs() # 移除所有的作业
Exemple #12
0
class Dummy(object):
    def __init__(self):

        self.is_ping = False
        self.pinger = None
        self.master_id = None
        self.thread_num = None
        pass

    def main(self):

        def has_thread_num(fn):
            def wrapped(bot, update):
                if self.thread_num:
                    fn(bot, update)
                else:
                    bot.sendMessage(update.message.chat_id, 'Please, set thread number!')
            return wrapped

        def set_thread_number(bot, update, args):
            chat_id = update.message.chat_id
            if self.master_id is not None and chat_id != self.master_id:
                bot.sendMessage(chat_id, 'You are not my master!')
                return
            self.thread_num = args[0]
            with open('data/bot.txt', 'w') as bot_data:
                bot_data.write(json.dumps(dict(thread_num=self.thread_num)))
            bot.sendMessage(chat_id, 'Thread number set =^-^=')

        def start_ping(bot, update):
            chat_id = update.message.chat_id
            if self.master_id is not None and chat_id != self.master_id:
                bot.sendMessage(chat_id, 'You are not my master!')
                return
            if self.is_ping:
                self.pinger.pause()
            else:
                if not self.pinger:
                    def tick():
                        if getters.ThreadData(self.thread_num).get_page_num() > 6:
                            status(bot, update)
                    self.master_id = update.message.chat_id
                    self.pinger = BackgroundScheduler()
                    self.pinger.add_job(tick, 'interval', minutes=60)
                    self.pinger.start()
                self.pinger.resume()
            self.is_ping = not self.is_ping
            bot.sendMessage(update.message.chat_id, 'ping {}'.format(self.is_ping and 'started' or 'ended'))

        @has_thread_num
        def page(bot, update):
            getter = getters.ThreadData(self.thread_num)
            page_num = getter.get_page_num()
            bot.sendMessage(update.message.chat_id, page_num)

        @has_thread_num
        def status(bot, update):
            bot.sendChatAction(update.message.chat_id, 'typing')
            getter = getters.ThreadData(self.thread_num)
            bot.sendMessage(update.message.chat_id,
                            templating.make_msg(getter.get_page_num(), getter.get_thread_stats()),
                            parse_mode='HTML')

        @has_thread_num
        @show_typing
        def last_post(bot, update):
            posts = getters.ThreadData(self.thread_num).get_posts()
            if len(posts):
                post = posts[-1]
                _show_post(bot, update, post)
            else:
                bot.sendMessage(update.message.chat_id, "No posts found for thread:{}".format(self.thread_num))

        @show_typing
        def _show_post(bot, update, post):
            post_num = "Post № {}".format(post['no'])
            chat_id = update.message.chat_id
            try:
                bot.sendMessage(chat_id, post_num)
                # FIXME no progress indication while acquiring image
                if post['ext'] in ['.gif', '.webm']:
                    bot.sendDocument(chat_id,
                                     document="https://i.4cdn.org/c/{0}{1}".format(post['tim'], post['ext']))
                else:
                    bot.sendPhoto(chat_id,
                                  photo="https://i.4cdn.org/c/{0}{1}".format(post['tim'], post['ext']))
                bot.sendMessage(chat_id, "{0}{1}".format(post['filename'], post['ext']))
            except KeyError:
                pass
            try:
                data = _prepare_post_text(post['com'])
                bot.sendMessage(chat_id, data['text'], parse_mode='HTML', reply_markup=data['markup'])
            except Exception as e:
                print('e:', e)
                pass

        def _prepare_post_text(text):
            keyboard = []
            markup = None
            result = text.replace('<br>', '\r\n')
            links = re.findall('#p(\d+)', result)
            result = re.sub('<a.+#p(\d+).+</a>', '&gt;&gt;\g<1>', result)
            for one in links:
                keyboard.append([InlineKeyboardButton(">>{}".format(one), callback_data=one)])
            if len(keyboard):
                markup = InlineKeyboardMarkup(keyboard)
            return dict(text=result, markup=markup)

        # Create the EventHandler and pass it your bot's token.
        updater = Updater(TOKEN)

        # Get the dispatcher to register handlers
        dp = updater.dispatcher

        # on different commands - answer in Telegram
        dp.add_handler(CommandHandler("start", start))
        dp.add_handler(CommandHandler("set", set_thread_number, pass_args=True))
        dp.add_handler(CommandHandler("help", bot_help))
        dp.add_handler(CommandHandler("page", page))
        dp.add_handler(CommandHandler("status", status))
        dp.add_handler(CommandHandler("ping", start_ping))
        dp.add_handler(CommandHandler("last", last_post))

        # on noncommand i.e message - echo the message on Telegram
        dp.add_handler(MessageHandler([Filters.text], echo))

        # log all errors
        dp.add_error_handler(error)

        # Start the Bot
        updater.start_polling()
        path = 'data/bot.txt'
        if os.path.isfile(path):
            self.thread_num = json.loads(open(path, 'r').read())['thread_num']

        # Run the bot until the you presses Ctrl-C or the process receives SIGINT,
        # SIGTERM or SIGABRT. This should be used most of the time, since
        # start_polling() is non-blocking and will stop the bot gracefully.
        updater.idle()
Exemple #13
0
            lcd.message = "Next pump in:\n" + str(deltaTime)
        else:
            lcd.clear()
            lcd.message = "PH: " + str(senPH) + "\n" + "EC: " + str(senEC)

        if sysError:
            print("System Paused!")
            lcd.clear()
            lcd.message = "System Paused!\nPress Select to Start"
            time.sleep(slp)
            scheduler.pause()
            while sysError:
                if lcd.select_button:
                    sysError = False
        else:
            scheduler.resume()

        #-------------------------------------------
        # Read Ultrasonic
        senUltra = readSenUltra()
        senPH = readSenPH()
        senEC = readSenEC()

        AutoLevelData()
        AutoLevelTest()

        # Error Checking, pause apscheduler before enterError.

        scheduler.pause()
        if senUltra < 22:
            sendEmail("Water is Low, Fill Up Soon!")
Exemple #14
0
class CronManager:
    def __init__(self, use_mongo_db=True):
        self.scheduler = BackgroundScheduler(
            timezone=timezone('Asia/Shanghai'))
        self.scheduler.configure()

        if use_mongo_db:
            self.job_store = MongoDBJobStore(database='apscheduler',
                                             collection='cronJob',
                                             client=db)
            self.scheduler.add_jobstore(self.job_store)
            self.is_replace_existing = True
        else:
            self.is_replace_existing = False

    def add_cron(self, cron_instance):
        try:
            if not isinstance(cron_instance, Cron):
                raise TypeError('please add correct cron!')
            if cron_instance.trigger_type == 'interval':
                seconds = cron_instance.trigger_args.get('seconds')
                if not isinstance(
                        seconds,
                        int) and not common.can_convert_to_int(seconds):
                    raise TypeError('please set correct time interval')
                seconds = int(seconds)
                if seconds <= 0:
                    raise ValueError('please set interval > 0')
                job = self.scheduler.add_job(
                    func=cron_instance.cron_mission,
                    trigger=cron_instance.trigger_type,
                    seconds=seconds,
                    replace_existing=self.is_replace_existing,
                    coalesce=True,
                    id=cron_instance.get_cron_job_id(),
                    max_instances=5,
                    jitter=0)
            elif cron_instance.trigger_type == 'date':
                run_date = cron_instance.trigger_args.get('run_date')
                # TODO 判断run_date类型
                job = self.scheduler.add_job(
                    func=cron_instance.cron_mission,
                    trigger=cron_instance.trigger_type,
                    run_date=run_date,
                    replace_existing=self.is_replace_existing,
                    coalesce=True,
                    id=cron_instance.get_cron_job_id())
            elif cron_instance.trigger_type == 'cron':
                raise TypeError('暂时不支持 trigger_type 等于 \'cron\'')

            return cron_instance.get_cron_job_id()
        except BaseException as e:
            with app.app_context():
                current_app.logger.error("add_cron failed. - %s" % str(e))

    def start(self, paused=False):
        self.scheduler.start(paused=paused)

    def pause_cron(self, cron_id=None, pause_all=False):
        if pause_all:
            self.scheduler.pause()
        elif cron_id:
            self.scheduler.pause_job(job_id=cron_id)

    def resume_cron(self, cron_id=None, resume_all=False):
        if resume_all:
            self.scheduler.resume()
        elif cron_id:
            self.scheduler.resume_job(job_id=cron_id)

    def del_cron(self, cron_id=None, del_all=False):
        if del_all:
            self.scheduler.remove_all_jobs()
        elif cron_id:
            self.scheduler.remove_job(job_id=cron_id)

    def update_cron(self, cron_job_id, project_id, cron_info):
        try:
            if not isinstance(cron_job_id, str):
                raise TypeError('cron_id must be str')

            if not isinstance(project_id, str):
                raise TypeError('project_id must be str')

            if not isinstance(cron_info, dict):
                raise TypeError('cron_info must be dict')

            trigger_type = cron_info.get('triggerType')
            interval = cron_info.get('interval')
            run_date = cron_info.get('runDate')
            test_suite_id_list = cron_info.get('testSuiteIdList')
            include_forbidden = cron_info.get('includeForbidden')
            test_env_id = cron_info.get('testEnvId')
            always_send_mail = cron_info.get('alwaysSendMail')
            alarm_mail_group_list = cron_info.get('alarmMailGroupList')
            enable_wxwork_notify = cron_info.get('enableWXWorkNotify')
            wxwork_api_key = cron_info.get('WXWorkAPIKey')
            wxwork_mention_mobile_list = cron_info.get(
                'WXWorkMentionMobileList')
            always_wxwork_notify = cron_info.get('alwaysWXWorkNotify')
            enable_ding_talk_notify = cron_info.get('enableDingTalkNotify')
            ding_talk_access_token = cron_info.get('DingTalkAccessToken')
            ding_talk_at_mobiles = cron_info.get('DingTalkAtMobiles')
            ding_talk_secret = cron_info.get('DingTalkSecret')
            always_ding_talk_notify = cron_info.get('alwaysDingTalkNotify')

            if trigger_type == 'interval' and int(interval) > 0:
                self.scheduler.modify_job(
                    job_id=cron_job_id,
                    trigger=IntervalTrigger(seconds=interval))
            elif trigger_type == 'date':
                self.scheduler.modify_job(
                    job_id=cron_job_id, trigger=DateTrigger(run_date=run_date))
            else:
                raise TypeError('更新定时任务触发器失败!')
            if run_date:
                cron = Cron(
                    cron_job_id=cron_job_id,
                    test_suite_id_list=test_suite_id_list,
                    project_id=project_id,
                    test_env_id=test_env_id,
                    include_forbidden=include_forbidden,
                    enable_wxwork_notify=enable_wxwork_notify,
                    wxwork_api_key=wxwork_api_key,
                    wxwork_mention_mobile_list=wxwork_mention_mobile_list,
                    always_wxwork_notify=always_wxwork_notify,
                    enable_ding_talk_notify=enable_ding_talk_notify,
                    ding_talk_access_token=ding_talk_access_token,
                    ding_talk_at_mobiles=ding_talk_at_mobiles,
                    ding_talk_secret=ding_talk_secret,
                    always_ding_talk_notify=always_ding_talk_notify,
                    always_send_mail=always_send_mail,
                    alarm_mail_group_list=alarm_mail_group_list,
                    trigger_type=trigger_type,  # 更新定时器时,此参数并没有真正起到作用, 仅修改展示字段
                    run_date=run_date)  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
            else:
                cron = Cron(
                    cron_job_id=cron_job_id,
                    test_suite_id_list=test_suite_id_list,
                    project_id=project_id,
                    include_forbidden=include_forbidden,
                    enable_wxwork_notify=enable_wxwork_notify,
                    wxwork_api_key=wxwork_api_key,
                    wxwork_mention_mobile_list=wxwork_mention_mobile_list,
                    always_wxwork_notify=always_wxwork_notify,
                    enable_ding_talk_notify=enable_ding_talk_notify,
                    ding_talk_access_token=ding_talk_access_token,
                    ding_talk_at_mobiles=ding_talk_at_mobiles,
                    ding_talk_secret=ding_talk_secret,
                    always_ding_talk_notify=always_ding_talk_notify,
                    test_env_id=test_env_id,
                    always_send_mail=always_send_mail,
                    alarm_mail_group_list=alarm_mail_group_list,
                    trigger_type=trigger_type,  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
                    seconds=interval)  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
            # 玄学,更改job的时候必须改args,不能改func
            self.scheduler.modify_job(job_id=cron_job_id,
                                      coalesce=True,
                                      args=[cron])
        except BaseException as e:
            with app.app_context():
                current_app.logger.error("update_cron failed. - %s" % str(e))

    def shutdown(self, force_shutdown=False):
        if force_shutdown:
            self.scheduler.shutdown(wait=False)
        else:
            self.scheduler.shutdown(wait=True)

    def get_jobs(self):
        return self.scheduler.get_jobs()
Exemple #15
0
class SellItem:
    """
     SellItem class docs
    """
    def __init__(self,
                 owner,
                 title,
                 itemtype,
                 description,
                 auction_type,
                 starting,
                 minbid=1.0,
                 image=None):

        self.lock = th.Lock()

        self.owner = owner
        self.owner.add_item(self)
        self.title = title
        self.itemtype = itemtype
        self.description = description
        self.auction_type = auction_type
        self.minbid = minbid
        self.image = image
        self.state = "onhold"
        self.auction_started = False
        self.bid_records = []
        self.creation_time = time.time()
        self.current_value = starting
        self.current_bidder = None
        self.auction_start_timestamp = None
        self.auction_end_timestamp = None
        self.obs = NotificationModule()

        #self.bid_operator = 1 if self.bidtype == "increment" else -1

        self.obs.notify(self.itemtype, "Object Created")
        # {"itemtype": [callback1,calback2,..]}
        self.callbacks = {}
        #self.stopbid = None

        if auction_type[0] == "decrement":
            self.scheduler = BackgroundScheduler()
            self.decrement_job = self.scheduler.add_job(
                self.__decrement_periodic,
                'interval',
                minutes=self.auction_type[1])
            self.scheduler.start(paused=True)

        elif auction_type[0] == "instantincrement":
            self.overall_bids = {}

    def __decrement_periodic(self):
        with self.lock:
            self.current_value -= self.auction_type[2]
            self.notify_user("Price dropped! Current:{}".format(
                self.current_value))
            if self.current_value <= self.auction_type[3]:
                self.auction_started = False
                self.current_bidder = False
                self.scheduler.pause()
                self.notify_user("Price<=STOP stop:{}".format(
                    self.auction_type[3]))
                self.state = "onhold"

    def startauction(self, owner=None):
        if owner != self.owner:
            raise Exception("User is not owner, can not sell")
        #if not (type(stopbid) is float or type(stopbid) is int):
        #    raise ValueError("amount is invalid")
        if self.auction_started:
            raise Exception("Auction is already started at {}".format(
                utilities.dateformatter(self.auction_start_timestamp)))
        #if stopbid:
        #    self.stopbid = stopbid
        self.state = "active"
        self.auction_started = True
        self.auction_start_timestamp = time.time()
        self.notify_user("Auction is started!")
        self.obs.notify(self.itemtype, "Auction Started!")
        if self.auction_type[0] == "decrement":
            self.scheduler.resume()

    def bid(self, user, amount):
        if user == self.owner:
            raise Exception("Owner cannot bid!")
        with self.lock:
            if not (type(amount) is float or type(amount) is int):
                raise ValueError("amount is invalid")
            if not type(user) is User:
                raise ValueError("invalid user")
            if not self.auction_started:
                raise Exception("Auction is not started")
            if amount <= 0:
                raise ValueError("Bid cannot be <= zero!")
            if amount < self.minbid:
                raise ValueError(
                    " Bid amount is lower than minimum bid amount({})".format(
                        self.minbid))

            if self.auction_type[0] == "increment":
                if amount < self.current_value + self.auction_type[1]:
                    raise ValueError(" Bid amount is lower than current value+delta(current:{},delta:{})."\
                        .format(self.current_value,self.auction_type[1]))
                if (user.reserve_amount(amount)):
                    if self.current_bidder:
                        self.current_bidder.release_amount(self.current_value)
                    self.current_value = amount
                    self.current_bidder = user
                    self.bid_records.append({
                        "bidder": user,
                        "amount": amount,
                        "timestamp": time.time()
                    })
                    if self.auction_type[2] <= self.current_value:
                        print("Satiyorum... Sattim!")
                        self.bid_records.append({
                            "bidder": user,
                            "amount": amount,
                            "timestamp": time.time()
                        })
                        self.auction_started = False
                        self.auction_end_timestamp = time.time()
                        self.current_bidder.checkout(amount, self, self.owner)
                        self.owner = self.current_bidder
                        self.state = "sold"
                else:
                    raise Exception(
                        "User does not have this much unreserved amount.")
            elif self.auction_type[0] == "decrement":
                if amount < self.current_value:
                    raise Exception(
                        "Auction type decrement. Value is lower than current({})"
                        .format(self.current_value))
                if (user.reserve_amount(amount)):
                    print("Satiyorum... Sattim!")
                    self.auction_started = False
                    self.auction_end_timestamp = time.time()
                    self.current_bidder = user
                    self.current_bidder.checkout(amount, self, self.owner)
                    self.bid_records.append({
                        "bidder": user,
                        "amount": amount,
                        "timestamp": time.time()
                    })
                    self.owner = self.current_bidder
                    self.scheduler.pause()
                    self.state = "sold"
                else:
                    raise Exception(
                        "User does not have this much unreserved amount.")
            else:
                if (amount < self.auction_type[1]):
                    raise Exception(
                        "Bid amount is lower than minbid({})".format(
                            self.auction_type[1]))
                if (user.reserve_amount(amount)):
                    self.current_value += amount
                    self.bid_records.append({
                        "bidder": user,
                        "amount": amount,
                        "timestamp": time.time()
                    })
                    if not user in self.overall_bids:
                        self.overall_bids[user] = amount
                    else:
                        self.overall_bids[user] += amount
                    max_user = user
                    for u in self.overall_bids:
                        if self.overall_bids[u] > self.overall_bids[max_user]:
                            max_user = u
                    if self.current_value >= self.auction_type[2]:
                        print("Satiyorum... Sattim!")
                        self.auction_started = False
                        self.auction_end_timestamp = time.time()
                        max_user.checkout(0, self, self.owner,
                                          self.overall_bids)
                        self.owner = max_user
                        self.state = "sold"

                else:
                    raise Exception(
                        "User does not have this much unreserved amount.!")

            self.notify_user()

    def sell(self, owner=None):
        with self.lock:
            if owner != self.owner:
                raise Exception("User is not owner, can not sell")
            if not self.auction_started:
                raise Exception("Auction is not started yet!")
            # OWNER SHOULD BE CHECKED, only owner can call sell()
            if self.auction_type[0] == "decrement":
                self.state = "onhold"
                self.notify_user("Item Auction Stopped")
                return

            if self.auction_type[0] == "instantincrement":
                if self.overall_bids:
                    self.state = "sold"
                    self.auction_started = False
                    self.auction_end_timestamp = time.time()
                    max_user = None
                    for u in self.overall_bids:
                        if not max_user:
                            max_user = u
                        elif self.overall_bids[u] > self.overall_bids[max_user]:
                            max_user = u

                    max_user.checkout(0, self, self.owner, self.overall_bids)
                    self.owner = max_user
                    return
                else:
                    self.state = "onhold"

            self.auction_started = False
            self.state = "onhold"
            self.notify_user()
            if self.current_value != 0 and self.current_bidder:
                self.current_bidder.checkout(self.current_value, self,
                                             self.owner)
                self.owner = self.current_bidder
                self.state = "sold"

    def view(self):
        bids = [(i["bidder"].email, i["amount"]) for i in self.bid_records]
        return {
            "title":
            self.title,
            "description":
            self.description,
            "auction_start":
            utilities.dateformatter(self.auction_start_timestamp)
            or "Auction is not started yet",
            "auction_end":
            utilities.dateformatter(self.auction_end_timestamp)
            or "Auction is not end",
            "bids":
            bids,
            "current_value":
            self.current_value,
            "current_bidder":
            self.current_bidder.email,
            "owner":
            self.owner.email
        }

    def watch(self, user, watchmethod):
        if not isinstance(user, User):
            raise ValueError("invalid user")
        with self.lock:
            if user in self.callbacks:
                raise Exception("User is already add watch_list")
            self.callbacks[user] = watchmethod

    def history(self):
        return {
            "creation": utilities.dateformatter(self.creation_time),
            "auction_start":
            utilities.dateformatter(self.auction_start_timestamp),
            "bids": self.bid_records,
            "current_value": self.current_value
        }

    def notify_user(self, descr="Item state is changed"):
        for user in self.callbacks:
            try:
                self.callbacks[user](descr)
            except:
                pass
Exemple #16
0
class CronManager:
    def __init__(self, use_mongo_db=True):

        self.scheduler = BackgroundScheduler(timezone=shanghai_tz)
        self.scheduler.configure()

        if use_mongo_db:
            self.job_store = MongoDBJobStore(database='apscheduler',
                                             collection='cronTab',
                                             client=db)
            self.scheduler.add_jobstore(self.job_store)
            self.is_replace_existing = True
        else:
            self.is_replace_existing = False

    def add_cron(self, cron_instance):
        if not isinstance(cron_instance, Cron):
            raise TypeError('please add correct cron!')

        if cron_instance.trigger_type == 'interval':
            seconds = cron_instance.trigger_args.get('seconds')
            if not isinstance(seconds,
                              int) and not common.can_convert_to_int(seconds):
                raise TypeError('请输入合法的时间间隔!')
            seconds = int(seconds)
            if seconds <= 0:
                raise TypeError('请输入大于0的时间间隔!')
            job = self.scheduler.add_job(
                func=cron_instance.cron_mission,
                trigger=cron_instance.trigger_type,
                seconds=seconds,
                replace_existing=self.is_replace_existing,
                coalesce=True,
                id=cron_instance.get_id(),
                max_instances=5,
                jitter=0)  # 玄学,新增job的时候不用加args,直接加对象调用的func
        elif cron_instance.trigger_type == 'date':
            run_date = cron_instance.trigger_args.get('run_date')
            # TODO 判断run_date类型
            job = self.scheduler.add_job(
                func=cron_instance.cron_mission,
                trigger=cron_instance.trigger_type,
                run_date=run_date,
                replace_existing=self.is_replace_existing,
                coalesce=True,
                id=cron_instance.get_id())  # 玄学,新增job的时候不用加args,直接加对象调用的func
        elif cron_instance.trigger_type == 'cron':
            raise TypeError('暂时不支持 trigger_type 等于 \'cron\'')

        return cron_instance.get_id()

    def start(self, paused=False):
        self.scheduler.start(paused=paused)

    def pause_cron(self, cron_id=None, pause_all=False):
        if pause_all:
            self.scheduler.pause()
        elif cron_id:
            self.scheduler.pause_job(job_id=cron_id)

    def resume_cron(self, cron_id=None, resume_all=False):
        if resume_all:
            self.scheduler.resume()
        elif cron_id:
            self.scheduler.resume_job(job_id=cron_id)

    def del_cron(self, cron_id=None, del_all=False):
        if del_all:
            self.scheduler.remove_all_jobs()
        elif cron_id:
            self.scheduler.remove_job(job_id=cron_id)

    def update_cron(self, cron_id, cron_info):
        if not isinstance(cron_id, str):
            raise TypeError('cron_id must be str')

        if not isinstance(cron_info, dict):
            raise TypeError('cron_info must be dict')

        trigger_type = cron_info.get('triggerType')
        interval = cron_info.get('interval')
        run_date = cron_info.get('runDate')
        test_case_suite_id_list = cron_info.get('testCaseSuiteIdList')
        is_execute_forbiddened_case = cron_info.get('isExecuteForbiddenedCase')
        test_case_id_list = cron_info.get('testCaseIdList')
        test_domain = cron_info.get('testDomain')
        global_vars_id = cron_info.get('globalVarsId')
        alarm_mail_list = cron_info.get('alarmMailList')
        is_ding_ding_notify = cron_info.get('isDingDingNotify')
        ding_ding_access_token = cron_info.get('dingdingAccessToken')
        ding_ding_notify_strategy = cron_info.get('dingdingNotifyStrategy')
        is_enterprise_wechat_notify = cron_info.get('isEnterpriseWechatNotify')
        enterprise_wechat_access_token = cron_info.get(
            'enterpriseWechatAccessToken')
        enterprise_wechat_notify_strategy = cron_info.get(
            'enterpriseWechatNotifyStrategy')
        cron_name = cron_info.get('name')

        try:
            if trigger_type == 'interval' and int(interval) > 0:
                self.scheduler.modify_job(
                    job_id=cron_id, trigger=IntervalTrigger(seconds=interval))
            elif trigger_type == 'date':
                # TODO 判断run_date类型
                self.scheduler.modify_job(
                    job_id=cron_id, trigger=DateTrigger(run_date=run_date))
            else:
                raise TypeError('更新定时任务触发器失败!')
            if run_date:
                cron = Cron(
                    test_case_suite_id_list=test_case_suite_id_list,
                    is_execute_forbiddened_case=is_execute_forbiddened_case,
                    test_domain=test_domain,
                    global_vars_id=global_vars_id,
                    alarm_mail_list=alarm_mail_list,
                    is_ding_ding_notify=is_ding_ding_notify,
                    ding_ding_access_token=ding_ding_access_token,
                    ding_ding_notify_strategy=ding_ding_notify_strategy,
                    is_enterprise_wechat_notify=is_enterprise_wechat_notify,
                    enterprise_wechat_access_token=
                    enterprise_wechat_access_token,
                    enterprise_wechat_notify_strategy=
                    enterprise_wechat_notify_strategy,
                    trigger_type=trigger_type,  # 更新定时器时,此参数并没有真正起到作用, 仅修改展示字段
                    test_case_id_list=test_case_id_list,
                    run_date=run_date,
                    cron_name=cron_name)  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
            else:
                cron = Cron(
                    test_case_suite_id_list=test_case_suite_id_list,
                    is_execute_forbiddened_case=is_execute_forbiddened_case,
                    test_domain=test_domain,
                    global_vars_id=global_vars_id,
                    alarm_mail_list=alarm_mail_list,
                    is_ding_ding_notify=is_ding_ding_notify,
                    ding_ding_access_token=ding_ding_access_token,
                    ding_ding_notify_strategy=ding_ding_notify_strategy,
                    is_enterprise_wechat_notify=is_enterprise_wechat_notify,
                    enterprise_wechat_access_token=
                    enterprise_wechat_access_token,
                    enterprise_wechat_notify_strategy=
                    enterprise_wechat_notify_strategy,
                    trigger_type=trigger_type,  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
                    test_case_id_list=test_case_id_list,
                    seconds=interval,  # 更新定时器时,此参数并没有起到作用, 仅修改展示字段
                    cron_name=cron_name)
            # 玄学,更改job的时候必须改args,不能改func
            self.scheduler.modify_job(job_id=cron_id,
                                      coalesce=True,
                                      args=[cron])

        except BaseException as e:
            raise TypeError('更新定时任务失败: %s' % e)

    def shutdown(self, force_shutdown=False):
        if force_shutdown:
            self.scheduler.shutdown(wait=False)
        else:
            self.scheduler.shutdown(wait=True)

    def get_crons(self):
        return self.scheduler.get_jobs()
Exemple #17
0
class APS_Schedule(object):
    """docstring for APS_Schedule"""
    def __init__(self):
        executors = {
            'default': ThreadPoolExecutor(20),
            'processpool': ProcessPoolExecutor(5)
        }

        # jobstores = {
        #     'mongo': MongoDBJobStore(collection='SchedularJobs', database='chatdb',
        #                              host=db_name, port=27017,
        #                              username=mongouser, password=mongopass),
        # }

        job_defaults = {
            'coalesce': True,
            'max_instances': 5,
            'misfire_grace_time': 1000
        }
        self.scheduler = BackgroundScheduler(executors=executors,
                                             job_defaults=job_defaults)

        self.scheduler.start()
        print('Press Ctrl+{0} to exit'.format('Break' if os.name ==
                                              'nt' else 'C'))
        # Execution will block here until Ctrl+C (Ctrl+Break on Windows) is pressed.

    def add_execution_reminder(self, msg_title, msg_body, execution_time,
                               user_id, notif_type, type_id):
        try:
            self.scheduler.add_job(
                _send_notification,
                'date',
                run_date=execution_time,
                args=[msg_title, msg_body, user_id, notif_type, type_id],
                id=str(type_id),
                replace_existing=True)
            return True
        except Exception as e:
            print(str(e))
            logger.critical(
                "couldnt add the job from schedular with exception : {}".
                format(str(e)))

    def remove_execution_reminder(self, job_id, job_type):
        try:
            print('before deleting the job.')
            job_del = self.scheduler.remove_job(str(job_id))
            print(job_del, 'after delete')
            return True

        except Exception as e:
            logger.critical(
                "couldnt remove the job from schedular with exception : {}".
                format(str(e)))

    def pause_jobs(self):
        try:
            self.scheduler.pause()
            return True
        except Exception as e:
            logger.error(
                "couldnt pause the schedular with exception : {}".format(
                    str(e)))

    def resume_jobs(self):
        try:
            self.scheduler.resume()
            return True
        except Exception as e:
            logger.error(
                "couldnt resume the schedular with exception : {}".format(
                    str(e)))

    def shutdown_schedular(self):
        try:
            sch = self.scheduler.shutdown()
            return sch
        except Exception as e:
            logger.error(
                "couldnt shutdown the schedular with exception : {}".format(
                    str(e)))
Exemple #18
0
class Jobs:
    def _listener(self, event):
        if event.code == EVENT_JOB_SUBMITTED:
            logger.debug(_("The job %s started"), event.job_id)
            self._job_set.add(event.job_id)
        else:
            if event.job_id in self._job_set:
                self._job_set.remove(event.job_id)
            else:
                logger.error(_("Job %s not found in job_set"),
                             event.job_id)  # pragma: no cover
            if event.exception:
                logger.error(_("The job %s crashed"),
                             event.job_id)  # pragma: no cover
            else:
                logger.debug(_("The job %s worked"), event.job_id)
        logger.debug(_("Job set: %s"), self._job_set)

    def __init__(self, url="sqlite:///jobs.sqlite", nb_executors=1):
        """Initialize class.

        Parameters
        ----------
        url: str
            SQLalchemy URL for persistent jobstore.
        nb_executors : int
            Number of concurrent executor processes.

        """
        self._job_set = set()
        logger.info(
            _("Creating scheduler, %s executors, storing in %s"),
            nb_executors,
            str(url)[0:str(url).find(":")],
        )
        jobstores = {
            "once": MemoryJobStore(),
            "default": SQLAlchemyJobStore(url=url)
        }
        executors = {"default": ProcessPoolExecutor(nb_executors)}
        job_defaults = {
            "coalesce": True,
            "max_instances": 1,
            "misfire_grace_time": 3600,
        }
        self._scheduler = BackgroundScheduler(
            jobstores=jobstores,
            executors=executors,
            job_defaults=job_defaults,
            timezone=utc,
        )
        self._scheduler.add_listener(
            self._listener,
            EVENT_JOB_SUBMITTED | EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        logger.info(
            _("Shutting down scheduler in __atexit__, if still running"))
        try:
            self._scheduler.shutdown(wait=False)
        except Exception:
            pass

    def shutdown(self):
        logger.info(_("Shutting down scheduler"))
        try:
            self._scheduler.shutdown()
        except SchedulerNotRunningError:  # pragma: no cover
            pass

    def _handler(self, signum, frame):  # pragma: no cover
        logger.error(_("Signal handler called with signal %s"), signum)
        try:
            self._scheduler.shutdown(wait=False)
        except SchedulerNotRunningError:
            pass
        try:
            parent_id = os.getpid()
            for child in psutil.Process(parent_id).children(recursive=True):
                child.kill()
        except Exception:
            pass
        sys.exit(1)

    def start(self, paused=False):
        logger.debug(_("Starting scheduler, paused=%s"), paused)
        self._scheduler.start(paused)
        signal.signal(signal.SIGINT, self._handler)
        # signal.signal(signal.SIGTERM, self._handler)

    # def pause(self):
    #     logger.debug(_("Pausing scheduler"))
    #     self._scheduler.pause()

    def resume(self):
        logger.debug(_("Resuming scheduler"))
        self._scheduler.resume()

    def remove_all_jobs(self):
        logger.debug(_("Removing all scheduled jobs"))
        self._scheduler.remove_all_jobs()

    def add_job_once(self, job_fn, args=None, kwargs=None):
        logger.debug(_("Adding immediate job %s"),
                     args[0].__name__ + "_" + args[2].site)
        self._scheduler.add_job(
            job_fn,
            args=args,
            kwargs=kwargs,
            id=args[0].__name__ + "_" + args[2].site,
            jobstore="once",
        )

    def add_job_schedule(
        self,
        job_fn,
        args=None,
        kwargs=None,
        year=None,
        month=None,
        day=None,
        week=None,
        day_of_week=None,
        hour=None,
        minute=None,
        second=None,
    ):
        logger.debug(_("Adding scheduled job %s"),
                     args[0].__name__ + "_" + args[2].site)
        self._scheduler.add_job(
            job_fn,
            args=args,
            kwargs=kwargs,
            id=args[0].__name__ + "_" + args[2].site,
            jobstore="default",
            trigger="cron",
            year=year,
            month=month,
            day=day,
            week=week,
            day_of_week=day_of_week,
            hour=hour,
            minute=minute,
            second=second,
            replace_existing=True,
        )

    def count_jobs(self):
        # self._scheduler.print_jobs()
        jobs = self._scheduler.get_jobs()
        logger.debug(_("Number of jobs scheduled, %s"), len(jobs))
        for j in jobs:
            logger.debug(
                _("Job %s, scheduled in: %s"),
                j.id,
                j.next_run_time - datetime.now(timezone.utc),
            )
        logger.debug(_("Number of jobs running, %s"), len(self._job_set))
        return len(self._job_set)

    def print_jobs(self):
        jobs = self._scheduler.get_jobs()
        logger.info(_("Number of jobs scheduled, %s"), len(jobs))
        for j in jobs:
            logger.info(_("Job %s, scheduled: %s"), j.id, j.trigger)
Exemple #19
0
            # time.sleep(2)  # 其他任务是独立的线程执行
            # print('sleep!')
            bb = raw_input("aaaaa:")
            if bb == '1':
                # schedmy2.start()
                if schedmy.state == 0:
                    pass
                else:
                    schedmy.pause()
                print schedmy.state
                # schedmy.pause_job()
            elif bb == '2':
                if schedmy.state == 0:
                    schedmy.start()
                else:
                    schedmy.resume()
                print schedmy.state
                # schedmy.resume_job()
            elif bb == '3':
                # schedmy.remove_job('autotest')
                schedmy.shutdown()
                print schedmy.state


    except(KeyboardInterrupt,SystemExit):
        print 111
        # schedmy.remove_job('autotest')
        # schedmy.remove_job('autotest2')


    # schedmy.add_job(job,trigger='cron',second = '*/5',id ='autotest')
Exemple #20
0
class ScheduleManager(IScheduleManager):
    def __init__(self, config=None, event_listener=None):
        self.__config = config
        self.__event_listener = event_listener
        jobstores, executors, job_defaults, timezone = self.__get_apscheduler_settings(
        )

        # initial apscheduler
        self.__scheduler = BackgroundScheduler(jobstores=jobstores,
                                               executors=executors,
                                               job_defaults=job_defaults,
                                               timezone=timezone)

        if self.__event_listener:
            self.__scheduler.add_listener(self.__event_listener.event_start,
                                          EVENT_SCHEDULER_STARTED)
            self.__scheduler.add_listener(self.__event_listener.event_shutdown,
                                          EVENT_SCHEDULER_SHUTDOWN)
            self.__scheduler.add_listener(self.__event_listener.event_pause,
                                          EVENT_SCHEDULER_PAUSED)
            self.__scheduler.add_listener(self.__event_listener.event_resume,
                                          EVENT_SCHEDULER_RESUMED)
            self.__scheduler.add_listener(
                self.__event_listener.event_job_submit, EVENT_JOB_SUBMITTED)
            self.__scheduler.add_listener(
                self.__event_listener.event_job_max_instances,
                EVENT_JOB_MAX_INSTANCES)
            self.__scheduler.add_listener(
                self.__event_listener.event_job_execute, EVENT_JOB_EXECUTED)
            self.__scheduler.add_listener(
                self.__event_listener.event_job_error, EVENT_JOB_ERROR)
            self.__scheduler.add_listener(self.__event_listener.event_job_miss,
                                          EVENT_JOB_MISSED)

    def __get_apscheduler_settings(self):
        try:
            jobstore_url = "oracle+cx_oracle://{username}:{password}${host}:{port}/{dbname}".format(
                username=self.__config.db_user,
                password=self.__config.db_pwd,
                host=self.__config.db_host,
                port=self.__config.db_port,
                dbname=self.__config.db_name,
            )

            jobstores = {
                "default":
                SQLAlchemyJobStore(url=jobstore_url,
                                   tablename=self.__config.tablename)
            }

            executors = {
                "default": ThreadPoolExecutor(self.__config.max_workers),
                "processpool": ProcessPoolExecutor(2)
            }

            job_defaults = {
                "coalesce": True,
                "max_instances": 10,
                "misfire_grace_time": 30
            }

            timezone = self.__config.timezone

            return jobstores, executors, job_defaults, timezone

        except Exception as e:
            raise e

    def start(self, paused=False) -> bool:
        try:
            if self.__scheduler.state == STATE_RUNNING:
                return True

            self.__scheduler.start(paused=paused)

        except Exception as e:
            logging.error(f"scheduler start error...... {str(e)}")
            raise e

    def shutdown(self, wait=False) -> bool:
        try:
            self.__scheduler.shutdown(wait=wait)
            if self.__scheduler.state == STATE_STOPPED:
                return True

            return False

        except Exception as e:
            logging.error(f"scheduler shutdown error...... {str(e)}")
            raise e

    def pause(self) -> bool:
        try:
            self.__scheduler.pause()
            if self.__scheduler.state == STATE_PAUSED:
                return True

            return False

        except Exception as e:
            logging.error(f"scheduler pause error...... {str(e)}")
            raise e

    def resume(self) -> bool:
        try:
            self.__scheduler.resume()
            if self.__scheduler.state == STATE_RUNNING:
                return True

            return False

        except Exception as e:
            logging.error(f"scheduler resume error...... {str(e)}")
            raise e

    def get_state(self) -> str:
        try:
            if self.__scheduler.state == STATE_RUNNING:
                return "RUNNING"

            if self.__scheduler.state == STATE_PAUSED:
                return "PAUSED"

            return "STOPPED"

        except Exception as e:
            logging.error(f"scheduler get_state error...... {str(e)}")
            raise e

    def get_job(self, id="") -> object:
        try:
            job = self.__scheduler.get_job(id)
            return job

        except Exception as e:
            logging.error(f"scheduler get_job error...... {str(e)}")
            raise e

    def add_job(self, task_id="", trigger=None, task=None) -> bool:
        try:
            settings = {}
            settings["id"] = task_id if task_id else str(uuid4())
            settings["func"] = task.run
            settings["coalesce"] = True
            settings["replace_existing"] = True
            settings = {**settings, **(trigger.get_settings())}

            job = self.__scheduler.add_job(**settings)

            return True if self.get_job(job.id) else False

        except Exception as e:
            logging.error(f"scheduler add_job error...... {str(e)}")
            raise e

    def remove_job(self, id: str) -> bool:
        try:
            self.__scheduler.remove_job(id)
            return True if not self.get_job(id) else False

        except JobLookupError as e:
            return False

        except Exception as e:
            logging.error(f"scheduler remove_job error...... {str(e)}")
            raise e

    def pause_job(self, id: str) -> bool:
        try:
            job = self.__scheduler.pause_job(id)
            return True if job else False

        except Exception as e:
            logging.error(f"scheduler pause_job error...... {str(e)}")
            raise e

    def resume_job(self, id: str) -> bool:
        try:
            job = self.__scheduler.resume_job(id)
            return True if job else False

        except Exception as e:
            logging.error(f"scheduler resume_job error...... {str(e)}")
            raise e
Exemple #21
0
class Thunderboard:

    def __init__(self, addr, addrType):
        self.addr = addr
        self.addrType = addrType
        self.char = dict()
        self.session = ''
        self.coinCell = False
        self.bleService = None
        self.senseData = dict()
        self.motionData = dict()
        self.thunderboardData = dict()
        self.bleService = Peripheral()
        self.schedulers = BackgroundScheduler()

        self.bleService.connect(self.addr, self.addrType)
        self.delegate = MyDelegate(self)
        self.bleService.setDelegate(self.delegate)
        self.enableNotification()

        self.characteristics = self.bleService.getCharacteristics()

        for k in self.characteristics:
            if k.uuid == '2a6e':
                self.char['temperature'] = k

            elif k.uuid == '2a6f':
                self.char['humidity'] = k

            elif k.uuid == '2a19':
                self.char['batterylevel'] = k

            elif k.uuid == 'ec61a454-ed01-a5e8-b8f9-de9ec026ec51':
                self.char['powertype'] = k

        self.job0 = self.schedulers.add_job(self.senseDataUpdate, replace_existing=True, trigger='interval', seconds=(
            300 / 1000))
        self.job1 = self.schedulers.add_job(self.motionDataUpdate, replace_existing=True, trigger='interval', seconds=(
            300 / 1000))

        self.schedulers.start()
        self.job0.pause()
        self.job1.pause()

    def jobInit(self, sense_interval, sense_interval_unit, motion_interval, motion_interval_unit):

        self.schedulers.pause()
        self.job0.remove()
        self.job1.remove()

        if sense_interval_unit == "seconds":
            self.job0 = self.schedulers.add_job(
                self.senseDataUpdate, replace_existing=True, trigger='interval', seconds=sense_interval)
        elif sense_interval_unit == "minutes":
            self.job0 = self.schedulers.add_job(
                self.senseDataUpdate, replace_existing=True, trigger='interval', minutes=sense_interval)
        elif sense_interval_unit == "days":
            self.job0 = self.schedulers.add_job(
                self.senseDataUpdate, replace_existing=True, trigger='interval', days=sense_interval)
        elif sense_interval_unit == "weeks":
            self.job0 = self.schedulers.add_job(
                self.senseDataUpdate, replace_existing=True, trigger='interval', weeks=sense_interval)

        if motion_interval_unit == "seconds":
            self.job1 = self.schedulers.add_job(
                self.motionDataUpdate, replace_existing=True, trigger='interval', seconds=motion_interval)
        elif motion_interval_unit == "minutes":
            self.job1 = self.schedulers.add_job(
                self.motionDataUpdate, replace_existing=True, trigger='interval', minutes=motion_interval)
        elif motion_interval_unit == "days":
            self.job1 = self.schedulers.add_job(
                self.motionDataUpdate, replace_existing=True, trigger='interval', days=motion_interval)
        elif motion_interval_unit == "weeks":
            self.job1 = self.schedulers.add_job(
                self.motionDataUpdate, replace_existing=True, trigger='interval', weeks=motion_interval)

        self.schedulers.resume()

    def senseDataUpdate(self):
        self.senseUpdate()
        self.thunderboardData['powertype'] = self.senseData['powertype']
        self.thunderboardData['batterylevel'] = self.senseData['batterylevel']
        self.thunderboardData['temperature'] = self.senseData['temperature']
        self.thunderboardData['humidity'] = self.senseData['humidity']

        # self.disconnect()

    def motionDataUpdate(self):
        self.thunderboardData['Orientation_x'] = self.motionData['Orientation']['x']
        self.thunderboardData['Orientation_y'] = self.motionData['Orientation']['y']
        self.thunderboardData['Orientation_z'] = self.motionData['Orientation']['z']
        self.thunderboardData['Acceleration_x'] = self.motionData['Acceleration']['x']
        self.thunderboardData['Acceleration_y'] = self.motionData['Acceleration']['y']
        self.thunderboardData['Acceleration_z'] = self.motionData['Acceleration']['z']
        # self.disconnect()

    def readTemperature(self):
        value = self.char['temperature'].read()
        value = struct.unpack('<H', value)
        value = value[0] / 100
        return value

    def readHumidity(self):
        value = self.char['humidity'].read()
        value = struct.unpack('<H', value)
        value = value[0] / 100
        return value

    def readBatteryLevel(self):
        value = self.char['batterylevel'].read()
        value = struct.unpack('B', value)
        value = value[0]
        return value

    def waitForNotification(self):
        if self.bleService.waitForNotifications(1.0):
            print("Waiting...")

    def enableNotification(self):
        self.bleService.writeCharacteristic(
            79, (1).to_bytes(2, byteorder='little'))
        self.bleService.writeCharacteristic(
            82, (1).to_bytes(2, byteorder='little'))

    def disableNotification(self):
        self.bleService.writeCharacteristic(
            79, (0).to_bytes(2, byteorder='little'))
        self.bleService.writeCharacteristic(
            82, (0).to_bytes(2, byteorder='little'))

    def connect(self):
        self.bleService.connect(self.addr, self.addrType)
        self.delegate = MyDelegate(self)
        self.bleService.setDelegate(self.delegate)
        self.enableNotification()

        self.job0.resume()
        self.job1.resume()

    def disconnect(self):

        self.job0.pause()
        self.job1.pause()
        sleep(0.5)
        del self.delegate
        self.bleService.disconnect()

    def senseUpdate(self):
        value = self.char['powertype'].read()
        if ord(value) == 0x04:
            self.coinCell = "coinCell"
        else:
            self.coinCell = "externalPower"
        self.senseData['powertype'] = self.coinCell

        for key in self.char.keys():
            if key == 'batterylevel':
                self.senseData['batterylevel'] = self.readBatteryLevel()

            elif key == 'temperature':
                self.senseData['temperature'] = self.readTemperature()

            elif key == 'humidity':
                self.senseData['humidity'] = self.readHumidity()
Exemple #22
0
class MainWindow(QtWidgets.QMainWindow, MainWindow.Ui_MainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        """
        Initializing the MainWindow
        """

        ## Setting up the MainWindow
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.setWindowTitle("TABFYE!")
        self.setWindowIcon(QIcon('appUi/icons8-eye-64.png'))

        ## Creating objects for classes imported from modules
        # ConfigParser for saving configuration
        self.config = ConfigParser()
        # BackgroundScheduler does the scheduling job of
        # showing the notification every @self.time_interval seconds/minutes
        self.scheduler = BackgroundScheduler()

        ## Variables
        # These variables determine the time in which
        # the reminder needs to be disabled
        self.disable_reminder_starthour = self.timeEdit.time().hour()
        self.disable_reminder_endhour = self.timeEdit_2.time().hour()
        self.disable_reminder_startmin = self.timeEdit.time().minute()
        self.disable_reminder_endmin = self.timeEdit_2.time().minute()
        # disable_reminder = True, if disable option is checked
        self.disable_reminder = False
        # do_not_start = True, if today's day name (e.g.Monday)
        # is checked
        self.do_not_start = False
        self.time_interval_in_seconds = True
        self.time_interval = 5
        self.s5.setChecked(True)

        ## Connecting the time interval options with a function
        self.s5.toggled.connect(self.select_time_interval)
        self.s10.toggled.connect(self.select_time_interval)
        self.m10.toggled.connect(self.select_time_interval)
        self.m20.toggled.connect(self.select_time_interval)
        self.m30.toggled.connect(self.select_time_interval)
        self.m40.toggled.connect(self.select_time_interval)
        self.h1.toggled.connect(self.select_time_interval)

        if self.time_interval_in_seconds == True:
            self.scheduler.add_job(self.break_remind_notifier,
                                   'interval',
                                   seconds=self.time_interval,
                                   id='reminder_job')
        else:
            self.scheduler.add_job(self.break_remind_notifier,
                                   'interval',
                                   minutes=self.time_interval,
                                   id='reminder_job')

        ## Open/create config file
        if not os.path.exists('config.ini'):
            print("Config file not found")

            self.config.add_section('day')
            self.config.set('day', 'Monday', 'False')
            self.config.set('day', 'Tuesday', 'False')
            self.config.set('day', 'Wednesday', 'False')
            self.config.set('day', 'Thursday', 'False')
            self.config.set('day', 'Friday', 'False')
            self.config.set('day', 'Saturday', 'False')
            self.config.set('day', 'Sunday', 'False')

            with open('config.ini', 'w') as file:
                self.config.write(file)

        else:
            print("Config file found")
            self.config.read('config.ini')

        # Determine today's day name
        now = datetime.datetime.now()
        self.today = now.strftime("%A")
        # print(self.today)

        # Restore the previous checkstates from the config file
        if self.config.get('day', 'Monday') == 'True':
            self.checkMonday.setChecked(True)
            if self.today == 'Monday':
                do_not_start = True
        if self.config.get('day', 'Tuesday') == 'True':
            self.checkTuesday.setChecked(True)
            if self.today == 'Tuesday':
                do_not_start = True
        if self.config.get('day', 'Wednesday') == 'True':
            self.checkWednesday.setChecked(True)
            if self.today == 'Wednesday':
                do_not_start = True
        if self.config.get('day', 'Thursday') == 'True':
            self.checkThursday.setChecked(True)
            if self.today == 'Thursday':
                do_not_start = True
        if self.config.get('day', 'Friday') == 'True':
            self.checkFriday.setChecked(True)
            if self.today == 'Friday':
                do_not_start = True
        if self.config.get('day', 'Saturday') == 'True':
            self.checkSaturday.setChecked(True)
            if self.today == 'Saturday':
                do_not_start = True
        if self.config.get('day', 'Sunday') == 'True':
            self.checkSunday.setChecked(True)
            if self.today == 'Sunday':
                do_not_start = True

        # Start the reminders only if today was not checked
        if self.do_not_start == False:
            self.scheduler.start()
        else:
            print("Disabled for today")

        ## Connecting the GUI objects with their functions
        self.enableReminder.setChecked(True)
        self.enableReminder.stateChanged.connect(self.reminder_function)
        self.disableReminder.stateChanged.connect(self.reminder_function)
        self.checkMonday.stateChanged.connect(self.check_day_of_the_week)
        self.checkTuesday.stateChanged.connect(self.check_day_of_the_week)
        self.checkWednesday.stateChanged.connect(self.check_day_of_the_week)
        self.checkThursday.stateChanged.connect(self.check_day_of_the_week)
        self.checkFriday.stateChanged.connect(self.check_day_of_the_week)
        self.checkSaturday.stateChanged.connect(self.check_day_of_the_week)
        self.checkSunday.stateChanged.connect(self.check_day_of_the_week)

        self.helpButton.clicked.connect(self.help_dialog)

        time = self.timeEdit.time()
        self.timeEdit.dateTimeChanged.connect(self.displayDT)
        self.timeEdit_2.dateTimeChanged.connect(self.displayDT)

    def select_time_interval(self):
        """
        Change the time interval in which the reminders are displayed
        :return: Nothing
        """
        if self.s5.isChecked():
            self.time_interval_in_seconds = True
            self.time_interval = 5
        elif self.s10.isChecked():
            self.time_interval_in_seconds = True
            self.time_interval = 10
        elif self.m10.isChecked():
            self.time_interval_in_seconds = False
            self.time_interval = 10
        elif self.m20.isChecked():
            self.time_interval_in_seconds = False
            self.time_interval = 20
        elif self.m30.isChecked():
            self.time_interval_in_seconds = False
            self.time_interval = 30
        elif self.m40.isChecked():
            self.time_interval_in_seconds = False
            self.time_interval = 40
        elif self.h1.isChecked():
            self.time_interval_in_seconds = False
            self.time_interval = 60

        if self.time_interval_in_seconds == True:
            print("Time interval : " + str(self.time_interval) + " seconds")
            # self.scheduler.shutdown()
            self.scheduler.remove_all_jobs()
            self.scheduler = BackgroundScheduler()
            self.scheduler.add_job(self.break_remind_notifier,
                                   'interval',
                                   seconds=self.time_interval)
        else:
            print("Time interval : " + str(self.time_interval) + " minutes")
            # self.scheduler.shutdown()
            self.scheduler.remove_all_jobs()
            self.scheduler = BackgroundScheduler()
            self.scheduler.add_job(self.break_remind_notifier,
                                   'interval',
                                   minutes=self.time_interval)

        self.enableReminder.setChecked(True)
        self.disableReminder.setChecked(False)
        if self.do_not_start == False:
            self.scheduler.start()

    def help_dialog(self):
        """
        Open the GUI help dialog
        :return: Nothing
        """
        self.window = QtWidgets.QMainWindow()
        self.ui = help.Ui_Dialog()
        self.ui.setupUi(self.window)
        self.ui.closeButton.clicked.connect(self.window.close)
        # self.window.resize(500, 440)
        self.window.setWindowIcon(QIcon('appUi/question.png'))
        self.window.show()

    def disable_reminder_in_timerange(self):
        """
        Set @self.disable_reminder = True, when @self.disableReminder is checked
        :return: 
        """
        self.disable_reminder = True
        # self.scheduler.pause()

    def reminder_function(self):
        """
        When the states of @self.enableReminder or @self.disableReminder are changed,
        turn on/off the reminding schedule to reflect the change
        :return: Nothing
        """

        # Get current time to compare with disalbe timings
        currentHour = QTime.currentTime().hour()
        currentMin = QTime.currentTime().minute()
        print("CurrentHour " + str(currentHour) + " CurrentMin " +
              str(currentMin))

        # Start/Resume/Pause reminding schedule according to
        # whether it is enabled and if the current time falls
        # into the disable time range
        if self.enableReminder.isChecked() == True:
            print("EnableReminder " + str(self.enableReminder.isChecked()))
            if self.disableReminder.isChecked() == True:
                print("DisableReminder " +
                      str(self.disableReminder.isChecked()))
                if not (currentHour >= self.disable_reminder_starthour
                        and currentMin >= self.disable_reminder_startmin and
                        ((currentHour < self.disable_reminder_endhour) or
                         (currentHour == self.disable_reminder_endhour
                          and currentMin < self.disable_reminder_endmin))):
                    self.scheduler.resume()
                else:
                    print("DisableReminder " +
                          str(self.disableReminder.isChecked()))
                    print("Pausing...")
                    self.scheduler.pause()
            else:
                self.scheduler.resume()
        else:
            print("EnableReminder " + str(self.enableReminder.isChecked()))
            self.scheduler.pause()

    def break_remind_notifier(self):
        """
        Show notification when the job is called for
        :return: Nothing
        """

        print("Look away for a while!")
        self.reminder_label.setText('Take a break!')

        # Windows 10 notifications need .ico files
        # but Linux needs .png
        # So check the OS for appropriate icons
        if os.name == 'nt':
            app_icon = 'appUi/icons8-eye-64.ico'
        elif os.name == 'posix':
            app_icon = 'appUi/icons8-eye-64.png'

        # Show the notification
        notification.notify(
            title='Take a break for your eyes!',
            message='Look at an object 20ft away for 20s',
            app_icon=app_icon,  # e.g. 'C:\\icon_32x32.ico'
            timeout=10,  # seconds
        )

        time.sleep(1)
        self.reminder_label.clear()
        print("Break over!")

    def displayDT(self):
        """
        Get the disable timings input when it is changed
        :return: Nothing
        """
        self.disable_reminder_starthour = self.timeEdit.time().hour()
        self.disable_reminder_endhour = self.timeEdit_2.time().hour()
        self.disable_reminder_startmin = self.timeEdit.time().minute()
        self.disable_reminder_endmin = self.timeEdit_2.time().minute()

        print("disable_reminder_starthour " +
              str(self.disable_reminder_starthour) +
              " disable_reminder_startmin " +
              str(self.disable_reminder_startmin))
        print("disable_reminder_endhour " +
              str(self.disable_reminder_endhour) +
              " disable_reminder_endmin " + str(self.disable_reminder_endmin))

        time = self.timeEdit.time().hour()
        time2 = self.timeEdit_2.time()
        currentTime = QTime.currentTime().hour()
        # if currentTime == time:
        #     print("Yeah, they are equal indeed")

    def check_day_of_the_week(self):
        """
        If today is checked, then disable the reminder for today,
        Resume otherwise
        :return: Nothing
        """
        if (self.checkMonday.isChecked() == True and self.today == 'Monday'
                or self.checkTuesday.isChecked() == True
                and self.today == 'Tuesday'
                or self.checkWednesday.isChecked() == True
                and self.today == 'Wednesdasy'
                or self.checkThursday.isChecked() == True
                and self.today == 'Thursday' or
                self.checkFriday.isChecked() == True and self.today == 'Friday'
                or self.checkSaturday.isChecked() == True
                and self.today == 'Saturday'
                or self.checkSunday.isChecked() == True
                and self.today == 'Sunday'):
            print("Today is checked")
            self.scheduler.pause()
        else:
            self.scheduler.resume()

    def __del__(self):
        """
        Destructor function
        :return: Nothing
        """
        print("Exiting app...")
        self.scheduler.shutdown()
        config = ConfigParser()
        config.read('config.ini')
        config.set('day', 'Monday', str(self.checkMonday.isChecked()))
        config.set('day', 'Tuesday', str(self.checkTuesday.isChecked()))
        config.set('day', 'Wednesday', str(self.checkWednesday.isChecked()))
        config.set('day', 'Thursday', str(self.checkThursday.isChecked()))
        config.set('day', 'Friday', str(self.checkFriday.isChecked()))
        config.set('day', 'Saturday', str(self.checkSaturday.isChecked()))
        config.set('day', 'Sunday', str(self.checkSunday.isChecked()))

        with open('config.ini', 'w') as file:
            config.write(file)
Exemple #23
0
class SchedulerManager(object):
    global _mongoclient

    def __init__(self):

        self._jobs = {}
        self._jobhandlers = {}  # format, key: jobid,  value: jobhandler
        self.create_scheduler()
        self.start()

    def create_scheduler(self):
        self.jobstores = {
            'mongo':
            MongoDBJobStore(collection='job1',
                            database='saasjob',
                            client=_mongoclient),
            'default':
            MemoryJobStore()
        }
        self.executors = {
            'default': ThreadPoolExecutor(20),
            'processpool': ProcessPoolExecutor(5)
        }
        self.job_defaults = {
            'coalesce': False,
            'misfire_grace_time': 1,
            'max_instances': 1
        }
        self._sched = BackgroundScheduler(jobstores=self.jobstores,
                                          executors=self.executors,
                                          job_defaults=self.job_defaults)
        # 添加 任务提交 事件监听
        self._sched.add_listener(self.when_job_submitted, EVENT_JOB_SUBMITTED)
        # # 添加 任务执行完成 事件监听
        # self._sched.add_listener(self.when_job_executed, EVENT_JOB_EXECUTED)
        # 添加 任务退出 事件监听
        self._sched.add_listener(self.when_job_crashed,
                                 EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

    def when_job_submitted(self, event):
        try:
            job_id = event.job_id
            if job_id not in self._jobhandlers and job_id in self._jobhandlers:
                self._jobhandlers.setdefault(job_id,
                                             JobHandler(self._jobs[job_id]))
            jobhandler = self._jobhandlers[event.job_id]
            jobhandler.when_job_submitted()
            print("%s submitted at %s" %
                  (event.job_id,
                   time.strftime("%Y-%m-%d %H:%M:%S",
                                 time.localtime(time.time()))))
        except:
            import traceback
            print(traceback.print_exc())

    def when_job_executed(self, event):
        try:
            if event.exception:
                job_id = event.job_id
                if job_id not in self._jobhandlers:
                    self._jobhandlers.setdefault(
                        job_id, JobHandler(self._jobs[job_id]))
                jobhandler = self._jobhandlers[event.job_id]
                jobhandler.when_job_crashed()
                print("%s crashed at %s" %
                      (event.job_id,
                       time.strftime("%Y-%m-%d %H:%M:%S",
                                     time.localtime(time.time()))))
            else:
                job_id = event.job_id
                if job_id not in self._jobhandlers:
                    self._jobhandlers.setdefault(
                        job_id, JobHandler(self._jobs[job_id]))
                jobhandler = self._jobhandlers[event.job_id]
                jobhandler.when_job_executed()
                print("%s executed at %s" %
                      (event.job_id,
                       time.strftime("%Y-%m-%d %H:%M:%S",
                                     time.localtime(time.time()))))
        except:
            import traceback
            print(traceback.print_exc())

    def when_job_crashed(self, event):
        try:
            if event.exception:
                job_id = event.job_id
                if job_id not in self._jobhandlers:
                    self._jobhandlers.setdefault(
                        job_id, JobHandler(self._jobs[job_id]))
                jobhandler = self._jobhandlers[event.job_id]
                jobhandler.when_job_crashed()
                print("%s crashed at %s" %
                      (event.job_id,
                       time.strftime("%Y-%m-%d %H:%M:%S",
                                     time.localtime(time.time()))))
        except:
            import traceback
            print(traceback.print_exc())

    def fresh_jobs(self):
        self._sched.pause()
        for _job in self._sched.get_jobs():
            job_id = self._get_job_attr(_job, "id")
            self._jobs.setdefault(job_id, _job)
        self._sched.resume()

    def sync_jobs(self, job_ids=set()):
        job_ids = (set(self._jobhandlers.keys())
                   | set(self._jobs.keys())) if len(job_ids) == 0 else job_ids
        for job_id in job_ids:
            if job_id in self._jobhandlers and job_id not in self._jobs:
                self._jobs[job_id] = self._jobhandlers[job_id]
            elif job_id not in self._jobhandlers and job_id in self._jobs:
                self._jobhandlers[job_id] = self._jobs[job_id]
        job_ids = set()
        return True

    def start(self):
        try:
            self._sched.start(paused=True)
            self.fresh_jobs()
            return True
        except:
            import traceback
            print(traceback.print_exc())
            return False
Exemple #24
0
class Scheduler(object):
    def __init__(self):
        self._scheduler = BackgroundScheduler(executors=config.EXECUTORS,
                                              job_defaults=config.JOB_DEFAULTS,
                                              timezone=config.TIME_ZONE)
        # self._all_jobs = {}

        self._scheduler.add_listener(self._on_job_add, EVENT_JOB_ADDED)
        self._scheduler.add_listener(self._on_job_remove, EVENT_JOB_REMOVED)
        self._scheduler.add_listener(self._on_job_modify, EVENT_JOB_MODIFIED)
        self._scheduler.add_listener(self._on_job_execute, EVENT_JOB_EXECUTED)
        self._scheduler.add_listener(self._on_job_error, EVENT_JOB_ERROR)
        self._scheduler.add_listener(self._on_scheduler_start,
                                     EVENT_SCHEDULER_STARTED)
        self._scheduler.add_listener(self._on_scheduler_stop,
                                     EVENT_SCHEDULER_SHUTDOWN)
        self._scheduler.add_listener(self._on_scheduler_pause,
                                     EVENT_SCHEDULER_PAUSED)
        self._scheduler.add_listener(self._on_scheduler_resume,
                                     EVENT_SCHEDULER_RESUMED)

    def start(self):
        if self.status() != STOPPED:
            raise ServiceException(ErrorCode.FAIL, '无法启动调度器,调度器不在停止状态')
        self._scheduler.start()

    def shutdown(self, waited=False):
        """
        :param waited: 等待所有任务执行结束后再停止
        :return:
        """
        if self.status() != RUNNING:
            raise ServiceException(ErrorCode.FAIL, '无法停止调度器,调度器不在运行状态')
        self._scheduler.remove_all_jobs()
        self._scheduler.shutdown(wait=waited)

    def pause(self):
        if self.status() != RUNNING:
            raise ServiceException(ErrorCode.FAIL, '无法暂停调度器,调度器不在运行状态')
        self._scheduler.pause()

    def resume(self):
        if self.status() != PAUSED:
            raise ServiceException(ErrorCode.FAIL, '无法重启调度器,调度器不在暂停状态')
        self._scheduler.resume()

    def status(self):
        """
        获取当前调度器状态
        0 停止,1 运行,2暂停
        :return:
        """
        return self._scheduler.state

    def add_job(self, task):
        if self.status() != RUNNING:
            raise ServiceException(ErrorCode.FAIL,
                                   '启动任务%s失败,调度器没有运行' % task.job_id)
        # 判断是否已经加入了调度器
        if self._scheduler.get_job(task.job_id) is None:
            # 动态导入脚本
            script = importlib.import_module('job.' + task.job_id)

            if script is None or not hasattr(script, 'run'):
                raise ServiceException(ErrorCode.FAIL,
                                       ("%s任务没有run方法" % task.job_id))

            try:
                cron_dict = eval(task.cron)
            except Exception as e:
                raise ServiceException(ErrorCode.FAIL,
                                       ("%s任务cron规则错误" % task.job_id), str(e))

            try:
                if task.type == Job.Type.INTERVAL.value:
                    self._scheduler.add_job(script.run,
                                            'interval',
                                            **cron_dict,
                                            id=task.job_id,
                                            max_instances=task.instance_cnt)
                elif task.type == Job.Type.CRON.value:
                    self._scheduler.add_job(script.run,
                                            'cron',
                                            **cron_dict,
                                            id=task.job_id,
                                            max_instances=task.instance_cnt)
            except Exception as e:
                raise ServiceException(ErrorCode.INTERNAL_ERROR,
                                       ("加入任务%s失败" % task.job_id), str(e))
        else:
            raise ServiceException(ErrorCode.FAIL, ("任务%s已存在" % task.job_id))

    def pause_job(self, task):
        current_job = self._scheduler.get_job(task.job_id)
        if current_job is not None:
            # 如果不在运行中
            if current_job.next_run_time is None:
                raise ServiceException(ErrorCode.FAIL,
                                       '无法暂停任务%s, 该任务现在已经停止' % (task.job_id))
            else:
                self._scheduler.pause_job(task.job_id)
        else:
            raise ServiceException(ErrorCode.FAIL, ("任务%s不存在" % task.job_id))

    def resume_job(self, task):
        current_job = self._scheduler.get_job(task.job_id)
        if current_job is not None:
            # 如果在运行中
            if current_job.next_run_time is not None:
                raise ServiceException(ErrorCode.FAIL,
                                       '无法重启任务%s, 该任务的现在已经在运行' % (task.job_id))
            else:
                self._scheduler.resume_job(task.job_id)
        else:
            raise ServiceException(ErrorCode.FAIL, ("任务%s不存在" % task.job_id))

    # def modify_job(self, task):
    #     current_job = self._scheduler.get_job(task.job_id)
    #     if current_job is not None:
    #         try:
    #             cron_dict = eval(task.cron)
    #         except Exception as e:
    #             raise ServiceException(ErrorCode.FAIL, ("%s任务cron规则错误" % task.job_id), str(e))
    #
    #         try:
    #             if task.type == Job.Type.INTERVAL.value:
    #                 self._scheduler.reschedule_job(task.job_id, trigger='interval', **cron_dict,
    #                                                max_instances=task.instance_cnt)
    #             elif task.type == Job.Type.CRON.value:
    #                 self._scheduler.reschedule_job(task.job_id, trigger='cron', **cron_dict,
    #                                                max_instances=task.instance_cnt)
    #         except Exception as e:
    #             raise ServiceException(ErrorCode.INTERNAL_ERROR, ("修改任务%s失败" % task.job_id), str(e))
    #     else:
    #         raise ServiceException(ErrorCode.FAIL, ("任务%s不存在" % task.job_id))

    def remove_job(self, task):
        current_job = self._scheduler.get_job(task.job_id)
        if current_job is not None:
            self._scheduler.remove_job(task.job_id)
        else:
            raise ServiceException(ErrorCode.FAIL, ("任务%s不存在" % task.job_id))

    ###### Listener ######
    def _on_job_add(self, event):
        from service.job_service import JobService
        job_id = event.job_id
        job = JobService.get_job(job_id)
        # 有自动加入的情况
        if job.status != job.Status.RUNNING.value:
            JobService.change_job_status(job_id, job.Status.RUNNING)
            job.status = job.Status.RUNNING.value
        logger.info('定时任务%s加入了调度器,信息:%s' % (job_id, str(job)))

    def _on_job_remove(self, event):
        from service.job_service import JobService
        job_id = event.job_id
        job = JobService.get_job(job_id)
        # 有自动删除的情况
        if job.status != job.Status.STOPPED.value:
            JobService.change_job_status(job_id, job.Status.STOPPED)
        logger.info('定时任务%s被移除了调度器,信息:%s' % (job_id, str(job)))

    def _on_job_modify(self, event):
        from service.job_service import JobService
        job_id = event.job_id
        job = self._scheduler.get_job(job_id)
        if job.next_run_time is None:
            job = JobService.get_job(job_id)
            logger.info('定时任务%s已暂停,信息:%s' % (job_id, str(job)))
            if job.status != job.Status.SUSPENDED.value:
                JobService.change_job_status(job_id, job.Status.SUSPENDED)
        else:
            logger.info('定时任务%s被修改或重启了并正在运行中,信息:%s' % (job_id, str(job)))

    def _on_job_error(self, event):
        from service.job_service import JobService
        e = event.exception
        job_id = event.job_id
        logger.warn('定时任务%s发生错误,将被移除调度器' % job_id)
        logger.error(str(e))
        task = JobService.get_job(job_id)
        self.remove_job(task)

    def _on_job_execute(self, event):
        from service.job_service import JobService
        job_id = event.job_id
        logger.info('定时任务%s开始执行' % job_id)
        JobService.add_executed_times(job_id, 1)

    def _on_scheduler_start(self, event):
        logger.info('调度器开始执行')

    def _on_scheduler_pause(self, event):
        logger.info('调度器暂停')

    def _on_scheduler_resume(self, event):
        logger.info('调度器重启')

    def _on_scheduler_stop(self, event):
        logger.info('调度器停止')

    def next_run_time(self, job_id):

        return self._scheduler.get_job(job_id).next_run_time
class PeriodicReporter(object):
    """
    This class is used to periodically get real-time market data from Yahoo finance database,
    the accessed data will not be saved at local,
    please use this with my Stock Data Reader class
    """
    def __init__(self, function):
        """

        :param function: function of the arranged job, in this case,
        it should be the getCurrentMarketData function
        """
        self._scheduler = None
        self.function = function
        self.existingJob = False
        self.start()

    def start(self):
        """
        method to start the reporter
        :return: None
        """
        self._scheduler = BackgroundScheduler()
        self._scheduler.start()

    def addJob(self, interval, *args):
        """
        add a reporter
        :param interval: the interval between two reports, 20 means 20 seconds, etc...
        :param args: tickerList,like:["AAPL","IBM","JPM"]
        :return: None
        """
        if not self.existingJob:
            self._scheduler.add_job(self.function,
                                    trigger='interval',
                                    seconds=interval,
                                    args=args)
            self.existingJob = True
        else:
            warnings.warn("Existing job will be removed!")
            self._scheduler.remove_all_jobs()
            self._scheduler.add_job(self.function,
                                    trigger='interval',
                                    seconds=interval,
                                    args=args)

    def removeJob(self):
        """
        remove the current reporter
        :return: None
        """
        self._scheduler.remove_all_jobs()
        self.existingJob = False

    def pause(self):
        """
        pause the current reporter
        :return: None
        """
        self._scheduler.pause()

    def resume(self):
        """
        resume the paused reporter
        :return: None
        """
        self._scheduler.resume()

    def getJob(self):
        """
        print the details of the current reporter
        :return: None
        """
        self._scheduler.print_jobs()

    def shutDown(self):
        """
        shut down the reporter
        :return: None
        """
        self._scheduler.shutdown()
class SpecificTimeReporter(object):
    """
    This class is used to get the real-time market data at specific time everyday from yahoo finance database,
    the accessed data will not be saved at local,
    please use this with my Stock Data Reader class
    """
    def __init__(self, function):
        """
        :param function: function of the arranged job, in this case,
        it should be the getCurrentMarketData function
        """
        self._scheduler = None
        self.function = function
        self.count = 1
        self._all_job = {}
        self.start()

    def start(self):
        """
        start the reporter
        :return: None
        """
        self._scheduler = BackgroundScheduler()
        self._scheduler.start()

    def convertInt2Time(self, hour, minute, second):
        """
        You do not need to call this method, you can treat this as a private method
        :param hour: integer ranging from 0 to 23
        :param minute: integer ranging from 0 to 59
        :param second: integer ranging from 0 to 59
        :return: string format of time
        """
        ans = ""
        if hour < 10:
            ans = ans + "0" + str(hour)
        else:
            ans = ans + str(hour)
        if minute < 10:
            ans = ans + "0" + str(minute)
        else:
            ans = ans + str(minute)
        if second < 10:
            ans = ans + "0" + str(second)
        else:
            ans = ans + str(second)
        return ans

    def addJob(self, hour, minute, second, *args):
        """
        add a reporter
        :param hour: integer ranging from 0 to 23
        :param minute: integer ranging from 0 to 59
        :param second: integer ranging from 0 to 59
        :param args: tickerList,like:["AAPL","IBM","JPM"]
        :return: None
        """
        timeString = self.convertInt2Time(hour, minute, second)

        if timeString not in self._all_job:
            self._all_job[timeString] = str(self.count)
            self._scheduler.add_job(self.function,
                                    trigger='cron',
                                    hour=hour,
                                    minute=minute,
                                    second=second,
                                    args=args,
                                    id=str(self.count))
            self.count = self.count + 1
        else:
            self._scheduler.reschedule_job(self._all_job[timeString],
                                           trigger='cron',
                                           hour=hour,
                                           minute=minute,
                                           second=second)

    def removeJob(self, hour, minute, second):
        """
        remove a reporter
        :param hour: integer ranging from 0 to 23
        :param minute: integer ranging from 0 to 59
        :param second: integer ranging from 0 to 59
        :return: None
        """
        timeString = self.convertInt2Time(hour, minute, second)
        if timeString not in self._all_job:
            warnings.warn("Job not found!")
        else:
            self._scheduler.remove_job(self._all_job[timeString])

    def removeAllJobs(self):
        """
        remove all reporters
        :return: None
        """
        self._scheduler.remove_all_jobs()

    def pause(self):
        """
        pause all reporters
        :return: None
        """
        self._scheduler.pause()

    def resume(self):
        """
        resume the paused reporters
        :return: None
        """
        self._scheduler.resume()

    def getAllJobs(self):
        """
        print the information of all reporters
        :return: None
        """
        self._scheduler.print_jobs()

    def shutDown(self):
        """
        shut down all reporters
        :return: None
        """
        self._scheduler.shutdown()
Exemple #27
0
class DataCollector:
    def __init__(self):
        self.logger = get_logger('data-collector')

        self.scheduler = BackgroundScheduler(timezone="Asia/Seoul")
        self.scheduler.start()
        self.templates = dict()

        self.__global_store = dict()

        self.job_broker = Celery('routine-jobs',
                                 broker=BROKER_URL,
                                 backend=CELERY_RESULT_BACKEND)

    # =========================================================================
    def add_job_schedules(self, schedule_templates: list):
        for schedule_template in schedule_templates:
            schedule_name, trigger = operator.itemgetter(
                'schedule_name', 'trigger')(schedule_template)

            # schedule name can't be duplicated.
            schedule_names = [
                x['schedule_name'] for x in self.get_schedule_jobs()
            ]
            if schedule_name in schedule_names:
                msg = f'The schedule name \'{schedule_name}\' is already assigned.'
                self.logger.error(msg)
                raise ExceptionScheduleReduplicated(msg)

            self._add_job_schedule(schedule_name,
                                   trigger_type=trigger['type'],
                                   trigger_setting=trigger['setting'])

            # store the schedule template
            self.templates[schedule_name] = schedule_template
            self.__global_store[schedule_name] = {'_gv': dict()}

    # =========================================================================
    def _add_job_schedule(self, key, trigger_type, trigger_setting):
        if trigger_type == 'crontab' and 'crontab' in trigger_setting:
            crontab = self.crontab_add_second(trigger_setting['crontab'])
            trigger_type = 'cron'
            trigger_setting = {**trigger_setting, **crontab}
            del trigger_setting['crontab']

        arguments = dict(func=self.request_data,
                         args=(key, ),
                         id=key,
                         trigger=trigger_type)
        arguments = {**arguments, **trigger_setting}

        self.scheduler.pause()
        try:
            self.scheduler.add_job(**arguments)
        finally:
            self.scheduler.resume()

    # =========================================================================
    def remove_job_schedule(self, schedule_name: str):
        self.get_schedule_job(schedule_name)
        self.scheduler.remove_job(schedule_name)
        try:
            del self.templates[schedule_name]
            del self.__global_store[schedule_name]
        except KeyError:
            # it should be failing to collect data. such as not connecting.
            pass

        return

    # =========================================================================
    def modify_job_schedule(self, schedule_name, trigger_type, trigger_args):
        if trigger_type == 'crontab' and 'crontab' in trigger_args:
            crontab = self.crontab_add_second(trigger_args['crontab'])
            trigger = 'cron'

            setting = {**trigger_args, **crontab}
            del setting['crontab']
        else:
            trigger = trigger_type
            setting = trigger_args

        job = self.scheduler.get_job(schedule_name)
        job.reschedule(trigger, **setting)
        self.templates[schedule_name]['trigger'] = dict(type=trigger_type,
                                                        setting=trigger_args)

    # =========================================================================
    @staticmethod
    def get_python_module(code, name):
        module = types.ModuleType(name)
        exec(code, module.__dict__)
        return module

    # =========================================================================
    @staticmethod
    def insert_number_each_line(data: str):
        result = list()
        data = data.split('\n')
        for (number, line) in enumerate(data):
            result.append(f'{number+1:04} {line}')
        return '\n'.join(result)

    # =========================================================================
    @staticmethod
    def filter_dict(dict_to_filter, thing_with_kwargs):
        sig = inspect.signature(thing_with_kwargs)
        filter_keys = [
            param.name for param in sig.parameters.values()
            if param.kind == param.POSITIONAL_OR_KEYWORD
        ]
        filtered_dict = {
            filter_key: dict_to_filter[filter_key]
            for filter_key in filter_keys
        }
        return filtered_dict

    # =========================================================================
    def _source(self, name, setting):
        source_type, code, arguments = operator.itemgetter(
            'type', 'code', 'arguments')(setting)
        module = DataCollector.get_python_module(code, name)
        try:
            _gv = self.__global_store[name]
            arguments = {**arguments, **_gv}
            filterd_arguments = DataCollector.filter_dict(
                arguments, module.main)
            data = module.main(**filterd_arguments)
        except Exception as e:
            code = DataCollector.insert_number_each_line(code)
            self.logger.error(f'{e}\ncode: \n{code}')
            raise
        return data

    # =========================================================================
    def request_data(self, schedule_name):
        schedule = self.templates[schedule_name]
        if schedule_name not in self.templates:
            msg = f'The template "{schedule_name}" ' \
                  f'is not in the main template store'
            self.logger.error(msg)
            raise KeyError(msg)

        # checking use flag
        if not schedule['use']:
            self.logger.info(f'{schedule_name} is disabled.')
            return

        # source
        data = self._source(schedule_name, schedule['source'])
        if data is None:
            message = f'[{schedule_name}] The user function returned None.'
            self.logger.warning(message)

        # works
        # calling function for each works with arguments via celery
        for work in schedule['works']:
            work_type, arguments = operator.itemgetter('type',
                                                       'arguments')(work)
            self.job_broker.send_task(work_type,
                                      args=(data, ),
                                      kwargs=arguments)

        # sending events to the event
        # PING
        # event emitting
        data = json.dumps(data)
        event = {
            'name': schedule_name,
            'event': {
                'type': 'data-collector',
                'schedule_name': schedule_name
            },
            'data': data
        }
        try:
            self.emit_event(schedule_name, event)
        except (urllib3.exceptions.MaxRetryError,
                requests.exceptions.ConnectionError) as e:
            self.logger.error(f'Connection Error: Failed to emit events.')
        except Exception as e:
            import traceback
            traceback.print_exc()
        return

    # =========================================================================
    def emit_event(self, name: str, event: dict):
        with requests.Session() as s:
            api = EVENT_COLLECTOR_URL + '/api/v1/events/emit'
            response = s.post(api, json=event)
            if response.status_code != 200:
                raise Exception(f'code: {response.status_code}\n'
                                f'messages: [{name}] - {response.reason}')
            data = json.loads(response.text)
            self.logger.info(f'[{name}] emitted a event.')

    # =========================================================================
    def remove_job_schedule(self, _id: str):
        self.scheduler.remove_job(_id)
        del self.data[_id]
        return

    # =========================================================================
    def modify_job_schedule(self, _id, seconds):
        self.scheduler.reschedule_job(_id, trigger='interval', seconds=seconds)

    # =========================================================================
    def get_schedule_jobs(self):
        jobs = self.scheduler.get_jobs()
        if not jobs:
            return jobs
        result = list()
        for job in jobs:
            schedule_name = job.id
            next_run_time = job.next_run_time
            template_data = self.templates[schedule_name]
            template_data['next_run_time'] = next_run_time
            result.append(template_data)
        return result
Exemple #28
0
class TradingService:
    __config = configparser.ConfigParser()
    __config.read(Paths.CONFIG)

    __commission = 0.0015

    def __init__(self):
        self.__currency = None
        self.__budget = 0
        self.__num_coin = 0.0
        self.__criteria = 0.0
        self.__agent = CoinAgent(self.__commission)
        self.__scheduler = BackgroundScheduler()

        self.__portfolio = None

    def start(self, currency, budget, criteria=-50.0, mins=60):
        self.__currency = currency
        self.__budget = budget
        self.__criteria = criteria

        self.__portfolio = {
            'principal': budget,
            'daily': budget,
            'time': time.localtime()
        }

        self.__scheduler.add_job(self.do_trading,
                                 'interval',
                                 minutes=mins,
                                 id='do_trading')
        self.__scheduler.start()

        SlackNotification.notify(
            'Coin Bot',
            'good',
            'Server started!',
            fields=[{
                'title': '지갑',
                'value': 'KRW {budget:,}\n'.format(budget=self.__budget),
                'short': True
            }])

        self.do_trading()

    def pause(self):
        self.__scheduler.pause()
        SlackNotification.notify('Coin Bot', 'good', 'Server paused!')

    def resume(self):
        self.__scheduler.resume()
        SlackNotification.notify('Coin Bot', 'good', 'Server resumed!')

    def stop(self):
        self.__scheduler.shutdown(False)
        SlackNotification.notify('Coin Bot', 'good', 'Server Stopped!')

    def result_notify(self, color, prediction, dist, latest_price, qty, msg,
                      portfolio, daily, total):
        SlackNotification.notify(
            title=self.__currency,
            color=color,
            msg='[{action}] {dist}\n'
            '가격 {price:,} 거래량 {qty:,.4f}\n'
            '*{msg}*'.format(action=prediction,
                             dist=dist,
                             price=latest_price,
                             qty=qty,
                             msg=msg),
            fields=[{
                'title':
                '지갑',
                'value':
                'KRW {budget:,}\n'
                'Coin {coin:,.4f}\n'
                '자산 {portfolio:,.4f}'.format(budget=self.__budget,
                                             coin=self.__num_coin,
                                             portfolio=portfolio),
                'short':
                True
            }, {
                'title':
                '수익률',
                'value':
                '일일 {daily:,.4f}% 기준 {daily_budget:,.4f}\n'
                '전체 {total:,.4f}% 기준 {total_budget:,.4f}'.format(
                    daily=daily,
                    total=total,
                    daily_budget=self.__portfolio['daily'],
                    total_budget=self.__portfolio['principal']),
                'short':
                True
            }],
        )

    def do_trading(self):
        prediction_debug = self.__config['debug'].getboolean('prediction')
        payment_debug = self.__config['debug'].getboolean('payment')
        logger.info('Debug: prediction %s, payment %s', prediction_debug,
                    payment_debug)

        trades = CoinTrader.get_trades(self.__currency)
        prediction, dist = self.__agent.predict(trades, debug=prediction_debug)
        ticker = CoinTrader.ticker(self.__currency)
        latest_price = int(ticker['last'])
        qty = 0.0
        color = 'good'
        msg = 'Success'
        if prediction == CoinAgent.Action.BUY:
            if self.__budget > 10:
                qty = self.__budget / latest_price
                status_code, error_code = CoinTrader.limit_buy(
                    latest_price, self.__currency, qty, debug=payment_debug)
                if status_code == 200 and error_code == 0:
                    self.__budget -= latest_price * qty
                    self.__num_coin += qty * (1.0 - self.__commission)
                else:
                    color = 'danger'
                    msg = 'error: status_code: {}, error_code: {}'.format(
                        status_code, error_code)
            else:
                color = 'warning'
                msg = 'Not enough budget'
        elif prediction == CoinAgent.Action.SELL:
            if self.__num_coin > 0.0001:
                qty = self.__num_coin
                status_code, error_code = CoinTrader.limit_sell(
                    latest_price, self.__currency, qty, debug=payment_debug)
                if status_code == 200 and error_code == 0:
                    self.__budget += latest_price * qty * (1.0 -
                                                           self.__commission)
                    self.__num_coin -= qty
                else:
                    color = 'danger'
                    msg = 'error: status_code: {}, error_code: {}'.format(
                        status_code, error_code)
            else:
                color = 'warning'
                msg = 'Not enough coins'

        portfolio = self.__budget + self.__num_coin * latest_price

        cur_time = time.localtime()
        if cur_time.tm_mday != self.__portfolio['time'].tm_mday:
            self.__portfolio['daily'] = portfolio
            self.__portfolio['time'] = cur_time

        daily = 100.0 * ((portfolio / self.__portfolio['daily']) - 1.0)
        total = 100.0 * ((portfolio / self.__portfolio['principal']) - 1.0)

        logger.debug(
            '[{}] {} {} portfolio {:,} latest price {:,}, qty {:,}'.format(
                self.__currency, prediction, dist, portfolio, latest_price,
                qty))

        self.result_notify(color=color,
                           prediction=prediction,
                           dist=dist,
                           latest_price=latest_price,
                           qty=qty,
                           msg=msg,
                           portfolio=portfolio,
                           daily=daily,
                           total=total)

        if total < self.__criteria:
            SlackNotification.notify(
                'Coin Bot', 'danger',
                '전체 수익률이 {}% 이하로 떨어져 강제 종료 합니다.'.format(self.__criteria))
            self.stop()
Exemple #29
0
class Timer_handler:
    
    ############################### constructor ###############################
    def __init__(self, state_handler, logger, path):
        self.boInit = True
        self._open_time = None
        self._close_time = None
        self._auto_open = None
        self._auto_close = None
        
        self.state_handler = state_handler
        self.scheduler = BackgroundScheduler()
        self.observers = []
        self.log = logger
        self.settings_file = path + "timer_data.pkl"
        #read most recent settings saved to file, if available
        try:
            #with open(os.environ['HOME'] + 
            #"/hendroid/client-raspi/timer_data.pkl", "rb") as input:
            with open(self.settings_file, "rb") as input:
                self.open_time = pickle.load(input)
                self.log.info("internal: read <open_time> from file: "
                      + str(self.open_time))
                self.close_time = pickle.load(input)
                self.log.info("internal: read <close_time> from file: "
                      + str(self.close_time))
                self.auto_open = pickle.load(input)
                self.log.info("internal: read <auto_open> from file: "
                      + str(self.auto_open))
                self.auto_close = pickle.load(input)
                self.log.info("internal: read <auto_close> from file: "
                      + str(self.auto_close))
                self.boInit = False
        except Exception as e:
            self.log.error("internal error: timer state read from file: ", 
                            exc_info=True)
            self.open_time = time(hour = 7, minute = 0)
            self.close_time = time(hour = 18, minute = 30)
            self.auto_open = False
            self.boInit = False
            self.auto_close = False
            self.log.info("internal: set timer to default settings")
        self.scheduler.start()
    
    
    ########################### property definition ###########################
    #Attrinutes are defined as properties as changing them requires some effort
    # (i.e. changing the Scheduler settings accordingly) rather than changing
    # them directly.
    @property
    def open_time(self):
        return self._open_time
    
    @property
    def close_time(self):
        return self._close_time
    
    @property
    def auto_open(self):
        return self._auto_open
    
    @property
    def auto_close(self):
        return self._auto_close
    
    @auto_open.setter
    def auto_open(self, value):
        if (isinstance(value, bool) 
            and value != None
            and (self.auto_open == None or value != self.auto_open)):
            self._auto_open = value
            if(self.scheduler.running):
                self.scheduler.pause()
            if(self.auto_open):
                self.scheduler.resume_job(job_id=self.open_job.id)
            else:
                self.scheduler.pause_job(job_id=self.open_job.id)
            self.log.info("internal: set <auto_open> to " + str(self.auto_open))
            if(self.scheduler.running):
                self.scheduler.resume()
            self.save_state()
            self.notify_observers("auto-open")
    
    @auto_close.setter
    def auto_close(self, value):
        if (isinstance(value, bool) 
            and value != None
            and (self.auto_close == None or value != self.auto_close)):
            self._auto_close = value
            if(self.scheduler.running):
                self.scheduler.pause()
            if(self.auto_close):
                self.scheduler.resume_job(job_id=self.close_job.id)
            else:
                self.scheduler.pause_job(job_id=self.close_job.id)
            self.log.info("internal: set <auto_close> to " + 
                            str(self.auto_close))
            if(self.scheduler.running):
                self.scheduler.resume()
            self.save_state()
            self.notify_observers("auto-close")
            
    @open_time.setter
    def open_time(self, value):
        if (isinstance(value, time) 
            and value != None
            and (self.open_time == None or value != self.open_time)):
            self._open_time = value
            if(self.scheduler.running):
                self.scheduler.pause()
            self.open_job = self.scheduler.add_job(self.exec_motion
                                                  ,trigger="cron"
                                                  ,args=["opening"]
                                                  ,id="jopen"
                                                  ,name="open_job"
                                                  ,max_instances=1
                                                  ,replace_existing=True
                                                  ,hour = self.open_time.hour
                                                  ,minute = self.open_time.minute
                                                  )
            self.log.info("internal: set <open_time> to " + str(self.open_time))
            if(self.scheduler.running):
                self.scheduler.resume()
            self.save_state()
            self.notify_observers("time-open")
            
    @close_time.setter
    def close_time(self, value):
        if (isinstance(value, time) 
            and value != None
            and (self.close_time == None or value != self.close_time)):
            self._close_time = value
            if(self.scheduler.running):
                self.scheduler.pause()
            self.close_job = self.scheduler.add_job(self.exec_motion
                                                    ,trigger="cron"
                                                    ,args=["closing"]
                                                    ,id="jclose"
                                                    ,name="close_job"
                                                    ,max_instances=1
                                                    ,replace_existing=True
                                                    ,hour = self.close_time.hour
                                                    ,minute = self.close_time.minute
                                                    )
            self.log.info("internal: set <close_time> to " + 
                            str(self.close_time))
            if(self.scheduler.running):
                self.scheduler.resume()
            self.save_state()
            self.notify_observers("time-close")
    
    
    ############################## other methods ##############################
    def register_observer(self, callback):
        self.log.info("internal: registering timer observer")
        self.observers.append(callback)
        self.update_observer(callback)
        
    #Update all observers of the object, i.e. notify them about values
    # of all properties of the object.
    def update_all_observers(self):
        [ self.update_observer(callback) for callback in self.observers ]
        
    #Update observer defined by callback parameter, i.e. notify it about values
    # of all properties of the object.
    def update_observer(self, callback):       
        self.notify_observers("auto-open", [callback])
        self.notify_observers("auto-close", [callback])
        self.notify_observers("time-open", [callback])
        self.notify_observers("time-close", [callback])
        
    # notify given observers about changes encoded in update parameter
    # update parameter must have the form: "<cat>-<subcat>" with
    # cat in {"auto", "time"} and subcat in {"open", "close"}.
    # If observers parameter is omittet, then all registered observers of the
    # object are notified.
    def notify_observers(self, update, observers=None):
        if(self.boInit == False):
            update_vals = {"time-open":   [self.open_time.hour
                                          ,self.open_time.minute]
                           ,"time-close": [self.close_time.hour
                                          ,self.close_time.minute]
                           ,"auto-close": [self.auto_close]
                           ,"auto-open":  [self.auto_open]
                           }
            val_str = ""
            for val in update_vals[update]:
                val_str = val_str + ":" + str(val) 
            update = update + "-" + val_str[1:]
            if(observers == None):
                observers = self.observers
            self.log.info("internal: Calling " + str(len(observers)) + 
                            " timer observers")
            [ callback(update) for callback in observers ]
        
    def exec_motion(self, arg):
        self.log.info("internal: scheduled event - " + arg)
        self.state_handler.handle_event(arg)
    
    def save_state(self):
        if(self.boInit == False):
            try:
                #with open(os.environ['HOME'] + "/hendroid/client-raspi/"
                 #         + "timer_data.pkl", "wb") as output:
                with open(self.settings_file, "wb") as output:
                    pickle.dump(self.open_time, output)
                    pickle.dump(self.close_time, output)
                    pickle.dump(self.auto_open, output)
                    pickle.dump(self.auto_close, output)
                    self.log.info("internal: successfully saved timer setting" +
                                    " to file")
            except Exception as e:
                self.log.error("internal error: write timer setting to file: ",
                                exec_info=True)
    
    def __del__(self):
        self.scheduler.shutdown()
Exemple #30
0
class Manager:

    timezone = pytz.timezone('America/New_York')

    def __init__(self, data):
        self.data = data
        self.algos = []
        self.broker = None
        self.logger = Logger()
        self.datetime = None
        self.scheduler = BackgroundScheduler()
        self.scheduler.configure(timezone=Manager.timezone)
        self.jobs = {}

    def init_broker(self, backtest=False, **kwargs):
        if backtest:
            self.broker = BacktestBroker(**kwargs)
        else:
            self.broker = AlpacaBroker(**kwargs)
        for algo in self.algos:
            algo.set_broker(self.broker)

    def add_algo(self, algo, live=False):
        if algo.data is None:
            algo.set_data_source(self.data)
        if algo.broker is None:
            algo.set_broker(self.broker)
        self.algos.append(algo)
        if live:
            trigger = convert_trigger_timezone(algo.trigger, Manager.timezone)
            job = self.scheduler.add_job(self.run_algo_live,
                                         trigger,
                                         kwargs={'algo': algo})
            self.jobs[algo] = job

    def stop_algo(self, algo):
        job = self.jobs[algo]
        job.remove()

    def remove_algo(self, algo):
        self.stop_algo(algo)
        del self.algos[algo]

    def log_state(self):
        value = self.broker.get_value(self.datetime)['value']
        benchmark_value = self.data.quote("SPY", self.datetime)
        self.logger.append(value, self.datetime)
        self.logger.append(benchmark_value, self.datetime, benchmark=True)

    def run_algo_live(self, algo):
        self.datetime = datetime.datetime.now().astimezone(Manager.timezone)
        # print("{time}: Running {algo}".format(time=self.datetime, algo=algo.__class__.__name__))
        algo.run_wrapper(time=self.datetime, update=True)

    def backtest(self,
                 start=datetime.datetime(2021, 3, 1),
                 end=datetime.datetime.now(),
                 log_schedule=[{
                     "minute": "30",
                     "hour": "9",
                     "day_of_week": "mon-fri"
                 }]):
        self.init_broker(backtest=True, data=self.data)
        log_trigger = build_trigger(log_schedule)
        algo_trigger = OrTrigger([algo.trigger for algo in self.algos])
        trigger = OrTrigger([algo_trigger, log_trigger])
        logging = isinstance(log_schedule, dict) or len(log_schedule) > 0
        if isinstance(start, int) and not isinstance(end, int):
            start = trading_day_offset(end, -start)
        if not isinstance(start, int) and isinstance(end, int):
            end = trading_day_offset(start, end)
        self.datetime = start
        while self.datetime < end:
            for algo in self.algos:
                if equals_runtime(algo.trigger, self.datetime):
                    print(self.datetime)
                    time = Manager.timezone.localize(self.datetime)
                    self.broker.check_limit_orders(time=time)
                    algo.run_wrapper(time=time, update=False)
            if logging and equals_runtime(log_trigger, self.datetime):
                self.log_state()
            self.datetime = next_runtime(trigger, self.datetime)
        metrics = self.logger.metrics()
        for metric, value in metrics.items():
            print("{metric}: {value:.3f}".format(metric=metric, value=value))
        self.logger.report()
        return metrics

    def run(self,
            paper=False,
            log_schedule=[{
                "minute": "30",
                "hour": "9",
                "day_of_week": "mon-fri"
            }]):
        self.init_broker(backtest=False, paper=paper)
        self.datetime = datetime.datetime.now().astimezone(Manager.timezone)
        for algo in self.algos:
            trigger = convert_trigger_timezone(algo.trigger, Manager.timezone)
            job = self.scheduler.add_job(self.run_algo_live,
                                         trigger,
                                         kwargs={'algo': algo})
            self.jobs[algo] = job
        log_trigger = convert_trigger_timezone(build_trigger(log_schedule),
                                               Manager.timezone)
        job = self.scheduler.add_job(self.log_state, log_trigger)
        self.jobs['logger'] = job
        self.start()
        self.interact()

    def start(self):
        self.scheduler.start()

    def stop(self):
        for algo in self.jobs.keys():
            self.stop_algo(algo)
        self.scheduler.shutdown(wait=True)

    def pause(self):
        self.scheduler.pause()

    def resume(self):
        self.scheduler.resume()

    def interact(self):
        code.interact(local=locals())
def main():
    global subs
    global player
    global bridge
    global SRT_FILENAME, AUDIO_FILENAME, MAX_BRIGHTNESS, TICK_TIME, HUE_IP_ADDRESS
    parser = argparse.ArgumentParser(description="LushRoom sound and light command-line player")
    # group = parser.add_mutually_exclusive_group()
    # group.add_argument("-v", "--verbose", action="store_true")
    # group.add_argument("-q", "--quiet", action="store_true")
    parser.add_argument("-s","--srt", default=SRT_FILENAME, help=".srt file name for lighting events")
    parser.add_argument("-a","--audio", default=AUDIO_FILENAME, help="audio file for sound stream")
    parser.add_argument("-b","--brightness", default=MAX_BRIGHTNESS, help="maximum brightness")
    parser.add_argument("-t","--time", default=TICK_TIME, help="time between events")
    parser.add_argument("--hue", default=HUE_IP_ADDRESS, help="Philips Hue bridge IP address")

    args = parser.parse_args()

    print(args)

    if PLAY_AUDIO:
        player = vlc.MediaPlayer(AUDIO_FILENAME)
        event_manager = player.event_manager()
        event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, end_callback)

    if PLAY_HUE:
        # b = Bridge('lushroom-hue.local')
        bridge = Bridge(HUE_IP_ADDRESS, config_file_path="/media/usb/python_hue")
        # If the app is not registered and the button is not pressed, press the button and call connect() (this only needs to be run a single time)
        bridge.connect()
        # Get the bridge state (This returns the full dictionary that you can explore)
        bridge.get_api()
        lights = bridge.lights
        # Print light names
        for l in lights:
            print(l.name)
            #print(dir(l))
        # Set brightness of each light to 10
        for l in lights:
            l.brightness = 1

        # Get a dictionary with the light name as the key
        light_names = bridge.get_light_objects('name')
        print("Light names:", light_names)

    subs = srtopen(SRT_FILENAME)

    print("Number of lighting events",len(subs))

    scheduler = BackgroundScheduler()
    scheduler.add_job(tick, 'interval', seconds=TICK_TIME)
    # scheduler.start(paused=True)
    if PLAY_AUDIO:
        player.play()
    scheduler.start(paused=False)

    try:
        # This is here to simulate application activity (which keeps the main thread alive).
        while True:
            sleep(0.01)
            try:
                if keyboard.is_pressed('p'): # pause
                    scheduler.pause()
                    player.pause()
                elif keyboard.is_pressed('r'): # resume
                    scheduler.resume()
                    player.play()
                # elif keyboard.is_pressed('s'): # stop
                #     scheduler.shutdown()
                #     player.stop()
                #     exit(0)
            except:
                pass
    except (KeyboardInterrupt, SystemExit):
        # Not strictly necessary if daemonic mode is enabled but should be done if possible
        scheduler.shutdown()
        player.stop()
Exemple #32
0
print(sched)
if sched == None:

    print('Starting Proces ...')
    sched = BackgroundScheduler(daemon=True)
    sched.add_job(sensor,
                  'interval',
                  seconds=int(get_current_interval()),
                  id='my_job_id')
    sched.start()
    sched.pause()
    #sched.resume()
    #MONITOR_BUTTON = 'Start'

    if get_monitor_status() == 'stop':
        sched.resume()

else:
    print('Process already created ...')


@app.route("/on_off")
def on_off():

    global MONITOR_BUTTON

    if get_monitor_status() == 'start':
        start()
        update_monitor_status('stop')
    else:
        stop()
Exemple #33
0
class Controller(object):
    def __init__(self, name="defaultController"):
        self.name = name
        self.workflows = {}
        self.instances = {}
        self.tree = None
        self.eventlog = []
        self.schedulerStatusListener = SchedulerStatusListener(self.eventlog)
        self.jobStatusListener = JobStatusListener(self.eventlog)
        self.jobExecutionListener = JobExecutionListener(self.eventlog)
        self.scheduler = BackgroundScheduler()
        self.scheduler.add_listener(
            self.schedulerStatusListener.callback(self),
            EVENT_SCHEDULER_START | EVENT_SCHEDULER_SHUTDOWN
            | EVENT_SCHEDULER_PAUSED | EVENT_SCHEDULER_RESUMED)
        self.scheduler.add_listener(self.jobStatusListener.callback(self),
                                    EVENT_JOB_ADDED | EVENT_JOB_REMOVED)
        self.scheduler.add_listener(self.jobExecutionListener.callback(self),
                                    EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
        self.ancestry = [self.name]

    def loadWorkflowsFromFile(self, path):
        self.tree = et.ElementTree(file=path)
        for workflow in self.tree.iter(tag="workflow"):
            name = workflow.get("name")
            self.workflows[name] = wf.Workflow(name=name,
                                               workflowConfig=workflow,
                                               parent_name=self.name)
        self.addChildWorkflows()
        self.addWorkflowScheduledJobs()

    def addChildWorkflows(self):
        for workflow in self.workflows:
            children = self.workflows[workflow].options.children
            for child in children:
                if child in self.workflows:
                    children[child] = self.workflows[child]

    def addWorkflowScheduledJobs(self):
        for workflow in self.workflows:
            if (self.workflows[workflow].options.enabled
                    and self.workflows[workflow].options.scheduler["autorun"]
                    == "true"):
                schedule_type = self.workflows[workflow].options.scheduler[
                    "type"]
                schedule = self.workflows[workflow].options.scheduler["args"]
                self.scheduler.add_job(self.workflows[workflow].execute,
                                       trigger=schedule_type,
                                       replace_existing=True,
                                       **schedule)

    def createWorkflowFromTemplate(self, name="emptyWorkflow"):
        self.loadWorkflowsFromFile(path=config.templatesPath + sep + name +
                                   ".workflow")

    def removeWorkflow(self, name=""):
        if name in self.workflows:
            del self.workflows[name]
            return True
        return False

    def updateWorkflowName(self, oldName="", newName=""):
        self.workflows[newName] = self.workflows.pop(oldName)
        self.workflows[newName].name = newName

    def executeWorkflow(self, name, start="start", data=None):
        steps, instances = self.workflows[name].execute(start=start, data=data)
        self.jobExecutionListener.execute_event_code(self, 'JobExecuted')
        return steps, instances

    # Starts active execution
    def start(self):
        self.scheduler.start()

    # Stops active execution
    def stop(self, wait=True):
        self.scheduler.shutdown(wait=wait)

    # Pauses active execution
    def pause(self):
        self.scheduler.pause()

    # Resumes active execution
    def resume(self):
        self.scheduler.resume()

    # Pauses active execution of specific job
    def pauseJob(self, job_id):
        self.scheduler.pause_job(job_id=job_id)

    # Resumes active execution of specific job
    def resumeJob(self, job_id):
        self.scheduler.resume_job(job_id=job_id)

    # Returns jobs scheduled for active execution
    def getScheduledJobs(self):
        self.scheduler.get_jobs()