tao_z
2022-08-07 dd84d3ff28816a22a911bb26b435026b728676db
widgets/ShifterTool.py
@@ -4,7 +4,7 @@
from logging import exception
import threading
from typing import List
from can import BusABC, Message
from can import BusABC, Message, Logger, Listener
from udsoncan.client import Client
from udsoncan.exceptions import TimeoutException
import udsoncan
@@ -23,22 +23,23 @@
import datetime
from ShifterDefine import *
from multiprocessing import Process, Queue, Value, Pipe
from hexread import *
MAX_RCV_NUM = 20
APP_ADDR_LOCATION_OFFSET = 8
APP_LENGTH_LOCATION_OFFSET = 12
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.ERROR)
consoleHandler.setLevel(logging.DEBUG)
fileHandler = logging.FileHandler('./log/ShiftTool.log',
                                  mode='a',
                                  encoding='UTF-8')
fileHandler.setLevel(logging.INFO)
fileHandler.setLevel(logging.DEBUG)
consoleHandler.setFormatter(formatter)
fileHandler.setFormatter(formatter)
@@ -236,11 +237,13 @@
        self.sendQueue = Queue()  # can layer send queue
        self.CANtoIsoTPQueue = Queue()  # CAN --> isotp
        self.shifter = ShifterClass()
        self.Vehicle = VehicleClass()
        self.devicedescription = HardwreDevice()
        self.windows = QtWidgets.QMainWindow()
        self.UI = Ui_MainWindow()
        self.UI.setupUi(window)
        self._dev_info = None
        self.dbc = cantools.database.load_file("DBC/SX7H.dbc")
        self.can_thread = threading.Thread(target=self.can_thread)
        self.TestPresentTimer = QtCore.QTimer()
        self.TestPresentTimer.timeout.connect(self.creat_testpresentReq)
@@ -253,6 +256,8 @@
            0x1c, 0x01, 0x06, 0x80, 0x1f, 0x01, 0x06, 0x80, 0xfb, 0x0a
        ]
        self.app_data: bytes = None
        self.start_timestamp = time.time()
        self.boot_logger = None
    def DeviceInit(self):
        self._usbcan = None
@@ -335,10 +340,18 @@
            seed[3])
        if level == 0x01:
            output_key_temp = 0x20AA097B
            output_key = struct.pack('BBBB', (output_key_temp >> 24) & 0xFF,
                                     (output_key_temp >> 16) & 0xFF,
                                     (output_key_temp >> 8) & 0xFF,
                                     output_key_temp & 0xFF)
            # output_key_temp = ((((temp_key >> 4) ^ temp_key)
            #                     << 3) ^ temp_key) & 0xFFFFFFFF
        elif level == 0x09:
        elif level == 0x11:
            output_key_temp = 0x70237577
            output_key = struct.pack('BBBB', (output_key_temp >> 24) & 0xFF,
                                     (output_key_temp >> 16) & 0xFF,
                                     (output_key_temp >> 8) & 0xFF,
                                     output_key_temp & 0xFF)
            # _temp_y = ((temp_key << 24) & 0xFF000000) + ((temp_key << 8) &
            #                                              0xFF0000) + ((temp_key >> 8) & 0xFF00) + ((temp_key >> 24) & 0xFF)
            # _temp_z = 0
