class Proto(QObject): __pyqtSignals__ = ('logMessage(QString, int)', 'ready()', 'readyAnswer()') def __init__(self, mode, parent=None): QObject.__init__(self, parent) # --- self.server = TcpServer(mode, self) self.server.logMessage.connect(self.emit_log) self.server.readByteArray.connect(self.on_read_bytearray) self.pending_data = [] self.stored_data = [] # --- self.client = TcpClient(self) self.client.logMessage.connect(self.emit_log) self.client.readByteArray.connect(self.on_read_bytearray_answer) self.pending_data_answer = [] self.stored_data_answer = [] # --- self.iserv = u'КАУС->ПРМК' self.iserv_2 = u'ПРМК->ПРДК' self.oserv = u'ПРМК->КАУС' self.oserv_2 = u'ПРДК->ПРМК' self.iclient = u'ПРДК->ПРМК' self.oclient = u'ПРМК->ПРДК' # --- self.dest_sign = u'ПРМК->КАУС' self.dest_sign_2 = u'КАУС->ПРМК' if mode == ImitParams.transmitter_mode: self.dest_sign = u'ПРДК->ПРМК' self.dest_sign_2 = u'ПРМК->ПРДК' # --- self.tflag = True if mode == ImitParams.transmitter_mode else False def pop_pending_data(self): try: pdata = self.pending_data.pop(0) return (pdata[0], pdata[1]) except IndexError: return None def pop_pending_data_prdk(self): try: pdata = self.pending_data_answer.pop(0) return (pdata[0], pdata[1]) except IndexError: return None def send_data(self, cmd, params): array, dgram = self.create_datagram(DATAGRAM_ANS4AUS, DEFAULT_SESSION_ID, [cmd] + params) dest = self.oserv if self.tflag: dest = self.oserv_2 self.emit_log(u'%s: %s' % (dest, dgram), 110) self.server.write(array) def send_data_prdk(self, cmd, params): array, dgram = self.create_datagram(DATAGRAM_ANS4AUS, DEFAULT_SESSION_ID, [cmd] + params) self.emit_log(u'ПРМК->ПРДК: %s' % dgram, 110) self.client.write(array) def create_datagram(self, dtype, dservice, info): array = QByteArray() array.append(chr(dtype)) info_size = len(info) hi = (info_size >> 8) & 0xFF lo = info_size & 0xFF array.append(chr(hi)) array.append(chr(lo)) array.append(chr(dservice)) for byte in info: array.append(chr(byte)) array.insert(0, chr(MARKER)) dgram = bytearray2str(array) return (array, dgram) def on_read_bytearray_answer(self, bytearray): # --- переводим QByteArray в список int ilist = bytearray2intlist(bytearray) # --- выполняем последовательный поиск МАРКЕРОВ from_index = 0 marker_index = -1 while True: try: marker_index = ilist.index(MARKER, from_index) # --- если маркер не первый - видимо это завершение предыдущей КДГ # --- или просто мусор (зависит от сохраненных ранее байтов) if from_index == 0 and marker_index > 0: if len(self.stored_data_answer) != 0: # имеются сохраненные данные => это завершение начатого пакета self.stored_data_answer += ilist[0:marker_index] # прицепляем "хвост" info = self.check_datagram_validation(self.stored_data_answer, False) if info and len(info) > 0: self.pending_data_answer.append((info[0], info[1:])) self.emit(SIGNAL('readyAnswer()')) self.stored_data_answer = [] from_index = marker_index + 1 continue # --- if len(self.stored_data_answer) != 0: self.emit_log(u'Данные отброшены (%d) - %s' % (len(self.stored_data_answer), intlist2str(self.stored_data_answer))) self.stored_data_answer = [] # --- kdg = self.check_datagram_validation(ilist[marker_index:], False) # --- if not kdg: from_index = marker_index + 1 continue # --- if len(kdg) == 0: self.stored_data_answer = ilist[marker_index:] from_index = marker_index + 1 continue # --- cmd = kdg[INFO_OFFSET] params = kdg[INFO_OFFSET + 1:] pdata = (cmd, params) self.pending_data_answer.append(pdata) self.emit(SIGNAL('readyAnswer()')) from_index = marker_index + len(kdg) except ValueError: if marker_index < 0: if len(self.stored_data_answer) > 0: self.stored_data_answer += ilist break # --- обрабатываем данные от сервера def on_read_bytearray(self, bytearray): # --- переводим QByteArray в список int ilist = bytearray2intlist(bytearray) # --- выполняем последовательный поиск МАРКЕРОВ from_index = 0 marker_index = -1 while True: try: marker_index = ilist.index(MARKER, from_index) # --- если маркер не первый - видимо это завершение предыдущей КДГ # --- или просто мусор (зависит от сохраненных ранее байтов) if from_index == 0 and marker_index > 0: if len(self.stored_data) != 0: # имеются сохраненные данные => это завершение начатого пакета self.stored_data += ilist[0:marker_index] # прицепляем "хвост" info = self.check_datagram_validation(self.stored_data) if info and len(info) > 0: self.pending_data.append((info[0], info[1:])) self.emit(SIGNAL('ready()')) self.stored_data = [] from_index = marker_index + 1 continue # --- if len(self.stored_data) != 0: self.emit_log(u'Данные отброшены (%d) - %s' % (len(self.stored_data), intlist2str(self.stored_data))) self.stored_data = [] # --- kdg = self.check_datagram_validation(ilist[marker_index:]) # --- if not kdg: from_index = marker_index + 1 continue # --- if len(kdg) == 0: self.stored_data = ilist[marker_index:] from_index = marker_index + 1 continue # --- self.pending_data.append((kdg[INFO_OFFSET], kdg[INFO_OFFSET + 1:])) self.emit(SIGNAL('ready()')) from_index = marker_index + len(kdg) except ValueError: if marker_index < 0: if len(self.stored_data) > 0: self.stored_data += ilist break def check_datagram_validation(self, pack, Server_Flag=True): """ Проверяем датаграмму на валидность pack = [int, int, ...] """ dgram = intlist2str(pack) if len(pack) < HEADER_SIZE: self.emit_log(u'Недостаточная длина пакета - %s' % dgram, 130) return None du = self.get_info_length(pack) df = len(pack) - HEADER_SIZE if du > df: return [] # незавершенная кодограмма dest = self.iserv if self.tflag: dest = self.iserv_2 elif not Server_Flag: dest = self.iclient self.emit_log(u'%s: %s' % (dest, dgram), 110) dtype = self.get_datagram_type(pack) dservice = self.get_service_type(pack) if dtype == DATAGRAM_NULL: return None elif dtype == DATAGRAM_REG4KRS: if Server_Flag: self.emit_log(u'Получен пакет регистрации, тип сеанса - %d' % dservice) array, dgram = self.create_datagram(DATAGRAM_SOK4AUS, DEFAULT_SESSION_ID, []) dest = self.iserv if self.tflag: dest = self.iserv_2 self.emit_log(u'%s: %s' % (dest, dgram), 110) self.server.write(array) self.emit_log(u'Сеанс управления открыт, тип сеанса - %d' % DEFAULT_SESSION_ID) else: self.emit_log(u'Ошибка регистрации - неожиданное сообщение', 130) return None elif dtype == DATAGRAM_CMD4KRS: kdg = pack[:INFO_OFFSET + du] return kdg elif dtype == DATAGRAM_ANS4AUS: if len(pack) <= HEADER_SIZE: return None kdg = pack[:INFO_OFFSET + du] return kdg else: #self.emit_log(u'Ошибка типа входящего сообщения (%d)' % dtype) return None def get_datagram_type(self, pack): return pack[TYPE_OFFSET] def get_service_type(self, pack): return pack[SERVICE_OFFSET] def get_info_length(self, pack): hi = pack[HIGH_LENGTH_OFFSET] << 8 low = pack[LOW_LENGTH_OFFSET] length = hi | low return length def emit_log(self, text, type_=10): self.emit(SIGNAL('logMessage(QString, int)'), text, type_)