def program_next_poll(self, interval, method, args, kwargs): t = Timer(interval=interval, function=self.poller, kwargs={'interval': interval, 'method': method, 'args': args, 'kwargs': kwargs}) self.current_timers.append(t) # save the timer to be able to kill it t.setName('Poller thread for %s' % type(method.__self__).__name__) t.setDaemon(True) # so it is not locking on exit t.start()
class SensorDataLogger(object): def __init__(self, sensors=[], interval=0.1, maxSamples=20000, name='Data logger'): self.sensors = sensors self.interval = interval # period between samples in seconds self.name = name self.results = [] self.maxSamples=maxSamples # self.basetime =time.time() self.is_running = False def getsample(self): # now = time.time() # Maybe have a FIFO queue to drop early samples and retain more recent ones? # Or something more intelligent? eg drop every othersample? (so resample, essentially?) if len(self.results) <= self.maxSamples: result=[datetime.now()] for s in self.sensors: result.append(s.value()) self.results.append(result) def _run(self): self.is_running = False self.start() self.getsample() def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.setName(self.name) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False #killThreads(self.name) # return self.results def log(self): return self.results
def scheduleOneTask(self, task, immediate=False): if immediate: waitTime = 0 else: waitTime = self.tactic(task) + 1 t = time.gmtime() curtime = datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=timezone.GMT()) dt = curtime + datetime.timedelta(seconds=waitTime) dateFormat = dt.astimezone(timezone.getTimeZone(globalProperty.getTimeZone())).strftime( "%Y-%m-%d %H:%M:%S %A (%Z)" ) # content = globalProperty.getRestSchTkMgrInstance().getContentOfJob(task['fileName']) self._dbutil.addNewScheduleJob(task, self.type, dateFormat) self.logger.info("Task %s will be kicked off on %s" % (str(task["fileName"]), dateFormat)) fileName = task["fileName"] funcArgs = [str(fileName)] funcKwargs = task t = Timer(waitTime, self.popUpTaskHandle, funcArgs, funcKwargs) timerName = "timer_%s" % fileName t.setName(timerName) t.start() # Record timer self.__timerDic[fileName] = t
def prepare_courier_timer(self, oid, courier_arrival_delay, arrival_time_approx, orig_order_event): if cfg['concurrency'] == 'temporal': timer = Timer(courier_arrival_delay, courier_arrives, (arrival_time_approx,self.q,orig_order_event)) timer.setName('CT') # technically there will be 1+ distinct threads, each with name CT, but keeps log simpler return timer else: # priority return 'courier_timer|%s' % oid
class Periodic_Timer_Thread(object): def __init__(self, interval, function, comment='', *args, **kwargs): self._timer = None self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.comment = comment self.is_running = False self.start() def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs) def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.setName(self.comment) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False
class MaxAgeDownload(object): def __init__(self, url, name): logging.getLogger(name).setLevel(LogLevel) self._timer = None self.url = url self.is_running = False self.name = name self.maxage = 1 self._timer = Timer(self.maxage, self._run) self._timer.setName(self.name) def _run(self): self.is_running = False rep = requests.get(self.url, stream=True) logging.getLogger(self.name).info("Downloading new Image.") self.maxage = int( rep.headers["Cache-Control"].split("max-age=")[1].split( ",")[0]) #Get the max-age using some hacky split strings self.start() img = open(self.name + "/" + str(int(time.time())) + ".jpg", "wb+") img.write(rep.raw.read()) img.close() def start(self): if not self.is_running: self._timer = Timer(self.maxage, self._run) self._timer.setName(self.name) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False
class ETagDownload(object): def __init__(self, url, name): logging.getLogger(name).setLevel(LogLevel) self._timer = None self.url = url self.is_running = False self.name = name self.ETag = "" self._timer = Timer(1, self._run) self._timer.setName(self.name) def _run(self): self.is_running = False rep = requests.get(self.url, stream=True, headers={"If-None-Match": self.ETag}) if rep.status_code == 200: logging.getLogger(self.name).info("Downloading new Image.") self.ETag = rep.headers["ETag"] img = open(self.name + "/" + str(int(time.time())) + ".jpg", "wb+") img.write(rep.raw.read()) img.close() self.start() def start(self): if not self.is_running: self.is_running = True self._timer = Timer(60, self._run) self._timer.setName(self.name) self._timer.start() def stop(self): self._timer.cancel() self.is_running = False
class TimeHandler: def __init__(self, name, interval, get_msg=None): self.name = name self.interval = interval self.get_msg = get_msg def run(self): try: msg = self.get_msg() if self.get_msg else None self.handle(msg) except Exception as e: logger.exception(f'<TimeHandler>-{self.name} exception:{e}') def stop(self): self.timer.cancel() self.timer.join() def start(self): self.timer = Timer(self.interval, self.run) self.timer.setName(self.name) self.timer.setDaemon(True) self.timer.start() @abstractmethod def handle(self, topic, msg): ...
def program_next_poll( self, interval: float, method: Callable[..., None], times: int = None, args: Tuple = None, kwargs: Mapping = None, ): if times is not None and times <= 0: return t = Timer( interval=interval, function=self.poller, kwargs={ "interval": interval, "method": method, "times": times, "args": args, "kwargs": kwargs, }, ) self.current_timers.append(t) # save the timer to be able to kill it t.setName(f"Poller thread for {type(method.__self__).__name__}") t.setDaemon(True) # so it is not locking on exit t.start()
def start_timeout(timer_name, seconds, callback): global global_timers disable_timeout(timer_name) timer = Timer(seconds, callback) timer.daemon = True timer.setName(timer_name) timer.start() global_timers[timer_name] = timer
def start_timer(name, interval, func, first_start=False): def _wrapper(): func() start_timer(name, interval, func) timer = Timer(interval / 100.0 if first_start else interval, _wrapper) timer.setName(name) timer.start()
def run(self): Sync.version() Sync.getaddr() Sync.getblocks() Sync.mempool() pingBroadcast = Timer(Config.getIntValue("PING_BROADCAST_SECONDS"), Sync.ping) pingBroadcast.setName('PING_BROADCAST') pingBroadcast.start()
def start_timeout(self, timer_name, seconds, callback): disable_timeout(timer_name) if callback is None: callback = timer_name timer = Timer(seconds, callback) timer.daemon = True timer.setName(timer_name) timer.start() self.timers[timer_name] = timer
def program_next_poll(self, interval, method, args, kwargs): t = Timer( interval=interval, function=self.poller, kwargs={"interval": interval, "method": method, "args": args, "kwargs": kwargs}, ) self.current_timers.append(t) # save the timer to be able to kill it t.setName("Poller thread for %s" % type(method.__self__).__name__) t.setDaemon(True) # so it is not locking on exit t.start()
def schedule(): """ Post endpoint that allows the user to set a schedule of when to start/stop the device """ global start_thread, stop_thread if request.method == 'POST': start_time = datetime.strptime(request.form['datetimepicker_start'], "%I:%M %p") end_time = datetime.strptime(request.form['datetimepicker_end'], "%I:%M %p") target_slider = float(request.form['temperatureSlider']) if start_time.time() >= datetime.now().time(): start_normalized = datetime.combine(date.today(), start_time.time()) if start_time >= end_time: end_normalized = datetime.combine( date.today() + timedelta(days=1), end_time.time()) else: end_normalized = datetime.combine(date.today(), end_time.time()) else: start_normalized = datetime.combine( date.today() + timedelta(days=1), start_time.time()) if start_time >= end_time: end_normalized = datetime.combine( date.today() + timedelta(days=2), end_time.time()) else: end_normalized = datetime.combine( date.today() + timedelta(days=1), end_time.time()) deviceInfo['cookStart'] = start_normalized.strftime("%b %d %I:%M %p") deviceInfo['cookEnd'] = end_normalized.strftime("%b %d %I:%M %p") start_stamp = time.mktime(start_normalized.timetuple()) end_stamp = time.mktime(end_normalized.timetuple()) now_stamp = time.mktime(datetime.now().timetuple()) deviceInfo['cookStartStamp'] = start_stamp deviceInfo['cookEndStamp'] = end_stamp start_delay = start_stamp - now_stamp end_delay = end_stamp - now_stamp device.set_target_temp(target_slider) start_thread = Timer(start_delay, thread_start_device) start_thread.setName('startDevice') start_thread.start() deviceInfo['cookScheduled'] = True stop_thread = Timer(end_delay, thread_stop_device) stop_thread.setName('stopDevice') stop_thread.start() return redirect(url_for("status"))
def _pushnext(res: None, tags: Any, *, frame: Optional[int]): _wait = self.wait if self.wait else 0.0 if Cmd.InitVideo.firstFrame: _wait = 0.0 Cmd.InitVideo.firstFrame = False last_timer = Timer(_wait, _display) last_timer.setName(f"PushNextFrame[{_wait}]") last_timer.start() if frame: self.ondisplay(frame)
def setTimer(self, syncer): self.__lock.acquire() self.idle = False syncerName = syncer.getName() timerName = "%s_timer" % syncerName funcArgs = [syncerName] funcKwargs = {} timer = Timer(self.timeout, self.__timesUp, funcArgs, funcKwargs) timer.setName(timerName) self.timerDic[timerName] = timer self.syncerDic[syncerName] = syncer timer.start() self.__lock.release()
def notify(self, subject, changeType, obj_id, *args): """ Notify all interested observers about an event with threads from the pool """ tasks = [] assert subject in self.SUBJECTS, 'Subject %s not in SUBJECTS' % subject args = [subject, changeType, obj_id] + list(args) self.observerLock.acquire() for ofunc, osubject, ochangeTypes, oid, cache in self.observers: try: if (subject == osubject and changeType in ochangeTypes and (oid is None or oid == obj_id)): if not cache: tasks.append(ofunc) else: if ofunc not in self.observerscache: def doQueue(ofunc): self.observerLock.acquire() if ofunc in self.observerscache: events = self.observerscache[ofunc] del self.observerscache[ofunc] else: events = [] self.observerLock.release() if events: if self.pool: self.pool.queueTask(ofunc, (events, )) else: ofunc(events) self.observerscache[ofunc] = [] t = Timer(cache, doQueue, (ofunc, )) t.setName("Notifier-timer") t.start() self.observerscache[ofunc].append(args) except: print_exc() print >> sys.stderr, "notify: OIDs were", ` oid `, ` obj_id ` self.observerLock.release() for task in tasks: if self.pool: self.pool.queueTask(task, args) else: task(*args) # call observer function in this thread
def notify(self, subject, changeType, obj_id, *args): """ Notify all interested observers about an event with threads from the pool """ tasks = [] assert subject in self.SUBJECTS, 'Subject %s not in SUBJECTS' % subject args = [subject, changeType, obj_id] + list(args) self.observerLock.acquire() for ofunc, osubject, ochangeTypes, oid, cache in self.observers: try: if (subject == osubject and changeType in ochangeTypes and (oid is None or oid == obj_id)): if not cache: tasks.append(ofunc) else: if ofunc not in self.observerscache: def doQueue(ofunc): self.observerLock.acquire() if ofunc in self.observerscache: events = self.observerscache[ofunc] del self.observerscache[ofunc] else: events = [] self.observerLock.release() if events: if self.pool: self.pool.queueTask(ofunc, (events,)) else: ofunc(events) self.observerscache[ofunc] = [] t = Timer(cache, doQueue, (ofunc,)) t.setName("Notifier-timer") t.start() self.observerscache[ofunc].append(args) except: print_exc() print >> sys.stderr, "notify: OIDs were", repr(oid), repr(obj_id) self.observerLock.release() for task in tasks: if self.pool: self.pool.queueTask(task, args) else: task(*args) # call observer function in this thread
def program_next_poll(self, interval: float, method: Callable[..., None], times: int = None, args: Tuple = None, kwargs: Mapping = None): if times is not None and times <= 0: return t = Timer(interval=interval, function=self.poller, kwargs={'interval': interval, 'method': method, 'times': times, 'args': args, 'kwargs': kwargs}) self.current_timers.append(t) # save the timer to be able to kill it t.setName(f'Poller thread for {type(method.__self__).__name__}') t.setDaemon(True) # so it is not locking on exit t.start()
def program_next_poll(self, interval: float, method: Callable[..., None], times: int=None, args: Tuple=None, kwargs: Mapping=None): if times is not None and times <= 0: return t = Timer(interval=interval, function=self.poller, kwargs={'interval': interval, 'method': method, 'times': times, 'args': args, 'kwargs': kwargs}) self.current_timers.append(t) # save the timer to be able to kill it t.setName('Poller thread for %s' % type(method.__self__).__name__) t.setDaemon(True) # so it is not locking on exit t.start()
def create_delta_thread(secs, filename, dToRun, dNow, hour, minutes, thread_name): t = Timer(secs, delta_utils.perform_database_update, args=(filename, )) t.start() if thread_name == None: thread_name = uuid.uuid4() t.setName(thread_name) tname = t.getName() print("Thread name of scheduled thread is " + str(tname)) if dToRun is None: dToRun = dNow file = open(constants.FILE_LOCATION_PATH + constants.THREADS_TO_RUN, 'w') file.write(tname + ":" + filename + ":" + str(dToRun) + ":" + str(hour) + ":" + str(minutes)) file.close() return tname
class FixedTimer(): def __init__(self, t, hFunction, name="timer-thread"): self.t = t self.hFunction = hFunction self.thread = Timer(self.t, self.handle_function) self.thread.setName(name) self.thread.setDaemon(True) def handle_function(self): self.hFunction() self.thread = Timer(self.t, self.handle_function) self.thread.start() def start(self): self.thread.start() def cancel(self): self.thread.cancel()
def timerThreads2(): t1 = Timer(interval=5, function=timerThreadFunc) t1.setName('t1') t2 = Timer(interval=5, function=timerThreadFunc) t2.setName('t2') logging.debug('starting timers...') t1.start() t2.start() logging.debug('waiting before canceling %s', t2.getName()) time.sleep(2) logging.debug('canceling %s', t2.getName()) print('before cancel t2.is_alive() = ', t2.is_alive()) t2.cancel() time.sleep(2) print('after cancel t2.is_alive() = ', t2.is_alive()) t1.join() t2.join() logging.debug('done')
class RepeatingDownload(object): def __init__(self, interval,url,saveLoc,start): logging.getLogger(saveLoc).setLevel(LogLevel) self._timer = None self.interval = interval self.function = downloadImage self.url = url self.saveLoc = saveLoc self.is_running = False self._timer = Timer(self.interval, self._run) self._timer.setName(self.saveLoc) self.restart(start) def _run(self): self.is_running = False self.start() self.function(self.url,self.saveLoc) logging.getLogger(self.saveLoc).info("Downloading new Image.") def start(self): logging.getLogger(self.saveLoc).debug("Start called!") if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.setName(self.saveLoc) self._timer.start() self.is_running = True def restart(self,start): self._starttimer = Timer((start-datetime.datetime.now()).seconds, self.start) self._starttimer.setName(self.saveLoc) self._starttimer.start() def stop(self): self._starttimer.cancel() self._timer.cancel() self.is_running = False
def NamedTimer(*args,**kwargs): t = Timer(*args,**kwargs) t.setDaemon(True) t.setName("NamedTimer"+t.getName()) return t
from threading import Timer import logging import time def thread_work(): logging.debug("Поехали!") if __name__ == "__main__": logging.basicConfig( level=logging.DEBUG, format='(%(threadName)-10s) %(message)s', ) my_timer1 = Timer(0.3, thread_work) my_timer1.setName("MyTreadTimer-1") my_timer2 = Timer(0.3, thread_work) my_timer2.setName("MyTreadTimer-2") logging.debug("Запуск таймеров!") my_timer1.start() my_timer2.start() logging.debug(f"Задержка перед отменой выполнения {my_timer2.getName()}") time.sleep(0.2) logging.debug(f"Отмена потока - {my_timer2.getName()}") my_timer2.cancel() logging.debug("Завершение")
#!/usr/bin/env python3 # timerthreads.py - timer threads from threading import Timer from time import sleep from logging import basicConfig, debug, DEBUG basicConfig(level=DEBUG, format="(%(threadName)s) %(message)s",) def myThread(): debug("myThread running") thread1 = Timer(3, myThread) thread1.setName("Thread1") thread2 = Timer(3, myThread) thread2.setName("Thread2") debug("starting timers") thread1.start() thread2.start() debug("waiting before canceling %s", thread2.getName()) sleep(2) debug("canceling %s", thread2.getName()) thread2.cancel() print("Main thread is done") ################################################## # # $ timerthreads.py # (MainThread) starting timers
def NamedTimer(*args, **kwargs): t = Timer(*args, **kwargs) t.setDaemon(True) t.setName('NamedTimer' + t.getName()) return t
class MainWindow(QObject): """ 控制系统的主窗口 """ def __init__(self): """ 初始化界面 """ # # 成员变量 # super().__init__() self.isPolling = False # 是否在轮询中 self.helper = Helper() # 控制器 self.polling_timer = None # 轮询定时器,设成成员变量是为了能够取消定时器 self.play_sound = True # 默认允许播放蜂鸣声 # # 初始化界面 # self.ui = QUiLoader().load('./QtDesigner/main_window.ui' ) # 加载 UI 文件,self.ui 就是应用中 MainWindow 这个对象 self.init_window() # 初始化主窗口 self.init_interval_combobox() # 初始化轮询时间下拉框 self.init_splitter() # 初始化分离器 self.init_table() # 初始化表格 self.init_output_edit() # 初始化输出信息的窗口 self.init_menu_bar() # 初始化菜单 self.ui.btn_submit.clicked.connect(self.start_polling) # 绑定点击事件 def init_window(self): """ 初始化主窗口 :return: 无 """ self.ui.setWindowTitle("光伏集群现场监控") # 窗口标题 # # 左上角图标,任务栏图标 # app_icon = QIcon("./other/logo.ico") self.ui.setWindowIcon(app_icon) # # 读取配置文件 # baudrate, address = self.helper.read_config() if baudrate != "" and address != "": self.ui.edit_baudrate.setText(baudrate) self.ui.edit_addr.setText(address) def init_menu_bar(self): """ 初始化菜单栏 :return: 无 """ self.ui.restart.triggered.connect( partial(self.one_key, self.ui.restart.text())) self.ui.lock.triggered.connect( partial(self.one_key, self.ui.lock.text())) self.ui.unlock1.triggered.connect( partial(self.one_key, self.ui.unlock1.text())) self.ui.wind_bread.triggered.connect( partial(self.one_key, self.ui.wind_bread.text())) self.ui.planish.triggered.connect( partial(self.one_key, self.ui.planish.text())) self.ui.snow_removal.triggered.connect( partial(self.one_key, self.ui.snow_removal.text())) self.ui.clean_board.triggered.connect( partial(self.one_key, self.ui.clean_board.text())) self.ui.sub_angle.triggered.connect( partial(self.one_key, self.ui.sub_angle.text())) self.ui.add_angle.triggered.connect( partial(self.one_key, self.ui.add_angle.text())) self.ui.advance.triggered.connect(self.show_advance_dialog) # # 日志 # self.ui.wind_log.triggered.connect(partial(self.show_window, "wind")) self.ui.error_log.triggered.connect(partial(self.show_window, "error")) # # 帮助 # self.ui.about.triggered.connect(self.show_about) self.ui.open_book.triggered.connect(partial(self.show_window, "book")) # # 蜂鸣报警声 # self.ui.close_beep.triggered.connect(self.set_play_sound) def init_interval_combobox(self): """ 初始化轮询时间下拉列表框 :return: 无 """ interval_list = ['5 s', '10 s', '15 s', '30 s', '60 s'] self.ui.combobox_interval.addItems(interval_list) def init_splitter(self): """ 初始化分离器控件 :return: 无 """ self.main_splitter = QSplitter(Qt.Vertical) # 新建一个分离器,垂直分离 # # 分离器添加控件 # self.main_splitter.addWidget(self.ui.tableView) self.main_splitter.addWidget(self.ui.output_edit) # # 设置窗口比例 # self.main_splitter.setStretchFactor(0, 8) self.main_splitter.setStretchFactor(1, 2) self.ui.data_layout.addWidget( self.main_splitter) # 把这个 splitter 放在一个布局里才能显示出来 def init_output_edit(self): """ 初始化输出框 :return: 无 """ self.ui.output_edit.setReadOnly(True) # 禁止编辑 # # 添加右键菜单 # self.ui.output_edit.setContextMenuPolicy( Qt.ActionsContextMenu) # 允许右键菜单 send_option = QAction(self.ui.output_edit) # 具体菜单项 send_option.setText("清除内容") send_option.triggered.connect( self.ui.output_edit.clear) # 点击菜单中的具体选项执行的函数 self.ui.output_edit.addAction(send_option) def init_table(self): """ 初始化表格样式 :return:无 """ self.ui.tableView.verticalHeader().setVisible(False) # 隐藏垂直表头 self.ui.tableView.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) # 设置每列宽度:根据表头调整表格宽度 self.ui.tableView.resizeColumnsToContents() # 根据内容调整列宽 self.ui.tableView.clicked.connect(self.handle_table_click) # 鼠标左键点击事件 def show_window(self, name: str): """ 显示 Windows 资源管理器 :param url: 路径 :return: 无 """ path = None if name == "wind": path = os.getcwd() + r"\log\wind_speed" elif name == "error": path = os.getcwd() + r"\log\error_log" elif name == "book": path = os.getcwd() + r"\other\光伏集群现场监控使用说明书.pdf" if os.path.exists(path): os.system("explorer.exe %s" % path) else: dail = InfoDialog("提示", "目前还没有日志!") dail.exec_() def show_about(self): """ 显示关于信息 :return: 无 """ dial = InfoDialog("关于", "四川近日点新能源科技有限公司\n联系电话:15108303256") dial.exec_() # 进入事件循环,不关闭不会退出循环 def set_play_sound(self): """ 设置蜂鸣声 :return: """ if self.play_sound is False: self.play_sound = True self.append_info("已打开蜂鸣报警声") self.ui.close_beep.setText("关闭蜂鸣报警声") else: self.play_sound = False self.append_info("已关闭蜂鸣报警声") self.ui.close_beep.setText("打开蜂鸣报警声") def get_serial_info(self): com_port = self.ui.box_com_port.currentText() # 端口号 collector_addr = self.ui.edit_addr.text() # 数采地址 baud_rate = self.ui.edit_baudrate.text() # 波特率 return com_port, collector_addr, baud_rate def one_key(self, option: str): """ 一键命令 :param option:命令 :return:无 """ # self.update_serial() if self.isPolling is False: self.append_info("请先开始轮询,然后再开始一键操作!", 'red') else: message.append({'cmd': 'one_key', 'option': "%s" % option}) @Slot(int) def update_member(self, member: int): """ 更新成员数 :param member:成员数 :return:无 """ self.ui.label_member.setText(str(member)) @Slot(str) def update_port(self, port_name_list: str): """ 初始化下拉列表框 :return:无 """ port_name_list = eval(port_name_list) self.ui.box_com_port.clear() self.ui.box_com_port.addItems(port_name_list) if len(port_name_list) > 0: self.append_info("共扫描到 %d 个串口设备:%s" % (len(port_name_list), port_name_list)) self.ui.btn_submit.setEnabled(True) # 可以轮询 else: self.append_info('未检测到任何串口设备,请检查连接是否正常', 'red') # # 加个 if 是为了判断是不是正在轮询中, # 有可能是正在轮询,突然没有一个串口设备了 # self.ui.btn_submit.setEnabled(False) # 禁止轮询 @Slot(str, str) def append_info(self, text: str, color: str = 'black'): """ 追加信息到输出狂 :param info:信息,字典字符串 :return: """ black = QColor(0, 0, 0) if color == 'red': c = QColor(255, 0, 0) elif color == 'green': c = QColor(0, 128, 0) else: c = black # # 使用指定颜色追加文本,然后恢复为黑色 # self.ui.output_edit.setTextColor(c) self.ui.output_edit.append(util.get_time() + " " + text) # 显示文本 self.ui.output_edit.setTextColor(black) self.ui.output_edit.moveCursor(QTextCursor.End) # 输出信息后滚动到最后 def handle_table_click(self, item: QModelIndex): """ 处理表格左键点击事件 :param item:点击的单元格 :return:无 """ # # 首先获取点击的行、列号 # 判断点击的单元格是否可点击,如果可以, # 就弹出编辑对话框 # i = item.row() j = item.column() if self.is_editable(i, j): # # 如果在轮询的话,立即停止,并标记需要恢复 # # recover = False # # if self.isPolling: # self.stop_polling() # recover = True # # 根据行号、列号计算出机器编号,然后显示修改窗口 # machine_number = self.helper.get_machine_number(i, j) if self.isPolling is False: self.append_info("请先开始轮询,再发送控制代码!", 'red') else: self.show_modify_dialog(machine_number) # if recover is True: # self.start_polling() def is_editable(self, i, j) -> bool: """ 判断该单元格是否可编辑 :param i:行,从 0 开始 :param j:列,从 0 开始 :return:是否可编辑 """ # # i % 4 == 1 表示 i 在控制代码行 # j % 2 == 1 表示 j 在控制代码列 # if i % 4 == 1 and j % 2 == 1: return True return False def set_enable(self, enable: bool): """ 是否允许编辑串口参数相关 :param enable: 是否允许 :return: 无 """ self.ui.box_com_port.setEnabled(enable) # 端口下拉框 self.ui.edit_baudrate.setEnabled(enable) # 波特率 self.ui.edit_addr.setEnabled(enable) # 地址 self.ui.combobox_interval.setEnabled(enable) # 轮询时间 def start_polling(self): """ 开始轮询按钮响应函数 提交轮询 or 停止轮询 :return:无 """ if not self.isPolling: self.isPolling = True self.ui.btn_submit.setText("停止轮询") self.set_enable(False) # 禁止编辑 self.update_serial() self.append_info("开始轮询") self.polling() else: self.stop_polling() def update_serial(self): com_port, collector_addr, baud_rate = self.get_serial_info() message.append({ 'cmd': 'update_serial', 'com_port': com_port, 'collector_addr': collector_addr, 'baud_rate': baud_rate }) def polling(self): """ 轮询查询 :return:无 """ # # 更新界面 # message.append({'cmd': 'member'}) message.append({'cmd': 'table'}) message.append({'cmd': 'wind_speed'}) self.next_polling() # 准备下一次轮询 @Slot() def stop_polling(self): """ 立即停止轮询 :return:无 """ # # 如果正在轮询,就停止轮询 # 点击“停止轮询”,则按钮立即显示“开始轮询” # if self.isPolling: self.ui.btn_submit.setText("开始轮询") self.set_enable(True) # 恢复允许编辑 self.isPolling = False self.append_info("结束轮询") # 信息台输出结束信息 self.close_serial() # # 强制停止子线程 # if self.polling_timer is not None and self.polling_timer.is_alive( ): util.stop_thread(self.polling_timer) def close_serial(self): """ 发命令关闭串口 :return: """ msg = {"cmd": 'close_serial'} message.append(msg) def next_polling(self): """ 设置一个定时器,到了一定时间后就启动轮询 :return:无 """ interval = int( self.ui.combobox_interval.currentText()[:-2]) # 获取间隔时间下拉框的值 self.polling_timer = Timer(interval, self.polling) self.polling_timer.setName("polling_timer") self.polling_timer.setDaemon(True) self.polling_timer.start() @Slot(str) def update_wind_speed(self, wind_speed: str): """ 更新风速 :param wind_speed:风速值 :return: 无 """ self.ui.label_wind_speed.setText(wind_speed + " m/s") collector_addr = self.ui.edit_addr.text() # 数采地址 self.helper.write_wind_speed(float(wind_speed), collector_addr) @Slot(str) def update_table(self, table_data: str): """ 更新表格数据 :param table_data:表格数据 :return:无 """ table_model, error_number = self.helper.get_table_model(table_data) if error_number != "": self.append_info("有异常机器编号:" + error_number) self.play_error_sound() collector_addr = self.ui.edit_addr.text() # 数采地址 self.helper.write_error(error_number, collector_addr) self.ui.tableView.setModel(table_model) def play_error_sound(self): """ 播放警报 :return: """ if self.play_sound: playsound.playsound("./other/bee.mp3") def show_modify_dialog(self, machine_number: int): """ 显示发送控制代码的对话框 :return: 无 """ input_dial = ModifyDialog("发送控制代码", "%d 号控制器:" % machine_number) if input_dial.exec_(): try: value = input_dial.textValue() # # 检查输入 # obj = re.match(r"^[0-9]{1,2}$", "12") if obj is None: raise ValueError else: code = int(value) if 1 <= code <= 99: code = int(input_dial.textValue()) self.send_control_code(machine_number, code) else: raise ValueError except ValueError: # # 提示输入有误 # info = "输入的控制代码有误!控制代码只能是:1~99" dial = InfoDialog("提示", info) dial.exec_() # 进入事件循环 def show_advance_dialog(self): """ 显示高级对话框,留着预防以后加什么新命令,可以通过这个对话框进行发送 :return: """ input_dial = ModifyDialog("发送控制代码", "对所有控制器发送:") if input_dial.exec_(): try: value = input_dial.textValue() # # 判断输入字符的长度,大于 2 就不是 1<= x <= 99 # obj = re.match(r"^[0-9]{1,2}$", "12") if obj is None: raise ValueError else: code = int(value) if 1 <= code <= 99: code = int(input_dial.textValue()) self.one_key(code) else: raise ValueError except ValueError: # # 提示输入有误 # info = "输入的控制代码有误!控制代码只能是 1~99!" dial = InfoDialog("提示", info) dial.exec_() # 进入事件循环 def send_control_code(self, machine_number: int, code: int) -> None: """ 发送控制代码 :param machine_number:机器编号 :param code:控制代码 :return:无 """ msg = {} msg["cmd"] = 'send_control_code' code = '{:04X}'.format(code) # 十进制控制代码转十六进制 msg['machine_number'] = "%d" % machine_number msg['code'] = "%s" % code message.append(msg)
class Robot(object): """ A class for robots""" def __init__(self, name, robotId, personalityColor, firmwareVersion, state, rType, ip, port): self.name = name self.robotId = robotId self.firmwareVersion = firmwareVersion self.personalityColor = personalityColor self.state = state self.robotType = rType self.ip = ip self.port = port self.cmd_dict = {} self.sensors = {} self.socket = None self.sensorTimer = None self.msgCnt = 0 self.msgBuffer = "" self.msgs = [] self.msgReader = None self.msgLock = RLock() self.MIN_HEAD_PAN = -120 self.MAX_HEAD_PAN = 120 self.MAX_HEAD_TILT = 30 self.MIN_HEAD_TILT = -17 def isConnected(self): return self.socket != None def notConnected(self): return not self.isConnected() def waitForConnectMsg(self): cnctMsgFound = False while not cnctMsgFound: nextMsg = self.popMessage() if nextMsg != None: logger.info("Connected to robot: %s" % self.name) cnctMsgFound = True time.sleep(1) def connect(self): logger.debug("Opening socket to robot: (%d) %s @ %s:%d" % (self.robotId, self.name, self.ip, self.port)) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.ip, self.port)) conn_msg = {"robotId": self.robotId, "userAgentName":"LongCat", "userAgentVersion":"1.1.1.1" } conn_json = json.dumps(conn_msg) + '\n' logger.debug('sending connection data: %s' % conn_json) self.socket.sendall(conn_json) logger.debug('connection data sent') self.startMsgReader() self.waitForConnectMsg() def disconnect(self): self.socket.close() self.socket = None def send_cmd_set(self): if self.notConnected(): print "!!! Robot cannot send command because it isn't connected." return if len(self.cmd_dict) > 0: cmd_set = {"typ":"RobotCommandSet","data":self.cmd_dict} json_cmd = json.dumps(cmd_set) + '\n' logger.debug ("sending command set: %s", json_cmd) self.socket.sendall(json_cmd) self.cmd_dict = {} def set_left_ear_rgb(self, r, g, b): self.cmd_dict[102] = {"r":r, "g":g, "b":b} def set_right_ear_rgb(self, r, g, b): self.cmd_dict[103] = {"r":r, "g":g, "b":b} def set_chest_rgb(self, w, d, x): self.cmd_dict[104] = {"r":w, "g":d, "b":x} def pan_head(self, degree): self.cmd_dict[203] = {"degree":degree} def tilt_head(self, degree): self.cmd_dict[202] = {"degree":degree} def lin_ang_body(self, speed_linear, speed_angular_rad, acc_linear, acc_angular): self.cmd_dict[204] = {"linear_cm_s":speed_linear, "angular_cm_s":speed_angular_rad, "linear_acc_cm_s_s":acc_linear, "angular_acc_deg_s_s":acc_angular} def __repr__(self): return self.__str__() def __str__(self): return "Robot(id: %d, name: %s, personalityColor: %s, isConnected: %s)" % (self.robotId, self.name, self.personalityColor, self.isConnected()) def readNextMsg(self): logger.debug("socket.recv(%d)" % BUFF_SIZE) self.msgBuffer += self.socket.recv(BUFF_SIZE) index = self.msgBuffer.find('\n') logger.debug("index: %d, msgBuffer length: %d", index, len(self.msgBuffer)) while index > 0: msgStr = self.msgBuffer[0:index] self.msgBuffer = self.msgBuffer[index + 1:] self.msgCnt += 1 msg = json.loads(msgStr) logger.debug("eventType: %s", msg['event']) self.addMessage(msg) index = self.msgBuffer.find('\n') def addMessage(self, msg): with self.msgLock: self.msgs.insert(0,msg) self.msgs = self.msgs[0:10] return len(self.msgs) def popMessage(self): with self.msgLock: try: return self.msgs.pop() except IndexError: return None def startMsgReader(self): if self.msgReader != None: self.msgReader.cancel() self.msgReader = Timer(.03, self.readNextMsg) self.msgReader.setName("%s-msg-reader" % self.name) self.msgReader.setDaemon(True) self.msgReader.start()
def schedule(function: callable) -> None: interval = 5 * 60 timer = Timer(interval, function) timer.setName('Communication Thread ' + str(randint(0, 10000))) timer.start()
class Robot(object): """created a class that holds robots information""" def __init__(self, name, robotId, personalityColor, firmwareVersion, state, rType, ip, port): """Init Function that sets all of the important variables""" self.name = name self.robotId = robotId self.firmwareVersion = firmwareVersion self.personalityColor = personalityColor self.state = state self.robotType = rType self.ip = ip self.port = port self.cmd_dict = {} self.sensors = {} self.socket = None self.sensorTimer = None self.msgCnt = 0 self.msgBuffer = "" self.msgs = [] self.msgReader = None self.msgLock = RLock() self.MIN_HEAD_PAN = -120 self.MAX_HEAD_PAN = 120 self.MAX_HEAD_TILT = 30 self.MIN_HEAD_TILT = -17 self.seeRobot = False self.isButton1Pressed = False self.isButton2Pressed = False self.isButton3Pressed = False self.isButtonMainPressed = False def isConnected(self): """Function that tells robot it is connected""" return self.socket != None def notConnected(self): """Function that tells the robot thaat it isnt connected""" return not self.isConnected() def waitForConnectMsg(self): """Function that tells the robot to wait for the connection message to print""" cnctMsgFound = False while not cnctMsgFound: nextMsg = self.popMessage() if nextMsg != None: logger.info("Connected to robot: %s" % self.name) cnctMsgFound = True time.sleep(1) def connect(self): """Function that tells the robot to connect to a unicast socket with the robot and send information. Also sends a connect messagge to the proxy app.""" logger.debug("Opening socket to robot: (%d) %s @ %s:%d" % (self.robotId, self.name, self.ip, self.port)) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.ip, self.port)) conn_msg = {"robotId": self.robotId, "userAgentName":"LongCat", "userAgentVersion":"1.1.1.1" } conn_json = json.dumps(conn_msg) + '\n' logger.debug('connection data sent') self.socket.sendall(conn_json) self.schedMsgReader() self.waitForConnectMsg() def disconnect(self): """Function that disconnects your robot""" self.socket.close() self.socket = None def send_cmd_set(self): """Function that sends a set of commands to your robot, which then will act them out.""" if self.notConnected(): print "!!! Robot cannot send command because it isn't connected." return if len(self.cmd_dict) > 0: cmd_set = {"typ":"RobotCommandSet","data":self.cmd_dict} json_cmd = json.dumps(cmd_set) + '\n' logger.debug ("sending command set: %s", json_cmd) self.socket.sendall(json_cmd) self.cmd_dict = {} #---------------------------------------------------------------------------------------------------------------------------------------------# #-All of the following commands are built in to the robot. Have there own unique IDs, and send themselves to a command set when you call them-# #---------------------------------------------------------------------------------------------------------------------------------------------# def set_left_ear_rgb(self, r, g, b): """Left ear color function: takes 0-1 values for r:red, g:green, & b:blue in that order. 102 is the robot has built in commandID's which is what the 102 is for, so the robot knows 102 = set left ear color. Sends command to command set.""" self.cmd_dict[102] = {"r":r, "g":g, "b":b} def set_right_ear_rgb(self, r, g, b): """Right ear color function takes same values as left ear color. ID: 103""" self.cmd_dict[103] = {"r":r, "g":g, "b":b} def set_chest_rgb(self, r, g, b): """Chest color function takes same values as left and right ear color. ID:104""" self.cmd_dict[104] = {"r":r, "g":g, "b":b} def pan_head(self, degree): """Function that turns head left to right. takes a degrees parameter. range from (-120(leftmost) to 120(rightmost)) ID: 203""" self.cmd_dict[203] = {"degree":degree} def tilt_head(self, degree): """Function that tilts heaad up and down. takes a degrees parameter. range from (-20(Downmost) to 7.5(upmost)) ID: 202""" self.cmd_dict[202] = {"degree":degree} def set_wheels(self, left_whl_velo, right_whl_velo): """Function that sets wheel speed. Takes a right and left wheel velocity parameter. Infinite range negative and positive, negative = backwards, positive = forwards. You can set each wheel at different velocities if you like. ID:211""" self.cmd_dict[211] = {"right_cm_s": right_whl_velo, "left_cm_s": left_whl_velo} def lin_ang_body(self, speed_linear, speed_angular_rad, acc_linear, acc_angular): """function that sets speed, intensity of turn, acceleration rate of speed and turn speed. speed (infinite neg. and pos.), turn (-12(left tight turn) to 12(right tight turn)), acceleration of speed and turn speed (1-1000). ID:204""" self.cmd_dict[204] = {"linear_cm_s":speed_linear, "angular_cm_s":speed_angular_rad, "linear_acc_cm_s_s":acc_linear, "angular_acc_deg_s_s":acc_angular} def set_eye(self, eye_on): """Function that sets eye lights on or off. ID:100""" self.cmd_dict[100] = {"index": [eye_on for x in range(0, 12)]} def __repr__(self): return self.__str__() def __str__(self): return "Robot(id: %d, name: %s, personalityColor: %s, isConnected: %s)" % (self.robotId, self.name, self.personalityColor, self.isConnected()) def readAndSched(self): """Function that reads messages recieved from robot, Keeps reading data constantly keeping you up to date with robot.""" try: logger.debug("socket.recv(%d)" % BUFF_SIZE) self.msgBuffer += self.socket.recv(BUFF_SIZE) logger.debug(self.msgBuffer) index = self.msgBuffer.find('\n') logger.debug("index: %d, msgBuffer length: %d", index, len(self.msgBuffer)) while index > 0: msgStr = self.msgBuffer[0:index] self.msgBuffer = self.msgBuffer[index + 1:] self.msgCnt += 1 msg = json.loads(msgStr) self.addMessage(msg) index = self.msgBuffer.find('\n') except err: logger.error('Error reading from socket: %s', err.message) self.schedMsgReader() def handleSensorSet(self, sensorSet): if msg['sensorId'] == '1001': self.isButtonMainPressed = msg['pressed'] if msg['sensorId'] == '1002': self.isbutton1Pressed = msg['Pressed'] if msg['sensorId'] == '1003': self.isButton2Pressed = msg['Pressed'] if msg['sensorId'] == '1004': self.isButton3Pressed = msg['Pressed'] def addMessage(self, msg): """Function that only reads last 10 messages, taking one off the end and adding one to the beginning""" with self.msgLock: self.msgs.insert(0,msg) self.msgs = self.msgs[0:10] if msg['event'] == 'RobotSensortSetUpdated': handleSensorSet(msg['data']['sensorSet']) return len(self.msgs) def popMessage(self): """Function that pops a message off the list after it is read.""" with self.msgLock: try: return self.msgs.pop() except IndexError: return None def schedMsgReader(self): """Function that starts reading messages and waits a certain amount of time then reads another.""" if self.msgReader != None: self.msgReader.cancel() self.msgReader = Timer(.03, self.readAndSched) self.msgReader.setName("%s-msg-reader" % self.name) self.msgReader.setDaemon(True) self.msgReader.start()
class Reader: """ The Morse decoding algorithm has to wait until two characters have been received before decoding either of them. This is because what appears to be two characters may be two halves of a single spaced character. The two characters are kept in a buffer which (clumsily) is represented as three lists: codeBuf, spaceBuf, and markBuf (see details in the `__init__` definition below). """ def __init__(self, wpm=20, codeType=config.CodeType.american, callback=None): self.codeType = codeType # American or International self.wpm = wpm # current code speed estimate self.dotLen = int(1200. / wpm) # nominal dot length (ms) self.truDot = self.dotLen # actual length of typical dot (ms) self.codeBuf = ['', ''] # code elements for two characters self.spaceBuf = [0, 0] # space before each character self.markBuf = [0, 0] # length of last dot or dash in character self.nChars = 0 # number of complete characters in buffer self.callback = callback # function to call when character decoded self.flusher = None # holds Timer (thread) to call flush if no code received self.latched = False # True if cicuit has been latched closed by a +1 code element self.mark = 0 # accumulates the length of a mark as positive code elements are received self.space = 1 # accumulates the length of a space as negative code elements are received def decode(self, codeSeq): # Code received - cancel an existing 'flusher' if self.flusher: self.flusher.cancel() self.flusher = None ## self.updateWPM(codeSeq) ### ZZZ temporarily disable code speed recognition nextSpace = 0 # space before next dot or dash i = 0 for i in range(0, len(codeSeq)): c = codeSeq[i] if c < 0: # start or continuation of space, or continuation of mark (if latched) c = -c if self.latched: # circuit has been latched closed self.mark += c elif self.space > 0: # continuation of space self.space += c else: # end of mark if self.mark > MINDASHLEN * self.truDot: self.codeBuf[self.nChars] += '-' # dash else: self.codeBuf[self.nChars] += '.' # dot self.markBuf[self.nChars] = self.mark self.mark = 0 self.space = c elif c == 1: # start (or continuation) of extended mark self.latched = True if self.space > 0: # start of mark if self.space > MINMORSESPACE * self.dotLen: # possible Morse or word space self.decodeChar(self.space) self.mark = 0 self.space = 0 else: # continuation of mark pass elif c == 2: # end of mark (or continuation of space) self.latched = False elif c > 2: # mark self.latched = False if self.space > 0: # start of new mark if self.space > MINMORSESPACE * self.dotLen: # possible Morse or word space self.decodeChar(self.space) self.mark = c self.space = 0 elif self.mark > 0: # continuation of mark self.mark += c self.flusher = Timer(((20.0 * self.truDot) / 1000.0), self.flush) # if idle call `flush` self.flusher.setName("Reader-Flusher") self.flusher.start() def setWPM(self, wpm): self.wpm = wpm self.dotLen = int(1200. / wpm) self.truDot = self.dotLen def updateWPM(self, codeSeq): for i in range(1, len(codeSeq) - 2, 2): minDotLen = int(0.5 * self.dotLen) maxDotLen = int(1.5 * self.dotLen) if codeSeq[i] > minDotLen and codeSeq[i] < maxDotLen and \ codeSeq[i] - codeSeq[i+1] < 2 * maxDotLen and \ codeSeq[i+2] < maxDotLen: dotLen = (codeSeq[i] - codeSeq[i + 1]) / 2 self.truDot = int(ALPHA * codeSeq[i] + (1 - ALPHA) * self.truDot) self.dotLen = int(ALPHA * dotLen + (1 - ALPHA) * self.dotLen) self.wpm = 1200. / self.dotLen def flush(self): if self.flusher: self.flusher.cancel() self.flusher = None if self.mark > 0 or self.latched: spacing = self.spaceBuf[self.nChars] if self.mark > MINDASHLEN * self.truDot: self.codeBuf[self.nChars] += '-' # dash elif self.mark > 2: self.codeBuf[self.nChars] += '.' # dot self.markBuf[self.nChars] = self.mark self.mark = 0 self.space = 1 # to prevent circuit opening mistakenly decoding as 'E' self.decodeChar(MAXINT) self.decodeChar(MAXINT) # a second time, to flush both characters self.codeBuf = ['', ''] self.spaceBuf = [0, 0] self.markBuf = [0, 0] self.nChars = 0 if self.latched: self.callback('_', float(spacing) / (3 * self.truDot) - 1) def decodeChar(self, nextSpace): self.nChars += 1 # number of complete characters in buffer (1 or 2) sp1 = self.spaceBuf[0] # space before 1st character sp2 = self.spaceBuf[1] # space before 2nd character sp3 = nextSpace # space before next character code = '' # the dots and dashes s = '' # the decoded character or pair of characters if self.nChars == 2 and sp2 < MAXMORSESPACE * self.dotLen and \ MORSERATIO * sp1 > sp2 and sp2 < MORSERATIO * sp3: # could be two halves of a spaced character code = self.codeBuf[0] + ' ' + self.codeBuf[ 1] # try combining the two halves s = self.lookupChar(code) if s != '' and s != '&': # yes, it's a spaced character, clear the whole buffer self.codeBuf[0] = '' self.markBuf[0] = 0 self.codeBuf[1] = '' self.spaceBuf[1] = 0 self.markBuf[1] = 0 self.nChars = 0 else: # it's not recognized as a spaced character, code = '' s = '' if self.nChars == 2 and sp2 < MINCHARSPACE * self.dotLen: # it's a single character, merge the two halves self.codeBuf[0] += self.codeBuf[1] self.markBuf[0] = self.markBuf[1] self.codeBuf[1] = '' self.spaceBuf[1] = 0 self.markBuf[1] = 0 self.nChars = 1 if self.nChars == 2: # decode the first character, otherwise wait for the next one to arrive code = self.codeBuf[0] s = self.lookupChar(code) if s == 'T' and self.markBuf[0] > MAXDASHLEN * self.dotLen: s = '_' elif s == 'T' and self.markBuf[0] > MINLLEN * self.dotLen and \ self.codeType == config.CodeType.american: s = 'L' elif s == 'E': if self.markBuf[0] == 1: s = '_' elif self.markBuf[0] == 2: s = '_' sp1 = 0 ### ZZZ eliminate space between underscores self.codeBuf[0] = self.codeBuf[1] self.spaceBuf[0] = self.spaceBuf[1] self.markBuf[0] = self.markBuf[1] self.codeBuf[1] = '' self.spaceBuf[1] = 0 self.markBuf[1] = 0 self.nChars = 1 self.spaceBuf[self.nChars] = nextSpace if code != '' and s == '': s = '[' + code + ']' if s != '': self.callback(s, float(sp1) / (3 * self.truDot) - 1) def lookupChar(self, code): codeTableIndex = 0 if self.codeType == config.CodeType.american else 1 if code in decodeTable[codeTableIndex]: return (decodeTable[codeTableIndex][code]) else: return ('') def displayBuffers(self, text): """Display the code buffer and other information for troubleshooting""" log.debug("{}: nChars = {}".format(text, self.nChars)) for i in range(2): print("{} '{}' {}".format(self.spaceBuf[i], self.codeBuf[i], self.markBuf[i]))
from threading import Timer from time import sleep from logging import basicConfig, debug, DEBUG basicConfig( level=DEBUG, format="(%(threadName)s) %(message)s", ) def myThread(): debug("myThread running") thread1 = Timer(3, myThread) thread1.setName("Thread1") thread2 = Timer(3, myThread) thread2.setName("Thread2") debug("starting timers") thread1.start() thread2.start() debug("waiting before canceling %s", thread2.getName()) sleep(2) debug("canceling %s", thread2.getName()) thread2.cancel() print "Main thread is done" ##################################################
class DriveThread(Thread): def __init__(self, logger, sbrick, channel, direction, power): Thread.__init__(self) self._sbrick = sbrick self._channel = channel self._direction = direction self._power = power self._logger = logger self._stop_event = Event() self._timer_thd = None def run(self): self.drive() def drive(self): self.drive_channel() self.break_channel() def stop(self): self._stop_event.set() self._timer_thd.cancel() def times_up(self): self._logger.debug('Drive action times_up {}{}{}{}'.format( SbrickAPI.drive_hex, self._channel, self._direction, self._power)) self._stop_event.set() def reset_command(self, channel, direction, power): self._channel = channel self._direction = direction self._power = power def reset_timer(self, exec_time): if self._timer_thd: self._timer_thd.cancel() if self._stop_event: self._stop_event.clear() if MAGIC_FOREVER == exec_time: return self._timer_thd = Timer(exec_time, self.times_up) self._timer_thd.setName('timer_' + self._channel) self._timer_thd.start() def drive_channel(self): while (not self._stop_event.is_set()): drive_hex_string = SbrickAPI.drive_hex + self._channel + self._direction + self._power self.exec_command(drive_hex_string) # TODO: not need to sleep #time.sleep(0.1) time.sleep(1) def break_channel(self): stop_hex_string = SbrickAPI.stop_hex + self._channel self.exec_command(stop_hex_string) def exec_command(self, hex_string): self._logger.debug('Exec command {}'.format(hex_string)) binary = bytes.fromhex(hex_string) self._sbrick.rcc_char_write_ex(binary, reconnect_do_again=False) #self._sbrick.rcc_char_read_ex(reconnect_do_again=False) @property def stop_event(self): return self._stop_event @property def timer_thd(self): return self._timer_thd
class PushManager(object): # pylint:disable=too-many-instance-attributes """Push notifications susbsytem manager.""" def __init__(self, auth_api, synchronizer, feedback_loop, sse_url=None): """ Class constructor. :param auth_api: sdk-auth-service api client :type auth_api: splitio.api.auth.AuthAPI :param synchronizer: split data synchronizer facade :type synchronizer: splitio.sync.synchronizer.Synchronizer :param feedback_loop: queue where push status updates are published. :type feedback_loop: queue.Queue :param sse_url: streaming base url. :type sse_url: str """ self._auth_api = auth_api self._feedback_loop = feedback_loop self._processor = MessageProcessor(synchronizer) self._status_tracker = PushStatusTracker() self._event_handlers = { EventType.MESSAGE: self._handle_message, EventType.ERROR: self._handle_error } self._message_handlers = { MessageType.UPDATE: self._handle_update, MessageType.CONTROL: self._handle_control, MessageType.OCCUPANCY: self._handle_occupancy } kwargs = {} if sse_url is None else {'base_url': sse_url} self._sse_client = SplitSSEClient(self._event_handler, self._handle_connection_ready, self._handle_connection_end, **kwargs) self._running = False self._next_refresh = Timer(0, lambda: 0) def update_workers_status(self, enabled): """ Enable/Disable push update workers. :param enabled: if True, enable workers. If False, disable them. :type enabled: bool """ self._processor.update_workers_status(enabled) def start(self): """Start a new connection if not already running.""" if self._running: _LOGGER.warning( 'Push manager already has a connection running. Ignoring') return self._trigger_connection_flow() def stop(self, blocking=False): """ Stop the current ongoing connection. :param blocking: whether to wait for the connection to be successfully closed or not :type blocking: bool """ if not self._running: _LOGGER.warning( 'Push manager does not have an open SSE connection. Ignoring') return self._running = False self._processor.update_workers_status(False) self._status_tracker.notify_sse_shutdown_expected() self._next_refresh.cancel() self._sse_client.stop(blocking) def _event_handler(self, event): """ Process an incoming event. :param event: Incoming event :type event: splitio.push.sse.SSEEvent """ try: parsed = parse_incoming_event(event) except EventParsingException: _LOGGER.error('error parsing event of type %s', event.event_type) _LOGGER.debug(str(event), exc_info=True) return try: handle = self._event_handlers[parsed.event_type] except KeyError: _LOGGER.error('no handler for message of type %s', parsed.event_type) _LOGGER.debug(str(event), exc_info=True) return try: handle(parsed) except Exception: #pylint:disable=broad-except _LOGGER.error( 'something went wrong when processing message of type %s', parsed.event_type) _LOGGER.debug(str(parsed), exc_info=True) def _token_refresh(self): """Refresh auth token.""" _LOGGER.info("retriggering authentication flow.") self.stop(True) self._trigger_connection_flow() def _trigger_connection_flow(self): """Authenticate and start a connection.""" try: token = self._auth_api.authenticate() except APIException: _LOGGER.error('error performing sse auth request.') _LOGGER.debug('stack trace: ', exc_info=True) self._feedback_loop.put(Status.PUSH_RETRYABLE_ERROR) return if not token.push_enabled: self._feedback_loop.put(Status.PUSH_NONRETRYABLE_ERROR) return _LOGGER.debug("auth token fetched. connecting to streaming.") self._status_tracker.reset() if self._sse_client.start(token): _LOGGER.debug("connected to streaming, scheduling next refresh") self._setup_next_token_refresh(token) self._running = True def _setup_next_token_refresh(self, token): """ Schedule next token refresh. :param token: Last fetched token. :type token: splitio.models.token.Token """ if self._next_refresh is not None: self._next_refresh.cancel() self._next_refresh = Timer( (token.exp - token.iat) - _TOKEN_REFRESH_GRACE_PERIOD, self._token_refresh) self._next_refresh.setName('TokenRefresh') self._next_refresh.start() def _handle_message(self, event): """ Handle incoming update message. :param event: Incoming Update message :type event: splitio.push.sse.parser.Update """ try: handle = self._message_handlers[event.message_type] except KeyError: _LOGGER.error('no handler for message of type %s', event.message_type) _LOGGER.debug(str(event), exc_info=True) return handle(event) def _handle_update(self, event): """ Handle incoming update message. :param event: Incoming Update message :type event: splitio.push.sse.parser.Update """ _LOGGER.debug('handling update event: %s', str(event)) self._processor.handle(event) def _handle_control(self, event): """ Handle incoming control message. :param event: Incoming control message. :type event: splitio.push.sse.parser.ControlMessage """ _LOGGER.debug('handling control event: %s', str(event)) feedback = self._status_tracker.handle_control_message(event) if feedback is not None: self._feedback_loop.put(feedback) def _handle_occupancy(self, event): """ Handle incoming notification message. :param event: Incoming occupancy message. :type event: splitio.push.sse.parser.Occupancy """ _LOGGER.debug('handling occupancy event: %s', str(event)) feedback = self._status_tracker.handle_occupancy(event) if feedback is not None: self._feedback_loop.put(feedback) def _handle_error(self, event): """ Handle incoming error message. :param event: Incoming ably error :type event: splitio.push.sse.parser.AblyError """ _LOGGER.debug('handling ably error event: %s', str(event)) feedback = self._status_tracker.handle_ably_error(event) if feedback is not None: self._feedback_loop.put(feedback) def _handle_connection_ready(self): """Handle a successful connection to SSE.""" self._feedback_loop.put(Status.PUSH_SUBSYSTEM_UP) _LOGGER.info('sse initial event received. enabling') def _handle_connection_end(self): """ Handle a connection ending. If the connection shutdown was not requested, trigger a restart. """ feedback = self._status_tracker.handle_disconnect() if feedback is not None: self._feedback_loop.put(feedback)
# 定时器 # threading.Timer继承自Thread,这个类用来定义延迟多久后执行一个函数 # Timer.cancel() 取消定时器,(定时器为执行函数时可以取消,在函数执行中无法取消) # Time.start() 启动定时器 # start方法执行之后,Timer对象会处于等待状态,等待了interval秒之后,开始执行function函数的。 # Timer是线程Thread的子类,Timer实例内部提供了一个finished属性,该属性是Event对象。 # cancel方法,本质上 是在worker函数执行前对finished属性set方法操作,从而跳过了worker函数执行,达到了取消的效果 from threading import Timer import logging import time logging.basicConfig(format="%(asctime)s %(threadName)s %(thread)s %(message)s",level=logging.INFO) def worker(): logging.info("in worker") time.sleep(5) logging.info("end in worker") t = Timer(2,worker) t.setName("timer1") #设置线程名称 # t.cancel() #取消定时器后,定时器不在执行 t.start() # t.cancel() #取消定时器后,定时器不在执行 time.sleep(3) #等待3秒后,定时器已经开始执行 # in worker打印过后一秒打印 ======end======== t.cancel() #当定时器执行后,无法取消 print("======end========")
def run_test(self): #{ ue_tests = [] max_duration = 0 is_logging = self.__globals['logging'] # Set up test-specific log directories, if user indicated logging was needed: if is_logging: # User wants logging if not os.path.exists(self.__globals['logdir']): os.mkdir(self.__globals['logdir']) test_logs = 'LoadTestLogs_' + str(datetime.now().strftime('%d-%m-%Y_%H%M%S')) test_logs_abs = os.path.join(self.__globals['logdir'], test_logs) os.mkdir(test_logs_abs) # Now loop through each UE config for ue_config in self.__ue_configs: ue_ip = self.__env.get_addr_of(ue_config['adaptername']) # Set up ue-specific log directories, if user indicated logging was needed: if is_logging: # User wants logging ue_logs = ue_config['adaptername'] + '_' + str(datetime.now().strftime('%d-%m-%Y_%H%M%S')) ue_logs_abs = os.path.join(test_logs_abs, ue_logs) os.mkdir(ue_logs_abs) # Convenience booleans for test_config and run_ue_test methods is_dl = False is_ul = False if ue_config['testtype'] == 'DL' or ue_config['testtype'] == 'SIM': is_dl = True if ue_config['testtype'] == 'UL' or ue_config['testtype'] == 'SIM': is_ul = True # Now get the test configs phase0_ue_test_config = self.get_test_config(ue_config, ue_ip, 0, is_dl, is_ul) phase1_ue_test_config = self.get_test_config(ue_config, ue_ip, 1, is_dl, is_ul) # Set up UE-specific log file path and file name prefix attributes, if user indicated logging was needed: if is_logging: # User wants logging phase0_ue_test_config['logpath'] = ue_logs_abs phase0_ue_test_config['logname'] = self.__globals['logprefix'] + ue_config['adaptername'] + '_Phase0' phase1_ue_test_config['logpath'] = ue_logs_abs phase1_ue_test_config['logname'] = self.__globals['logprefix'] + ue_config['adaptername'] + '_Phase1' # max_duration should contain the highest duration value from all UE tests # If the UE test is TCP then the total test duration is t1 # If the UE test is UDP then the total test duration is t2 if ue_config['traffictype'] == 'UDP': if int(ue_config['t2']) > max_duration: max_duration = int(ue_config['t2']) else: if int(ue_config['t1']) > max_duration: max_duration = int(ue_config['t1']) # Create Timer threads for each phase, delayed by the phase delay, passing in test_config and the interrupt event: phase0Process = Timer(phase0_ue_test_config['delay'], run_ue_test, [self.__interrupt_event, phase0_ue_test_config, is_dl, is_ul, is_logging]) # Name the threads for debug purposes phase0Process.setName(ue_config['adaptername'] + '-phase0') phase1Process = Timer(phase1_ue_test_config['delay'], run_ue_test, [self.__interrupt_event, phase1_ue_test_config, is_dl, is_ul, is_logging]) phase1Process.setName(ue_config['adaptername'] + '-phase1') # And add it to the list of threads: # All the tests are started at the same time, but are timed to start when needed using Timer threads: ue_tests.append(phase0Process) # Only add Phase 1 if testing UDP: if ue_config['traffictype'] == 'UDP': ue_tests.append(phase1Process) # Now run all the threads together: for t in ue_tests: t.start() try: # Wait for end of test, or until user hits Ctrl-C time.sleep(max_duration + 5) logging.debug('Total test waiting finished after ' + str(max_duration + 5) + ' seconds') except KeyboardInterrupt: # Inform all the threads an interrupt was encountered: self.__interrupt_event.set() # And cancel any Timer threads still waiting: for t in ue_tests: t.cancel() logging.warning('Process interrupted by user.\n') logging.warning('Tearing down processes and closing logs...\n')
try: db_inst = MssqlConnection() room_dict = db_inst.room_id2desc db_inst.transfor_absolute_time() except Exception: log_msg = 'Something wrong with the database when try transforing absolute time !!!' log_handler.error(log_msg) return ERR pointer = 0 timer = Timer(THRESHOLD_LOAD_CYCLE, timer_work) while not stopEvent.isSet(): dbIsReady = MssqlConnection.test_connection() if dbIsReady == SUC: timer = Timer(THRESHOLD_LOAD_CYCLE, timer_work) timer.setName(THREAD_POLICY) timer.start() while timer.isAlive(): sleep(0.1) else: log_msg = 'Something wrong with the database, system will reconnect in %d seconds !!!' %db_reconnect_cycle[pointer] log_handler.error(log_msg) sleep(db_reconnect_cycle[pointer]) pointer = (pointer + 1) % len(db_reconnect_cycle) timer.cancel() log_msg = 'Load Threshold Thread shutdown and cleaned! ' log_handler.work(log_msg) # log_manager.add_work_log(log_msg, sys._getframe().f_code.co_name) print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'