@@ -354,13 +367,21 @@
            #     _temp_z = _temp_z & 0xFFFFFFFF
            # output_key_temp = (((_temp_z << 24) & 0xFF000000) | ((_temp_z << 8) & 0xFF0000) | (
            #     (_temp_z >> 8) & 0xFF00) | ((_temp_z >> 24) & 0xFF))
        elif level == 0x7D:
            output_key_temp = 0xAB2F9F36099D81F3
            output_key = struct.pack(
                'BBBBBBBB', (output_key_temp >> 56) & 0xFF,
                (output_key_temp >> 48) & 0xFF, (output_key_temp >> 40) & 0xFF,
                (output_key_temp >> 32) & 0xFF, (output_key_temp >> 24) & 0xFF,
                (output_key_temp >> 16) & 0xFF, (output_key_temp >> 8) & 0xFF,
                output_key_temp & 0xFF)
        else:
            output_key_temp = temp_key
        output_key = struct.pack('BBBB', (output_key_temp >> 24) & 0xFF,
                                 (output_key_temp >> 16) & 0xFF,
                                 (output_key_temp >> 8) & 0xFF,
                                 output_key_temp & 0xFF)
            output_key = struct.pack('BBBB', (output_key_temp >> 24) & 0xFF,
                                     (output_key_temp >> 16) & 0xFF,
                                     (output_key_temp >> 8) & 0xFF,
                                     output_key_temp & 0xFF)
        return output_key
@@ -395,7 +416,15 @@
        msg.channel = 0
        msg.data = isotp_msg.data  # bytearray
        msg.is_extended_id = False
        msg.timestamp = time.time() - self.start_timestamp
        msg.is_error_frame = False
        msg.is_remote_frame = False
        self.Tool_send(msg)
    def Tool_send(self, msg: Message):
        self._usbcan.send(msg)
        if self.boot_logger is not None:
            self.boot_logger.on_message_received(msg)
    def WidgetsInit(self):
        # self.UI.setupUi(self)
@@ -430,9 +459,11 @@
        self.UI.comboBox_6.addItems(list(DID_dic.keys()))
        self.DID_display()
        self.UI.comboBox_6.activated.connect(self.DID_display)
        self.UI.comboBox_7.addItems(list(DTCGroup_dic.keys()))
        self.UI.comboBox_7.activated.connect(self.ClearDTC)
        self.UI.pushButton_31.clicked.connect(self.SecurityUnlockLevel_1)
        self.UI.pushButton_32.clicked.connect(self.SecurityUnlockLevel_3)
        self.UI.pushButton_32.clicked.connect(self.SecurityUnlockLevel_2)
        self.UI.pushButton_12.clicked.connect(self.ReadSupplyID)
        self.UI.pushButton_4.clicked.connect(self.ReadVIN)
