def _connect(self): if not self._conn_attemts_timeout == None: # включен таймаут переподключения self._conn_attemts_timeout -= 1 if self._conn_attemts_timeout >= 0: # если время не вышло то выходим return try: self._ser_thread = SerialReaderThread(self._com_port, self._com_baudrate, SerialLineReader) self._ser_thread.start() _, self._ser_reader = self._ser_thread.connect() self._connected = True self._conn_attemts_timeout = None except Exception as e: log.exception("can't connect to serial device") log.info("retrying after {} ticks.".format(СONN_ATTEMTS_TIMEOUT)) self._connected = False self._conn_attemts_timeout = СONN_ATTEMTS_TIMEOUT self._callBack(ON_PROTOCOL_ERROR)
def storeData(self, accounts): start_time = clock() try: now_d = datetime.now() for acc in accounts: # цикл по ЛС for meter in accounts[acc]: # цикл по счетчикам data_s = "stored data: meter_id={}, count={}, updated={}".format( meter["meter_id"], meter[DB_MTR_COUNT_NEW], now_d) log.debug(data_s) need_commit = True if need_commit: pass except Exception as e: self._db_error = True log.exception("can't update data into database") finally: pass log.debug("completed in {:g} sec.".format(clock() - start_time))
def _speak_error(self): # произносит стандратное сообщение об ошибке. self._set_state(State.READY_FOR_HANGOFF) try: #self._speaker.speakAndWait([self._error_message]) self._begin_speaking([self._error_message]) except Exception as e: log.exception("can't speak error sound sequence")
def storeData(self, accounts): start_time = clock() conn = self._db_connect() need_commit = False if not conn: self._db_error = True return cursor = conn.cursor(dictionary=True) # request_text = """UPDATE `meters` # SET `updated` = %(date)s, # `count` = %(count)s # WHERE `meters`.`id` = %(meter_id)s""" request_text = """INSERT INTO `meters_readings` (`id`, `meter_id`, `count`, `updated`) VALUES (NULL, '%(meter_id)s', '%(count)s', %(date)s)""" try: now_d = datetime.now() for acc in accounts: # цикл по ЛС for meter in accounts[acc]: # цикл по счетчикам #if meter["__data_confirmed__"]: cursor.execute( request_text, { 'meter_id': meter["meter_id"], 'count': meter[DB_MTR_COUNT_NEW], 'date': now_d }) log.debug("update row in 'meters' with id '{}'".format( meter["meter_id"])) need_commit = True if need_commit: conn.commit() except SQLError as e: self._db_error = True log.exception("can't update data into database") finally: cursor.close() conn.close() log.debug("completed in {:g} sec.".format(clock() - start_time))
def _sendCmd(self, cmd): try: # формирование команды устройству cmd_line = COMMANDS[cmd]["CMD"] + END_LINE # сброс таймаута и служебных полей self._set_cmd_timeout(CMD_TIMEOUT) self._set_last_cmd(cmd) # отправка команды self._ser_thread.write(cmd_line.encode()) except Exception as e: log.exception("can't send command '{}' to device".format(cmd)) self._callBack(ON_PROTOCOL_ERROR) # вызов события self._callBack(ON_CMD_SENT, cmd=cmd)
def fetchCallerInfo(self, caller_number): start_time = clock() accounts = {} pers_gr = "" try: for item in self._data: if not item["phone_number"] == caller_number: continue acc = item["account"] if not acc in accounts: accounts[acc] = [] mtr = item.copy() # поле для новых показаний mtr[DB_MTR_COUNT_NEW] = mtr[DB_MTR_COUNT] accounts[acc].append(mtr) pers_gr = mtr[DB_PERSONAL_GREATING] except Exception as e: self._db_error = True log.exception("can't fetch data from database") finally: pass # определение функции для извлечения ключа сортировки def sf(item): return item[DB_MTR_INDEX] # сортировка по номеру в УС for acc in accounts: accounts[acc].sort(key=sf) log.debug("completed in {:g} sec.".format(clock() - start_time)) log.debug("collected accounts : {}".format(list(accounts.keys()))) return (accounts, pers_gr)
def _begin_speaking(self, sound, critical = True): if not isinstance(sound, list) and not isinstance(sound, tuple): snd = [sound] else: snd = [] for item in sound: if item: if isinstance(item, list) or isinstance(item, tuple): snd += list(item) else: snd.append(item) try: self._speaker.speak(snd) self._speaking = True except Exception as e: log.exception("can't speak sound sequence '{}'.".format(snd)) if critical: log.error("end the call due to an exception while speaking critical sound sequence") self._set_state(State.READY_FOR_HANGOFF) return False return True
def _db_connect(self): conn = None if not sql.paramstyle == 'pyformat': log.error('sql paramstyle = "{}" not supported.'.format( sql.paramstyle)) return conn tryes = 3 while tryes > 0: try: conn = sql.connect(host=self._db_host, port=self._db_port, database=self._db_database, user=self._db_user, password=self._db_password) tryes = 0 except SQLError as e: tryes -= 1 log.exception("can't connect to database server") return conn
def fetchCallerInfo(self, caller_number): start_time = clock() conn = self._db_connect() accounts = {} pers_gr = "" if not conn: self._db_error = True return (accounts, pers_gr) cursor = conn.cursor(dictionary=True) request_text = """SELECT `clients`.`id` AS `client_id`, `clients`.`account`, `clients`.`phone_number`, `clients`.`registration_date`, `meters`.`id` AS `meter_id`, `meters`.`index_num`, `meters`.`updated`, `meters`.`count`, `pers_set`.`greeting_f` FROM `clients` INNER JOIN `meters` ON `meters`.`owner_id` = `clients`.`id` AND `clients`.`phone_number`=%(phone)s LEFT JOIN `pers_set` ON `pers_set`.`phone_number`=%(phone)s""" try: cursor.execute(request_text, {'phone': caller_number}) for item in cursor.fetchall(): acc = item["account"] if not acc in accounts: accounts[acc] = [] mtr = item.copy() # поле для новых показаний mtr[DB_MTR_COUNT_NEW] = mtr[DB_MTR_COUNT] accounts[acc].append(mtr) pers_gr = item[DB_PERSONAL_GREATING] except SQLError as e: self._db_error = True log.exception("can't fetch data from database") finally: cursor.close() conn.close() # определение функции для извлечения ключа сортировки def sf(item): return item[DB_MTR_INDEX] # сортировка по номеру в УС for acc in accounts: accounts[acc].sort(key=sf) log.debug("completed in {:g} sec.".format(clock() - start_time)) log.debug("collected accounts : {}".format(list(accounts.keys()))) return (accounts, pers_gr)
def _process_message(self, msg): head, args = self._parse_msg(msg) # получаем имя последней отправленной команды lc = self._get_last_cmd() if lc: # была отправлена команда - ожидаемо что это результат ее выполнения if COMMANDS[lc]["CMD"] == msg: # включен режим эхо. устройство отправляет полученную команду обратно перед отправкой ответа pass elif head in COMMANDS[lc]["RESULT"].values(): # результат выполнения команды is_ok = (head == COMMANDS[lc]["RESULT"]["SUCCESS"]) # обработка последовательностей команд self._add_cmd_seq_result(is_ok) # вызываем событие при этом забываем последнюю команду self._callBack(ON_CMD_RESULT, cmd=self._get_last_cmd(True), result=is_ok, test_result=self._get_last_test_result(True)) elif "RESPONSE" in COMMANDS[lc] and head == COMMANDS[lc][ "RESPONSE"]["HEAD"]: # команда возращает ответ try: self._set_last_test_result( args[COMMANDS[lc]["RESPONSE"]["PARAMS"].index( COMMANDS[lc]["TEST"]["PARAM"])] in COMMANDS[lc] ["TEST"]["VALUE"]) except IndexError as e: #raise Exception("unexpected params count returned by command {}".format(lc)) log.exception( "unexpected params count returned by command {}". format(lc)) self._callBack(ON_PROTOCOL_ERROR) else: # вернулась какая то дичь # обработка последовательностей команд if self._is_cmd_seq(): self._cmd_seq_end(False) #raise Exception("unexpected result of command {}".format(lc)) log.error("unexpected result '{}' of command {}".format( msg, lc)) self._callBack(ON_PROTOCOL_ERROR) else: # не было команды устройству - незатребованный результат if head == MSG_END_CALL: # завершение вызова на той стороне self._callBack(ON_END_CALL) elif head == MSG_INCOMING_CALL: # входящий вызов self._callBack(ON_INCOMING_CALL) elif head == MSG_CLIP_INFO: # входящий вызов self._callBack(ON_CALLER_NUMBER_RECIEVED, number=args[0]) elif head == MSG_DTMF_RECIEVED: # получен символ self._callBack(ON_DTMF_RECIEVED, symbol=args[0]) else: self._callBack(ON_UNKNOWN_MSG, message=msg)