コード例 #1
0
ファイル: proto.py プロジェクト: nmix/imit-63
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_)