@@ -455,6 +486,18 @@
        self.UI.pushButton_48.clicked.connect(self.start_programming)
        self.UI.pushButton_46.clicked.connect(self.loadAppfile)
        self.UI.radioButton_2.toggled.connect(self.SetFromBootFlag)
        self.UI.pushButton_47.clicked.connect(self.SetBootLog)
        # self.UI.comboBox_10.activated.connect(self.ReportByMask)
        self.UI.comboBox_11.addItems(list(ReportBymask_DTC.keys()))
        self.UI.comboBox_12.addItems(list(DTC_Dic.keys()))
        self.UI.comboBox_13.addItems(list(DTC_Control_dic.keys()))
        self.UI.comboBox_13.activated.connect(self.DTC_Control)
        self.UI.pushButton_49.clicked.connect(self.ReportSupportDTC)
        self.UI.comboBox_11.activated.connect(self.ReportByMask)
        self.UI.comboBox_12.activated.connect(self.ReportSnapshotByDTC)
    def _formatMsgData(self, index, item, received):
        '''msg data to list
@@ -488,7 +531,7 @@
            data.append('标准帧')
        data.append(' '.join(
            ['0x' + '{:0<2x}'.format(a).upper() for a in list(item.data)]))
            ['0x' + '{:0>2x}'.format(a).upper() for a in list(item.data)]))
        return data
    def can_thread_stop(self):
@@ -508,7 +551,7 @@
                        self.needdisconnect.value = 0
                        self._isOpen.value = 0
                else:
                    msg, num = self._usbcan.Receive(len=1)
                    msg, num = self._usbcan.Receive(len=10, timeout=10)
                    if not num == 0:
                        for i in range(num):
                            if msg[i].arbitration_id == self.shifter.canid.phy_txId:
@@ -517,12 +560,15 @@
                                    msg[i])  # send msg to isotp
                            self.msgQueue.put(msg[i])
                            if self.boot_logger is not None:
                                self.boot_logger.on_message_received(msg[i])
                            # logger.info('time:'.format(msg[i].timestamp)+'Rx: ID=0x{:0<3x} '.format(msg[i].arbitration_id) + ' '.join(['0x' +
                            #    '{:0<2x}'.format(a).upper() for a in list(msg[i].data)]))
                            # send signal to update screen
                        g_signal.sig_MsgReceived.emit(num)
                # msgToSendCnt = self.sendQueue.qsize()
                # if msgToSendCnt > 0:
                #     msg = Message()
@@ -531,7 +577,7 @@
                #         msg = self.sendQueue.get()
                #         # logger.info('Tx: ID=0x{:0<3x} '.format(
                #         #     msg.arbitration_id)+'DLC={} '.format(msg.dlc)+'externd flag ={} '.format(msg.is_extended_id)+'remote frame:{} '.format(msg.is_remote_frame))
                #         self._usbcan.send(msg)
                #         self.Tool_send(msg)
    def send_dump(self):
        msg = Message()
        msg.arbitration_id = self.shifter.canid.phy_rxId
@@ -539,19 +585,34 @@
        msg.channel = 0
        msg.data = [0x02, 0x3e, 0x80, 0, 0, 0, 0, 0]
        msg.is_extended_id = False
        self._usbcan.send(msg)
        msg.is_remote_frame = False
        msg.is_error_frame = False
        msg.timestamp = time.time() - self.start_timestamp
        self.Tool_send(msg)
    def send_VehiclePosition(self, data=[]):
        msg = Message()
        msg.arbitration_id = 0x10
        msg.dlc = 8
        msg.channel = 0
        msg.data = data
        msg.is_extended_id = False
        msg.is_remote_frame = False
        msg.is_error_frame = False
        msg.timestamp = time.time() - self.start_timestamp
        self.Tool_send(msg)
    def open_close(self):
        if self._isOpen.value == 0:
            if self._usbcan is None:
                self.update_HardwareDevice()
                can_filters = [{'can_id': 0x420, 'can_mask': 0xFFFFFFFF}]
                can_filters = [{'can_id': 0x5E0, 'can_mask': 0xFFFFFFFF}]
                bitrate = list(
                    TIMING_DICT.keys())[self.devicedescription.baudrate]
                self._usbcan = USBCAN(device_type=4,
                                      device_index=0,
                                      can_index=0,
                                      can_index=self.devicedescription.channel,
                                      bitrate=bitrate,
                                      can_filters=can_filters)
                if not self._usbcan.InitAndStart():
@@ -572,6 +633,9 @@
            self.needdisconnect.value = 1
            self._deviceOpenUpdate()
            self.TestPresentTimer.stop()
    def closeEvent(self, e):
        self.boot_logger.stop()
    def update_HardwareDevice(self):
@@ -615,6 +679,38 @@
        self.UI.pushButton_41.setStyleSheet(
            Style_dic[self.shifter.UnlockButton])
        self.UI.pushButton_40.setStyleSheet(Style_dic[self.shifter.Pbutton])
        #X2
        self.UI.pushButton_37.setStyleSheet(
            Style_dic[self.shifter.position == 2])
        #X1
        self.UI.pushButton_38.setStyleSheet(
            Style_dic[self.shifter.position == 3])
        #Z
        self.UI.pushButton_30.setStyleSheet(
            Style_dic[self.shifter.position == 0])
        #Y1
        self.UI.pushButton_33.setStyleSheet(
            Style_dic[self.shifter.position == 4])
        #Y2
        self.UI.pushButton_34.setStyleSheet(
            Style_dic[self.shifter.position == 5])
        #M
        self.UI.pushButton_39.setStyleSheet(
            Style_dic[self.shifter.position == 0xe])
        #M+
        self.UI.pushButton_35.setStyleSheet(
            Style_dic[self.shifter.position == 0xd])
        #M-
        self.UI.pushButton_36.setStyleSheet(
            Style_dic[self.shifter.position == 0xc])
        self.UI.pushButton_42.setStyleSheet(
            ColorStyle_dic[self.Vehicle.ShiftLeverPos == "P"])
        self.UI.pushButton_43.setStyleSheet(
            ColorStyle_dic[self.Vehicle.ShiftLeverPos == "D"])
        self.UI.pushButton_44.setStyleSheet(
            ColorStyle_dic[self.Vehicle.ShiftLeverPos == "N"])
        self.UI.pushButton_45.setStyleSheet(
            ColorStyle_dic[self.Vehicle.ShiftLeverPos == "R"])
    def _updateRootList(self):
        _dataSize = self.msgQueue.qsize()
@@ -625,7 +721,10 @@
        for i in range(_dataSize):
            receiveNum += 1
            msg = self.msgQueue.get()
            self.shifter.FramUnpack(msg.arbitration_id, msg.data)
            # if msg.arbitration_id == 0x420:
            #     self.shifter.FramUnpack(msg.arbitration_id, msg.data)
            #     resp_data = self.Vehicle.ShiftLogic(self.shifter)
            #     self.send_VehiclePosition(resp_data)
            formateddata.append(self._formatMsgData(
                receiveNum, msg, True))  # return a data list
        self._insertDataSmooth(data=formateddata, datasize=_dataSize)
@@ -661,16 +760,20 @@
    def sessioncontrol_req(self):
        sesson = self.UI.comboBox.currentIndex() + 1
        t = threading.Thread(target=self.udsclient.change_session,
                             args=(sesson, ))
        t.start()
        t.join()
        # self.udsclient.change_session(sesson)
        self.udsclient.change_session(sesson)
    # self.UI.comboBox_8.addItems(['0x01硬件复位', '0x03软件复位'])
    def MCUReset_req(self):
        req = 0x03 if self.UI.comboBox_8.currentData() == '0x01硬件复位' else 0x01
        req = 0x03 if self.UI.comboBox_8.currentText() == '0x01硬件复位' else 0x01
        self.udsclient.ecu_reset(req)
    def ClearDTC(self):
        self.udsclient.clear_dtc(
            group=DTCGroup_dic[self.UI.comboBox_7.currentText()])
    def DTC_Control(self):
        self.udsclient.control_dtc_setting(
            setting_type=DTC_Control_dic[self.UI.comboBox_13.currentText()])
    def Security_req(self):
        self.udsclient.unlock_security_access(1)
@@ -682,11 +785,18 @@
            self.UI.pushButton_31.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def SecurityUnlockLevel_3(self):
        data = self.udsclient.unlock_security_access(9)
    def SecurityUnlockLevel_2(self):
        data = self.udsclient.unlock_security_access(0x11)
        if data.positive:
            self.UI.pushButton_32.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def SecurityUnlockLevel_3(self):
        data = self.udsclient.unlock_security_access(0x7d)
        if data.positive:
            self.UI.pushButton_32.setStyleSheet(
                "background-color:rgb(0, 128, 0)")
        return data
    def ReadSupplyID(self):
        data = self.ReadByDID(0xF18A)
@@ -723,7 +833,8 @@
        self.UI.lineEdit_2.clear()
        data = self.ReadByDID(tempdid)
        if data is not None and len(str(data[tempdid])):
            self.UI.lineEdit_2.setText(str(data[tempdid]) + ' ')
            # print(data[tempdid])
            self.UI.lineEdit_2.setText(data[tempdid])
    def WriteDataByID(self):
        tempdid = DID_dic[self.UI.comboBox_6.currentText()]
@@ -745,14 +856,23 @@
            req = 1
        else:
            req = 3
        self.udsclient.communication_control(control_type=0,
                                             communication_type=req)
        try:
            self.udsclient.communication_control(control_type=req,
                                                 communication_type=1)
        except Exception as e:
            self.disp_string('%s' % e)
    def StartCalibraiton(self):
        startcmd = bytearray([0x0, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(startcmd)):
            self.UI.pushButton_9.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
        sesson = 3
        self.UI.comboBox.setCurrentIndex(sesson - 1)
        response = self.udsclient.change_session(sesson)
        if response.positive:
            response = self.SecurityUnlockLevel_3()
        if response.positive:
            startcmd = bytearray([0x8, 0x0, 0x0, 0x0])
            if self.RequestRoutControl(0xFFAA, bytes(startcmd)):
                self.UI.pushButton_9.setStyleSheet(
                    "background-color:rgb(255, 85, 127)")
    def Calibraiton_Z(self):
        calcmd = bytearray([0x1, 0x0, 0x0, 0x0])
@@ -761,43 +881,43 @@
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_M(self):
        calcmd = bytearray([0x2, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x0, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_13.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_MP(self):
        calcmd = bytearray([0x3, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x2, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_18.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_MN(self):
        calcmd = bytearray([0x4, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x3, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_22.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_X2(self):
        calcmd = bytearray([0x5, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x4, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_24.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_X1(self):
        calcmd = bytearray([0x6, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x5, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_26.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_Y1(self):
        calcmd = bytearray([0x7, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x6, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_27.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
    def Calibraiton_Y2(self):
        calcmd = bytearray([0x8, 0x0, 0x0, 0x0])
        calcmd = bytearray([0x7, 0x0, 0x0, 0x0])
        if self.RequestRoutControl(0xFFAA, bytes(calcmd)):
            self.UI.pushButton_28.setStyleSheet(
                "background-color:rgb(255, 85, 127)")
@@ -812,6 +932,68 @@
        resp_1 = self.udsclient.start_routine(routine_id=routine_id, data=data)
        return resp_1.positive
    def ReportSupportDTC(self):
        resp_1 = self.udsclient.get_supported_dtc()
        if resp_1.positive:
            for i in range(len(resp_1.data) // 4):
                a = i * 4 + 2
                b = i * 4 + 3
                c = i * 4 + 4
                d = i * 4 + 5
                dtc_hex = resp_1.data[a] << 16 | resp_1.data[
                    b] << 8 | resp_1.data[c] << 0
                log = 'DTC:0x%.6x Status:0x%.2x ' % (
                    dtc_hex, resp_1.data[d]) + DTC_DescriptionDic[dtc_hex]
                for j in range(8):
                    if resp_1.data[d] >> j & 0x1:
                        log += ' bit%d' % j
                self.disp_string(log)
    def ReportByMask(self):
        mask = ReportBymask_DTC[self.UI.comboBox_11.currentText()]
        resp_1 = self.udsclient.get_dtc_by_status_mask(status_mask=mask)
        if resp_1.positive:
            for i in range(len(resp_1.data) // 4):
                a = i * 4 + 2
                b = i * 4 + 3
                c = i * 4 + 4
                d = i * 4 + 5
                dtc_hex = resp_1.data[a] << 16 | resp_1.data[
                    b] << 8 | resp_1.data[c] << 0
                log = 'DTC:0x%.2x%.2x%.2x Status:0x%.2x %s ' % (
                    resp_1.data[a], resp_1.data[b], resp_1.data[c],
                    resp_1.data[d], DTC_DescriptionDic[dtc_hex])
                for j in range(8):
                    if resp_1.data[d] >> j & 0x1:
                        log += 'bit%d ' % j
                self.disp_string(log)
    def ReportSnapshotByDTC(self):
        dtc = DTC_Dic[self.UI.comboBox_12.currentText()][
            self.UI.comboBox_12.currentIndex()]
        try:
            resp = self.udsclient.get_dtc_snapshot_by_dtc_number(
                dtc=dtc, record_number=1)
            if resp.positive:
                number_of_did = resp.data[6]
                status = resp.data[4]
                print(status)
                dtc = resp.service_data.dtcs[0]
                snapshots = dtc.snapshots
                # print(dtc.id)
                # print(dtc.status.get_byte())
                log = "DTC:0x%.6x Status:0x%.2x" % (dtc.id, status) + ' '
                # print(type(snapshots[0].did))
                # print(type(snapshots[0].data))
                for i in range(number_of_did):
                    log += (DTC_SanpshotDescriptionDic[snapshots[i].did] +
                            ':' + snapshots[i].data + ' ')
                self.disp_string(log)
                # print(snapshots[i].did, snapshots[i].data)
        except Exception as e:
            self.disp_string('%s' % e)
    def SetFromBootFlag(self):
        self.startfromboot = self.UI.radioButton_2.isChecked()
@@ -824,7 +1006,7 @@
            response = self.udsclient.change_session(3)
            if response.positive:
                self.disp_string('>>> 解锁安全访问')
                response = self.udsclient.unlock_security_access(9)
                response = self.udsclient.unlock_security_access(0x11)
            if response.positive:
                # 检查编程条件
@@ -859,7 +1041,7 @@
        if response.positive:
            # 安全访问
            self.disp_string('>>> 安全访问')
            response = self.udsclient.unlock_security_access(9)
            response = self.udsclient.unlock_security_access(0x11)
        # print(response)
        if response.positive:
            self.disp_string('>>> 请求下载驱动文件')
@@ -995,11 +1177,48 @@
        if fileName != '':
            self.UI.comboBox_4.addItem(fileName)
            self.UI.comboBox_4.setCurrentText(fileName)
            with open(fileName, 'rb') as fd:
                self.app_data = fd.read()
                drv_data_len = len(
                    self.drv_data) if self.drv_data is not None else 0
                app_data_len = len(
                    self.app_data) if self.app_data is not None else 0
                total_len = drv_data_len + app_data_len
                self.UI.progressBar.setRange(0, total_len)
            # with open(fileName, 'rb') as fd:
            #     self.app_data = fd.read()
            #     drv_data_len = len(
            #         self.drv_data) if self.drv_data is not None else 0
            #     app_data_len = len(
            #         self.app_data) if self.app_data is not None else 0
            #     total_len = drv_data_len + app_data_len
            #     self.UI.progressBar.setRange(0, total_len)
            # print(self.app_data)
            # print("===============================================")
            hex_read = Hex_read()
            hex_read.Open_file(fileName)
            self.app_data = hex_read.data
            drv_data_len = len(
                self.drv_data) if self.drv_data is not None else 0
            app_data_len = len(
                self.app_data) if self.app_data is not None else 0
            total_len = drv_data_len + app_data_len
            self.UI.progressBar.setRange(0, total_len)
    def SetBootLog(self):
        if self.in_programming:
            self.disp_string('## 正在编程中')
            return
        fileName, _ = QtWidgets.QFileDialog.getSaveFileName(
            None, 'comboBox_10', '.',
            'All Files (*);;ASC Files (*.asc);;Blf Files (*.blf)')
        if fileName != '':
            self.UI.comboBox_10.addItem(fileName)
            self.UI.comboBox_10.setCurrentText(fileName)
            print(fileName)
            self.boot_logger = Logger(fileName)
            # self.listener = [self.boot_logger]
            # with open(fileName, 'rb') as fd:
            #     self.app_data = fd.read()
            #     drv_data_len = len(
            #         self.drv_data) if self.drv_data is not None else 0
            #     app_data_len = len(
            #         self.app_data) if self.app_data is not None else 0
            #     total_len = drv_data_len + app_data_len
            #     self.UI.progressBar.setRange(0, total_len)