Procházet zdrojové kódy

就定义为1.0版本吧

Franike před 1 rokem
revize
aea24957bb
95 změnil soubory, kde provedl 9336 přidání a 0 odebrání
  1. 114 0
      .gitignore
  2. binární
      assets/icon/balance.png
  3. binární
      assets/icon/bcu.png
  4. binární
      assets/icon/cell.png
  5. binární
      assets/icon/cut.png
  6. binární
      assets/icon/data.png
  7. binární
      assets/icon/download.png
  8. binární
      assets/icon/hard.png
  9. binární
      assets/icon/home.png
  10. binární
      assets/icon/protect.png
  11. binární
      assets/icon/set.png
  12. binární
      assets/icon/start.png
  13. binární
      assets/icon/stop.png
  14. binární
      assets/logo.png
  15. 107 0
      build_pyd.py
  16. binární
      config/ControlCAN.dll
  17. binární
      config/PCANBasic.dll
  18. binární
      config/kerneldlls/CAN232.dll
  19. binární
      config/kerneldlls/CANETE.dll
  20. binární
      config/kerneldlls/CANET_TCP.dll
  21. binární
      config/kerneldlls/PC104C2.dll
  22. binární
      config/kerneldlls/PC104CAN.dll
  23. binární
      config/kerneldlls/PCI5121.dll
  24. binární
      config/kerneldlls/gisadll.dll
  25. binární
      config/kerneldlls/gpcidll.dll
  26. binární
      config/kerneldlls/isa5420.dll
  27. 20 0
      config/kerneldlls/kerneldll.ini
  28. binární
      config/kerneldlls/usbcan.dll
  29. binární
      config/libPCBUSB.0.12.1.dylib
  30. 0 0
      controller/__init__.py
  31. 50 0
      controller/bms_balance_ctl.py
  32. 21 0
      controller/bms_cell_ctl.py
  33. 14 0
      controller/bms_double_ccu_ctl.py
  34. 99 0
      controller/bms_download_ctl.py
  35. 38 0
      controller/bms_hard_ctl.py
  36. 1267 0
      controller/bms_home_ctl.py
  37. 78 0
      controller/bms_login_ctl.py
  38. 410 0
      controller/bms_main_ctl.py
  39. 76 0
      controller/bms_protect_ctl.py
  40. 16 0
      controller/bms_record_ctl.py
  41. 18 0
      controller/bms_set_ctl.py
  42. 23 0
      controller/bms_status_ctl.py
  43. binární
      doc/芯祥_上位机规划V1.2-20231229.vsdx
  44. binární
      doc/芯祥_储能BMS平台项目内网CAN通讯协议V1.2_20231229.xls
  45. 0 0
      model/__init__.py
  46. 264 0
      model/record_model.py
  47. 10 0
      requirements.txt
  48. 54 0
      start.py
  49. 0 0
      ui/__init__.py
  50. 280 0
      ui/balance.py
  51. 235 0
      ui/cell.py
  52. 45 0
      ui/double_ccu.py
  53. 189 0
      ui/download.py
  54. 366 0
      ui/hard.py
  55. 187 0
      ui/home.py
  56. 158 0
      ui/login.py
  57. 0 0
      ui/main/__init__.py
  58. 435 0
      ui/main/center_page.py
  59. 37 0
      ui/main/main.py
  60. 686 0
      ui/main/top_page.py
  61. 471 0
      ui/main/under_page.py
  62. 0 0
      ui/own/__init__.py
  63. 21 0
      ui/own/frame_theme.py
  64. 257 0
      ui/own/led.py
  65. 63 0
      ui/own/my_chart_view.py
  66. 87 0
      ui/own/palette_theme.py
  67. 76 0
      ui/own/switch_button.py
  68. 58 0
      ui/own/troublebar.py
  69. 932 0
      ui/protect.py
  70. 27 0
      ui/record.py
  71. 19 0
      ui/set.py
  72. 125 0
      ui/statusbar.py
  73. 0 0
      utils/__init__.py
  74. 543 0
      utils/can.py
  75. 32 0
      utils/delay.py
  76. 42 0
      utils/globalvar.py
  77. 43 0
      utils/hex_bit.py
  78. 28 0
      utils/log_signal.py
  79. 66 0
      utils/qt.py
  80. 27 0
      utils/resource.py
  81. 0 0
      widget/__init__.py
  82. 32 0
      widget/bms_balance.py
  83. 43 0
      widget/bms_cell.py
  84. 15 0
      widget/bms_double_ccu.py
  85. 33 0
      widget/bms_download.py
  86. 46 0
      widget/bms_hard.py
  87. 194 0
      widget/bms_home.py
  88. 63 0
      widget/bms_login.py
  89. 167 0
      widget/bms_main.py
  90. 60 0
      widget/bms_protect.py
  91. 16 0
      widget/bms_record.py
  92. 16 0
      widget/bms_set.py
  93. 49 0
      widget/bms_status_bar.py
  94. 0 0
      worker/__init__.py
  95. 388 0
      worker/bms_work.py

+ 114 - 0
.gitignore

@@ -0,0 +1,114 @@
+# Mac
+.DS_Store
+*/.DS_Store
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# vscode 
+.vscode
+.vscode/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+
+*.csv
+**/Thumbs.db

binární
assets/icon/balance.png


binární
assets/icon/bcu.png


binární
assets/icon/cell.png


binární
assets/icon/cut.png


binární
assets/icon/data.png


binární
assets/icon/download.png


binární
assets/icon/hard.png


binární
assets/icon/home.png


binární
assets/icon/protect.png


binární
assets/icon/set.png


binární
assets/icon/start.png


binární
assets/icon/stop.png


binární
assets/logo.png


+ 107 - 0
build_pyd.py

@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :setup.py
+@时间    :2022/02/21 17:00:46
+@作者    :None
+@版本    :1.0
+@说明    :源码编译文件
+'''
+
+
+import sys
+import os
+import shutil
+import time
+from distutils.core import setup
+from Cython.Build import cythonize
+
+# import zipextimporter
+
+start_time = time.time()
+curr_dir = os.path.abspath('.')
+parent_path = sys.argv[1] if len(sys.argv) > 1 else ""
+setup_file = __file__.replace('/', '')
+build_dir = "build"
+build_tmp_dir = build_dir + "/temp"
+
+s = "# cython: language_level=3"
+
+"""
+获取py文件的路径
+:param base_path: 根路径
+:param parent_path: 父路径
+:param excepts: 排除文件
+:return: py文件的迭代器
+"""
+
+
+def get_py(base_path=os.path.abspath('.'), parent_path='', name='', excepts=(), copyOther=False, delC=False):
+
+    full_path = os.path.join(base_path, parent_path, name)
+    for filename in os.listdir(full_path):
+        full_filename = os.path.join(full_path, filename)
+        if os.path.isdir(full_filename) and filename != build_dir and not filename.startswith('.'):
+            for f in get_py(base_path, os.path.join(parent_path, name), filename, excepts, copyOther, delC):
+                yield f
+        elif os.path.isfile(full_filename):
+            ext = os.path.splitext(filename)[1]
+            if ext == ".c":
+                if delC and os.stat(full_filename).st_mtime > start_time:
+                    os.remove(full_filename)
+            elif full_filename not in excepts and os.path.splitext(filename)[1] not in ('.pyc', '.pyx'):
+                if os.path.splitext(filename)[1] in ('.py', '.pyx') and not filename.startswith('__'):
+                    path = os.path.join(parent_path, name, filename)
+                    yield path
+        else:
+            pass
+
+
+def pack_pyd():
+    # 获取py列表
+    module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,)))
+    try:
+        setup(
+            ext_modules=cythonize(module_list, language_level="3"),
+            script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir],
+        )
+    except Exception as ex:
+        print("error! ", str(ex))
+    else:
+        module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), copyOther=True))
+
+    module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), delC=True))
+    if os.path.exists(build_tmp_dir):
+        shutil.rmtree(build_tmp_dir)
+
+    print("complate! time:", time.time() - start_time, 's')
+
+
+"""
+删除编译过程中生成的.c文件
+:param path:
+:param excepts:
+:return:
+"""
+
+
+def delete_c(path='.', excepts=(setup_file,)):
+
+    dirs = os.listdir(path)
+    for dir in dirs:
+        new_dir = os.path.join(path, dir)
+        if os.path.isfile(new_dir):
+            ext = os.path.splitext(new_dir)[1]
+            if ext == '.c':
+                os.remove(new_dir)
+        elif os.path.isdir(new_dir):
+            delete_c(new_dir)
+
+
+if __name__ == '__main__':
+    try:
+        pack_pyd()
+    except Exception as e:
+        print(str(e))
+    finally:
+        delete_c()

binární
config/ControlCAN.dll


binární
config/PCANBasic.dll


binární
config/kerneldlls/CAN232.dll


binární
config/kerneldlls/CANETE.dll


binární
config/kerneldlls/CANET_TCP.dll


binární
config/kerneldlls/PC104C2.dll


binární
config/kerneldlls/PC104CAN.dll


binární
config/kerneldlls/PCI5121.dll


binární
config/kerneldlls/gisadll.dll


binární
config/kerneldlls/gpcidll.dll


binární
config/kerneldlls/isa5420.dll


+ 20 - 0
config/kerneldlls/kerneldll.ini

@@ -0,0 +1,20 @@
+[KERNELDLL]
+COUNT=18
+1=PCI5121.dll
+2=PCI9810B.dll
+3=USBCAN.dll
+4=USBCAN.dll
+5=PCI9820B.dll
+6=CAN232.dll
+7=PCI5121.dll
+8=CANLite.dll
+9=ISA9620B.dll
+10=ISA5420.dll
+11=PC104CAN.dll
+12=CANETE.dll
+13=DNP9810B.dll
+14=PCI9840B.dll
+15=PC104C2.dll
+16=PCI9820I.dll
+17=CANET_TCP.dll
+18=pec9920.dll

binární
config/kerneldlls/usbcan.dll


binární
config/libPCBUSB.0.12.1.dylib


+ 0 - 0
controller/__init__.py


+ 50 - 0
controller/bms_balance_ctl.py

@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from utils.globalvar import SD
+from widget.bms_balance import Win_Balance
+
+
+class BmsBalanceControll:
+    def __init__(self):
+        self._view = Win_Balance()
+        self.init()
+
+    def init(self):
+        self._view.balance_control_signal.connect(self._cell_balance_ctl)
+        
+    def _cell_balance_ctl(self, cmu_id, cell_id, state):
+        print(cmu_id, cell_id, state)
+        if (cell_id <= 40):
+            try:
+                data = []
+                if len(data) < 8:
+                    data += (8 - len(data)) * [0]
+                data[0] = 0x02
+                data[1] = 0xC0
+                data[2] = cmu_id
+                data[3] = ((1 if (state > 0) else 0) << (cell_id - 1)) & 0xFF
+                data[4] = (((1 if (state > 0) else 0) << (cell_id - 1)) & 0xFF00) >> 8
+                data[5] = (((1 if (state > 0) else 0) << (cell_id - 1)) & 0xFF0000) >> 16
+                data[6] = (((1 if (state > 0) else 0) << (cell_id - 1)) & 0xFF000000) >> 24
+                data[7] = (((1 if (state > 0) else 0) << (cell_id - 1)) & 0xFF00000000) >> 32
+                msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+            except:
+                self._view.can_connect_error()
+        else:
+            try:
+                data = []
+                if len(data) < 8:
+                    data += (8 - len(data)) * [0]
+                data[0] = 0x03
+                data[1] = 0xC0
+                data[2] = cmu_id
+                data[3] = ((1 if (state > 0) else 0) << (cell_id - 41)) & 0xFF
+                data[4] = (((1 if (state > 0) else 0) << (cell_id - 41)) & 0xFF00) >> 8
+                data[5] = (((1 if (state > 0) else 0) << (cell_id - 41)) & 0xFF0000) >> 16
+                data[6] = (((1 if (state > 0) else 0) << (cell_id - 41)) & 0xFF000000) >> 24
+                data[7] = (((1 if (state > 0) else 0) << (cell_id - 41)) & 0xFF00000000) >> 32
+                msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+            except:
+                self._view.can_connect_error()

+ 21 - 0
controller/bms_cell_ctl.py

@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from widget.bms_cell import Win_Cell
+
+
+class BmsCellControll:
+    def __init__(self):
+        self._view = Win_Cell()
+        self.init()
+
+    def init(self):
+        self._view.cell_vol_signal.connect(self._page_index)
+        self._view.cell_temp_signal.connect(self._page_index)
+        self._view.jz_temp_signal.connect(self._page_index)
+        self._view.bcu_temp_signal.connect(self._page_index)
+        self._view.mos_temp_signal.connect(self._page_index)
+
+    def _page_index(self,index):
+        self._view.cell_tab.setCurrentIndex(index)

+ 14 - 0
controller/bms_double_ccu_ctl.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from widget.bms_double_ccu import Win_Double_Ccu
+
+
+class BmsDoubleCcuControll:
+    def __init__(self):
+        self._view = Win_Double_Ccu()
+    #     self.init()
+
+    # def init(self):
+        

+ 99 - 0
controller/bms_download_ctl.py

@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from widget.bms_download import Win_Download
+from utils.globalvar import SD
+
+
+class BmsDownloadControll:
+    def __init__(self):
+        self._view = Win_Download()
+        self.init()
+
+    def init(self):
+        self._view.bms_sn_signal.connect(self._bms_sn_set)
+        self._view.bat_sn_signal.connect(self._bat_sn_set)
+        
+
+    def _bms_sn_set(self):
+        bms_sn_str = self._view.edt_bms_sn.text()
+        bms_sn_list = list(bms_sn_str)
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xB2
+            data[2] = ord(bms_sn_list[0])
+            data[3] = ord(bms_sn_list[1])
+            data[4] = ord(bms_sn_list[2])
+            data[5] = ord(bms_sn_list[3])
+            data[6] = ord(bms_sn_list[4])
+            data[7] = ord(bms_sn_list[5])
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+            
+            data[0] = 0x01
+            data[1] = 0xB2
+            data[2] = ord(bms_sn_list[6])
+            data[3] = ord(bms_sn_list[7])
+            data[4] = ord(bms_sn_list[8])
+            data[5] = ord(bms_sn_list[9])
+            data[6] = ord(bms_sn_list[10])
+            data[7] = ord(bms_sn_list[11])
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+
+            data[0] = 0x02
+            data[1] = 0xB2
+            data[2] = ord(bms_sn_list[12])
+            data[3] = ord(bms_sn_list[13])
+            data[4] = ord(bms_sn_list[14])
+            data[5] = ord(bms_sn_list[15])
+            data[6] = 0xFF
+            data[7] = 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+        except IndexError:
+            self._view.index_error()
+        except:
+            self._view.can_connect_error()
+
+    def _bat_sn_set(self):
+        bat_sn_str = self._view.edt_battery_sn.text()
+        bat_sn_list = list(bat_sn_str)
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x03
+            data[1] = 0xB2
+            data[2] = ord(bat_sn_list[0])
+            data[3] = ord(bat_sn_list[1])
+            data[4] = ord(bat_sn_list[2])
+            data[5] = ord(bat_sn_list[3])
+            data[6] = ord(bat_sn_list[4])
+            data[7] = ord(bat_sn_list[5])
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+            
+            data[0] = 0x04
+            data[1] = 0xB2
+            data[2] = ord(bat_sn_list[6])
+            data[3] = ord(bat_sn_list[7])
+            data[4] = ord(bat_sn_list[8])
+            data[5] = ord(bat_sn_list[9])
+            data[6] = ord(bat_sn_list[10])
+            data[7] = ord(bat_sn_list[11])
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+
+            data[0] = 0x05
+            data[1] = 0xB2
+            data[2] = ord(bat_sn_list[12])
+            data[3] = ord(bat_sn_list[13])
+            data[4] = ord(bat_sn_list[14])
+            data[5] = ord(bat_sn_list[15])
+            data[6] = 0xFF
+            data[7] = 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+        except IndexError:
+            self._view.index_error()
+        except:
+            self._view.can_connect_error()

+ 38 - 0
controller/bms_hard_ctl.py

@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from widget.bms_hard import Win_Hard
+from utils.globalvar import SD
+from utils.qt import QDateTime
+
+class BmsHardControll:
+    def __init__(self):
+        self._view = Win_Hard()
+        self.init()
+
+    def init(self):
+        self._view.rtc_update_signal.connect(self._rtc_time_update)
+
+
+    def _rtc_time_update(self):
+        dataTime = QDateTime.currentDateTime()
+        text = dataTime.toString("yy MM dd HH mm ss")
+        time_str = text.split(" ")
+        print(time_str)
+        # time_list = [bcd_hex(data) for data in time_str]
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x05
+            data[1] = 0xB0
+            data[2] = int(time_str[0])
+            data[3] = int(time_str[1])
+            data[4] = int(time_str[2])
+            data[5] = int(time_str[3])
+            data[6] = int(time_str[4])
+            data[7] = int(time_str[5])
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1803, data)
+        except:
+            self._view.can_connect_error()

+ 1267 - 0
controller/bms_home_ctl.py

@@ -0,0 +1,1267 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :bms_home_ctl.py
+@时间    :2022/02/21 16:56:26
+@作者    :None
+@版本    :1.0
+@说明    :主页面 CTL
+'''
+
+from controller.bms_cell_ctl import BmsCellControll
+from controller.bms_double_ccu_ctl import BmsDoubleCcuControll
+from controller.bms_protect_ctl import BmsProtectControll
+from controller.bms_hard_ctl import BmsHardControll
+from controller.bms_balance_ctl import BmsBalanceControll
+from controller.bms_record_ctl import BmsRecordControll
+from controller.bms_download_ctl import BmsDownloadControll
+from controller.bms_set_ctl import BmsSetControll
+from controller.bms_status_ctl import BmsStatusControll
+from model.record_model import RecordModel
+from widget.bms_home import Win_GotionBMS
+from utils.globalvar import SD
+from controller.bms_main_ctl import BmsMainControll
+from utils.qt import QTimer, QThread, QColor, Qt, QDateTime, QtGui, QtWidgets, QPixmap,QApplication
+from utils.hex_bit import a_bit
+from worker.bms_work import BmsSend, BmsReceived
+from ui.own.palette_theme import set_edt_bg
+
+class BmsHomeControll:
+    def __init__(self):
+        self._view = Win_GotionBMS()
+        self._model = RecordModel()
+        self.bms_sn_version = ["" for i in range(16)]
+        self.battery_sn_version = ["" for i in range(16)]
+        self.cell_single_volt = [0 for i in range(396)]
+        self.cell_single_temp = [0 for i in range(360)]
+        self.init()
+
+    def init(self):
+        self.bms_main_ctl = BmsMainControll()
+        self._view.bms_tab.addWidget(self.bms_main_ctl._view.main)
+        self.bms_cell_ctl = BmsCellControll()
+        self._view.bms_tab.addWidget(self.bms_cell_ctl._view.cell)
+        self.bms_double_ccu_ctl = BmsDoubleCcuControll()
+        self._view.bms_tab.addWidget(self.bms_double_ccu_ctl._view.double_ccu)
+        self.bms_protect_ctl = BmsProtectControll()
+        self._view.bms_tab.addWidget(self.bms_protect_ctl._view.protect)
+        self.bms_hard_ctl = BmsHardControll()
+        self._view.bms_tab.addWidget(self.bms_hard_ctl._view.hard)
+        self.bms_balance_ctl = BmsBalanceControll()
+        self._view.bms_tab.addWidget(self.bms_balance_ctl._view.balance)
+        self.bms_record_ctl = BmsRecordControll()
+        self._view.bms_tab.addWidget(self.bms_record_ctl._view.record)
+        self.bms_download_ctl = BmsDownloadControll()
+        self._view.bms_tab.addWidget(self.bms_download_ctl._view.download)
+        self.bms_set_ctl = BmsSetControll()
+        self._view.bms_tab.addWidget(self.bms_set_ctl._view.set)
+        self.bms_status = BmsStatusControll()
+        self._view.setStatusBar(self.bms_status._view.statusbar)
+        self._view.main_control_signal.connect(self._page_index)
+        self._view.cell_inf_signal.connect(self._page_index)
+        self._view.double_ccu_signal.connect(self._page_index)
+        self._view.protect_inf_signal.connect(self._page_index)
+        self._view.hard_cali_signal.connect(self._page_index)
+        self._view.balance_inf_signal.connect(self._page_index)
+        self._view.data_inf_signal.connect(self._page_index)
+        self._view.download_signal.connect(self._page_index)
+        self._view.set_inf_signal.connect(self._page_index)
+        self._view.can_start_signal.connect(self.bcu_connect)
+        self._view.can_stop_signal.connect(self.bcu_disconnect)
+        self._view.cut_start_signal.connect(self.app_cut)
+        self._view.bcu_online_list_signal.connect(self._view._bcu_connect_get)
+
+
+    def _page_index(self,index):
+        self._view.bms_tab.setCurrentIndex(index)
+
+    def bcu_connect(self):
+        try:
+            SD.CAN_ON_OFF = SD.CAN_CONTROL.open_device()
+        except:
+            SD.CAN_ON_OFF = 0
+
+        if SD.CAN_ON_OFF:
+            self.bms_status._view.label_bms_connect.setText("通讯已连接" if SD.SYSTEM_LANGUAGE == 0 else "BMS Connected")
+            SD.START_RUN = True
+            # CAN数据发送类
+            # self.bms_send_thread = QThread()
+            # self.bms_send = BmsSend()
+            # self.bms_send.moveToThread(self.bms_send_thread)
+            # self.bms_send_thread.started.connect(self.bms_send.send)
+            # CAN数据接收类
+            self.bms_received_thread = QThread()
+            self.bms_received = BmsReceived()
+            self.bms_received.moveToThread(self.bms_received_thread)
+            self.bms_received_thread.started.connect(self.bms_received.received)
+            # 启动线程
+            # self.bms_send_thread.start()
+            self.bms_received_thread.start()
+
+            self.bms_received.to_show_masterid_signal.connect(self._get_master_id)
+            self.bms_received.to_show_0000_signal.connect(self._inf_0000_signal)
+            self.bms_received.to_show_0001_signal.connect(self._inf_0001_signal)
+            self.bms_received.to_show_0002_signal.connect(self._inf_0002_signal)
+            self.bms_received.to_show_0003_signal.connect(self._inf_0003_signal)
+            self.bms_received.to_show_0004_signal.connect(self._inf_0004_signal)
+            self.bms_received.to_show_0005_signal.connect(self._inf_0005_signal)
+            self.bms_received.to_show_0006_signal.connect(self._inf_0006_signal)
+            self.bms_received.to_show_0007_signal.connect(self._inf_0007_signal)
+            self.bms_received.to_show_0008_signal.connect(self._inf_0008_signal)
+            self.bms_received.to_show_0009_signal.connect(self._inf_0009_signal)
+            self.bms_received.to_show_000A_signal.connect(self._inf_000A_signal)
+            self.bms_received.to_show_000B_signal.connect(self._inf_000B_signal)
+            self.bms_received.to_show_000C_signal.connect(self._inf_000C_signal)
+            self.bms_received.to_show_000D_signal.connect(self._inf_000D_signal)
+            self.bms_received.to_show_000E_signal.connect(self._inf_000E_signal)
+            self.bms_received.to_show_000F_signal.connect(self._inf_000F_signal)
+            self.bms_received.to_show_0010_signal.connect(self._inf_0010_signal)
+            self.bms_received.to_show_0011_signal.connect(self._inf_0011_signal)
+            self.bms_received.to_show_0012_signal.connect(self._inf_0012_signal)
+            self.bms_received.to_show_0013_signal.connect(self._inf_0013_signal)
+            self.bms_received.to_show_0014_signal.connect(self._inf_0014_signal)
+            self.bms_received.to_show_0015_signal.connect(self._inf_0015_signal)
+            self.bms_received.to_show_0016_signal.connect(self._inf_0016_signal)
+            self.bms_received.to_show_0017_signal.connect(self._inf_0017_signal)
+            self.bms_received.to_show_0018_signal.connect(self._inf_0018_signal)
+            self.bms_received.to_show_0019_signal.connect(self._inf_0019_signal)
+            self.bms_received.to_show_001A_signal.connect(self._inf_001A_signal)
+            self.bms_received.to_show_001B_signal.connect(self._inf_001B_signal)
+            self.bms_received.to_show_001C_signal.connect(self._inf_001C_signal)
+            self.bms_received.to_show_001D_signal.connect(self._inf_001D_signal)
+            self.bms_received.to_show_001E_signal.connect(self._inf_001E_signal)
+            self.bms_received.to_show_001F_signal.connect(self._inf_001F_signal)
+            self.bms_received.to_show_0020_signal.connect(self._inf_0020_signal)
+            self.bms_received.to_show_0021_signal.connect(self._inf_0021_signal)
+            self.bms_received.to_show_0022_signal.connect(self._inf_0022_signal)
+            self.bms_received.to_show_0023_signal.connect(self._inf_0023_signal)
+            self._view.btn_start.setDisabled(True)
+            self._view.btn_stop.setDisabled(False)
+        else:
+            self._view.can_connect_error()
+            
+    def bcu_disconnect(self):
+        if SD.CAN_ON_OFF:
+            SD.CAN_ON_OFF = False
+            SD.START_RUN = False
+            SD.CAN_CONTROL.close_can()
+
+            # if self.bms_send_thread.isRunning():
+            #     self.bms_send_thread.quit()
+            #     self.bms_send_thread.wait()
+
+            # if self.bms_send_thread.isFinished():
+            #     del self.bms_send
+            #     del self.bms_send_thread
+
+            if self.bms_received_thread.isRunning():
+                self.bms_received_thread.quit()
+                self.bms_received_thread.wait()
+
+            if self.bms_received_thread.isFinished():
+                del self.bms_received
+                del self.bms_received_thread
+            self._view.btn_start.setDisabled(False)
+            self._view.btn_stop.setDisabled(True)
+            self.bms_status._view.label_bms_connect.setText("通讯未连接" if SD.SYSTEM_LANGUAGE == 0 else "Not Connected")
+            
+        else:
+            self._view.can_connect_error() 
+
+
+    def app_cut(self):
+        # return
+        main_window = QApplication.primaryScreen()
+        pixmap = main_window.grabWindow(QtWidgets.QApplication.desktop().winId())
+        pixmap.save("screenshot.png"); 
+        # QtWidgets.QWidget.screen().grabWindow(0).save()
+
+    def _get_master_id(self, data):
+        SD.BCU_LIST[data - 1] = 1
+        SD.BCU_LIFE_STATE[data - 1] = QDateTime.currentMSecsSinceEpoch()
+        current_secs_since_epoch = QDateTime.currentMSecsSinceEpoch()
+        for i in range(9):
+            if current_secs_since_epoch - SD.BCU_LIFE_STATE[i] > 2000:
+                SD.BCU_LIST[i] = 0
+        self._view.bcu_online_list_signal.emit(SD.BCU_LIST)
+
+    def _inf_0000_signal(self, data):
+        self._model.ccu_id = SD.BCU_ID
+
+        if SD.CCU_TYPE == 1:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_1, QColor(Qt.gray) if (data[0] & 0x01 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_2, QColor(Qt.gray) if (data[0] & 0x02 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_3, QColor(Qt.gray) if (data[0] & 0x04 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_4, QColor(Qt.gray) if (data[0] & 0x08 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_5, QColor(Qt.gray) if (data[0] & 0x10 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_6, QColor(Qt.gray) if (data[0] & 0x20 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_7, QColor(Qt.gray) if (data[0] & 0x40 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.di_8, QColor(Qt.gray) if (data[0] & 0x80 == 0) else QColor(Qt.green))
+
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_1, QColor(Qt.gray) if (data[1] & 0x01 == 0) else QColor(Qt.green))
+            self._model.p = data[1] & 0x01
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_2, QColor(Qt.gray) if (data[1] & 0x02 == 0) else QColor(Qt.green))
+            self._model.n = (data[1] & 0x02) >> 1
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_3, QColor(Qt.gray) if (data[1] & 0x04 == 0) else QColor(Qt.green))
+            self._model.pre = (data[1] & 0x04) >> 2
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_4, QColor(Qt.gray) if (data[1] & 0x08 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_5, QColor(Qt.gray) if (data[1] & 0x10 == 0) else QColor(Qt.green))
+            self._model.dlq = (data[1] & 0x10) >> 4
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_6, QColor(Qt.gray) if (data[1] & 0x20 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_7, QColor(Qt.gray) if (data[1] & 0x40 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_8, QColor(Qt.gray) if (data[1] & 0x80 == 0) else QColor(Qt.green))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.fjd_1, QColor(Qt.gray) if (data[2] & 0x01 == 0) else QColor(Qt.green))
+            self._model.gjd_first = data[2] & 0x01
+            set_edt_bg(self.bms_main_ctl._view.under_widget.fjd_1, QColor(Qt.gray) if (data[2] & 0x02 == 0) else QColor(Qt.green))
+            self._model.gjd_second = (data[2] & 0x02) >> 1
+            
+
+    def _inf_0001_signal(self, data):
+        # 系统状态
+        if data[0] & 0x0F == 0x00:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.gray))
+        elif data[0] & 0x0F == 0x01:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.gray))
+        elif data[0] & 0x0F == 0x02:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.gray))
+        elif data[0] & 0x0F == 0x03:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.gray))
+        elif data[0] & 0x0F == 0x04:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_high_no, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_chg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_dchg, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_stop, QColor(Qt.gray))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.sys_status_sleep, QColor(Qt.green))
+        
+        # 最高报警等级
+        if (data[0] & 0x30) >> 4 == 0x00:
+            self.bms_status._view.qrb_status_normal.setChecked(1)
+            self.bms_status._view.qrb_status_warn.setChecked(0)
+            self.bms_status._view.qrb_status_warner.setChecked(0)
+            self.bms_status._view.qrb_status_warnest.setChecked(0)
+        elif (data[0] & 0x30) >> 4 == 0x01:
+            self.bms_status._view.qrb_status_normal.setChecked(0)
+            self.bms_status._view.qrb_status_warn.setChecked(1)
+            self.bms_status._view.qrb_status_warner.setChecked(0)
+            self.bms_status._view.qrb_status_warnest.setChecked(0)
+        elif (data[0] & 0x30) >> 4 == 0x02:
+            self.bms_status._view.qrb_status_normal.setChecked(0)
+            self.bms_status._view.qrb_status_warn.setChecked(0)
+            self.bms_status._view.qrb_status_warner.setChecked(1)
+            self.bms_status._view.qrb_status_warnest.setChecked(0)
+        else:
+            self.bms_status._view.qrb_status_normal.setChecked(0)
+            self.bms_status._view.qrb_status_warn.setChecked(0)
+            self.bms_status._view.qrb_status_warner.setChecked(0)
+            self.bms_status._view.qrb_status_warnest.setChecked(1)
+    
+        self._model.fault_level = (data[0] & 0x30) >> 4
+
+        # 继电器
+        if SD.CCU_TYPE == 1:
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_1, QColor(Qt.gray) if (data[0] & 0x40 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_2, QColor(Qt.gray) if (data[0] & 0x80 == 0) else QColor(Qt.green))
+
+        # SOC
+        self.bms_main_ctl._view.top_widget.lb_soc_value.setText(str(round(data[1] * 0.4, 1)))
+        self._model.soc = round(data[1] * 0.4, 1)
+
+        # 总压
+        self.bms_main_ctl._view.top_widget.lb_tv_value.setText(str(round((data[3] << 8 | data[2]) * 0.1, 1)))
+        self._model.volt = round((data[3] << 8 | data[2]) * 0.1, 1)
+
+        # 电流
+        self.bms_main_ctl._view.top_widget.lb_tcur_value.setText(str(round((data[5] << 8 | data[4]) * 0.1 - 3200, 1)))
+        self._model.cur = round((data[5] << 8 | data[4]) * 0.1 - 3200, 1)
+
+        # SOH
+        self.bms_main_ctl._view.top_widget.lb_tsoh_value.setText(str(round(data[6] * 0.4, 1)))
+        self._model.soh = round(data[6] * 0.4, 1)
+
+        # MOS标志
+        if SD.CCU_TYPE == 0: 
+            set_edt_bg(self.bms_main_ctl._view.under_widget.mos_dchg, QColor(Qt.gray) if (data[7] & 0x01 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.mos_chg, QColor(Qt.gray) if (data[7] & 0x02 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.mos_pre, QColor(Qt.gray) if (data[7] & 0x04 == 0) else QColor(Qt.green))
+        
+        if SD.CCU_TYPE == 1: 
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_4, QColor(Qt.gray) if (data[7] & 0x08 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_3, QColor(Qt.gray) if (data[7] & 0x40 == 0) else QColor(Qt.green))
+            set_edt_bg(self.bms_main_ctl._view.under_widget.do_5, QColor(Qt.gray) if (data[7] & 0x80 == 0) else QColor(Qt.green))
+
+        set_edt_bg(self.bms_main_ctl._view.under_widget.permit_chg, QColor(Qt.gray) if (data[0] & 0x40 == 0) else QColor(Qt.red))
+        set_edt_bg(self.bms_main_ctl._view.under_widget.permit_dchg, QColor(Qt.gray) if (data[0] & 0x80 == 0) else QColor(Qt.red))
+
+
+    def _inf_0002_signal(self, data):
+        # 单体过压告警
+        if data[0] & 0x03 == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.over_cell_warn, QColor(Qt.gray))
+        elif data[0] & 0x03 == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.over_cell_warn, QColor(Qt.red))
+        elif data[0] & 0x03 == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.over_cell_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.over_cell_warn, QColor(Qt.yellow))
+
+        # 总压过压告警
+        if (data[0] & 0x0C >> 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.hv_warn, QColor(Qt.gray))
+        elif (data[0] & 0x0C >> 2) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.hv_warn, QColor(Qt.red))
+        elif (data[0] & 0x0C >> 2) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.hv_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.hv_warn, QColor(Qt.yellow))
+
+        # 单体欠压告警
+        if (data[0] & 0x30 >> 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.under_cell_warn, QColor(Qt.gray))
+        elif (data[0] & 0x30 >> 4) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.under_cell_warn, QColor(Qt.red))
+        elif (data[0] & 0x30 >> 4) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.under_cell_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.under_cell_warn, QColor(Qt.yellow))
+
+        # 总压欠压告警
+        if (data[0] & 0xC0 >> 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.lv_warn, QColor(Qt.gray))
+        elif (data[0] & 0xC0 >> 6) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.lv_warn, QColor(Qt.red))
+        elif (data[0] & 0xC0 >> 6) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.lv_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.lv_warn, QColor(Qt.yellow))
+
+        # =====================================================================================
+        # 充电低温告警
+        if data[1] & 0x03 == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_lt_warn, QColor(Qt.gray))
+        elif data[1] & 0x03 == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_lt_warn, QColor(Qt.red))
+        elif data[1] & 0x03 == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_lt_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_lt_warn, QColor(Qt.yellow))
+
+        # 充电高温告警
+        if (data[1] & 0x0C >> 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_ht_warn, QColor(Qt.gray))
+        elif (data[1] & 0x0C >> 2) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_ht_warn, QColor(Qt.red))
+        elif (data[1] & 0x0C >> 2) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_ht_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_ht_warn, QColor(Qt.yellow))
+
+        # 放电低温告警
+        if (data[1] & 0x30 >> 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_lt_warn, QColor(Qt.gray))
+        elif (data[1] & 0x30 >> 4) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_lt_warn, QColor(Qt.red))
+        elif (data[1] & 0x30 >> 4) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_lt_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_lt_warn, QColor(Qt.yellow))
+
+        # 放电高温告警
+        if (data[1] & 0xC0 >> 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_ht_warn, QColor(Qt.gray))
+        elif (data[1] & 0xC0 >> 6) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_ht_warn, QColor(Qt.red))
+        elif (data[1] & 0xC0 >> 6) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_ht_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_ht_warn, QColor(Qt.yellow))
+
+        # =====================================================================================
+        # 充电过流告警
+        if data[2] & 0x03 == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_hcur_warn, QColor(Qt.gray))
+        elif data[2] & 0x03 == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_hcur_warn, QColor(Qt.red))
+        elif data[2] & 0x03 == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_hcur_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_hcur_warn, QColor(Qt.yellow))
+
+        # 放电过流告警
+        if (data[2] & 0x0C >> 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_hcur_warn, QColor(Qt.gray))
+        elif (data[2] & 0x0C >> 2) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_hcur_warn, QColor(Qt.red))
+        elif (data[2] & 0x0C >> 2) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_hcur_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_hcur_warn, QColor(Qt.yellow))
+
+        # 单体压差告警
+        if (data[2] & 0x30 >> 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_vol_warn, QColor(Qt.gray))
+        elif (data[2] & 0x30 >> 4) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_vol_warn, QColor(Qt.red))
+        elif (data[2] & 0x30 >> 4) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_vol_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_vol_warn, QColor(Qt.yellow))
+
+        # 单体温差告警
+        if (data[2] & 0xC0 >> 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_temp_warn, QColor(Qt.gray))
+        elif (data[2] & 0xC0 >> 6) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_temp_warn, QColor(Qt.red))
+        elif (data[2] & 0xC0 >> 6) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_temp_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.diff_cell_temp_warn, QColor(Qt.yellow))
+
+        # =====================================================================================
+        # 绝缘过低报警
+        if data[3] & 0x03 == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.against_warn, QColor(Qt.gray))
+        elif data[3] & 0x03 == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.against_warn, QColor(Qt.red))
+        elif data[3] & 0x03 == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.against_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.against_warn, QColor(Qt.yellow))
+
+        # 正极绝缘过低报警
+        if (data[3] & 0x0C >> 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.gray))
+        elif (data[3] & 0x0C >> 2) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.red))
+        elif (data[3] & 0x0C >> 2) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.yellow))
+
+        # 负极绝缘过低报警
+        if (data[3] & 0x30 >> 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.gray))
+        elif (data[3] & 0x30 >> 4) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.red))
+        elif (data[3] & 0x30 >> 4) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_against_warn, QColor(Qt.yellow))
+
+        # 极柱温度过高
+        if (data[3] & 0xC0 >> 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.gray))
+        elif (data[3] & 0xC0 >> 6) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.red))
+        elif (data[3] & 0xC0 >> 6) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.yellow))
+
+        # =====================================================================================
+        # 总压检测故障
+        if a_bit(data[4], 1) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.vol_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.vol_fault, QColor(Qt.red))
+        
+        # 总压检测故障
+        if a_bit(data[4], 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cur_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cur_fault, QColor(Qt.red))
+
+        # 总控通讯故障
+        if a_bit(data[4], 3) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_control_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_control_fault, QColor(Qt.red))
+
+        # BMU通讯故障
+        if a_bit(data[4], 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.bmu_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.bmu_fault, QColor(Qt.red))
+
+        # 急停
+        if a_bit(data[4], 5) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.stop_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.stop_fault, QColor(Qt.red))
+
+        # NTC故障
+        if a_bit(data[4], 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ntc_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ntc_fault, QColor(Qt.red))
+
+        # AFE失效
+        if a_bit(data[4], 7) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.afe_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.afe_fault, QColor(Qt.red))
+
+        # 主正接触器故障
+        if a_bit(data[4], 8) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.p_fault, QColor(Qt.red))
+
+        # =====================================================================================
+        # 主负接触器故障
+        if a_bit(data[5], 1) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.n_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.n_fault, QColor(Qt.red))
+        
+        # 预充故障
+        if a_bit(data[5], 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.pre_chg_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.pre_chg_fault, QColor(Qt.red))
+
+        # 充电MOS故障
+        if a_bit(data[5], 3) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_mos_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.chg_mos_fault, QColor(Qt.red))
+
+        # 放电MOS故障
+        if a_bit(data[5], 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_mos_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dchg_mos_fault, QColor(Qt.red))
+
+        # 风扇控制失效
+        if a_bit(data[5], 5) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.fan_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.fan_fault, QColor(Qt.red))
+
+        # 热失控故障
+        if a_bit(data[5], 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.temp_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.temp_fault, QColor(Qt.red))
+
+        # 温升过高故障
+        if a_bit(data[5], 7) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.temp_up_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.temp_up_fault, QColor(Qt.red))
+
+        # 中间接触器故障
+        if a_bit(data[5], 8) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.center_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.center_fault, QColor(Qt.red))
+
+        # =====================================================================================
+        # 单体断线故障
+        if a_bit(data[6], 1) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cell_single_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cell_single_fault, QColor(Qt.red))
+        
+        # 主控硬件故障
+        if a_bit(data[6], 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_hard_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_hard_fault, QColor(Qt.red))
+
+        # 主控初始化故障
+        if a_bit(data[6], 3) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_start_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_start_fault, QColor(Qt.red))
+
+        # EEPROM故障
+        if a_bit(data[6], 4) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.eeprom_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.eeprom_fault, QColor(Qt.red))
+
+        # 熔断器故障
+        if a_bit(data[6], 5) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.rdq_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.rdq_fault, QColor(Qt.red))
+
+        # 断路器反馈故障
+        if a_bit(data[6], 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dlq_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.dlq_fault, QColor(Qt.red))
+
+        # 簇间压差故障
+        if a_bit(data[6], 7) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_diff_vol_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_diff_vol_fault, QColor(Qt.red))
+
+        # PCS通讯故障
+        if a_bit(data[6], 8) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.pcs_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.pcs_fault, QColor(Qt.red))
+
+        # =====================================================================================
+        # 跳机故障
+        if a_bit(data[7], 1) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jump_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jump_fault, QColor(Qt.red))
+        
+        # 极柱温度过高故障
+        if a_bit(data[7], 2) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.jz_ht_warn, QColor(Qt.red))
+
+        # 主控检测温度过高故障
+        if a_bit(data[7], 3) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_ht_warn, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.ccu_ht_warn, QColor(Qt.red))
+
+        # MOS温度过高故障
+        if (data[7] & 0x18 >> 3) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.mos_ht_warn, QColor(Qt.gray))
+        elif (data[7] & 0x18 >> 3) == 1:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.mos_ht_warn, QColor(Qt.red))
+        elif (data[2] & 0x18 >> 3) == 2:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.mos_ht_warn, QColor(Qt.magenta))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.mos_ht_warn, QColor(Qt.yellow))
+
+        # 电芯故障
+        if a_bit(data[7], 6) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cell_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.cell_fault, QColor(Qt.red))
+
+        # SOC过低故障
+        if a_bit(data[7], 7) == 0:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.soc_fault, QColor(Qt.gray))
+        else:
+            set_edt_bg(self.bms_main_ctl._view.center_widget.soc_fault, QColor(Qt.red))
+
+
+    def _inf_0003_signal(self, data):
+        # 最高单体电压值
+        self.bms_main_ctl._view.top_widget.lb_tcellhv_value.setText(str(data[1] << 8 | data[0]))
+        self._model.max_cell_volt = data[1] << 8 | data[0]
+        # 最高单体电压所在编号
+        self.bms_main_ctl._view.top_widget.lb_tcellhv_index_value.setText(str(data[3] << 8 | data[2]))
+        self._model.max_cell_volt_id = data[3] << 8 | data[2]
+        # 最低单体电压值
+        self.bms_main_ctl._view.top_widget.lb_tcelllv_value.setText(str(data[5] << 8 | data[4]))
+        self._model.min_cell_volt = data[5] << 8 | data[4]
+        # 最低单体电压所在编号
+        self.bms_main_ctl._view.top_widget.lb_tcelllv_index_value.setText(str(data[7] << 8 | data[6]))
+        self._model.min_cell_volt_id = data[7] << 8 | data[6]
+
+
+    def _inf_0004_signal(self, data):
+        # 最大压差
+        self.bms_main_ctl._view.top_widget.lb_diff_vol_value.setText(str(data[1] << 8 | data[0]))
+        # 平均电压
+        self.bms_main_ctl._view.top_widget.lb_avg_vol_value.setText(str(data[3] << 8 | data[2]))
+        self._model.avg_cell_volt = data[3] << 8 | data[2]
+        # 最大温差
+        self.bms_main_ctl._view.top_widget.lb_diff_temp_value.setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)))
+        # 平均温度
+        self.bms_main_ctl._view.top_widget.lb_avg_temp_value.setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)))
+        self._model.avg_cell_temp = round((data[7] << 8 | data[6]) * 0.1 - 40, 1)
+
+    def _inf_0005_signal(self, data):
+        # 最高单体温度值
+        self.bms_main_ctl._view.top_widget.lb_h_temp_value.setText(str(round((data[1] << 8 | data[0]) * 0.1 - 40, 1)))
+        self._model.max_cell_temp = round((data[1] << 8 | data[0]) * 0.1 - 40, 1)
+        # 最高单体温度所在编号
+        self.bms_main_ctl._view.top_widget.lb_h_temp_index_value.setText(str(data[3] << 8 | data[2]))
+        self._model.max_cell_temp_id = data[3] << 8 | data[2]
+        # 最低单体温度值
+        self.bms_main_ctl._view.top_widget.lb_l_temp_value.setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)))
+        self._model.min_cell_temp = round((data[5] << 8 | data[4]) * 0.1 - 40, 1)
+        # # 最低单体温度所在编号
+        # self.bms_main_ctl._view.top_widget.lb_tcelllv_index_value.setText(str(data[7] << 8 | data[6]))
+        self._model.min_cell_temp_id = data[7] << 8 | data[6]
+
+
+    def _inf_0006_signal(self, data):
+        # 当前允许最大放电功率
+        self.bms_main_ctl._view.top_widget.lb_dchg_kw_value.setText(str(round((data[1] << 8 | data[0]) * 0.1, 1)))
+        # 当前允许最大充电功率
+        self.bms_main_ctl._view.top_widget.lb_chg_kw_value.setText(str(round((data[3] << 8 | data[2]) * 0.1, 1)))
+        # # 当前可放电量
+        # self.bms_main_ctl._view.top_widget.lb_.setText(str((data[5] << 8 | data[4]) * 0.1 - 40))
+        # # 当前可充电量
+        # self.bms_main_ctl._view.top_widget.lb_avg_temp_value.setText(str((data[7] << 8 | data[6]) * 0.1 - 40))
+
+
+    def _inf_0007_signal(self, data):
+        # 当前允许最大充电电压
+        self.bms_main_ctl._view.top_widget.lb_max_chg_vol_value.setText(str(round((data[1] << 8 | data[0]) * 0.1, 1)))
+        # 当前允许最大充电电流
+        self.bms_main_ctl._view.top_widget.lb_max_chg_cur_value.setText(str(round((data[3] << 8 | data[2]) * 0.1 - 3200, 1)))
+        # 当前允许最大放电电流
+        self.bms_main_ctl._view.top_widget.lb_max_dchg_cur_value.setText(str(round((data[5] << 8 | data[4]) * 0.1 - 3200, 1)))
+        # 当前允许放电限制电压
+        self.bms_main_ctl._view.top_widget.lb_max_dchg_vol_value.setText(str(round((data[7] << 8 | data[6]) * 0.1, 1)))
+
+    def _inf_0008_signal(self, data):
+        # 电池组单体电压累加和
+        self.bms_main_ctl._view.top_widget.lb_sum_vol_value.setText(str(round((data[1] << 8 | data[0]) * 0.1, 1)))
+        # 总压一检测
+        self.bms_main_ctl._view.top_widget.lb_tv_value.setText(str(round((data[3] << 8 | data[2]) * 0.1, 1)))
+        # 总压二检测
+        self.bms_main_ctl._view.top_widget.lb_tv_2_value.setText(str(round((data[5] << 8 | data[4]) * 0.1, 1)))
+        # 总压三检测
+        self.bms_main_ctl._view.top_widget.lb_tv_3_value.setText(str(round((data[7] << 8 | data[6]) * 0.1, 1)))
+    
+
+    def _inf_0009_signal(self, data):
+        # 电池组标称容量
+        self.bms_main_ctl._view.top_widget.lb_nom_cap_value.setText(str(round((data[1] << 8 | data[0]) * 0.1, 1)))
+        # 电池组总容量
+        self.bms_main_ctl._view.top_widget.lb_all_cap_value.setText(str(round((data[3] << 8 | data[2]) * 0.1, 1)))
+        # 电池组剩余容量
+        self.bms_main_ctl._view.top_widget.lb_left_cap_value.setText(str(round((data[5] << 8 | data[4]) * 0.1, 1)))
+        # SOE
+        self.bms_main_ctl._view.top_widget.lb_tsoe_value.setText(str(round(data[6] * 0.4, 1)))
+   
+
+    def _inf_000A_signal(self, data):
+        # 最高单体SOC
+        self.bms_main_ctl._view.top_widget.lb_soc_high_value.setText(str(round((data[1] << 8 | data[0]) * 0.4, 1)))
+        self._model.max_soc = round((data[1] << 8 | data[0]) * 0.4, 1)
+        # 最低单体SOC
+        self.bms_main_ctl._view.top_widget.lb_soc_low_value.setText(str(round((data[3] << 8 | data[2]) * 0.4, 1)))
+        self._model.min_soc = round((data[3] << 8 | data[2]) * 0.4, 1)
+        # 平均单体SOC
+        self.bms_main_ctl._view.top_widget.lb_soc_avg_value.setText(str(round((data[5] << 8 | data[4]) * 0.4, 1)))
+        self._model.avg_soc = round((data[5] << 8 | data[4]) * 0.4, 1)
+        # 循环次数
+        self.bms_main_ctl._view.top_widget.lb_circle_num_value.setText(str(data[7] << 8 | data[6]))
+
+    def _inf_000B_signal(self, data):
+        # 电池组标称能量
+        self.bms_main_ctl._view.top_widget.lb_nom_energy_value.setText(str(round((data[1] << 8 | data[0]) * 0.1, 1)))
+        # 电池组总能量
+        self.bms_main_ctl._view.top_widget.lb_all_energy_value.setText(str(round((data[3] << 8 | data[2]) * 0.1, 1)))
+        # 电池组剩余能量
+        self.bms_main_ctl._view.top_widget.lb_left_energy_value.setText(str(round((data[5] << 8 | data[4]) * 0.1, 1)))
+        # 供电采样电压
+        self.bms_main_ctl._view.top_widget.lb_gdcy_vol_value.setText(str(round((data[7] << 8 | data[6]) * 0.1, 1)))
+
+
+    def _inf_000C_signal(self, data):
+        # 累计放电电量
+        self.bms_main_ctl._view.top_widget.lb_chg_kwh_value.setText(str(round((data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]) * 0.01, 2)))
+        # 累计充电电量
+        self.bms_main_ctl._view.top_widget.lb_dchg_kwh_value.setText(str(round((data[7] << 24 | data[6] << 16 | data[5] << 8 | data[4]) * 0.01, 2)))
+    
+
+    def _inf_000D_signal(self, data):
+        # 当天累计放电电量
+        self.bms_main_ctl._view.top_widget.lb_nowday_chg_energy_value.setText(str(round((data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]) * 0.01, 2)))
+        # 当天累计充电电量
+        self.bms_main_ctl._view.top_widget.lb_nowday_dchg_energy_value.setText(str(round((data[7] << 24 | data[6] << 16 | data[5] << 8 | data[4]) * 0.01, 2)))
+    
+
+    def _inf_000E_signal(self, data):
+        # 系统对地绝缘阻值
+        self.bms_main_ctl._view.top_widget.lb_sys_against_value.setText(str(data[1] << 8 | data[0]))
+        # 正母线对地绝缘阻值
+        self.bms_main_ctl._view.top_widget.lb_sys_p_against_value.setText(str(data[3] << 8 | data[2]))
+        # 负母线对地绝缘阻值
+        self.bms_main_ctl._view.top_widget.lb_sys_n_against_value.setText(str(data[5] << 8 | data[4]))
+
+
+    def _inf_000F_signal(self, data):
+        # 单体电压
+        if data[1] == 0:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 1).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 1).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 1).setText(str(data[7] << 8 | data[6]) + " mV")   
+
+        if data[1] == 1:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 1).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 4).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 4).setText(str(data[7] << 8 | data[6]) + " mV")   
+
+        if data[1] == 2:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 4).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 4).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 7).setText(str(data[7] << 8 | data[6]) + " mV")   
+
+        if data[1] == 3:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 7).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 7).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 7).setText(str(data[7] << 8 | data[6]) + " mV") 
+
+        if data[1] == 4:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 10).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 10).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 10).setText(str(data[7] << 8 | data[6]) + " mV") 
+
+        if data[1] == 5:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 10).setText(str(data[3] << 8 | data[2]) + " mV")
+
+        if data[0] < 25:
+            # 单体信息页面
+            self.bms_cell_ctl._view.cell_vol_table.cellWidget(3 * data[1], data[0] + 1).setText(str(data[3] << 8 | data[2]) + " mV")
+            self.bms_cell_ctl._view.cell_vol_table.cellWidget(3 * data[1] + 1, data[0] + 1).setText(str(data[5] << 8 | data[4]) + " mV")   
+            self.bms_cell_ctl._view.cell_vol_table.cellWidget(3 * data[1] + 2, data[0] + 1).setText(str(data[7] << 8 | data[6]) + " mV")   
+            
+            self.cell_single_volt[3 * data[1]] = data[3] << 8 | data[2]
+            self.cell_single_volt[3 * data[1] + 1] = data[5] << 8 | data[4]
+            self.cell_single_volt[3 * data[1] + 2] = data[7] << 8 | data[6]
+
+            self._model.cell_volt = self.cell_single_volt
+
+            # 硬件校准页面
+            if (self.bms_hard_ctl._view.cb_bmu_index.currentIndex() == data[0]):
+                self.bms_hard_ctl._view.hard_table.item(3 * data[1], 3).setText(str(data[3] << 8 | data[2]))
+                self.bms_hard_ctl._view.hard_table.item(3 * data[1] + 1, 3).setText(str(data[5] << 8 | data[4]))
+                self.bms_hard_ctl._view.hard_table.item(3 * data[1] + 2, 3).setText(str(data[7] << 8 | data[6]))
+
+
+    def _inf_0010_signal(self, data):
+        # 单体温度
+        if data[1] == 0:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 2).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 2).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 2).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")
+
+        if data[1] == 1:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 2).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 5).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")  
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 5).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")
+
+        if data[1] == 2:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 5).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 5).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 8).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")
+        if data[1] == 3:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 8).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 8).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 8).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")
+
+        if data[1] == 4:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(0, 11).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(1, 11).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(2, 11).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")
+
+        if data[1] == 5:
+            self.bms_cell_ctl._view.home_cell_table.cellWidget(3, 11).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+
+        if data[0] < 25: 
+            self.bms_cell_ctl._view.cell_temp_table.cellWidget(3 * data[1], data[0] + 1).setText(str(round((data[3] << 8 | data[2]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.cell_temp_table.cellWidget(3 * data[1] + 1, data[0] + 1).setText(str(round((data[5] << 8 | data[4]) * 0.1 - 40, 1)) + " ℃")
+            self.bms_cell_ctl._view.cell_temp_table.cellWidget(3 * data[1] + 2, data[0] + 1).setText(str(round((data[7] << 8 | data[6]) * 0.1 - 40, 1)) + " ℃")   
+
+            self.cell_single_temp[3 * data[1]] = round((data[3] << 8 | data[2]) * 0.1 - 40, 1)
+            self.cell_single_temp[3 * data[1] + 1] = round((data[5] << 8 | data[4]) * 0.1 - 40, 1)
+            self.cell_single_temp[3 * data[1] + 2] = round((data[7] << 8 | data[6]) * 0.1 - 40, 1)
+
+            self._model.cell_temp = self.cell_single_temp
+
+    # to do
+    def _inf_0011_signal(self, data):
+        # 最高单体电压所在从控编号
+        self.bms_main_ctl._view.top_widget.lb_tcellhv_slave_index_value.setText(str(data[0]))
+        # 最高单体电压所在从控内编号
+        self.bms_main_ctl._view.top_widget.lb_tcellhv_in_index_value.setText(str(data[1]))
+        # 最高单体温度所在从控编号
+        self.bms_main_ctl._view.top_widget.lb_h_temp_slave_index_value.setText(str(data[2]))
+        # 最高单体温度所在从控内编号
+        self.bms_main_ctl._view.top_widget.lb_h_temp_in_index_value.setText(str(data[3]))
+        # 最低单体电压所在从控编号
+        self.bms_main_ctl._view.top_widget.lb_tcelllv_slave_index_value.setText(str(data[4]))
+        # 最低单体电压所在从控内编号
+        self.bms_main_ctl._view.top_widget.lb_tcelllv_in_index_value.setText(str(data[5]))
+        # to do
+        # # 最低单体温度所在从控编号
+        # self.bms_main_ctl._view.top_widget.lb_l_temp_slave_index_value.setText(str(data[6]))
+        # # 最低单体温度所在从控内编号
+        # self.bms_main_ctl._view.top_widget.lb_h_temp_in_index_value.setText(str(data[7]))
+
+    def _inf_0012_signal(self, data):
+        return
+        # if SD.CCU_TYPE == 1:
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_1, QColor(Qt.gray) if (data[0] & 0x01 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_2, QColor(Qt.gray) if (data[0] & 0x02 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_3, QColor(Qt.gray) if (data[0] & 0x04 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_4, QColor(Qt.gray) if (data[0] & 0x08 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_5, QColor(Qt.gray) if (data[0] & 0x10 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_6, QColor(Qt.gray) if (data[0] & 0x20 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_7, QColor(Qt.gray) if (data[0] & 0x40 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.di_8, QColor(Qt.gray) if (data[0] & 0x80 == 0) else QColor(Qt.green))
+
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_1, QColor(Qt.gray) if (data[1] & 0x01 == 0) else QColor(Qt.green))
+        #     self._model.p(data[1] & 0x01)
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_2, QColor(Qt.gray) if (data[1] & 0x02 == 0) else QColor(Qt.green))
+        #     self._model.n((data[1] & 0x02) >> 1)
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_3, QColor(Qt.gray) if (data[1] & 0x04 == 0) else QColor(Qt.green))
+        #     self._model.pre((data[1] & 0x04) >> 2)
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_4, QColor(Qt.gray) if (data[1] & 0x08 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_5, QColor(Qt.gray) if (data[1] & 0x10 == 0) else QColor(Qt.green))
+        #     self._model.dlq((data[1] & 0x10) >> 4)
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_6, QColor(Qt.gray) if (data[1] & 0x20 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_7, QColor(Qt.gray) if (data[1] & 0x40 == 0) else QColor(Qt.green))
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.do_8, QColor(Qt.gray) if (data[1] & 0x80 == 0) else QColor(Qt.green))
+        # else:
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.fjd_1, QColor(Qt.gray) if (data[2] & 0x01 == 0) else QColor(Qt.green))
+        #     self._model.gjd_first(data[2] & 0x01)
+        #     set_edt_bg(self.bms_main_ctl._view.under_widget.fjd_1, QColor(Qt.gray) if (data[2] & 0x02 == 0) else QColor(Qt.green))
+        #     self._model.gjd_second((data[2] & 0x02) >> 1)
+              
+
+    # def _inf_0013_signal(self, data):
+    #     # BMS 电池编码								
+    #     self.bms_sn_version = ["" for i in range(8)]
+    #     self.bms_sn_version[0] = chr(data[0])
+    #     self.bms_sn_version[1] = chr(data[1])
+    #     self.bms_sn_version[2] = chr(data[2])
+    #     self.bms_sn_version[3] = chr(data[3])
+    #     self.bms_sn_version[4] = chr(data[4])
+    #     self.bms_sn_version[5] = chr(data[5])
+    #     self.bms_sn_version[6] = chr(data[6])
+    #     self.bms_sn_version[7] = chr(data[7])
+    #     bms_sn_version = ''.join(self.bms_sn_version)
+    #     self.bms_download_ctl._view.message_table.cellWidget(5, 2).setText(bms_sn_version)
+
+
+    def _inf_0013_signal(self, data):
+        # BMS 硬件版本号
+        self.bms_hard_version = ["" for i in range(8)]
+        self.bms_hard_version[0] = chr(data[0])
+        self.bms_hard_version[1] = chr(data[1])
+        self.bms_hard_version[2] = chr(data[2])
+        self.bms_hard_version[3] = chr(data[3])
+        self.bms_hard_version[4] = chr(data[4])
+        self.bms_hard_version[5] = chr(data[5])
+        self.bms_hard_version[6] = chr(data[6])
+        self.bms_hard_version[7] = chr(data[7])
+        bms_hard_version = ''.join(self.bms_hard_version)
+        self.bms_download_ctl._view.message_table.item(3, 2).setText(bms_hard_version)
+    
+
+    def _inf_0014_signal(self, data):
+        # BMS Boot版本号
+        self.bms_boot_version = ["" for i in range(8)]
+        self.bms_boot_version[0] = chr(data[0])
+        self.bms_boot_version[1] = chr(data[1])
+        self.bms_boot_version[2] = chr(data[2])
+        self.bms_boot_version[3] = chr(data[3])
+        self.bms_boot_version[4] = chr(data[4])
+        self.bms_boot_version[5] = chr(data[5])
+        self.bms_boot_version[6] = chr(data[6])
+        self.bms_boot_version[7] = chr(data[7])
+        bms_boot_version = ''.join(self.bms_boot_version)
+        self.bms_download_ctl._view.message_table.item(0, 2).setText(bms_boot_version)
+
+
+    def _inf_0016_signal(self, data):
+        # BMS 软件版本号
+        self.bms_soft_version = ["" for i in range(8)]
+        self.bms_soft_version[0] = chr(data[0])
+        self.bms_soft_version[1] = chr(data[1])
+        self.bms_soft_version[2] = chr(data[2])
+        self.bms_soft_version[3] = chr(data[3])
+        self.bms_soft_version[4] = chr(data[4])
+        self.bms_soft_version[5] = chr(data[5])
+        self.bms_soft_version[6] = chr(data[6])
+        self.bms_soft_version[7] = chr(data[7])
+        bms_soft_version = ''.join(self.bms_soft_version)
+        self.bms_download_ctl._view.message_table.item(1, 2).setText(bms_soft_version)
+
+
+    def _inf_0015_signal(self, data):
+        # BMS 算法版本号								
+        self.bms_sf_version = ["" for i in range(8)]
+        self.bms_sf_version[0] = chr(data[0])
+        self.bms_sf_version[1] = chr(data[1])
+        self.bms_sf_version[2] = chr(data[2])
+        self.bms_sf_version[3] = chr(data[3])
+        self.bms_sf_version[4] = chr(data[4])
+        self.bms_sf_version[5] = chr(data[5])
+        self.bms_sf_version[6] = chr(data[6])
+        self.bms_sf_version[7] = chr(data[7])
+        bms_sf_version = ''.join(self.bms_sf_version)
+        self.bms_download_ctl._view.message_table.item(2, 2).setText(bms_sf_version)
+
+
+    def _inf_0017_signal(self, data):
+        # RTC时钟
+        self.bms_hard_ctl._view.lb_rtc.setText(str(data[0] + 2000)+ "-" + str(data[1]) + "-" + str(data[2])+ " " + str(data[3]) + ":" + str(data[4]) + ":" + str(data[5]))
+
+
+    def _inf_0018_signal(self, data):
+        # 电池均衡状态
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_0019_signal(self, data):
+        # 电池均衡状态
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[5], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.green))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.on_off_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_001A_signal(self, data):
+        # 电池均衡故障
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_001B_signal(self, data):
+        # 电池均衡故障
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[5], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.balance_fault_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_001C_signal(self, data):
+        # 电池连接线状态
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 1).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 9).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 17).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 25).widget(), QtGui.QColor(Qt.white))
+        # for i in range(8):
+        #     if a_bit(data[1], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 1, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 1, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[2], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 9, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 9, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[3], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 17, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 17, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[4], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 25, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 25, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_001D_signal(self, data):
+        # 电池连接线状态
+        for i in range(8):
+            if a_bit(data[1], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 33).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[2], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 41).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[3], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 49).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[4], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 57).widget(), QtGui.QColor(Qt.white))
+            if a_bit(data[5], i + 1) == 1:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.red))
+            else:
+                set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(data[0] - 1, i + 65).widget(), QtGui.QColor(Qt.white))
+        # for i in range(8):
+        #     if a_bit(data[1], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 33, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 33, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[2], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 41, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 41, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[3], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 49, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 49, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[4], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 57, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 57, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+        #     if a_bit(data[5], i + 1) == 1:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 65, data[0] + 1).widget(), QtGui.QColor(Qt.red))
+        #     else:
+        #         set_edt_bg(self.bms_balance_ctl._view.line_qscrollarea_layout.itemAtPosition(i + 65, data[0] + 1).widget(), QtGui.QColor(Qt.white))
+
+
+    def _inf_001E_signal(self, data):
+        return  
+
+    def _inf_001F_signal(self, data):
+        return
+
+    def _inf_0020_signal(self, data):
+        # BMS 电池编码								
+        self.bms_sn_version[0] = chr(data[0])
+        self.bms_sn_version[1] = chr(data[1])
+        self.bms_sn_version[2] = chr(data[2])
+        self.bms_sn_version[3] = chr(data[3])
+        self.bms_sn_version[4] = chr(data[4])
+        self.bms_sn_version[5] = chr(data[5])
+        self.bms_sn_version[6] = chr(data[6])
+        self.bms_sn_version[7] = chr(data[7])
+
+    def _inf_0021_signal(self, data):
+        self.bms_sn_version[8] = chr(data[0])
+        self.bms_sn_version[9] = chr(data[1])
+        self.bms_sn_version[10] = chr(data[2])
+        self.bms_sn_version[11] = chr(data[3])
+        self.bms_sn_version[12] = chr(data[4])
+        self.bms_sn_version[13] = chr(data[5])
+        self.bms_sn_version[14] = chr(data[6])
+        self.bms_sn_version[15] = chr(data[7])
+
+        bms_sn_version = ''.join(self.bms_sn_version)
+        self.bms_download_ctl._view.message_table.item(4, 2).setText(bms_sn_version)
+
+    def _inf_0022_signal(self, data):
+        # BMS 电池编码								
+        self.battery_sn_version[0] = chr(data[0])
+        self.battery_sn_version[1] = chr(data[1])
+        self.battery_sn_version[2] = chr(data[2])
+        self.battery_sn_version[3] = chr(data[3])
+        self.battery_sn_version[4] = chr(data[4])
+        self.battery_sn_version[5] = chr(data[5])
+        self.battery_sn_version[6] = chr(data[6])
+        self.battery_sn_version[7] = chr(data[7])
+
+    def _inf_0023_signal(self, data):
+        self.battery_sn_version[8] = chr(data[0])
+        self.battery_sn_version[9] = chr(data[1])
+        self.battery_sn_version[10] = chr(data[2])
+        self.battery_sn_version[11] = chr(data[3])
+        self.battery_sn_version[12] = chr(data[4])
+        self.battery_sn_version[13] = chr(data[5])
+        self.battery_sn_version[14] = chr(data[6])
+        self.battery_sn_version[15] = chr(data[7])
+
+        battery_sn_version = ''.join(self.battery_sn_version)
+        self.bms_download_ctl._view.message_table.item(5, 2).setText(battery_sn_version)
+        self.bms_status._view.lb_bms_sn.setText("BATSN:" + battery_sn_version)
+
+        dataTime = QDateTime.currentDateTime()
+        text = dataTime.toString("yyyy-MM-dd HH:mm:ss")
+        self._model.now_time = text
+
+    
+    def run(self):
+        self._view.show()

+ 78 - 0
controller/bms_login_ctl.py

@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from sys import argv
+from utils.globalvar import SD
+from widget.bms_login import Win_Login
+from controller.bms_home_ctl import BmsHomeControll
+from utils.qt import QApplication
+
+class BmsLoginControll:
+    def __init__(self):
+        # 不需要从命令行输入参数
+        self._app = QApplication(argv)
+        self._view = Win_Login()
+        self.init()
+
+    def init(self):
+        self._view.login_signal.connect(self._verify_user)
+        self._view.cancel_signal.connect(self._login_cancel)
+        self._view.home_show_signal.connect(self._show_main)
+        self._view.language_signal.connect(self._change_language)
+
+    def _verify_user(self):
+        password = self._view.edt_password.text().strip()
+        if self._view.cb_role.currentIndex() == 0:
+            self._view.on_success()
+        elif self._view.cb_role.currentIndex() == 1:
+            if password == "embmstest":
+                self._view.on_success()
+            else:
+                self._view.on_error()
+        elif self._view.cb_role.currentIndex() == 2:
+            if password == "embms":
+                self._view.on_success()
+            else:
+                self._view.on_error()
+        elif self._view.cb_role.currentIndex() == 3:
+            if password == "embmspack":
+                self._view.on_success()
+            else:
+                self._view.on_error()
+        elif self._view.cb_role.currentIndex() == 4:
+            if password == "embmsAdministrator":
+                self._view.on_success()
+            else:
+                self._view.on_error()
+
+    def _show_main(self):
+        self.home = BmsHomeControll()
+        self.home.run()
+
+    def _login_cancel(self):
+        self._view.close()
+
+    def _change_language(self, index):
+        SD.SYSTEM_LANGUAGE = index
+        self._view.setWindowTitle("用户登录" if SD.SYSTEM_LANGUAGE == 0 else "Login")
+        self._view.lb_role.setText("登录角色" if SD.SYSTEM_LANGUAGE == 0 else "Role")
+        self._view.lb_password.setText("登录密码" if SD.SYSTEM_LANGUAGE == 0 else "PassWord")
+        self._view.lb_prj.setText("登录项目" if SD.SYSTEM_LANGUAGE == 0 else "Project")
+        self._view.lb_con_type.setText("通讯类型" if SD.SYSTEM_LANGUAGE == 0 else "Conn Type")
+        self._view.lb_channel.setText("索引号" if SD.SYSTEM_LANGUAGE == 0 else "Index")
+        self._view.lb_index.setText("通道号" if SD.SYSTEM_LANGUAGE == 0 else "Channel")
+        self._view.lb_baudrate.setText("波特率" if SD.SYSTEM_LANGUAGE == 0 else "BPS")
+        self._view.edt_password.setPlaceholderText("密码" if SD.SYSTEM_LANGUAGE == 0 else "PassWord")
+        self._view.btn_login.setText("登录" if SD.SYSTEM_LANGUAGE == 0 else "Login")
+        self._view.btn_cancel.setText("取消" if SD.SYSTEM_LANGUAGE == 0 else "Cancel")
+        self._view.cb_role.setItemText(0, "普通用户" if SD.SYSTEM_LANGUAGE == 0 else "Normal")
+        self._view.cb_role.setItemText(1, "调试工程师" if SD.SYSTEM_LANGUAGE == 0 else "Test")
+        self._view.cb_role.setItemText(2, "BMS产线操作员" if SD.SYSTEM_LANGUAGE == 0 else "Em")
+        self._view.cb_role.setItemText(3, "PACK产线操作" if SD.SYSTEM_LANGUAGE == 0 else "Pack")
+        self._view.cb_role.setItemText(4, "系统管理员" if SD.SYSTEM_LANGUAGE == 0 else "Manager")
+        self._view.cb_prj.setItemText(0, "户储" if SD.SYSTEM_LANGUAGE == 0 else "Home")
+        self._view.cb_prj.setItemText(1, "工商业" if SD.SYSTEM_LANGUAGE == 0 else "Industry")
+
+    def run(self):
+        self._view.show()
+        return self._app.exec_()

+ 410 - 0
controller/bms_main_ctl.py

@@ -0,0 +1,410 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from widget.bms_main import Win_Main
+from utils.globalvar import SD
+from utils.qt import Qt
+
+class BmsMainControll:
+    def __init__(self):
+        self._view = Win_Main()
+        self.i = 0
+        self.init()
+
+    def init(self):
+        self._view.up_signal.connect(self.sys_up)
+        self._view.down_signal.connect(self.sys_down)
+        self._view.controll_signal.connect(self.sys_controller)
+        self._view.do1_signal.connect(self.do1)
+        self._view.do2_signal.connect(self.do2)
+        self._view.do3_signal.connect(self.do3)
+        self._view.do4_signal.connect(self.do4)
+        self._view.do5_signal.connect(self.do5)
+        self._view.do6_signal.connect(self.do6)
+        self._view.do7_signal.connect(self.do7)
+        self._view.do8_signal.connect(self.do8)
+        
+        self._view.fault_release_signal.connect(self.operate1)
+        self._view.jy_signal.connect(self.operate2)
+        self._view.jy_one_signal.connect(self.operate3)
+        self._view.chg_mos_signal.connect(self.operate4)
+        self._view.dchg_mos_signal.connect(self.operate5)
+        self._view.pre_mos_signal.connect(self.operate6)
+        self._view.gjd1_signal.connect(self.operate7)
+        self._view.gjd2_signal.connect(self.operate8)
+        self._view.chg_signal.connect(self.operate9)
+        self._view.sleep_signal.connect(self.operate10)
+        self._view.reset_signal.connect(self.operate11)
+        self._view.clear_balance_signal.connect(self.operate12)
+        self._view.fan_signal.connect(self.operate13)
+
+    def sys_up(self):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0xFF
+            data[1] = 0xFF
+            data[2] = 0xAA
+            data[6] = self.i
+            self.i = self.i + 1
+            if self.i == 255:
+                self.i = 0
+            data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def sys_down(self):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0xFF
+            data[1] = 0xFF
+            data[2] = 0xBB
+            data[6] = self.i
+            self.i = self.i + 1
+            if self.i == 255:
+                self.i = 0
+            data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def sys_controller(self, check_status):
+        if check_status:
+            try:
+                data = []
+                if len(data) < 8:
+                    data += (8 - len(data)) * [0]
+                data[0] = 0xFF
+                data[1] = 0xFF
+                data[2] = 0xAA
+                data[6] = self.i
+                self.i = self.i + 1
+                if self.i == 255:
+                    self.i = 0
+                data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+                msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+                data[0] = 4
+                data[1] = 0xFF
+                data[2] = 0
+                data[6] = self.i
+                self.i = self.i + 1
+                if self.i == 255:
+                    self.i = 0
+                data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+                msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+            except:
+                # self._view.under_widget.snkz_check_box.setCheckState(Qt.Unchecked)
+                self._view.can_connect_error()
+        else:
+            try:
+                data = []
+                if len(data) < 8:
+                    data += (8 - len(data)) * [0]
+                data[0] = 5
+                data[1] = 0xFF
+                data[2] = 0
+                data[6] = self.i
+                self.i = self.i + 1
+                if self.i == 255:
+                    self.i = 0
+                data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+                msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+            except:
+                self._view.can_connect_error()
+
+    def do1(self, do1_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do1_status >> 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do2(self, do2_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = do2_status & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do3(self, do3_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do3_status << 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do4(self, do4_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do4_status << 2) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do5(self, do5_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do5_status << 3) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do6(self, do6_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do6_status << 4) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do7(self, do7_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do7_status << 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def do8(self, do8_status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x01
+            data[1] = 0xC0
+            data[2] = (do8_status << 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+    def operate1(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status >> 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate2(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate3(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 1) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate4(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 2) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate5(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 3) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate6(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 4) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate7(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 5) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate8(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = (status << 6) & 0xFF
+            data[3] = 0
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate9(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = 0
+            data[3] = (status >> 1) & 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+    def operate10(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = 0
+            data[3] = (status) & 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate11(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = 0
+            data[3] = (status >> 1) & 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+
+    def operate12(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = 0
+            data[3] = (status >> 2) & 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()
+
+    def operate13(self, status):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0x00
+            data[1] = 0xC0
+            data[2] = 0
+            data[3] = (status >> 4) & 0xFF
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1804, data)
+        except:
+            self._view.can_connect_error()

+ 76 - 0
controller/bms_protect_ctl.py

@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from utils.globalvar import SD
+from widget.bms_protect import Win_Protect
+
+
+class BmsProtectControll:
+    def __init__(self):
+        self._view = Win_Protect()
+        self.i = 0
+        self.init()
+
+    def init(self):
+        self._view.on_read_param_signal.connect(self._read_param)
+        self._view.on_write_param_signal.connect(self._write_param)
+        self._view.on_exit_param_signal.connect(self._exit_param)
+        
+
+    def _read_param(self):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 0xFF
+            data[1] = 0xFF
+            data[2] = 0xBB
+            data[6] = self.i
+            self.i = self.i + 1
+            if self.i == 255:
+                self.i = 0
+            data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+            data[0] = 1
+            data[2] = 0
+            data[6] = self.i
+            self.i = self.i + 1
+            if self.i == 255:
+                self.i = 0
+            data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+        except:
+            self._view.can_connect_error()
+
+    def _write_param(self):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = int(self._view.qline_addr.text(), 16) & 0xFF
+            data[1] = int(self._view.qline_addr.text(), 16) >> 8
+            data[2] = int(float(self._view.qline_data.text())) & 0xFF
+            data[3] = int(float(self._view.qline_data.text())) >> 8 
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1802, data)
+        except ValueError:
+            self._view.set_error()
+        except:
+            self._view.can_connect_error()
+
+
+    def _exit_param(self):
+        try:
+            data = []
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+            data[0] = 3
+            data[1] = 0xFF
+            data[6] = self.i
+            self.i = self.i + 1
+            if self.i == 255:
+                self.i = 0
+            data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+            msg = SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x1801, data)
+        except:
+            self._view.can_connect_error()

+ 16 - 0
controller/bms_record_ctl.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from utils.delay import m_delay
+from utils.globalvar import SD
+from widget.bms_record import Win_Record
+
+
+class BmsRecordControll:
+    def __init__(self):
+        self._view = Win_Record()
+    #     self.init()
+
+    # def init(self):
+        

+ 18 - 0
controller/bms_set_ctl.py

@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from utils.delay import m_delay
+from utils.globalvar import SD
+from utils.hex_bit import a_bit
+from utils.log_signal import LogSignal
+from widget.bms_set import Win_Set
+
+
+class BmsSetControll:
+    def __init__(self):
+        self._view = Win_Set()
+    #     self.init()
+
+    # def init(self):
+        

+ 23 - 0
controller/bms_status_ctl.py

@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :bms_status_ctl.py
+@时间    :2022/02/21 16:57:56
+@作者    :None
+@版本    :1.0
+@说明    : 状态栏 CTL
+'''
+
+
+from utils.delay import m_delay
+from utils.globalvar import SD
+from os import path
+from widget.bms_status_bar import Win_Bms_Status_Bar
+
+
+class BmsStatusControll:
+    def __init__(self):
+        self._view = Win_Bms_Status_Bar()
+
+    def run(self):
+        self._view.show()

binární
doc/芯祥_上位机规划V1.2-20231229.vsdx


binární
doc/芯祥_储能BMS平台项目内网CAN通讯协议V1.2_20231229.xls


+ 0 - 0
model/__init__.py


+ 264 - 0
model/record_model.py

@@ -0,0 +1,264 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+class RecordModel:
+    def __init__(self):
+        # 时间戳	簇号	故障等级	簇电压	簇电流	簇SOC	簇SOH	
+        self.__now_time = ""
+        self.__ccu_id = 0
+        self.__fault_level = 0
+        self.__volt = 0
+        self.__cur = 0
+        self.__soc = 0
+        self.__soh = 0
+        # 簇单体V平均	簇单体Vmax单体号	簇单体Vmax	簇单体Vmin单体号	簇单体Vmin	簇单体T平均	簇单体Tmax单体号	簇单体Tmax	簇单体Tmin单体号	簇单体Tmin	
+        self.__avg_cell_volt = 0
+        self.__max_cell_volt_id = 0
+        self.__max_cell_volt = 0
+        self.__min_cell_volt_id = 0
+        self.__min_cell_volt = 0
+        self.__avg_cell_temp = 0
+        self.__max_cell_temp_id = 0
+        self.__max_cell_temp = 0
+        self.__min_cell_temp_id = 0
+        self.__min_cell_temp = 0
+
+        # 主正接触器	主负接触器	预充接触器	断路器	干接点1	干接点2	最高单体SOC	最低单体SOC	平均单体SOC
+        self.__p = 0
+        self.__n = 0
+        self.__pre = 0
+        self.__dlq = 0
+        self.__gjd_first = 0
+        self.__gjd_second = 0
+        self.__max_soc = 0
+        self.__min_soc = 0
+        self.__avg_soc = 0      
+
+        self.__cell_volt = [0 for i in range(396)]
+        self.__cell_temp = [0 for i in range(360)]
+
+    @property
+    def now_time(self):
+        return self.__now_time
+
+    @now_time.setter
+    def now_time(self, value):
+        self.__now_time = value
+
+    @property
+    def ccu_id(self):
+        return self.__ccu_id
+
+    @ccu_id.setter
+    def ccu_id(self, value):
+        self.__ccu_id = value
+
+    @property
+    def fault_level(self):
+        return self.__fault_level
+
+    @fault_level.setter
+    def fault_level(self, value):
+        self.__fault_level = value
+
+    @property
+    def volt(self):
+        return self.__volt
+
+    @volt.setter
+    def volt(self, value):
+        self.__volt = value
+
+    @property
+    def cur(self):
+        return self.__cur
+
+    @cur.setter
+    def cur(self, value):
+        self.__cur = value
+
+
+    @property
+    def soc(self):
+        return self.__soc
+
+    @soc.setter
+    def soc(self, value):
+        self.__soc = value
+
+    @property
+    def soh(self):
+        return self.__soh
+
+    @soh.setter
+    def soh(self, value):
+        self.__soh = value
+
+
+    @property
+    def avg_cell_volt(self):
+        return self.__avg_cell_volt
+
+    @avg_cell_volt.setter
+    def avg_cell_volt(self, value):
+        self.__avg_cell_volt = value
+
+    @property
+    def max_cell_volt_id(self):
+        return self.__max_cell_volt_id
+
+    @max_cell_volt_id.setter
+    def max_cell_volt_id(self, value):
+        self.__max_cell_volt_id = value
+
+    @property
+    def max_cell_volt(self):
+        return self.__max_cell_volt
+
+    @max_cell_volt.setter
+    def max_cell_volt(self, value):
+        self.__max_cell_volt = value
+
+    @property
+    def min_cell_volt_id(self):
+        return self.__min_cell_volt_id
+
+    @min_cell_volt_id.setter
+    def min_cell_volt_id(self, value):
+        self.__min_cell_volt_id = value
+
+    @property
+    def min_cell_volt(self):
+        return self.__min_cell_volt
+
+    @min_cell_volt.setter
+    def min_cell_volt(self, value):
+        self.__min_cell_volt = value
+
+    @property
+    def avg_cell_temp(self):
+        return self.__avg_cell_temp
+
+    @avg_cell_temp.setter
+    def avg_cell_temp(self, value):
+        self.__avg_cell_temp = value
+
+    @property
+    def max_cell_temp_id(self):
+        return self.__max_cell_temp_id
+
+    @max_cell_temp_id.setter
+    def max_cell_temp_id(self, value):
+        self.__max_cell_temp_id = value
+
+    @property
+    def max_cell_temp(self):
+        return self.__max_cell_temp
+
+    @max_cell_temp.setter
+    def max_cell_temp(self, value):
+        self.__max_cell_temp = value
+
+    @property
+    def min_cell_temp_id(self):
+        return self.__min_cell_temp_id
+
+    @min_cell_temp_id.setter
+    def min_cell_temp_id(self, value):
+        self.__min_cell_temp_id = value
+
+    @property
+    def min_cell_temp(self):
+        return self.__min_cell_temp
+
+    @min_cell_temp.setter
+    def min_cell_temp(self, value):
+        self.__min_cell_temp = value
+
+    @property
+    def p(self):
+        return self.__p
+
+    @p.setter
+    def p(self, value):
+        self.__p = value
+
+    @property
+    def n(self):
+        return self.__n
+
+    @n.setter
+    def n(self, value):
+        self.__n = value
+
+    @property
+    def pre(self):
+        return self.__pre
+
+    @pre.setter
+    def pre(self, value):
+        self.__pre = value
+
+    @property
+    def dlq(self):
+        return self.__dlq
+
+    @dlq.setter
+    def dlq(self, value):
+        self.__dlq = value
+
+    @property
+    def gjd_first(self):
+        return self.__gjd_first
+
+    @gjd_first.setter
+    def gjd_first(self, value):
+        self.__gjd_first = value
+
+    @property
+    def gjd_second(self):
+        return self.__gjd_second
+
+    @gjd_second.setter
+    def gjd_second(self, value):
+        self.__gjd_second = value
+
+    @property
+    def max_soc(self):
+        return self.__max_soc
+
+    @max_soc.setter
+    def max_soc(self, value):
+        self.__max_soc = value
+
+    @property
+    def min_soc(self):
+        return self.__min_soc
+
+    @min_soc.setter
+    def min_soc(self, value):
+        self.__min_soc = value
+
+    @property
+    def avg_soc(self):
+        return self.__avg_soc
+
+    @avg_soc.setter
+    def avg_soc(self, value):
+        self.__avg_soc = value
+
+    @property
+    def cell_volt(self):
+        return self.__cell_volt
+
+    @cell_volt.setter
+    def cell_volt(self, value):
+        self.__cell_volt = value
+
+    @property
+    def cell_temp(self):
+        return self.__cell_temp
+
+    @cell_temp.setter
+    def cell_temp(self, value):
+        self.__cell_temp = value

+ 10 - 0
requirements.txt

@@ -0,0 +1,10 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+#    pip-compile requirements.txt
+#
+
+
+PySide2
+QCustomPlot2

+ 54 - 0
start.py

@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :start.py
+@时间    :2023/11/26 15:57:45
+@作者    :樊春春
+@版本    :1.0
+@邮箱    :[email protected]
+@说明    :
+'''
+
+
+from sys import exit
+from controller.bms_login_ctl import BmsLoginControll
+from utils.globalvar import SD
+from utils.qt import QApplication, QCoreApplication, Qt, QStyleFactory
+import locale
+
+
+
+def bms_start():
+    # 主版本号
+    SD.MAJOR_VERSION_NUMBER = 1
+    # 子版本号
+    SD.MINOR_VERSION_NUMBER = 0
+    # 修正版本号
+    SD.REVISION_NUMBER = "0-build_test"
+
+    local_tuple = locale.getdefaultlocale()
+
+    if local_tuple[0].startswith("zh"):
+        SD.SYSTEM_LANGUAGE = 0
+
+    if local_tuple[0].startswith("en"):
+        SD.SYSTEM_LANGUAGE = 1
+
+    # 适配分辨率
+    if hasattr(Qt, 'AA_EnableHighDpiScaling'):
+        QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
+
+    if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
+        QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
+        SD.HIGH_DPI = 0
+    else:
+        SD.HIGH_DPI = 1
+    main_connrtoller = BmsLoginControll()
+
+    QApplication.setStyle(QStyleFactory.create("windows"))
+
+    exit(main_connrtoller.run())
+
+
+if __name__ == "__main__":
+    bms_start()

+ 0 - 0
ui/__init__.py


+ 280 - 0
ui/balance.py

@@ -0,0 +1,280 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from ui.main.center_page import CenterPage
+from ui.main.under_page import UnderPage
+from utils.qt import QtWidgets, QtCore, Qt, QtGui
+from ui.own.palette_theme import set_edt_bg
+
+class Balance(MyFrame):
+    def setupUi(self, Balance):
+        self.balance = MyFrame(Balance)
+        self.balance_layout = QtWidgets.QGridLayout(self.balance)
+        self.balance_layout.setContentsMargins(5, 5, 5, 5)
+        self.balance_layout.setSpacing(0)
+
+        self.line_groupbox = QtWidgets.QGroupBox(self.balance)
+        self.line_groupbox.setTitle("采样线故障(红色:故障)")
+        self.line_groupbox_layout = QtWidgets.QHBoxLayout(self.line_groupbox)
+        self.line_qscrollarea = QtWidgets.QScrollArea(self.line_groupbox)
+        self.line_qscrollarea.setWidgetResizable(True)
+        self.line_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.line_groupbox_layout.addWidget(self.line_qscrollarea)
+        self.line_qwidget = QtWidgets.QWidget()
+        self.line_qscrollarea.setWidget(self.line_qwidget)
+        self.line_qscrollarea_layout = QtWidgets.QGridLayout(self.line_qwidget)
+        self.line_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.line_qscrollarea_layout.setSpacing(0)
+        for i in range(15):
+            bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+            bmu_label.setAlignment(Qt.AlignCenter)
+            self.line_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)
+        for i in range(15):
+            for j in range(72):
+                qline_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+                qline_lebal.setAlignment(Qt.AlignCenter)
+                qline_lebal.setFixedWidth(50)
+                qline_lebal.setReadOnly(True)
+                self.line_qscrollarea_layout.addWidget(qline_lebal, i, j + 1, 1, 1)
+
+        # self.line_groupbox = QtWidgets.QGroupBox(self.balance)
+        # self.line_groupbox.setTitle("采样线故障(红:故障)")
+        # self.line_groupbox_layout = QtWidgets.QVBoxLayout(self.line_groupbox)
+        # self.line_qscrollarea = QtWidgets.QScrollArea(self.line_groupbox)
+        # self.line_qscrollarea.setWidgetResizable(True)
+        # # self.line_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        # self.line_groupbox_layout.addWidget(self.line_qscrollarea)
+        # self.line_qwidget = QtWidgets.QWidget()
+        # self.line_qscrollarea.setWidget(self.line_qwidget)
+        # self.line_qscrollarea_layout = QtWidgets.QGridLayout(self.line_qwidget)
+        # self.line_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        # self.line_qscrollarea_layout.setSpacing(0)
+        # for i in range(15):
+        #     bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+        #     bmu_label.setAlignment(Qt.AlignCenter)
+        #     self.line_qscrollarea_layout.addWidget(bmu_label, 0, i, 1, 1)
+        # for i in range(15):
+        #     for j in range(72):
+        #         qline_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+        #         qline_lebal.setAlignment(Qt.AlignCenter)
+        #         qline_lebal.setReadOnly(True)
+        #         qline_lebal.setFixedWidth(50)
+        #         self.line_qscrollarea_layout.addWidget(qline_lebal, j + 1, i, 1, 1)
+        # to do
+        # set_edt_bg(self.line_qscrollarea_layout.itemAtPosition(2, 0).widget(), QtGui.QColor(Qt.red))
+        # set_edt_bg(self.line_qscrollarea_layout.itemAtPosition(3, 1).widget(), QtGui.QColor(Qt.red))
+
+        # self.line_status_widget = QtWidgets.QWidget()
+        # self.line_status_widget_layout = QtWidgets.QHBoxLayout(self.line_status_widget)
+        # self.line_status_widget_layout.setContentsMargins(0, 0, 0, 0)
+        # self.line_status_widget_layout.setSpacing(0)
+        # self.line_status_widget_layout.addStretch()
+        # self.qline_lebal = QtWidgets.QLineEdit("")
+        # self.qline_lebal.setAlignment(Qt.AlignCenter)
+        # self.qline_lebal.setReadOnly(True)
+        # set_edt_bg(self.qline_lebal, QtGui.QColor(Qt.white))
+        # self.line_status_widget_layout.addWidget(self.qline_lebal)
+        # self.lb_lebal = QtWidgets.QLabel("   无故障   ")
+        # self.line_status_widget_layout.addWidget(self.lb_lebal)
+        # self.line_status_widget_layout.addStretch()
+        # self.line_groupbox_layout.addWidget(self.line_status_widget)
+
+        # self.line_status_widget_2 = QtWidgets.QWidget()
+        # self.line_status_widget_2_layout = QtWidgets.QHBoxLayout(self.line_status_widget_2)
+        # self.line_status_widget_2_layout.setContentsMargins(0, 0, 0, 0)
+        # self.line_status_widget_2_layout.setSpacing(0)
+        # self.line_status_widget_2_layout.addStretch()
+        # self.qline_bal = QtWidgets.QLineEdit("")
+        # self.qline_bal.setAlignment(Qt.AlignCenter)
+        # self.qline_bal.setReadOnly(True)
+        # set_edt_bg(self.qline_bal, QtGui.QColor(Qt.red))
+        # self.line_status_widget_2_layout.addWidget(self.qline_bal)
+        # self.lb_bal = QtWidgets.QLabel("采样线故障")
+        # self.line_status_widget_2_layout.addWidget(self.lb_bal)
+        # self.line_status_widget_2_layout.addStretch()
+
+        # self.line_groupbox_layout.addWidget(self.line_status_widget_2)
+
+
+        self.balance_layout.addWidget(self.line_groupbox, 0, 0, 1, 1)
+
+        self.on_off_groupbox = QtWidgets.QGroupBox(self.balance)
+        self.on_off_groupbox.setTitle("均衡开关(绿色:开启)")
+        self.on_off_groupbox_layout = QtWidgets.QHBoxLayout(self.on_off_groupbox)
+        self.on_off_qscrollarea = QtWidgets.QScrollArea(self.on_off_groupbox)
+        self.on_off_qscrollarea.setWidgetResizable(True)
+        self.on_off_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.on_off_groupbox_layout.addWidget(self.on_off_qscrollarea)
+        self.on_off_qwidget = QtWidgets.QWidget()
+        self.on_off_qscrollarea.setWidget(self.on_off_qwidget)
+        self.on_off_qscrollarea_layout = QtWidgets.QGridLayout(self.on_off_qwidget)
+        self.on_off_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.on_off_qscrollarea_layout.setSpacing(0)
+        for i in range(15):
+            bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+            bmu_label.setAlignment(Qt.AlignCenter)
+            self.on_off_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)
+        for i in range(15):
+            for j in range(72):
+                qon_off_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+                qon_off_lebal.setAlignment(Qt.AlignCenter)
+                qon_off_lebal.setFixedWidth(50)
+                qon_off_lebal.setReadOnly(True)
+                self.on_off_qscrollarea_layout.addWidget(qon_off_lebal, i, j + 1, 1, 1)
+
+        # set_edt_bg(self.on_off_qscrollarea_layout.itemAtPosition( 0 + 0,1).widget(), QtGui.QColor(Qt.red))
+        # set_edt_bg(self.on_off_qscrollarea_layout.itemAtPosition( 0 + 2, 6).widget(), QtGui.QColor(Qt.red))
+        # set_edt_bg(self.on_off_qscrollarea_layout.itemAtPosition(3, 1).widget(), QtGui.QColor(Qt.red))
+
+        # self.on_off_widget = QtWidgets.QWidget()
+        # self.on_off_widget_layout = QtWidgets.QVBoxLayout(self.on_off_widget)
+        # self.on_off_widget_layout.setContentsMargins(0, 0, 0, 0)
+        # self.on_off_widget_layout.setSpacing(0)
+        # self.on_off_widget_layout.addStretch()
+        # self.qline_l = QtWidgets.QLineEdit("")
+        # self.qline_l.setAlignment(Qt.AlignCenter)
+        # self.qline_l.setReadOnly(True)
+        # set_edt_bg(self.qline_l, QtGui.QColor(Qt.white))
+        # self.on_off_widget_layout.addWidget(self.qline_l)
+        # self.lb_l = QtWidgets.QLabel("关闭均衡")
+        # self.lb_l.setAlignment(Qt.AlignCenter)
+        # self.on_off_widget_layout.addWidget(self.lb_l)
+        # self.qline_ll = QtWidgets.QLineEdit("")
+        # self.qline_ll.setAlignment(Qt.AlignCenter)
+        # self.qline_ll.setReadOnly(True)
+        # set_edt_bg(self.qline_ll, QtGui.QColor(Qt.green))
+        # self.on_off_widget_layout.addWidget(self.qline_ll)
+        # self.lb_ll = QtWidgets.QLabel("打开均衡")
+        # self.lb_ll.setAlignment(Qt.AlignCenter)
+        # self.on_off_widget_layout.addWidget(self.lb_ll)
+        # self.on_off_widget_layout.addStretch()
+
+        # self.on_off_groupbox_layout.addWidget(self.on_off_widget)
+
+
+        self.balance_layout.addWidget(self.on_off_groupbox, 0, 1, 1, 1)
+
+        # self.balance_control_groupbox = QtWidgets.QGroupBox(self.balance)
+        # self.balance_control_groupbox.setTitle("均衡强制控制(选中:控制)")
+        # self.balance_control_groupbox_layout = QtWidgets.QVBoxLayout(self.balance_control_groupbox)
+        # self.balance_control_qscrollarea = QtWidgets.QScrollArea(self.balance_control_groupbox)
+        # self.balance_control_qscrollarea.setWidgetResizable(True)
+        # # self.balance_control_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        # self.balance_control_groupbox_layout.addWidget(self.balance_control_qscrollarea)
+        # self.balance_control_qwidget = QtWidgets.QWidget()
+        # self.balance_control_qscrollarea.setWidget(self.balance_control_qwidget)
+        # self.balance_control_qscrollarea_layout = QtWidgets.QGridLayout(self.balance_control_qwidget)
+        # self.balance_control_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        # self.balance_control_qscrollarea_layout.setSpacing(0)
+        # for i in range(15):
+        #     bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+        #     bmu_label.setAlignment(Qt.AlignCenter)
+        #     self.balance_control_qscrollarea_layout.addWidget(bmu_label, 0, i, 1, 1)
+        # for i in range(15):
+        #     for j in range(72):
+        #         qbalance_control_widget = QtWidgets.QWidget()
+        #         qbalance_control_widget_layout = QtWidgets.QHBoxLayout(qbalance_control_widget)
+        #         qbalance_control_widget_layout.setContentsMargins(5, 5, 5, 5)
+        #         qbalance_control_widget_layout.setSpacing(0)
+        #         qbalance_control_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+        #         qbalance_control_lebal.setAlignment(Qt.AlignCenter)
+        #         qbalance_control_lebal.setReadOnly(True)
+        #         qbalance_control_lebal.setFixedWidth(50)
+        #         qbalance_control_widget_layout.addWidget(qbalance_control_lebal)
+        #         qbalance_control_checkbox = QtWidgets.QCheckBox()
+        #         qbalance_control_widget_layout.addWidget(qbalance_control_checkbox)
+        #         self.balance_control_qscrollarea_layout.addWidget(qbalance_control_widget, j + 1, i, 1, 1)
+        
+        self.balance_control_groupbox = QtWidgets.QGroupBox(self.balance)
+        self.balance_control_groupbox.setTitle("均衡强制控制(选中:控制)")
+        self.balance_control_groupbox_layout = QtWidgets.QHBoxLayout(self.balance_control_groupbox)
+        self.balance_control_qscrollarea = QtWidgets.QScrollArea(self.balance_control_groupbox)
+        self.balance_control_qscrollarea.setWidgetResizable(True)
+        self.balance_control_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.balance_control_groupbox_layout.addWidget(self.balance_control_qscrollarea)
+        self.balance_control_qwidget = QtWidgets.QWidget()
+        self.balance_control_qscrollarea.setWidget(self.balance_control_qwidget)
+        self.balance_control_qscrollarea_layout = QtWidgets.QGridLayout(self.balance_control_qwidget)
+        self.balance_control_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.balance_control_qscrollarea_layout.setSpacing(0)
+        for i in range(15):
+            bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+            bmu_label.setAlignment(Qt.AlignCenter)
+            self.balance_control_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)
+        for i in range(15):
+            for j in range(72):
+                qbalance_control_widget = QtWidgets.QWidget()
+                qbalance_control_widget_layout = QtWidgets.QHBoxLayout(qbalance_control_widget)
+                qbalance_control_widget_layout.setContentsMargins(5, 5, 5, 5)
+                qbalance_control_widget_layout.setSpacing(0)
+                qbalance_control_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+                qbalance_control_lebal.setAlignment(Qt.AlignCenter)
+                qbalance_control_lebal.setReadOnly(True)
+                qbalance_control_lebal.setFixedWidth(50)
+                qbalance_control_widget_layout.addWidget(qbalance_control_lebal)
+                qbalance_control_checkbox = QtWidgets.QCheckBox()
+                qbalance_control_widget_layout.addWidget(qbalance_control_checkbox)
+                self.balance_control_qscrollarea_layout.addWidget(qbalance_control_widget, i, j + 1, 1, 1)
+        
+        self.balance_layout.addWidget(self.balance_control_groupbox, 1, 0, 1, 1)
+        # self.balance_control_qscrollarea_layout.itemAtPosition(0 + 0, 1).widget().layout().itemAt(1).widget().stateChanged.connect(lambda state = self.balance_control_qscrollarea_layout.itemAtPosition(0 + 0, 1).widget().layout().itemAt(1).widget(), cmu_id = i + 1, cell_id = j + 1: self._balance_ctl(state, cmu_id, cell_id))    
+        # set_edt_bg(self.on_off_qscrollarea_layout.itemAtPosition( 0 + 0,1).widget(), QtGui.QColor(Qt.red))
+        # self.balance_control_qscrollarea_layout.itemAtPosition(2, 3).widget().layout().itemAt(1).widget().setCheckState(Qt.Checked)
+        # self.balance_control_qscrollarea_layout.itemAtPosition(0, 1).widget().layout().itemAt(1).widget().setCheckState(Qt.Checked)
+
+        self.balance_fault_groupbox = QtWidgets.QGroupBox(self.balance)
+        self.balance_fault_groupbox.setTitle("均衡故障(红色:故障)")
+        self.balance_fault_groupbox_layout = QtWidgets.QHBoxLayout(self.balance_fault_groupbox)
+        self.balance_fault_qscrollarea = QtWidgets.QScrollArea(self.balance_fault_groupbox)
+        self.balance_fault_qscrollarea.setWidgetResizable(True)
+        self.balance_fault_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.balance_fault_groupbox_layout.addWidget(self.balance_fault_qscrollarea)
+        self.balance_fault_qwidget = QtWidgets.QWidget()
+        self.balance_fault_qscrollarea.setWidget(self.balance_fault_qwidget)
+        self.balance_fault_qscrollarea_layout = QtWidgets.QGridLayout(self.balance_fault_qwidget)
+        self.balance_fault_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.balance_fault_qscrollarea_layout.setSpacing(0)
+        for i in range(15):
+            bmu_label = QtWidgets.QLabel("CMU" + str(i + 1))
+            bmu_label.setAlignment(Qt.AlignCenter)
+            self.balance_fault_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)
+        for i in range(15):
+            for j in range(72):
+                qbalance_fault_lebal = QtWidgets.QLineEdit("C" + str(j + 1))
+                qbalance_fault_lebal.setAlignment(Qt.AlignCenter)
+                qbalance_fault_lebal.setReadOnly(True)
+                qbalance_fault_lebal.setFixedWidth(50)
+                self.balance_fault_qscrollarea_layout.addWidget(qbalance_fault_lebal, i, j + 1, 1, 1)
+
+        # set_edt_bg(self.balance_fault_qscrollarea_layout.itemAtPosition( 0 + 0,1).widget(), QtGui.QColor(Qt.red))
+        # set_edt_bg(self.balance_fault_qscrollarea_layout.itemAtPosition( 0 + 2, 6).widget(), QtGui.QColor(Qt.red))
+
+        # self.balance_fault_widget = QtWidgets.QWidget()
+        # self.balance_fault_widget_layout = QtWidgets.QVBoxLayout(self.balance_fault_widget)
+        # self.balance_fault_widget_layout.setContentsMargins(0, 0, 0, 0)
+        # self.balance_fault_widget_layout.setSpacing(0)
+        # self.balance_fault_widget_layout.addStretch()
+        # self.edt_fault = QtWidgets.QLineEdit("")
+        # self.edt_fault.setAlignment(Qt.AlignCenter)
+        # self.edt_fault.setReadOnly(True)
+        # set_edt_bg(self.edt_fault, QtGui.QColor(Qt.white))
+        # self.balance_fault_widget_layout.addWidget(self.edt_fault)
+        # self.lb_fault = QtWidgets.QLabel("无故障")
+        # self.lb_fault.setAlignment(Qt.AlignCenter)
+        # self.balance_fault_widget_layout.addWidget(self.lb_fault)
+        # self.edt_faultl = QtWidgets.QLineEdit("")
+        # self.edt_faultl.setAlignment(Qt.AlignCenter)
+        # self.edt_faultl.setReadOnly(True)
+        # set_edt_bg(self.edt_faultl, QtGui.QColor(Qt.red))
+        # self.balance_fault_widget_layout.addWidget(self.edt_faultl)
+        # self.lb_faultl = QtWidgets.QLabel("均衡故障")
+        # self.lb_faultl.setAlignment(Qt.AlignCenter)
+        # self.balance_fault_widget_layout.addWidget(self.lb_faultl)
+        # self.balance_fault_widget_layout.addStretch()
+
+        # self.balance_fault_groupbox_layout.addWidget(self.balance_fault_widget)        
+        
+        self.balance_layout.addWidget(self.balance_fault_groupbox, 1, 1, 1, 1)
+
+        QtCore.QMetaObject.connectSlotsByName(Balance)

+ 235 - 0
ui/cell.py

@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.own.frame_theme import MyFrame
+from utils.qt import QtWidgets, QMetaObject, QVBoxLayout, QGroupBox, Qt, QtCore
+from utils.globalvar import SD
+from ui.own.switch_button import SwitchButton
+
+class Cell(MyFrame):
+    def setupUi(self, Cell):
+        self.cell = MyFrame(Cell)
+        self.cell_layout = QVBoxLayout(self.cell)
+        self.cell_layout.setContentsMargins(0, 0, 0, 0)
+        self.cell_layout.setSpacing(0)
+
+        self.group_cell_box = QGroupBox(self.cell)
+        self.group_cell_box.setTitle("单体信息")
+        self.group_cell_box_layout = QVBoxLayout(self.group_cell_box)
+
+        self.btn_widget = QtWidgets.QWidget(self.group_cell_box)
+        self.btn_widget_layout = QtWidgets.QHBoxLayout(self.btn_widget)
+
+        self.btn_cell_vol = QtWidgets.QPushButton("单体电压")
+        self.btn_widget_layout.addWidget(self.btn_cell_vol)
+        self.btn_cell_temp = QtWidgets.QPushButton("单体温度")
+        self.btn_widget_layout.addWidget(self.btn_cell_temp)
+
+        self.btn_jz_temp = QtWidgets.QPushButton("极柱温度")
+        self.btn_widget_layout.addWidget(self.btn_jz_temp)
+        self.btn_bcu_temp = QtWidgets.QPushButton("极柱温度")
+        self.btn_widget_layout.addWidget(self.btn_bcu_temp)
+
+        self.btn_widget_layout.addStretch() 
+        self.wdwdw = QtWidgets.QWidget(self.btn_widget)
+        self.wdwdw_layout = QtWidgets.QVBoxLayout(self.wdwdw)
+        self.plot_switch = SwitchButton(self.btn_widget)
+        self.plot_switch.setMinimumSize(QtCore.QSize(70, 30))
+        # size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        # size_policy.setHorizontalStretch(0)
+        # size_policy.setVerticalStretch(0)
+        # size_policy.setHeightForWidth(self.plot_switch.sizePolicy().hasHeightForWidth())
+        self.wdwdw_layout.addWidget(self.plot_switch)
+        self.btn_widget_layout.addWidget(self.wdwdw)
+        self.lb_plot_switch = QtWidgets.QLabel("柱状图")
+        self.btn_widget_layout.addWidget(self.lb_plot_switch)
+
+        # self.btn_widget_layout.addStretch() 
+
+        self.group_cell_box_layout.addWidget(self.btn_widget)
+
+        self.under_right_widget = QtWidgets.QWidget(self.group_cell_box)
+        self.under_right_layout = QVBoxLayout(self.under_right_widget)
+        self.under_right_layout.setContentsMargins(0, 0, 0, 0)
+        self.under_right_layout.setSpacing(0)
+
+        self.cell_tab = QtWidgets.QStackedWidget(self.under_right_widget)
+        self.cell_vol_table = QtWidgets.QTableWidget(self.cell_tab)
+        self.cell_vol_table.setColumnCount(16)
+        self.cell_vol_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        # 设置只能选择行
+        self.cell_vol_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.cell_vol_table.setHorizontalHeaderLabels(["CMU ID", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"])
+        self.cell_vol_table.verticalHeader().setVisible(False)
+        self.cell_vol_table.verticalHeader().setHighlightSections(True)
+        self.cell_vol_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cell_vol_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cell_vol_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.cell_vol_table.setRowCount(72)
+        for i in range(72):
+            item = QtWidgets.QTableWidgetItem("C" + str(i + 1))
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.cell_vol_table.setItem(i, 0, item)
+            for j in range(15):
+                item = QtWidgets.QLineEdit("mV")
+                item.setAlignment(Qt.AlignRight)
+                item.setReadOnly(True)
+                self.cell_vol_table.setCellWidget(i, j + 1, item)                
+        self.cell_tab.addWidget(self.cell_vol_table)
+
+        # self.cell_vol_table.cellWidget(0, 1).setText("333333mV")
+        # self.cell_vol_table.cellWidget(1, 1).setText("333333mV")
+
+        self.cell_temp_table = QtWidgets.QTableWidget(self.cell_tab)
+        self.cell_temp_table.setColumnCount(16)
+        self.cell_temp_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        # 设置只能选择行
+        self.cell_temp_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.cell_temp_table.setHorizontalHeaderLabels(["CMU ID", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"])
+        self.cell_temp_table.verticalHeader().setVisible(False)
+        self.cell_temp_table.verticalHeader().setHighlightSections(True)
+        self.cell_temp_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cell_temp_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cell_temp_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.cell_temp_table.setRowCount(72)
+        for i in range(72):
+            item = QtWidgets.QTableWidgetItem("T" + str(i + 1))
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.cell_temp_table.setItem(i, 0, item)
+            for j in range(15):
+                item = QtWidgets.QLineEdit("℃")
+                item.setAlignment(Qt.AlignRight)
+                item.setReadOnly(True)
+                self.cell_temp_table.setCellWidget(i, j + 1, item)                
+        self.cell_tab.addWidget(self.cell_temp_table)
+
+        self.under_right_layout.addWidget(self.cell_tab)
+        self.group_cell_box_layout.addWidget(self.under_right_widget)
+        self.cell_layout.addWidget(self.group_cell_box)
+        
+        #============================================================
+        self.home_cell_table = QtWidgets.QTableWidget(self.group_cell_box)
+        self.home_cell_table.setColumnCount(12)
+        self.home_cell_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        # 设置只能选择行
+        self.home_cell_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.home_cell_table.setHorizontalHeaderLabels(["编号", "电压", "温度", "编号", "电压", "温度", "编号", "电压", "温度", "编号", "电压", "温度"])
+        self.home_cell_table.verticalHeader().setVisible(False)
+        self.home_cell_table.verticalHeader().setHighlightSections(True)
+        self.home_cell_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.home_cell_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        # self.home_cell_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.home_cell_table.setRowCount(4)
+        for i in range(4):
+            for j in range(12):
+                if j%3 == 0:
+                    item = QtWidgets.QTableWidgetItem(str(int((i + 1) + 4 * (j/3))))
+                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+                    self.home_cell_table.setItem(i, j, item)
+                if j%3 == 1:
+                    item = QtWidgets.QLineEdit("mV")
+                    item.setAlignment(Qt.AlignRight)
+                    item.setReadOnly(True)
+                    self.home_cell_table.setCellWidget(i, j, item)
+                if j%3 == 2:
+                    item = QtWidgets.QLineEdit("℃")
+                    item.setAlignment(Qt.AlignRight)
+                    item.setReadOnly(True)
+                    self.home_cell_table.setCellWidget(i, j, item)
+        self.group_cell_box_layout.addWidget(self.home_cell_table)            
+        # self.cell_layout.addWidget(self.group_cell_box_layout)
+
+        if SD.CCU_TYPE == 1:
+            self.btn_widget.setHidden(False)
+            self.home_cell_table.setHidden(True)
+        else:
+            self.btn_widget.setHidden(True)
+            self.cell_tab.setHidden(True)
+            self.home_cell_table.setHidden(False)
+            self.group_cell_box_layout.addStretch() 
+
+        self.group_set_box = QGroupBox(self.cell)
+        self.group_set_box.setTitle("基本配置")
+        self.group_set_box_layout = QtWidgets.QHBoxLayout(self.group_set_box)
+
+        self.set_widget = QtWidgets.QWidget(self.group_set_box)
+        self.set_widget_layout = QtWidgets.QGridLayout(self.set_widget)
+        
+        self.lb_cell_dccs = QtWidgets.QLabel("电池串数")
+        self.set_widget_layout.addWidget(self.lb_cell_dccs, 0, 0)
+        self.edt_cell_dccs = QtWidgets.QLineEdit("")
+        self.set_widget_layout.addWidget(self.edt_cell_dccs, 0, 1)
+        self.lb_cell_d = QtWidgets.QLabel("串")
+        self.set_widget_layout.addWidget(self.lb_cell_d, 0, 2)
+
+        self.lb_cell_temp = QtWidgets.QLabel("电池温度")
+        self.set_widget_layout.addWidget(self.lb_cell_temp, 1, 0)
+        self.edt_cell_temp = QtWidgets.QLineEdit("")
+        self.set_widget_layout.addWidget(self.edt_cell_temp, 1, 1)
+        self.lb_cell_dd = QtWidgets.QLabel("个")
+        self.set_widget_layout.addWidget(self.lb_cell_dd, 1, 2)
+
+        self.lb_mos_temp = QtWidgets.QLabel("MOS温度")
+        self.set_widget_layout.addWidget(self.lb_mos_temp, 2, 0)
+        self.edt_mos_temp = QtWidgets.QLineEdit("")
+        self.set_widget_layout.addWidget(self.edt_mos_temp, 2, 1)
+        self.lb_mos_dd = QtWidgets.QLabel("个")
+        self.set_widget_layout.addWidget(self.lb_mos_dd, 2, 2)
+
+        self.wgpe = QtWidgets.QLabel("温感配置")
+        self.set_widget_layout.addWidget(self.wgpe, 0, 4, 1, 2)
+
+        self.lb_t1 = QtWidgets.QLabel("T1")
+        self.set_widget_layout.addWidget(self.lb_t1, 1, 4, 1, 1)
+        self.cb_t1 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t1, 1, 5, 1, 1)  
+        self.lb_t2 = QtWidgets.QLabel("T2")
+        self.set_widget_layout.addWidget(self.lb_t2, 2, 4, 1, 1)
+        self.cb_t2 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t2, 2, 5, 1, 1)  
+        self.lb_t3 = QtWidgets.QLabel("T3")
+        self.set_widget_layout.addWidget(self.lb_t3, 3, 4, 1, 1)
+        self.cb_t3 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t3, 3, 5, 1, 1)  
+        self.lb_t4 = QtWidgets.QLabel("T4")
+        self.set_widget_layout.addWidget(self.lb_t4, 4, 4, 1, 1)
+        self.cb_t4 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t4, 4, 5, 1, 1) 
+
+        self.lb_t5 = QtWidgets.QLabel("T5")
+        self.set_widget_layout.addWidget(self.lb_t5, 1, 7, 1, 1)
+        self.cb_t5 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t5, 1, 8, 1, 1)  
+        self.lb_t6 = QtWidgets.QLabel("T6")
+        self.set_widget_layout.addWidget(self.lb_t6, 2, 7, 1, 1)
+        self.cb_t6 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t6, 2, 8, 1, 1)  
+        self.lb_t7 = QtWidgets.QLabel("T7")
+        self.set_widget_layout.addWidget(self.lb_t7, 3, 7, 1, 1)
+        self.cb_t7 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t7, 3, 8, 1, 1)  
+        self.lb_t8 = QtWidgets.QLabel("T8")
+        self.set_widget_layout.addWidget(self.lb_t8, 4, 7, 1, 1)
+        self.cb_t8 = QtWidgets.QCheckBox(self.set_widget)
+        self.set_widget_layout.addWidget(self.cb_t8, 4, 8, 1, 1) 
+
+        self.group_set_box_layout.addWidget(self.set_widget)
+
+        self.btn_set_widget = QtWidgets.QWidget(self.group_set_box)
+        self.btn_set_widget_layout = QtWidgets.QVBoxLayout(self.btn_set_widget)
+
+        self.btn_read_set_param = QtWidgets.QPushButton("读取参数")
+        self.btn_set_widget_layout.addWidget(self.btn_read_set_param)
+        self.btn_update_set_param = QtWidgets.QPushButton("更新参数")
+        self.btn_set_widget_layout.addWidget(self.btn_update_set_param)
+
+        self.group_set_box_layout.addWidget(self.btn_set_widget)
+
+        self.group_set_box_layout.addStretch() 
+        self.cell_layout.addWidget(self.group_set_box)
+
+        if SD.CCU_TYPE == 1:
+            self.group_set_box.setHidden(True)
+
+        QMetaObject.connectSlotsByName(Cell)

+ 45 - 0
ui/double_ccu.py

@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from ui.main.top_page import TopPage
+from ui.main.center_page import CenterPage
+from ui.main.under_page import UnderPage
+from utils.qt import QtWidgets, QtCore
+
+
+class DoubleCcu(MyFrame):
+    def setupUi(self, DoubleCcu):
+        self.double_ccu = MyFrame(DoubleCcu)
+        self.double_ccu_layout = QtWidgets.QVBoxLayout(self.double_ccu)
+        self.double_ccu_layout.setContentsMargins(0, 0, 0, 0)
+        self.double_ccu_layout.setSpacing(0)
+
+        self.double_ccu_top_widget = MyFrame(self.double_ccu)
+        self.group_cell_box_layout = QtWidgets.QHBoxLayout(self.double_ccu_top_widget)
+
+        self.on_line_ccu = QtWidgets.QLabel("在线簇数")
+        self.group_cell_box_layout.addWidget(self.on_line_ccu)
+        self.on_line_ccu_value = QtWidgets.QLabel("")
+        self.group_cell_box_layout.addWidget(self.on_line_ccu_value)
+
+        self.double_ccu_layout.addWidget(self.double_ccu_top_widget)
+
+        self.double_ccu_under_widget = MyFrame(self.double_ccu)
+        self.double_ccu_under_layout = QtWidgets.QHBoxLayout(self.double_ccu_under_widget)
+
+        self.on_line_ccu_table = QtWidgets.QTableWidget(self.double_ccu_under_widget)
+        self.on_line_ccu_table.setColumnCount(15)
+        self.on_line_ccu_table.verticalHeader().setVisible(False)
+        self.on_line_ccu_table.verticalHeader().setHighlightSections(True)
+        self.on_line_ccu_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        # self.on_line_ccu_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        # self.on_line_ccu_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+
+        self.on_line_ccu_table.setHorizontalHeaderLabels(["簇号", "运行状态", "总电压", "总电流", "SOC", "SOH", "SOE", "绝缘阻值", "最高单体电压", "最高单体电压编号", "最低单体电压", "最低单体电压编号", "最高单体温度", "最高单体温度编号", "最低单体温度", "最低单体温度编号"])
+        self.on_line_ccu_table.setRowCount(20)
+        self.double_ccu_under_layout.addWidget(self.on_line_ccu_table)
+
+        self.double_ccu_layout.addWidget(self.double_ccu_under_widget)
+
+        QtCore.QMetaObject.connectSlotsByName(DoubleCcu)

+ 189 - 0
ui/download.py

@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from ui.main.top_page import TopPage
+from ui.main.center_page import CenterPage
+from ui.main.under_page import UnderPage
+from utils.qt import QtWidgets, QtCore, Qt, QtGui
+
+
+class Download(MyFrame):
+    def setupUi(self, Download):
+        self.reg = QtCore.QRegExp('^[a-zA-Z0-9_-]{16,16}$')
+        self.validator = QtGui.QRegExpValidator(self)
+        self.validator.setRegExp(self.reg)
+
+        self.download = MyFrame(Download)
+        self.download_layout = QtWidgets.QHBoxLayout(self.download)
+        self.download_layout.setContentsMargins(0, 0, 0, 0)
+        self.download_layout.setSpacing(0)
+
+
+        self.message = QtWidgets.QWidget()
+        self.message_layout = QtWidgets.QVBoxLayout(self.message)
+        self.message_layout.setContentsMargins(0, 0, 0, 0)
+        self.message_layout.setSpacing(0)
+
+        self.message_widget = QtWidgets.QGroupBox("追溯信息")
+        self.message_box_layout = QtWidgets.QVBoxLayout(self.message_widget)
+        self.message_table = QtWidgets.QTableWidget(self.message_widget)
+        self.message_table.setColumnCount(3)
+        self.message_table.setShowGrid(True)
+        self.message_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        self.message_table.verticalHeader().setVisible(False)
+        self.message_table.verticalHeader().setHighlightSections(True)
+        self.message_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.message_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.message_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        # self.message_table.horizontalHeader().setDefaultAlignment(Qt.AlignmentFlag.AlignCenter)
+        self.message_table.setHorizontalHeaderLabels(["序号", "参数名称", "值"])
+        self.message_table.setRowCount(6)
+
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(0, 0, item)
+        item = QtWidgets.QTableWidgetItem("Bootloader软件版本")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(0, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(0, 2, item)
+
+        item = QtWidgets.QTableWidgetItem("2")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(1, 0, item)
+        item = QtWidgets.QTableWidgetItem("应用程序软件版本号")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(1, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(1, 2, item)
+
+        item = QtWidgets.QTableWidgetItem("3")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(2, 0, item)
+        item = QtWidgets.QTableWidgetItem("算法软件版本号")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(2, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(2, 2, item)
+
+        item = QtWidgets.QTableWidgetItem("4")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(3, 0, item)
+        item = QtWidgets.QTableWidgetItem("硬件版本号")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(3, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(3, 2, item)
+
+        item = QtWidgets.QTableWidgetItem("5")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(4, 0, item)
+        item = QtWidgets.QTableWidgetItem("BMS序列号")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(4, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(4, 2, item)
+
+        item = QtWidgets.QTableWidgetItem("6")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(5, 0, item)
+        item = QtWidgets.QTableWidgetItem("电池编码")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(5, 1, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.message_table.setItem(5, 2, item)
+
+
+        self.message_box_layout.addWidget(self.message_table)
+        self.btn_read_version = QtWidgets.QPushButton("读取版本信息")
+        self.message_box_layout.addWidget(self.btn_read_version)
+        self.message_layout.addWidget(self.message_widget)
+
+        # spacerItem3 = QtWidgets.QSpacerItem(40, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        # self.message_layout.addItem(spacerItem3)
+
+        self.second_widget = MyFrame()
+        self.second_widget_layout = QtWidgets.QGridLayout(self.second_widget)
+        self.lb_sblx = QtWidgets.QLabel("设备类型")    
+        self.second_widget_layout.addWidget(self.lb_sblx, 0, 0, 1, 1)
+        self.cb_sblx = QtWidgets.QComboBox()
+        self.cb_sblx.addItem("总控(BAU)")
+        self.cb_sblx.addItem("主控(BCU)")
+        self.cb_sblx.addItem("从控(CMU)")
+        self.second_widget_layout.addWidget(self.cb_sblx, 0, 1, 1, 1)
+        self.lb_bau = QtWidgets.QLabel("BAU")    
+        self.second_widget_layout.addWidget(self.lb_bau, 1, 0, 1, 1)
+        self.cb_bau = QtWidgets.QComboBox()
+        self.second_widget_layout.addWidget(self.cb_bau, 1, 1, 1, 1)
+        self.lb_bcu = QtWidgets.QLabel("BCU")    
+        self.second_widget_layout.addWidget(self.lb_bcu, 2, 0, 1, 1)
+        self.cb_bcu = QtWidgets.QComboBox()
+        self.second_widget_layout.addWidget(self.cb_bcu, 2, 1, 1, 1)
+        self.lb_cmu = QtWidgets.QLabel("CMU")    
+        self.second_widget_layout.addWidget(self.lb_cmu, 3, 0, 1, 1)
+        self.cb_cmu = QtWidgets.QComboBox()
+        self.second_widget_layout.addWidget(self.cb_cmu, 3, 1, 1, 1)
+        self.message_layout.addWidget(self.second_widget)
+
+        # spacerItem2 = QtWidgets.QSpacerItem(40, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        # self.message_layout.addItem(spacerItem2)
+
+        self.third_widget = MyFrame()
+        self.third_widget_layout = QtWidgets.QGridLayout(self.third_widget)
+        self.lb_cxwj = QtWidgets.QLabel("程序文件:")    
+        self.third_widget_layout.addWidget(self.lb_cxwj, 0, 0, 1, 1)
+        self.edt_filename = QtWidgets.QLineEdit()
+        self.edt_filename.setReadOnly(True)
+        self.third_widget_layout.addWidget(self.edt_filename, 0, 1, 1, 3)
+        self.btn_chose = QtWidgets.QPushButton("选择...")    
+        self.third_widget_layout.addWidget(self.btn_chose, 0, 4, 1, 1)
+        self.btn_start_up = QtWidgets.QPushButton("开始升级")    
+        self.third_widget_layout.addWidget(self.btn_start_up, 1, 0, 1, 1)
+        self.btn_stop_up = QtWidgets.QPushButton("中止")    
+        self.third_widget_layout.addWidget(self.btn_stop_up, 1, 2, 1, 1)
+        self.btn_restart_up = QtWidgets.QPushButton("复位强制升级")    
+        self.third_widget_layout.addWidget(self.btn_restart_up, 1, 4, 1, 1)
+        self.message_layout.addWidget(self.third_widget)
+
+        self.message_layout.addStretch() 
+
+        self.download_layout.addWidget(self.message, 1)
+
+        self.right_widget = QtWidgets.QWidget()
+        self.right_widget_layout = QtWidgets.QVBoxLayout(self.right_widget)
+
+        self.first_frame = MyFrame(self.right_widget)
+        self.first_frame_layout = QtWidgets.QGridLayout(self.first_frame)
+        self.lb_bms_sn = QtWidgets.QLabel("BMS序列号")
+        self.first_frame_layout.addWidget(self.lb_bms_sn, 0, 0, 1, 1)
+        self.btn_bms_sn = QtWidgets.QPushButton("录入")
+        self.first_frame_layout.addWidget(self.btn_bms_sn, 1, 0, 1, 1)
+        self.edt_bms_sn = QtWidgets.QLineEdit(self.first_frame)
+        self.edt_bms_sn.setValidator(self.validator)
+        self.first_frame_layout.addWidget(self.edt_bms_sn, 0, 1, 2, 4)       
+        self.right_widget_layout.addWidget(self.first_frame)
+
+        self.second_frame = MyFrame(self.right_widget)
+        self.second_frame_layout = QtWidgets.QGridLayout(self.second_frame)
+        self.lb_battery_sn = QtWidgets.QLabel("电池编码")
+        self.second_frame_layout.addWidget(self.lb_battery_sn, 0, 0, 1, 1)
+        self.btn_battery_sn = QtWidgets.QPushButton("录入")
+        self.second_frame_layout.addWidget(self.btn_battery_sn, 1, 0, 1, 1)
+        self.edt_battery_sn = QtWidgets.QLineEdit(self.first_frame)
+        self.edt_battery_sn.setValidator(self.validator)
+        self.second_frame_layout.addWidget(self.edt_battery_sn, 0, 1, 2, 4)  
+        self.right_widget_layout.addWidget(self.second_frame)
+
+        spacerItem1 = QtWidgets.QSpacerItem(40, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.right_widget_layout.addItem(spacerItem1)
+
+        self.download_layout.addWidget(self.right_widget, 1)
+
+        QtCore.QMetaObject.connectSlotsByName(Download)

+ 366 - 0
ui/hard.py

@@ -0,0 +1,366 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from ui.own.palette_theme import set_edt_bg
+from utils.qt import QtWidgets, QtCore, Qt, QColor
+
+
+class Hard(MyFrame):
+    def setupUi(self, Hard):
+
+        self.hard = MyFrame(Hard)
+        self.hard_layout = QtWidgets.QHBoxLayout(self.hard)
+        # self.hard_layout.setContentsMargins(5, 5, 5, 5)
+        self.hard_layout.setSpacing(0)
+
+        self.hard_left_groupbox = QtWidgets.QGroupBox(self.hard)
+        self.hard_left_groupbox.setTitle("单体电压校准")
+        self.hard_left_groupbox_layout = QtWidgets.QVBoxLayout(self.hard_left_groupbox)
+
+        self.hard_left_top_widget = QtWidgets.QWidget()
+        self.hard_left_top_layout = QtWidgets.QHBoxLayout(self.hard_left_top_widget)
+
+        self.lb_cj = QtWidgets.QLabel("从机编号选择:")
+        self.hard_left_top_layout.addWidget(self.lb_cj)
+        self.cb_bmu_index = QtWidgets.QComboBox()
+        for i in range(15):
+            self.cb_bmu_index.addItem(str(i + 1))
+        self.hard_left_top_layout.addWidget(self.cb_bmu_index)
+
+
+        self.hard_left_top_layout.addStretch() 
+
+        self.hard_left_groupbox_layout.addWidget(self.hard_left_top_widget)
+
+        self.hard_table = QtWidgets.QTableWidget(self.hard_left_groupbox)
+        self.hard_table.setColumnCount(6)
+        self.hard_table.verticalHeader().setVisible(False)
+        self.hard_table.verticalHeader().setHighlightSections(True)
+        self.hard_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.hard_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.hard_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.hard_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        # 设置只能选择行
+        self.hard_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.hard_table.setHorizontalHeaderLabels(["序号", "参数名称", "电池真实值", "BMS上传值", "误差", "单位"])
+        self.hard_table.setRowCount(72)
+
+        for i in range(72):
+            item = QtWidgets.QTableWidgetItem(str(i + 1))
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setItem(i, 0, item)
+            item = QtWidgets.QTableWidgetItem("mV")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setItem(i, 5, item)
+            # if i == 0:
+            #     item = QtWidgets.QTableWidgetItem("所有单体电压")
+            #     item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            #     self.hard_table.setItem(0, 1, item)               
+            # else:
+            item = QtWidgets.QTableWidgetItem("C" + str(i + 1) + "单体电压")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setItem(i, 1, item)
+            item = QtWidgets.QLineEdit()
+            item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setCellWidget(i, 2, item)  
+            item = QtWidgets.QTableWidgetItem("")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setItem(i, 3, item) 
+            item = QtWidgets.QTableWidgetItem("")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.hard_table.setItem(i, 4, item)            
+        
+        # self.hard_table.item(0, 3).setText("2200")
+        # self.hard_table.item(4, 3).setText("2200")
+        # self.hard_table.item(8, 3).setText("2200")
+
+        self.hard_left_groupbox_layout.addWidget(self.hard_table)
+
+        self.set_widget = QtWidgets.QWidget()
+        self.set_widget_layout = QtWidgets.QGridLayout(self.set_widget)
+        self.lb_wctj = QtWidgets.QLabel("误差统计:最大值")
+        self.set_widget_layout.addWidget(self.lb_wctj, 0, 0, 1, 2)
+
+        self.edt_max = QtWidgets.QLineEdit(self.set_widget)
+        self.edt_max.setText("0")
+        self.edt_max.setAlignment(Qt.AlignCenter)
+        self.edt_max.setReadOnly(True)
+        set_edt_bg(self.edt_max, QColor(Qt.gray))
+        self.set_widget_layout.addWidget(self.edt_max, 0, 2, 1, 1)
+
+        self.lb_zxz = QtWidgets.QLabel("mV   最小值")
+        self.set_widget_layout.addWidget(self.lb_zxz, 0, 3, 1, 1)
+
+        self.edt_min = QtWidgets.QLineEdit(self.set_widget)
+        self.edt_min.setText("0")
+        self.edt_min.setAlignment(Qt.AlignCenter)
+        self.edt_min.setReadOnly(True)
+        set_edt_bg(self.edt_min, QColor(Qt.gray))
+        self.set_widget_layout.addWidget(self.edt_min, 0, 4, 1, 1)
+
+        self.lb_jz = QtWidgets.QLabel("mV   均值")
+        self.set_widget_layout.addWidget(self.lb_jz, 0, 5, 1, 1)      
+
+        self.edt_avg = QtWidgets.QLineEdit(self.set_widget)
+        self.edt_avg.setText("0")
+        self.edt_avg.setAlignment(Qt.AlignCenter)
+        self.edt_avg.setReadOnly(True)
+        set_edt_bg(self.edt_avg, QColor(Qt.gray))
+        self.set_widget_layout.addWidget(self.edt_avg, 0, 6, 1, 1)
+
+        self.lb_bzz = QtWidgets.QLabel("mV   标准差")
+        self.set_widget_layout.addWidget(self.lb_bzz, 0, 7, 1, 1)      
+
+        self.edt_bzc = QtWidgets.QLineEdit(self.set_widget)
+        self.edt_bzc.setText("0")
+        self.edt_bzc.setAlignment(Qt.AlignCenter)
+        self.edt_bzc.setReadOnly(True)
+        set_edt_bg(self.edt_bzc, QColor(Qt.gray))
+        self.set_widget_layout.addWidget(self.edt_bzc, 0, 8, 1, 1)
+
+        self.lb_dw = QtWidgets.QLabel("mV")
+        self.set_widget_layout.addWidget(self.lb_dw, 0, 9, 1, 1)  
+
+        self.lb_dtjzz = QtWidgets.QLabel("单体校准值")
+        self.set_widget_layout.addWidget(self.lb_dtjzz, 1, 0, 1, 1)  
+
+        self.edt_cell = QtWidgets.QLineEdit(self.set_widget)
+        self.edt_cell.setText("0")
+        self.edt_cell.setAlignment(Qt.AlignCenter)
+        self.edt_cell.setReadOnly(True)
+        set_edt_bg(self.edt_cell, QColor(Qt.gray))
+        self.set_widget_layout.addWidget(self.edt_cell, 1, 1, 1, 1)
+
+        self.lb_dsw = QtWidgets.QLabel("mV")
+        self.set_widget_layout.addWidget(self.lb_dsw, 1, 2, 1, 1)  
+
+        self.btn_hand = QtWidgets.QPushButton("手动校准")
+        self.set_widget_layout.addWidget(self.btn_hand, 1, 4, 1, 2)  
+
+        self.btn_auto = QtWidgets.QPushButton("自动校准")
+        self.set_widget_layout.addWidget(self.btn_auto, 1, 7, 1, 2)  
+
+        self.hard_left_groupbox_layout.addWidget(self.set_widget)
+
+        self.hard_layout.addWidget(self.hard_left_groupbox, 1)
+
+        self.hard_right_frame = MyFrame(self.hard)
+        self.hard_right_frame_layout = QtWidgets.QVBoxLayout(self.hard_right_frame)
+
+        self.rtc_groupbox = QtWidgets.QGroupBox("RTC时钟校准")
+        self.rtc_groupbox_layout = QtWidgets.QHBoxLayout(self.rtc_groupbox)
+        self.lb_rtc = QtWidgets.QLabel("RTC时钟")
+        self.rtc_groupbox_layout.addWidget(self.lb_rtc)
+        self.qline_rtc = QtWidgets.QLineEdit(self.rtc_groupbox)
+        self.qline_rtc.setReadOnly(True)
+        self.rtc_groupbox_layout.addWidget(self.qline_rtc)
+        self.qcheckbox_rtc = QtWidgets.QCheckBox("实时更新")
+        self.rtc_groupbox_layout.addWidget(self.qcheckbox_rtc)
+        self.btn_rtc = QtWidgets.QPushButton("时钟校准")
+        self.rtc_groupbox_layout.addWidget(self.btn_rtc)
+        self.hard_right_frame_layout.addWidget(self.rtc_groupbox, 1)
+
+
+        self.vol_groupbox = QtWidgets.QGroupBox("总电压校准")
+        self.vol_groupbox_layout = QtWidgets.QVBoxLayout(self.vol_groupbox)
+        self.vol_table = QtWidgets.QTableWidget(self.vol_groupbox)
+        self.vol_table.setColumnCount(7)
+        self.vol_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        self.vol_table.verticalHeader().setVisible(False)
+        self.vol_table.verticalHeader().setHighlightSections(True)
+        self.vol_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.vol_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.vol_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.vol_table.setHorizontalHeaderLabels(["序号", "参数名称", "模拟总压值", "BMS上传值", "校准值", "误差", "单位"])
+        self.vol_table.setRowCount(3)
+
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(0, 0, item)
+        item = QtWidgets.QTableWidgetItem("总压")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(0, 1, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(0, 2, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(0, 3, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(0, 4, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(0, 5, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(0, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("2")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(1, 0, item)
+        item = QtWidgets.QTableWidgetItem("总压2")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(1, 1, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(1, 2, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(1, 3, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(1, 4, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(1, 5, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(1, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("3")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(2, 0, item)
+        item = QtWidgets.QTableWidgetItem("总压3")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(2, 1, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(2, 2, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(2, 3, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setCellWidget(2, 4, item)
+        item = QtWidgets.QTableWidgetItem("")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(2, 5, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.vol_table.setItem(2, 6, item)
+
+        self.vol_groupbox_layout.addWidget(self.vol_table)
+        self.vol_widget = QtWidgets.QWidget(self.vol_groupbox)
+        self.vol_widget_layout = QtWidgets.QHBoxLayout(self.vol_widget)
+        self.btn_hand_cali = QtWidgets.QPushButton("手动校准")
+        self.vol_widget_layout.addWidget(self.btn_hand_cali)
+        self.btn_auto_cali = QtWidgets.QPushButton("自动校准")
+        self.vol_widget_layout.addWidget(self.btn_auto_cali)
+        self.vol_groupbox_layout.addWidget(self.vol_widget)
+        self.hard_right_frame_layout.addWidget(self.vol_groupbox, 3)
+
+
+        self.cur_groupbox = QtWidgets.QGroupBox("总电流校准")
+        self.cur_groupbox_layout = QtWidgets.QVBoxLayout(self.cur_groupbox)
+        self.cur_table = QtWidgets.QTableWidget(self.cur_groupbox)
+        self.cur_table.setColumnCount(5)
+        self.cur_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        self.cur_table.verticalHeader().setVisible(False)
+        self.cur_table.verticalHeader().setHighlightSections(True)
+        self.cur_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cur_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.cur_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.cur_table.setHorizontalHeaderLabels(["测试工步", "STEP1", "STEP2", "STEP3", "单位"])
+        self.cur_table.setRowCount(3)
+
+        item = QtWidgets.QTableWidgetItem("模拟电流值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(0, 0, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setCellWidget(0, 1, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setCellWidget(0, 2, item)
+        item = QtWidgets.QLineEdit()
+        item.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setCellWidget(0, 3, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(0, 4, item)
+
+        item = QtWidgets.QTableWidgetItem("BMS上传值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(1, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(1, 4, item)
+
+        item = QtWidgets.QTableWidgetItem("误差")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(2, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.cur_table.setItem(2, 4, item)
+
+        self.cur_groupbox_layout.addWidget(self.cur_table)
+        self.cur_widget = QtWidgets.QWidget(self.cur_groupbox)
+        self.cur_widget_layout = QtWidgets.QHBoxLayout(self.cur_widget)
+        self.lb_cali = QtWidgets.QLabel("增益校准值")
+        self.cur_widget_layout.addWidget(self.lb_cali)
+        self.qline_cali = QtWidgets.QLabel(self.cur_widget)
+        self.cur_widget_layout.addWidget(self.qline_cali)
+        self.lb_zero = QtWidgets.QLabel("零漂校准值")
+        self.cur_widget_layout.addWidget(self.lb_zero)
+        self.qline_zero = QtWidgets.QLabel(self.cur_widget)
+        self.cur_widget_layout.addWidget(self.qline_zero)
+        self.btn_cur_hand_cali = QtWidgets.QPushButton("手动校准")
+        self.cur_widget_layout.addWidget(self.btn_cur_hand_cali)
+        self.btn_hand_auto_cali = QtWidgets.QPushButton("自动校准")
+        self.cur_widget_layout.addWidget(self.btn_hand_auto_cali)
+        self.cur_groupbox_layout.addWidget(self.cur_widget)
+        self.hard_right_frame_layout.addWidget(self.cur_groupbox, 3)
+
+        self.temp_groupbox = QtWidgets.QGroupBox("从控温度配置")
+        self.temp_groupbox_layout = QtWidgets.QHBoxLayout(self.temp_groupbox)
+        self.temp_qscrollarea = QtWidgets.QScrollArea(self.temp_groupbox)
+        self.temp_qscrollarea.setWidgetResizable(True)
+        self.temp_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.temp_groupbox_layout.addWidget(self.temp_qscrollarea)
+        self.temp_qwidget = QtWidgets.QWidget()
+        self.temp_qscrollarea.setWidget(self.temp_qwidget)
+        self.temp_qscrollarea_layout = QtWidgets.QGridLayout(self.temp_qwidget)
+        # self.temp_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.temp_qscrollarea_layout.setSpacing(0)
+        for i in range(16):
+            if i == 0:
+                bmu_label = QtWidgets.QLabel("CMU ID")
+                # bmu_label.setAlignment(Qt.AlignCenter)
+                self.temp_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)  
+            else:              
+                bmu_label = QtWidgets.QLabel("CMU" + str(i))
+                # bmu_label.setAlignment(Qt.AlignCenter)
+                self.temp_qscrollarea_layout.addWidget(bmu_label, i, 0, 1, 1)
+        for i in range(16):
+            for j in range(72):
+                if i == 0:
+                    bmu_label = QtWidgets.QLabel("T" + str(j + 1))
+                    # bmu_label.setAlignment(Qt.AlignCenter)
+                    self.temp_qscrollarea_layout.addWidget(bmu_label, i , j + 1, 1, 1)               
+                else:
+                    qtemp_checkbox = QtWidgets.QCheckBox()
+                    # qtemp_lebal.setAlignment(Qt.AlignCenter)
+                    # qtemp_checkbox
+                    qtemp_checkbox.setFixedWidth(40)
+                    # qtemp_lebal.setReadOnly(True)
+                    self.temp_qscrollarea_layout.addWidget(qtemp_checkbox, i, j + 1, 1, 1)
+
+        self.hard_right_frame_layout.addWidget(self.temp_groupbox, 2)
+        
+        self.btn_widget = QtWidgets.QWidget()
+        self.btn_widget_layout = QtWidgets.QHBoxLayout(self.btn_widget)
+
+        self.btn_read_hard_param = QtWidgets.QPushButton("读取硬件参数")
+        self.btn_widget_layout.addWidget(self.btn_read_hard_param)
+
+        self.btn_exit_hard_param = QtWidgets.QPushButton("退出参数标定")
+        self.btn_widget_layout.addWidget(self.btn_exit_hard_param)
+
+        self.hard_right_frame_layout.addWidget(self.btn_widget)
+        self.hard_right_frame_layout.addStretch()
+
+        self.hard_layout.addWidget(self.hard_right_frame, 1)
+
+        QtCore.QMetaObject.connectSlotsByName(Hard)

+ 187 - 0
ui/home.py

@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import os
+from ui.own.frame_theme import MyFrame
+from utils.globalvar import SD
+from ui.own.led import Led
+from ui.own.switch_button import SwitchButton
+from ui.own.palette_theme import set_my_palette
+from utils.qt import Qt, QWidget, QVBoxLayout, QHBoxLayout, QStackedWidget, QPixmap, QLabel, QGroupBox, QRect, QPushButton, QSizePolicy, QLineEdit, QTabWidget, QComboBox, QPlainTextEdit, QSize, QCoreApplication, QMetaObject, QIcon
+from utils.resource import resource_path
+
+
+class UiBmsHomePage(object):
+    def setupUi(self, main):
+        main.resize(1366, 768)
+        main.setMinimumSize(1366, 768)
+
+        # main.resize(1920, 1080)
+        # main.setMinimumSize(1920, 1080)
+
+        set_my_palette(main)
+
+        self.central_widget = QWidget(main)
+        self.main_layout = QVBoxLayout(self.central_widget)
+        self.main_layout.setContentsMargins(0, 0, 0, 0)
+        self.main_layout.setSpacing(0)
+
+        # 主窗口上侧布局
+        self.top_widget = QWidget(self.central_widget)
+
+        # 主窗口上采用水平布局
+        self.top_layout = QHBoxLayout(self.top_widget)
+        self.top_layout.setContentsMargins(0, 0, 0, 0)
+        self.top_layout.setSpacing(0)
+
+        self.label = QLabel(self.top_widget)
+        self.label.setText("")
+        self.label.setTextFormat(Qt.RichText)
+        self.label.setPixmap(QPixmap(resource_path(os.path.join("assets", "logo.png"))))
+        self.label.setScaledContents(False)
+        self.top_layout.addWidget(self.label)  
+
+        self.top_layout.addStretch() 
+
+        self.btn_start = QPushButton("启动")
+        self.btn_start.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "start.png")))))
+        self.top_layout.addWidget(self.btn_start)  
+
+        self.top_layout.addStretch() 
+
+        self.btn_stop = QPushButton("停止")
+        self.btn_stop.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "stop.png")))))
+        self.top_layout.addWidget(self.btn_stop)  
+
+        self.top_layout.addStretch() 
+
+        self.btn_cut = QPushButton("截图")
+        self.btn_cut.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "cut.png")))))
+        self.top_layout.addWidget(self.btn_cut)
+
+        self.top_layout.addStretch() 
+
+        self.label_lb = QLabel("当前在线主控: ")
+        self.top_layout.addWidget(self.label_lb)
+        self.edt_online = QLineEdit()
+        self.edt_online.setReadOnly(True)
+        self.edt_online.setFixedWidth(500)
+        self.top_layout.addWidget(self.edt_online)
+
+        self.top_layout.addStretch() 
+
+        self.zkc = QLabel("主控选择:")
+        self.top_layout.addWidget(self.zkc)
+        self.cb_bcu = QComboBox()
+        for i in range(15):
+            self.cb_bcu.addItem("BMU" + str(i + 1))
+        self.top_layout.addWidget(self.cb_bcu)
+
+        self.top_layout.addStretch() 
+
+        self.ckc = QLabel("从控选择:")
+        self.top_layout.addWidget(self.ckc)
+        self.cb_bmu = QComboBox()
+        for i in range(15):
+            self.cb_bmu.addItem("CMU" + str(i + 1))
+        self.top_layout.addWidget(self.cb_bmu)
+
+        self.top_layout.addStretch() 
+
+        self.main_layout.addWidget(self.top_widget, 1)
+
+        # 主窗口下侧布局
+        self.under_widget = QWidget(self.central_widget)
+
+        # 主窗口下采用水平布局
+        self.under_layout = QHBoxLayout(self.under_widget)
+        self.under_layout.setContentsMargins(0, 0, 0, 0)
+        self.under_layout.setSpacing(0)
+
+        # 主窗口下左侧布局
+        self.under_left_widget = QWidget(self.under_widget)
+
+        # 主窗口左侧采用垂直布局
+        self.under_left_layout = QVBoxLayout(self.under_left_widget)
+        self.under_left_layout.setContentsMargins(0, 0, 0, 0)
+        self.under_left_layout.setSpacing(0)
+
+
+        self.btn_main_control = QPushButton(self.under_left_widget)
+        self.btn_main_control.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "home.png")))))
+        self.btn_main_control.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_main_control)
+
+        self.btn_cell_inf = QPushButton(self.under_left_widget)
+        self.btn_cell_inf.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "cell.png")))))
+        self.btn_cell_inf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_cell_inf)
+
+        self.btn_double_ccu = QPushButton(self.under_left_widget)
+        self.btn_double_ccu.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "bcu.png")))))
+        self.btn_double_ccu.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_double_ccu)
+
+        self.btn_protect_inf = QPushButton(self.under_left_widget)
+        self.btn_protect_inf.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "protect.png")))))
+        self.btn_protect_inf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_protect_inf)
+
+        self.btn_hard_cali = QPushButton(self.under_left_widget)
+        self.btn_hard_cali.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "hard.png")))))
+        self.btn_hard_cali.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_hard_cali)
+
+        self.btn_balance_inf = QPushButton(self.under_left_widget)
+        self.btn_balance_inf.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "balance.png")))))
+        self.btn_balance_inf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_balance_inf)
+
+        self.btn_data_inf = QPushButton(self.under_left_widget)
+        self.btn_data_inf.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "data.png")))))
+        self.btn_data_inf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_data_inf)
+
+        self.btn_download = QPushButton(self.under_left_widget)
+        self.btn_download.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "download.png")))))
+        self.btn_download.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_download)
+
+        self.btn_set_inf = QPushButton(self.under_left_widget)
+        self.btn_set_inf.setIcon(QIcon(QPixmap(resource_path(os.path.join("assets/icon", "set.png")))))
+        self.btn_set_inf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        self.under_left_layout.addWidget(self.btn_set_inf)
+
+        self.under_layout.addWidget(self.under_left_widget, 1)
+
+        self.under_right_widget = QWidget(self.central_widget)
+
+        self.under_right_layout = QVBoxLayout(self.under_right_widget)
+        self.under_right_layout.setContentsMargins(0, 0, 0, 0)
+        self.under_right_layout.setSpacing(0)
+
+        self.bms_tab = QStackedWidget(self.under_right_widget)
+        self.under_right_layout.addWidget(self.bms_tab)
+
+        self.under_layout.addWidget(self.under_right_widget, 9)
+
+        self.main_layout.addWidget(self.under_widget, 9)
+
+        main.setCentralWidget(self.central_widget)
+
+        self.retranslateUi(main)
+        QMetaObject.connectSlotsByName(main)
+
+    def retranslateUi(self, MainWindow):
+        _translate = QCoreApplication.translate
+        MainWindow.setWindowTitle(_translate("MainWindow", "EnergyMath"))
+        # self.groupbox_bms_log.setTitle(_translate("MainWindow", "连接状态"))
+        self.btn_main_control.setText("主控信息")
+        self.btn_cell_inf.setText("单体信息")
+        self.btn_double_ccu.setText("并簇信息")
+        self.btn_protect_inf.setText("保护参数")
+        self.btn_hard_cali.setText("硬件校准")
+        self.btn_balance_inf.setText("均衡状态")
+        self.btn_data_inf.setText("数据记录")
+        self.btn_download.setText("下载调试")
+        self.btn_set_inf.setText("设置")

+ 158 - 0
ui/login.py

@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import os
+from ui.own.palette_theme import set_my_palette, set_sure_background
+from utils.resource import resource_path
+from utils.globalvar import SD
+from utils.qt import QPixmap, Qt, QFont, QWidget, QComboBox, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QSize, QRect, QCoreApplication, QMetaObject
+
+
+class UiBmsLoginPage(object):
+    def setupUi(self, bms_login):
+        bms_login.resize(400, 500)
+        bms_login.setMinimumSize(QSize(400, 500))
+        bms_login.setMaximumSize(QSize(400, 500))
+        set_my_palette(bms_login)
+
+        self.layoutWidget = QWidget(bms_login)
+        self.layoutWidget.setGeometry(QRect(70, 90, 261, 351))
+
+        self.verticalLayout = QVBoxLayout(self.layoutWidget)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+
+
+        self.h_layout_role = QHBoxLayout()
+        self.lb_role = QLabel()
+        self.h_layout_role.addWidget(self.lb_role)
+        self.cb_role = QComboBox()
+        self.cb_role.setObjectName("cb_role")
+        for i in range(5):
+            self.cb_role.addItem("")
+        self.cb_role.setItemText(0, "普通用户")
+        self.cb_role.setItemText(1, "调试工程师")
+        self.cb_role.setItemText(2, "BMS产线操作员")
+        self.cb_role.setItemText(3, "PACK产线操作")
+        self.cb_role.setItemText(4, "系统管理员")
+        self.h_layout_role.addWidget(self.cb_role)
+        self.verticalLayout.addLayout(self.h_layout_role)
+
+
+        self.h_layout_password = QHBoxLayout()
+        self.lb_password = QLabel()
+        self.h_layout_password.addWidget(self.lb_password)
+        self.edt_password = QLineEdit()
+        self.edt_password.setEchoMode(QLineEdit.Password)
+        self.edt_password.setObjectName("edt_password")
+        self.h_layout_password.addWidget(self.edt_password)
+        self.verticalLayout.addLayout(self.h_layout_password)
+
+        self.h_layout_prj = QHBoxLayout()
+        self.lb_prj = QLabel()
+        self.h_layout_prj.addWidget(self.lb_prj)
+        self.cb_prj = QComboBox()
+        self.cb_prj.setObjectName("cb_prj")
+        for i in range(2):
+            self.cb_prj.addItem("")
+        self.cb_prj.setItemText(0, "户储")
+        self.cb_prj.setItemText(1, "工商业")
+        self.cb_prj.setCurrentIndex(1)
+        self.h_layout_prj.addWidget(self.cb_prj)
+        self.verticalLayout.addLayout(self.h_layout_prj)
+
+
+        self.h_layout_con_type = QHBoxLayout()
+        self.lb_con_type = QLabel()
+        self.h_layout_con_type.addWidget(self.lb_con_type)
+        self.cb_con_type = QComboBox()
+        self.cb_con_type.setObjectName("cb_con_type")
+        self.cb_con_type.addItem("")
+        self.cb_con_type.addItem("")
+        self.cb_con_type.setItemText(0, "ZLGCAN")
+        self.cb_con_type.setItemText(1, "PCAN")
+        self.h_layout_con_type.addWidget(self.cb_con_type)
+        self.verticalLayout.addLayout(self.h_layout_con_type)
+
+
+        self.h_layout_channel = QHBoxLayout()
+        self.lb_channel = QLabel()
+        self.h_layout_channel.addWidget(self.lb_channel)
+        self.cb_channel = QComboBox()
+        self.cb_channel.setObjectName("cb_channel")
+        for i in range(9):
+            self.cb_channel.addItem("")
+        self.cb_channel.setItemText(0, "0")
+        self.cb_channel.setItemText(1, "1")
+        self.cb_channel.setItemText(2, "2")
+        self.cb_channel.setItemText(3, "3")
+        self.cb_channel.setItemText(4, "4")
+        self.cb_channel.setItemText(5, "5")
+        self.cb_channel.setItemText(6, "6")
+        self.cb_channel.setItemText(7, "7")
+        self.cb_channel.setItemText(8, "8")
+        self.h_layout_channel.addWidget(self.cb_channel)
+        self.verticalLayout.addLayout(self.h_layout_channel)
+
+        self.h_layout_index = QHBoxLayout()
+        self.lb_index = QLabel()
+        self.h_layout_index.addWidget(self.lb_index)
+        self.cb_index = QComboBox()
+        self.cb_index.setObjectName("cb_index")
+        for i in range(2):
+            self.cb_index.addItem("")
+        self.cb_index.setItemText(0, "0")
+        self.cb_index.setItemText(1, "1")
+        self.h_layout_index.addWidget(self.cb_index)
+        self.verticalLayout.addLayout(self.h_layout_index)
+
+        self.h_layout_baudrate = QHBoxLayout()
+        self.lb_baudrate = QLabel()
+        self.h_layout_baudrate.addWidget(self.lb_baudrate)
+        self.cb_baudrate = QComboBox()
+        self.cb_baudrate.setObjectName("cb_baudrate")
+        for i in range(3):
+            self.cb_baudrate.addItem("")
+        self.cb_baudrate.setItemText(0, "125Kbps")
+        self.cb_baudrate.setItemText(1, "250Kbps")
+        self.cb_baudrate.setItemText(2, "500Kbps")
+        self.h_layout_baudrate.addWidget(self.cb_baudrate)
+        self.verticalLayout.addLayout(self.h_layout_baudrate)
+
+        self.cb_change_languqge = QComboBox(bms_login)
+        self.cb_change_languqge.setObjectName("language")
+        self.cb_change_languqge.addItem("")
+        self.cb_change_languqge.addItem("")
+        self.cb_change_languqge.setItemText(0, "中文")
+        self.cb_change_languqge.setItemText(1, "English")
+        self.verticalLayout.addWidget(self.cb_change_languqge)
+
+        self.horizontalLayout = QHBoxLayout()
+
+        self.btn_login = QPushButton(self.layoutWidget)
+        self.btn_login.setObjectName("btn_login")
+        set_sure_background(self.btn_login)
+        self.horizontalLayout.addWidget(self.btn_login)
+
+        self.btn_cancel = QPushButton(self.layoutWidget)
+        self.btn_cancel.setObjectName("btn_cancel")
+        self.horizontalLayout.addWidget(self.btn_cancel)
+
+        self.verticalLayout.addLayout(self.horizontalLayout)
+
+
+        self.retranslateUi(bms_login)
+        QMetaObject.connectSlotsByName(bms_login)
+
+    def retranslateUi(self, bms_login):
+        _translate = QCoreApplication.translate
+        bms_login.setWindowTitle(_translate("bms_login", "用户登录" if SD.SYSTEM_LANGUAGE == 0 else "Login"))
+        self.lb_role.setText("登录角色" if SD.SYSTEM_LANGUAGE == 0 else "Role")
+        self.lb_password.setText("登录密码" if SD.SYSTEM_LANGUAGE == 0 else "PassWord")
+        self.lb_prj.setText("登录项目" if SD.SYSTEM_LANGUAGE == 0 else "Project")
+        self.lb_con_type.setText("通讯类型" if SD.SYSTEM_LANGUAGE == 0 else "Conn Type")
+        self.lb_channel.setText("索引号" if SD.SYSTEM_LANGUAGE == 0 else "Index")
+        self.lb_index.setText("通道号" if SD.SYSTEM_LANGUAGE == 0 else "Channel")
+        self.lb_baudrate.setText("波特率" if SD.SYSTEM_LANGUAGE == 0 else "BPS")
+        self.edt_password.setPlaceholderText("密码" if SD.SYSTEM_LANGUAGE == 0 else "PassWord")
+        self.btn_login.setText(_translate("bms_login", "登录" if SD.SYSTEM_LANGUAGE == 0 else "Login"))
+        self.btn_cancel.setText(_translate("bms_login", "取消" if SD.SYSTEM_LANGUAGE == 0 else "Cancel"))

+ 0 - 0
ui/main/__init__.py


+ 435 - 0
ui/main/center_page.py

@@ -0,0 +1,435 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import os
+from ui.own.frame_theme import MyFrame
+from ui.own.palette_theme import set_edt_bg
+from utils.qt import QtWidgets, QtGui, QIcon, QPixmap, Qt, QColor
+from utils.resource import resource_path
+from utils.globalvar import SD
+
+
+class CenterPage(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        super(CenterPage, self).__init__(parent)
+        self.initUI()
+
+    def initUI(self):
+        self.verticalLayout = QtWidgets.QVBoxLayout(self)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+        self.verticalLayout.setSpacing(0)
+
+        # 设置参数
+        self.center_widget = MyFrame(self)
+        self.center_layout = QtWidgets.QVBoxLayout(self.center_widget)
+        self.center_layout.setContentsMargins(0, 0, 0, 0)
+        self.center_layout.setSpacing(0)
+        self.center_groupbox = QtWidgets.QGroupBox(self.center_widget)
+        self.center_groupbox.setTitle("告警信息" if SD.SYSTEM_LANGUAGE == 0 else "Warn")
+        self.center_groupbox_layout = QtWidgets.QHBoxLayout(self.center_groupbox)
+
+        self.center_qscrollarea = QtWidgets.QScrollArea(self.center_groupbox)
+        self.center_qscrollarea.setWidgetResizable(True)
+        self.center_groupbox_layout.addWidget(self.center_qscrollarea,9)
+
+        self.center_qwidget = QtWidgets.QWidget()
+        self.center_qscrollarea.setWidget(self.center_qwidget)
+
+        self.center_qscrollarea_layout = QtWidgets.QGridLayout(self.center_qwidget)
+        self.center_qscrollarea_layout.setObjectName("scrollLayout")
+        self.center_qscrollarea_layout.setContentsMargins(0, 0, 0, 0)
+        self.center_qscrollarea_layout.setSpacing(0)
+
+
+        self.over_cell_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.over_cell_warn.setText("单体过压告警" if SD.SYSTEM_LANGUAGE == 0 else "Warn")
+        self.over_cell_warn.setAlignment(Qt.AlignCenter)
+        self.over_cell_warn.setReadOnly(True)
+        set_edt_bg(self.over_cell_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.over_cell_warn, 0, 0, 1, 1)
+
+        self.under_cell_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.under_cell_warn.setText("单体欠压告警")
+        self.under_cell_warn.setAlignment(Qt.AlignCenter)
+        self.under_cell_warn.setReadOnly(True)
+        set_edt_bg(self.under_cell_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.under_cell_warn, 0, 1, 1, 1)
+
+        self.hv_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.hv_warn.setText("总压过压告警")
+        self.hv_warn.setAlignment(Qt.AlignCenter)
+        self.hv_warn.setReadOnly(True)
+        set_edt_bg(self.hv_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.hv_warn, 0, 2, 1, 1)
+
+        self.lv_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.lv_warn.setText("总压欠压告警")
+        self.lv_warn.setAlignment(Qt.AlignCenter)
+        self.lv_warn.setReadOnly(True)
+        set_edt_bg(self.lv_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.lv_warn, 0, 3, 1, 1)
+
+        self.chg_lt_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.chg_lt_warn.setText("充电低温告警")
+        self.chg_lt_warn.setAlignment(Qt.AlignCenter)
+        self.chg_lt_warn.setReadOnly(True)
+        set_edt_bg(self.chg_lt_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.chg_lt_warn, 0, 4, 1, 1)
+
+        self.chg_ht_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.chg_ht_warn.setText("充电高温告警")
+        self.chg_ht_warn.setAlignment(Qt.AlignCenter)
+        self.chg_ht_warn.setReadOnly(True)
+        set_edt_bg(self.chg_ht_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.chg_ht_warn, 0, 5, 1, 1)
+
+        self.dchg_ht_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.dchg_ht_warn.setText("放电高温告警")
+        self.dchg_ht_warn.setAlignment(Qt.AlignCenter)
+        self.dchg_ht_warn.setReadOnly(True)
+        set_edt_bg(self.dchg_ht_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.dchg_ht_warn, 0, 6, 1, 1)
+
+        self.dchg_lt_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.dchg_lt_warn.setText("放电低温告警")
+        self.dchg_lt_warn.setAlignment(Qt.AlignCenter)
+        self.dchg_lt_warn.setReadOnly(True)
+        set_edt_bg(self.dchg_lt_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.dchg_lt_warn, 0, 7, 1, 1)
+
+        self.chg_hcur_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.chg_hcur_warn.setText("充电过流告警")
+        self.chg_hcur_warn.setAlignment(Qt.AlignCenter)
+        self.chg_hcur_warn.setReadOnly(True)
+        set_edt_bg(self.chg_hcur_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.chg_hcur_warn, 0, 8, 1, 1)
+
+        self.dchg_hcur_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.dchg_hcur_warn.setText("放电过流告警")
+        self.dchg_hcur_warn.setAlignment(Qt.AlignCenter)
+        self.dchg_hcur_warn.setReadOnly(True)
+        set_edt_bg(self.dchg_hcur_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.dchg_hcur_warn, 0, 9, 1, 1)
+
+
+        self.diff_cell_temp_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.diff_cell_temp_warn.setText("单体温差告警")
+        self.diff_cell_temp_warn.setAlignment(Qt.AlignCenter)
+        self.diff_cell_temp_warn.setReadOnly(True)
+        set_edt_bg(self.diff_cell_temp_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.diff_cell_temp_warn, 1, 0, 1, 1)
+
+        self.diff_cell_vol_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.diff_cell_vol_warn.setText("单体压差告警")
+        self.diff_cell_vol_warn.setAlignment(Qt.AlignCenter)
+        self.diff_cell_vol_warn.setReadOnly(True)
+        set_edt_bg(self.diff_cell_vol_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.diff_cell_vol_warn, 1, 1, 1, 1)
+
+        self.against_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.against_warn.setText("绝缘过低告警")
+        self.against_warn.setAlignment(Qt.AlignCenter)
+        self.against_warn.setReadOnly(True)
+        set_edt_bg(self.against_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.against_warn, 1, 2, 1, 1)
+
+        self.p_against_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.p_against_warn.setText("正极绝缘过低告警")
+        self.p_against_warn.setAlignment(Qt.AlignCenter)
+        self.p_against_warn.setReadOnly(True)
+        set_edt_bg(self.p_against_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.p_against_warn, 1, 3, 1, 1)
+
+        self.n_against_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.n_against_warn.setText("负极绝缘过低告警")
+        self.n_against_warn.setAlignment(Qt.AlignCenter)
+        self.n_against_warn.setReadOnly(True)
+        set_edt_bg(self.n_against_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.n_against_warn, 1, 4, 1, 1)
+
+        self.against_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.against_fault.setText("绝缘监测故障")
+        self.against_fault.setAlignment(Qt.AlignCenter)
+        self.against_fault.setReadOnly(True)
+        set_edt_bg(self.against_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.against_fault, 1, 5, 1, 1)
+
+        self.vol_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.vol_fault.setText("总压检测故障")
+        self.vol_fault.setAlignment(Qt.AlignCenter)
+        self.vol_fault.setReadOnly(True)
+        set_edt_bg(self.vol_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.vol_fault, 1, 6, 1, 1)
+
+        self.cur_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.cur_fault.setText("电流检测故障")
+        self.cur_fault.setAlignment(Qt.AlignCenter)
+        self.cur_fault.setReadOnly(True)
+        set_edt_bg(self.cur_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.cur_fault, 1, 7, 1, 1)
+
+        self.ccu_control_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ccu_control_fault.setText("总控通讯故障")
+        self.ccu_control_fault.setAlignment(Qt.AlignCenter)
+        self.ccu_control_fault.setReadOnly(True)
+        set_edt_bg(self.ccu_control_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.ccu_control_fault, 1, 8, 1, 1)
+
+        self.bmu_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.bmu_fault.setText("BMU通讯故障")
+        self.bmu_fault.setAlignment(Qt.AlignCenter)
+        self.bmu_fault.setReadOnly(True)
+        set_edt_bg(self.bmu_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.bmu_fault, 1, 9, 1, 1)
+
+
+        self.stop_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.stop_fault.setText("急停")
+        self.stop_fault.setAlignment(Qt.AlignCenter)
+        self.stop_fault.setReadOnly(True)
+        set_edt_bg(self.stop_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.stop_fault, 2, 0, 1, 1)
+
+        self.ntc_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ntc_fault.setText("NTC故障")
+        self.ntc_fault.setAlignment(Qt.AlignCenter)
+        self.ntc_fault.setReadOnly(True)
+        set_edt_bg(self.ntc_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.ntc_fault, 2, 1, 1, 1)
+
+        self.afe_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.afe_fault.setText("AFE失效")
+        self.afe_fault.setAlignment(Qt.AlignCenter)
+        self.afe_fault.setReadOnly(True)
+        set_edt_bg(self.afe_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.afe_fault, 2, 2, 1, 1)
+
+        self.p_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.p_fault.setText("主正接触器故障")
+        self.p_fault.setAlignment(Qt.AlignCenter)
+        self.p_fault.setReadOnly(True)
+        set_edt_bg(self.p_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.p_fault, 2, 3, 1, 1)
+
+        self.n_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.n_fault.setText("主负接触器故障")
+        self.n_fault.setAlignment(Qt.AlignCenter)
+        self.n_fault.setReadOnly(True)
+        set_edt_bg(self.n_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.n_fault, 2, 4, 1, 1)
+
+        self.pre_chg_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.pre_chg_fault.setText("预充故障")
+        self.pre_chg_fault.setAlignment(Qt.AlignCenter)
+        self.pre_chg_fault.setReadOnly(True)
+        set_edt_bg(self.pre_chg_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.pre_chg_fault, 2, 5, 1, 1)
+
+        self.center_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.center_fault.setText("中间接触器故障")
+        self.center_fault.setAlignment(Qt.AlignCenter)
+        self.center_fault.setReadOnly(True)
+        set_edt_bg(self.center_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.center_fault, 2, 6, 1, 1)
+
+        self.dlq_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.dlq_fault.setText("断路器反馈故障")
+        self.dlq_fault.setAlignment(Qt.AlignCenter)
+        self.dlq_fault.setReadOnly(True)
+        set_edt_bg(self.dlq_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.dlq_fault, 2, 7, 1, 1)
+
+        self.rdq_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.rdq_fault.setText("熔断器故障")
+        self.rdq_fault.setAlignment(Qt.AlignCenter)
+        self.rdq_fault.setReadOnly(True)
+        set_edt_bg(self.rdq_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.rdq_fault, 2, 8, 1, 1)
+
+        self.cell_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.cell_fault.setText("电芯故障")
+        self.cell_fault.setAlignment(Qt.AlignCenter)
+        self.cell_fault.setReadOnly(True)
+        set_edt_bg(self.cell_fault, QColor(Qt.gray))
+
+        self.mos_ht_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.mos_ht_warn.setText("MOS温度过高告警")
+        self.mos_ht_warn.setAlignment(Qt.AlignCenter)
+        self.mos_ht_warn.setReadOnly(True)
+        set_edt_bg(self.mos_ht_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.mos_ht_warn, 3, 0, 1, 1)
+
+        self.jz_ht_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.jz_ht_warn.setText("极柱温度过高告警")
+        self.jz_ht_warn.setAlignment(Qt.AlignCenter)
+        self.jz_ht_warn.setReadOnly(True)
+        set_edt_bg(self.jz_ht_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.jz_ht_warn, 3, 1, 1, 1)
+
+        self.ccu_ht_warn = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ccu_ht_warn.setText("主控检测温度过高")
+        self.ccu_ht_warn.setAlignment(Qt.AlignCenter)
+        self.ccu_ht_warn.setReadOnly(True)
+        set_edt_bg(self.ccu_ht_warn, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.ccu_ht_warn, 3, 2, 1, 1)
+
+        self.fan_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.fan_fault.setText("风扇控制失效")
+        self.fan_fault.setAlignment(Qt.AlignCenter)
+        self.fan_fault.setReadOnly(True)
+        set_edt_bg(self.fan_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.fan_fault, 3, 3, 1, 1)
+
+        self.temp_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.temp_fault.setText("热失控故障")
+        self.temp_fault.setAlignment(Qt.AlignCenter)
+        self.temp_fault.setReadOnly(True)
+        set_edt_bg(self.temp_fault, QColor(Qt.gray))
+
+        self.temp_up_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.temp_up_fault.setText("温升过高故障")
+        self.temp_up_fault.setAlignment(Qt.AlignCenter)
+        self.temp_up_fault.setReadOnly(True)
+        set_edt_bg(self.temp_up_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.temp_up_fault, 3, 5, 1, 1)
+
+        self.cell_single_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.cell_single_fault.setText("单体断线故障")
+        self.cell_single_fault.setAlignment(Qt.AlignCenter)
+        self.cell_single_fault.setReadOnly(True)
+        set_edt_bg(self.cell_single_fault, QColor(Qt.gray))
+
+        self.ccu_hard_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ccu_hard_fault.setText("主控硬件故障")
+        self.ccu_hard_fault.setAlignment(Qt.AlignCenter)
+        self.ccu_hard_fault.setReadOnly(True)
+        set_edt_bg(self.ccu_hard_fault, QColor(Qt.gray))
+
+        self.ccu_start_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ccu_start_fault.setText("主控初始化故障")
+        self.ccu_start_fault.setAlignment(Qt.AlignCenter)
+        self.ccu_start_fault.setReadOnly(True)
+        set_edt_bg(self.ccu_start_fault, QColor(Qt.gray))
+
+        self.eeprom_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.eeprom_fault.setText("EEPROM故障")
+        self.eeprom_fault.setAlignment(Qt.AlignCenter)
+        self.eeprom_fault.setReadOnly(True)
+        set_edt_bg(self.eeprom_fault, QColor(Qt.gray))
+
+        self.soc_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.soc_fault.setText("SOC过低故障")
+        self.soc_fault.setAlignment(Qt.AlignCenter)
+        self.soc_fault.setReadOnly(True)
+        set_edt_bg(self.soc_fault, QColor(Qt.gray))
+
+        self.ccu_diff_vol_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.ccu_diff_vol_fault.setText("簇间压差故障")
+        self.ccu_diff_vol_fault.setAlignment(Qt.AlignCenter)
+        self.ccu_diff_vol_fault.setReadOnly(True)
+        set_edt_bg(self.ccu_diff_vol_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.ccu_diff_vol_fault, 4, 1, 1, 1)
+
+        self.pcs_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.pcs_fault.setText("PCS通讯故障")
+        self.pcs_fault.setAlignment(Qt.AlignCenter)
+        self.pcs_fault.setReadOnly(True)
+        set_edt_bg(self.pcs_fault, QColor(Qt.gray))
+
+        self.jump_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.jump_fault.setText("跳机故障")
+        self.jump_fault.setAlignment(Qt.AlignCenter)
+        self.jump_fault.setReadOnly(True)
+        set_edt_bg(self.jump_fault, QColor(Qt.gray))
+        self.center_qscrollarea_layout.addWidget(self.jump_fault, 4, 3, 1, 1)
+
+        self.chg_mos_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.chg_mos_fault.setText("充电MOS故障")
+        self.chg_mos_fault.setAlignment(Qt.AlignCenter)
+        self.chg_mos_fault.setReadOnly(True)
+        set_edt_bg(self.chg_mos_fault, QColor(Qt.gray))
+
+        self.dchg_mos_fault = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.dchg_mos_fault.setText("放电MOS故障")
+        self.dchg_mos_fault.setAlignment(Qt.AlignCenter)
+        self.dchg_mos_fault.setReadOnly(True)
+        set_edt_bg(self.dchg_mos_fault, QColor(Qt.gray))
+
+        if SD.CCU_TYPE == 1:
+            self.chg_mos_fault.setHidden(True)
+            self.dchg_mos_fault.setHidden(True)
+            self.center_qscrollarea_layout.addWidget(self.cell_fault, 2, 9, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.temp_fault, 3, 4, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.temp_up_fault, 3, 5, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.cell_single_fault, 3, 6, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.ccu_hard_fault, 3, 7, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.ccu_start_fault, 3, 8, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.eeprom_fault, 3, 9, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.soc_fault, 4, 0, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.pcs_fault, 4, 2, 1, 1)
+        else:
+            self.jump_fault.setHidden(True)
+            self.ccu_diff_vol_fault.setHidden(True)
+            self.center_qscrollarea_layout.addWidget(self.mos_ht_warn, 1, 8, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.temp_up_fault, 1, 9, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.pre_chg_fault, 2, 3, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.chg_mos_fault, 2, 4, 1, 1) 
+            self.center_qscrollarea_layout.addWidget(self.dchg_mos_fault, 2, 5, 1, 1)  
+            self.center_qscrollarea_layout.addWidget(self.temp_fault, 2, 6, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.cell_single_fault, 2, 7, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.ccu_hard_fault, 2, 8, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.ccu_start_fault, 2, 9, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.eeprom_fault, 3, 0, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.cell_fault, 3, 1, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.soc_fault, 3, 2, 1, 1)
+            self.center_qscrollarea_layout.addWidget(self.pcs_fault, 3, 3, 1, 1)
+
+
+        self.center_right_widget = QtWidgets.QWidget(self.center_groupbox)
+        self.center_right_layout = QtWidgets.QGridLayout(self.center_right_widget)
+
+        self.normal = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.normal.setAlignment(Qt.AlignCenter)
+        self.normal.setReadOnly(True)
+        set_edt_bg(self.normal, QColor(Qt.gray))
+        self.center_right_layout.addWidget(self.normal, 0, 0, 1, 1)
+        self.lb_normal = QtWidgets.QLabel(self.center_qscrollarea)
+        self.lb_normal.setAlignment(Qt.AlignCenter)
+        self.lb_normal.setText("正常")
+        self.center_right_layout.addWidget(self.lb_normal, 0, 1, 1, 1)
+
+        self.third = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.third.setAlignment(Qt.AlignCenter)
+        self.third.setReadOnly(True)
+        set_edt_bg(self.third, QColor(Qt.yellow))
+        self.center_right_layout.addWidget(self.third, 1, 0, 1, 1)
+        self.lb_third = QtWidgets.QLabel(self.center_qscrollarea)
+        self.lb_third.setAlignment(Qt.AlignCenter)
+        self.lb_third.setText("三级告警")
+        self.center_right_layout.addWidget(self.lb_third, 1, 1, 1, 1)
+
+        self.second = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.second.setAlignment(Qt.AlignCenter)
+        self.second.setReadOnly(True)
+        set_edt_bg(self.second, QColor(Qt.magenta))
+        self.center_right_layout.addWidget(self.second, 2, 0, 1, 1)
+        self.lb_second = QtWidgets.QLabel(self.center_qscrollarea)
+        self.lb_second.setAlignment(Qt.AlignCenter)
+        self.lb_second.setText("二级告警")
+        self.center_right_layout.addWidget(self.lb_second, 2, 1, 1, 1)
+
+        self.first = QtWidgets.QLineEdit(self.center_qscrollarea)
+        self.first.setAlignment(Qt.AlignCenter)
+        self.first.setReadOnly(True)
+        set_edt_bg(self.first, QColor(Qt.red))
+        self.center_right_layout.addWidget(self.first, 3, 0, 1, 1)
+        self.lb_first = QtWidgets.QLabel(self.center_qscrollarea)
+        self.lb_first.setAlignment(Qt.AlignCenter)
+        self.lb_first.setText("一级告警/故障")
+        self.center_right_layout.addWidget(self.lb_first, 3, 1, 1, 1)
+
+        self.center_groupbox_layout.addWidget(self.center_right_widget, 1)
+
+        self.center_layout.addWidget(self.center_groupbox)
+        self.verticalLayout.addWidget(self.center_widget)

+ 37 - 0
ui/main/main.py

@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :main.py
+@时间    :2023/11/26 16:04:21
+@作者    :樊春春
+@版本    :1.0
+@邮箱    :[email protected]
+@说明    :
+'''
+
+
+
+from ui.own.frame_theme import MyFrame
+from ui.main.top_page import TopPage
+from ui.main.center_page import CenterPage
+from ui.main.under_page import UnderPage
+from utils.qt import QHBoxLayout, QMetaObject, QVBoxLayout
+
+
+class Main(MyFrame):
+    def setupUi(self, Main):
+        self.main = MyFrame(Main)
+        self.main_layout = QVBoxLayout(self.main)
+        self.main_layout.setContentsMargins(0, 0, 0, 0)
+        self.main_layout.setSpacing(0)
+
+        self.top_widget = TopPage(self.main)
+        self.main_layout.addWidget(self.top_widget)
+
+        self.center_widget = CenterPage(self.main)
+        self.main_layout.addWidget(self.center_widget)
+
+        self.under_widget = UnderPage(self.main)
+        self.main_layout.addWidget(self.under_widget)
+
+        QMetaObject.connectSlotsByName(Main)

+ 686 - 0
ui/main/top_page.py

@@ -0,0 +1,686 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import os
+from ui.own.frame_theme import MyFrame
+from utils.qt import QtWidgets, QtGui, QIcon, QPixmap, Qt
+from utils.resource import resource_path
+from utils.globalvar import SD
+
+
+class TopPage(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        super(TopPage, self).__init__(parent)
+        self.initUI()
+
+    def initUI(self):
+        self.verticalLayout = QtWidgets.QVBoxLayout(self)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+        self.verticalLayout.setSpacing(0)
+
+        # 设置参数
+        self.top_widget = MyFrame(self)
+        self.top_layout = QtWidgets.QVBoxLayout(self.top_widget)
+        self.top_layout.setContentsMargins(0, 0, 0, 0)
+        self.top_layout.setSpacing(0)
+        self.top_groupbox = QtWidgets.QGroupBox(self.top_widget)
+        self.top_groupbox.setTitle("参数配置")
+        self.top_groupbox_layout = QtWidgets.QHBoxLayout(self.top_groupbox)
+
+        self.top_qscrollarea = QtWidgets.QScrollArea(self.top_groupbox)
+        self.top_qscrollarea.setWidgetResizable(True)
+        # self.top_qscrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        self.top_groupbox_layout.addWidget(self.top_qscrollarea)
+
+        self.top_qwidget = QtWidgets.QWidget()
+        self.top_qscrollarea.setWidget(self.top_qwidget)
+
+        self.top_qscrollarea_layout = QtWidgets.QGridLayout(self.top_qwidget)
+        self.top_qscrollarea_layout.setObjectName("scrollLayout")
+        # self.top_qscrollarea_layout.setContentsMargins(3, 3, 3, 3)
+        self.top_qscrollarea_layout.setSpacing(0)
+
+
+        self.tv = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tv.setTitle("总压")
+        self.tv_layout = QtWidgets.QHBoxLayout(self.tv)
+        self.lb_tv_value = QtWidgets.QLabel(self.tv)
+        self.lb_tv_value.setText("    ")
+        self.tv_layout.addWidget(self.lb_tv_value)
+        self.lb_tv = QtWidgets.QLabel(self.tv)
+        self.lb_tv.setText("V")
+        self.tv_layout.addWidget(self.lb_tv)
+        self.top_qscrollarea_layout.addWidget(self.tv, 0, 0, 1, 1)
+
+        self.tcur = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcur.setTitle("电流")
+        self.tcur_layout = QtWidgets.QHBoxLayout(self.tcur)
+        self.lb_tcur_value = QtWidgets.QLabel(self.tcur)
+        self.lb_tcur_value.setText("    ")
+        self.tcur_layout.addWidget(self.lb_tcur_value)
+        self.lb_tcur = QtWidgets.QLabel(self.tcur)
+        self.lb_tcur.setText("A")
+        self.tcur_layout.addWidget(self.lb_tcur)
+        self.top_qscrollarea_layout.addWidget(self.tcur, 0, 1, 1, 1)
+
+        self.tsoc = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tsoc.setTitle("SOC")
+        self.soc_layout = QtWidgets.QHBoxLayout(self.tsoc)
+        self.lb_soc_value = QtWidgets.QLabel(self.tsoc)
+        self.lb_soc_value.setText("    ")
+        self.soc_layout.addWidget(self.lb_soc_value)
+        self.lb_soc = QtWidgets.QLabel(self.tsoc)
+        self.lb_soc.setText("%")
+        self.soc_layout.addWidget(self.lb_soc)
+        self.top_qscrollarea_layout.addWidget(self.tsoc, 0, 2, 1, 1)
+
+        self.tsoh = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tsoh.setTitle("SOH")
+        self.tsoh_layout = QtWidgets.QHBoxLayout(self.tsoh)
+        self.lb_tsoh_value = QtWidgets.QLabel(self.tsoh)
+        self.lb_tsoh_value.setText("    ")
+        self.tsoh_layout.addWidget(self.lb_tsoh_value)
+        self.lb_tsoh = QtWidgets.QLabel(self.tsoh)
+        self.lb_tsoh.setText("%")
+        self.tsoh_layout.addWidget(self.lb_tsoh)
+        self.top_qscrollarea_layout.addWidget(self.tsoh, 0, 3, 1, 1)
+
+        self.tsoe = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tsoe.setTitle("SOE")
+        self.tsoe_layout = QtWidgets.QHBoxLayout(self.tsoe)
+        self.lb_tsoe_value = QtWidgets.QLabel(self.tsoe)
+        self.lb_tsoe_value.setText("    ")
+        self.tsoe_layout.addWidget(self.lb_tsoe_value)
+        self.lb_tsoe = QtWidgets.QLabel(self.tsoe)
+        self.lb_tsoe.setText("%")
+        self.tsoe_layout.addWidget(self.lb_tsoe)
+        self.top_qscrollarea_layout.addWidget(self.tsoe, 0, 4, 1, 1)
+
+        self.tcellhv = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcellhv.setTitle("单体最高电压")
+        self.tcellhv_layout = QtWidgets.QHBoxLayout(self.tcellhv)
+        self.lb_tcellhv_value = QtWidgets.QLabel(self.tcellhv)
+        self.lb_tcellhv_value.setText("    ")
+        self.tcellhv_layout.addWidget(self.lb_tcellhv_value)
+        self.lb_tcellhv = QtWidgets.QLabel(self.tcellhv)
+        self.lb_tcellhv.setText("mV")
+        self.tcellhv_layout.addWidget(self.lb_tcellhv)
+        self.top_qscrollarea_layout.addWidget(self.tcellhv, 0, 5, 1, 1)
+
+        self.tcelllv = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcelllv.setTitle("单体最低电压")
+        self.tcelllv_layout = QtWidgets.QHBoxLayout(self.tcelllv)
+        self.lb_tcelllv_value = QtWidgets.QLabel(self.tcelllv)
+        self.lb_tcelllv_value.setText("    ")
+        self.tcelllv_layout.addWidget(self.lb_tcelllv_value)
+        self.lb_tcelllv = QtWidgets.QLabel(self.tcelllv)
+        self.lb_tcelllv.setText("mV")
+        self.tcelllv_layout.addWidget(self.lb_tcelllv)
+        self.top_qscrollarea_layout.addWidget(self.tcelllv, 0, 6, 1, 1)
+
+        self.tcellhv_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcellhv_index.setTitle("最高单体电压编号")
+        self.tcellhv_index_layout = QtWidgets.QHBoxLayout(self.tcellhv_index)
+        self.lb_tcellhv_index_value = QtWidgets.QLabel(self.tcellhv_index)
+        self.lb_tcellhv_index_value.setText("    ")
+        self.tcellhv_index_layout.addWidget(self.lb_tcellhv_index_value)
+        self.lb_tcellhv_index = QtWidgets.QLabel(self.tcellhv_index)
+        self.lb_tcellhv_index.setText("")
+        self.tcellhv_index_layout.addWidget(self.lb_tcellhv_index)
+        self.top_qscrollarea_layout.addWidget(self.tcellhv_index, 0, 7, 1, 1)
+
+        self.tcellhv_slave_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcellhv_slave_index.setTitle("最高单体电压从控编号")
+        self.tcellhv_slave_index_layout = QtWidgets.QHBoxLayout(self.tcellhv_slave_index)
+        self.lb_tcellhv_slave_index_value = QtWidgets.QLabel(self.tcellhv_slave_index)
+        self.lb_tcellhv_slave_index_value.setText("    ")
+        self.tcellhv_slave_index_layout.addWidget(self.lb_tcellhv_slave_index_value)
+        self.lb_tcellhv_slave_index = QtWidgets.QLabel(self.tcellhv_slave_index)
+        self.lb_tcellhv_slave_index.setText("")
+        self.tcellhv_slave_index_layout.addWidget(self.lb_tcellhv_slave_index)
+        self.top_qscrollarea_layout.addWidget(self.tcellhv_slave_index, 0, 8, 1, 1)
+
+        self.tcellhv_in_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcellhv_in_index.setTitle("最高单体电压从控内编号")
+        self.tcellhv_in_index_layout = QtWidgets.QHBoxLayout(self.tcellhv_in_index)
+        self.lb_tcellhv_in_index_value = QtWidgets.QLabel(self.tcellhv_in_index)
+        self.lb_tcellhv_in_index_value.setText("    ")
+        self.tcellhv_in_index_layout.addWidget(self.lb_tcellhv_in_index_value)
+        self.lb_tcellhv_in_index = QtWidgets.QLabel(self.tcellhv_in_index)
+        self.lb_tcellhv_in_index.setText("")
+        self.tcellhv_in_index_layout.addWidget(self.lb_tcellhv_in_index)
+        self.top_qscrollarea_layout.addWidget(self.tcellhv_in_index, 0, 9, 1, 1)
+
+        self.tcelllv_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcelllv_index.setTitle("最低单体电压编号")
+        self.tcelllv_index_layout = QtWidgets.QHBoxLayout(self.tcelllv_index)
+        self.lb_tcelllv_index_value = QtWidgets.QLabel(self.tcelllv_index)
+        self.lb_tcelllv_index_value.setText("    ")
+        self.tcelllv_index_layout.addWidget(self.lb_tcelllv_index_value)
+        self.lb_tcelllv_index = QtWidgets.QLabel(self.tcelllv_index)
+        self.lb_tcelllv_index.setText("")
+        self.tcelllv_index_layout.addWidget(self.lb_tcelllv_index)
+        self.top_qscrollarea_layout.addWidget(self.tcelllv_index, 1, 0, 1, 1)
+
+        self.tcelllv_slave_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcelllv_slave_index.setTitle("最低单体电压从控编号")
+        self.tcelllv_slave_index_layout = QtWidgets.QHBoxLayout(self.tcelllv_slave_index)
+        self.lb_tcelllv_slave_index_value = QtWidgets.QLabel(self.tcelllv_slave_index)
+        self.lb_tcelllv_slave_index_value.setText("    ")
+        self.tcelllv_slave_index_layout.addWidget(self.lb_tcelllv_slave_index_value)
+        self.lb_tcelllv_slave_index = QtWidgets.QLabel(self.tcelllv_slave_index)
+        self.lb_tcelllv_slave_index.setText("")
+        self.tcelllv_slave_index_layout.addWidget(self.lb_tcelllv_slave_index)
+        self.top_qscrollarea_layout.addWidget(self.tcelllv_slave_index, 1, 1, 1, 1)
+
+        self.tcelllv_in_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tcelllv_in_index.setTitle("最低单体电压从控内编号")
+        self.tcelllv_in_index_layout = QtWidgets.QHBoxLayout(self.tcelllv_in_index)
+        self.lb_tcelllv_in_index_value = QtWidgets.QLabel(self.tcelllv_in_index)
+        self.lb_tcelllv_in_index_value.setText("    ")
+        self.tcelllv_in_index_layout.addWidget(self.lb_tcelllv_in_index_value)
+        self.lb_tcelllv_in_index = QtWidgets.QLabel(self.tcelllv_in_index)
+        self.lb_tcelllv_in_index.setText("")
+        self.tcelllv_in_index_layout.addWidget(self.lb_tcelllv_in_index)
+        self.top_qscrollarea_layout.addWidget(self.tcelllv_in_index, 1, 2, 1, 1)
+
+        self.avg_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.avg_vol.setTitle("平均电压")
+        self.avg_vol_layout = QtWidgets.QHBoxLayout(self.avg_vol)
+        self.lb_avg_vol_value = QtWidgets.QLabel(self.avg_vol)
+        self.lb_avg_vol_value.setText("    ")
+        self.avg_vol_layout.addWidget(self.lb_avg_vol_value)
+        self.lb_avg_vol = QtWidgets.QLabel(self.avg_vol)
+        self.lb_avg_vol.setText("mV")
+        self.avg_vol_layout.addWidget(self.lb_avg_vol)
+        self.top_qscrollarea_layout.addWidget(self.avg_vol, 1, 3, 1, 1)
+
+        self.diff_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.diff_vol.setTitle("单体最大压差")
+        self.diff_vol_layout = QtWidgets.QHBoxLayout(self.diff_vol)
+        self.lb_diff_vol_value = QtWidgets.QLabel(self.diff_vol)
+        self.lb_diff_vol_value.setText("    ")
+        self.diff_vol_layout.addWidget(self.lb_diff_vol_value)
+        self.lb_diff_vol = QtWidgets.QLabel(self.diff_vol)
+        self.lb_diff_vol.setText("mV")
+        self.diff_vol_layout.addWidget(self.lb_diff_vol)
+        self.top_qscrollarea_layout.addWidget(self.diff_vol, 1, 4, 1, 1)
+
+        self.h_temp = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.h_temp.setTitle("最高电池温度")
+        self.h_temp_layout = QtWidgets.QHBoxLayout(self.h_temp)
+        self.lb_h_temp_value = QtWidgets.QLabel(self.h_temp)
+        self.lb_h_temp_value.setText("    ")
+        self.h_temp_layout.addWidget(self.lb_h_temp_value)
+        self.lb_h_temp = QtWidgets.QLabel(self.h_temp)
+        self.lb_h_temp.setText("℃")
+        self.h_temp_layout.addWidget(self.lb_h_temp)
+        self.top_qscrollarea_layout.addWidget(self.h_temp, 1, 5, 1, 1)
+
+        self.l_temp = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.l_temp.setTitle("最低电池温度")
+        self.l_temp_layout = QtWidgets.QHBoxLayout(self.l_temp)
+        self.lb_l_temp_value = QtWidgets.QLabel(self.l_temp)
+        self.lb_l_temp_value.setText("    ")
+        self.l_temp_layout.addWidget(self.lb_l_temp_value)
+        self.lb_l_temp = QtWidgets.QLabel(self.l_temp)
+        self.lb_l_temp.setText("℃")
+        self.l_temp_layout.addWidget(self.lb_l_temp)
+        self.top_qscrollarea_layout.addWidget(self.l_temp, 1, 6, 1, 1)
+
+        self.h_temp_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.h_temp_index.setTitle("最高单体温度编号")
+        self.h_temp_index_layout = QtWidgets.QHBoxLayout(self.h_temp_index)
+        self.lb_h_temp_index_value = QtWidgets.QLabel(self.h_temp_index)
+        self.lb_h_temp_index_value.setText("    ")
+        self.h_temp_index_layout.addWidget(self.lb_h_temp_index_value)
+        self.lb_h_temp_index = QtWidgets.QLabel(self.h_temp_index)
+        self.lb_h_temp_index.setText("")
+        self.h_temp_index_layout.addWidget(self.lb_h_temp_index)
+        self.top_qscrollarea_layout.addWidget(self.h_temp_index, 1, 7, 1, 1)
+
+        self.h_temp_slave_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.h_temp_slave_index.setTitle("最高单体温度从控编号")
+        self.h_temp_slave_index_layout = QtWidgets.QHBoxLayout(self.h_temp_slave_index)
+        self.lb_h_temp_slave_index_value = QtWidgets.QLabel(self.h_temp_slave_index)
+        self.lb_h_temp_slave_index_value.setText("    ")
+        self.h_temp_slave_index_layout.addWidget(self.lb_h_temp_slave_index_value)
+        self.lb_h_temp_slave_index = QtWidgets.QLabel(self.h_temp_slave_index)
+        self.lb_h_temp_slave_index.setText("")
+        self.h_temp_slave_index_layout.addWidget(self.lb_h_temp_slave_index)
+        self.top_qscrollarea_layout.addWidget(self.h_temp_slave_index, 1, 8, 1, 1)
+
+        self.h_temp_in_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.h_temp_in_index.setTitle("最高单体温度从控内编号")
+        self.h_temp_in_index_layout = QtWidgets.QHBoxLayout(self.h_temp_in_index)
+        self.lb_h_temp_in_index_value = QtWidgets.QLabel(self.h_temp_in_index)
+        self.lb_h_temp_in_index_value.setText("    ")
+        self.h_temp_in_index_layout.addWidget(self.lb_h_temp_in_index_value)
+        self.lb_h_temp_in_index = QtWidgets.QLabel(self.h_temp_in_index)
+        self.lb_h_temp_in_index.setText("")
+        self.h_temp_in_index_layout.addWidget(self.lb_h_temp_in_index)
+        self.top_qscrollarea_layout.addWidget(self.h_temp_in_index, 1, 9, 1, 1)
+
+        self.avg_temp = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.avg_temp.setTitle("平均温度")
+        self.avg_temp_layout = QtWidgets.QHBoxLayout(self.avg_temp)
+        self.lb_avg_temp_value = QtWidgets.QLabel(self.avg_temp)
+        self.lb_avg_temp_value.setText("    ")
+        self.avg_temp_layout.addWidget(self.lb_avg_temp_value)
+        self.lb_avg_temp = QtWidgets.QLabel("℃")
+        self.avg_temp_layout.addWidget(self.lb_avg_temp)
+        self.top_qscrollarea_layout.addWidget(self.avg_temp, 2, 0, 1, 1)
+
+        self.diff_temp = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.diff_temp.setTitle("单体最大温差")
+        self.diff_temp_layout = QtWidgets.QHBoxLayout(self.diff_temp)
+        self.lb_diff_temp_value = QtWidgets.QLabel(self.diff_temp)
+        self.lb_diff_temp_value.setText("    ")
+        self.diff_temp_layout.addWidget(self.lb_diff_temp_value)
+        self.lb_diff_temp = QtWidgets.QLabel(self.diff_temp)
+        self.lb_diff_temp.setText("℃")
+        self.diff_temp_layout.addWidget(self.lb_diff_temp)
+        self.top_qscrollarea_layout.addWidget(self.diff_temp, 2, 1, 1, 1)
+
+        self.sys_against = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.sys_against.setTitle("系统绝缘阻抗")
+        self.sys_against_layout = QtWidgets.QHBoxLayout(self.sys_against)
+        self.lb_sys_against_value = QtWidgets.QLabel(self.sys_against)
+        self.lb_sys_against_value.setText("    ")
+        self.sys_against_layout.addWidget(self.lb_sys_against_value)
+        self.lb_sys_against = QtWidgets.QLabel(self.sys_against)
+        self.lb_sys_against.setText("kΩ")
+        self.sys_against_layout.addWidget(self.lb_sys_against)
+        self.top_qscrollarea_layout.addWidget(self.sys_against, 2, 2, 1, 1)
+
+        self.sys_p_against = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.sys_p_against.setTitle("系统正极绝缘阻抗")
+        self.sys_p_against_layout = QtWidgets.QHBoxLayout(self.sys_p_against)
+        self.lb_sys_p_against_value = QtWidgets.QLabel(self.sys_p_against)
+        self.lb_sys_p_against_value.setText("    ")
+        self.sys_p_against_layout.addWidget(self.lb_sys_p_against_value)
+        self.lb_sys_p_against = QtWidgets.QLabel(self.sys_p_against)
+        self.lb_sys_p_against.setText("kΩ")
+        self.sys_p_against_layout.addWidget(self.lb_sys_p_against)
+        self.top_qscrollarea_layout.addWidget(self.sys_p_against, 2, 3, 1, 1)
+
+        self.sys_n_against = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.sys_n_against.setTitle("系统负极绝缘阻抗")
+        self.sys_n_against_layout = QtWidgets.QHBoxLayout(self.sys_n_against)
+        self.lb_sys_n_against_value = QtWidgets.QLabel(self.sys_n_against)
+        self.lb_sys_n_against_value.setText("    ")
+        self.sys_n_against_layout.addWidget(self.lb_sys_n_against_value)
+        self.lb_sys_n_against = QtWidgets.QLabel(self.sys_n_against)
+        self.lb_sys_n_against.setText("kΩ")
+        self.sys_n_against_layout.addWidget(self.lb_sys_n_against)
+        self.top_qscrollarea_layout.addWidget(self.sys_n_against, 2, 4, 1, 1)
+
+        self.nom_cap = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.nom_cap.setTitle("标称容量")
+        self.nom_cap_layout = QtWidgets.QHBoxLayout(self.nom_cap)
+        self.lb_nom_cap_value = QtWidgets.QLabel(self.nom_cap)
+        self.lb_nom_cap_value.setText("    ")
+        self.nom_cap_layout.addWidget(self.lb_nom_cap_value)
+        self.lb_nom_cap = QtWidgets.QLabel(self.nom_cap)
+        self.lb_nom_cap.setText("Ah")
+        self.nom_cap_layout.addWidget(self.lb_nom_cap)
+        self.top_qscrollarea_layout.addWidget(self.nom_cap, 2, 5, 1, 1)
+
+        self.all_cap = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.all_cap.setTitle("总容量")
+        self.all_cap_layout = QtWidgets.QHBoxLayout(self.all_cap)
+        self.lb_all_cap_value = QtWidgets.QLabel(self.all_cap)
+        self.lb_all_cap_value.setText("    ")
+        self.all_cap_layout.addWidget(self.lb_all_cap_value)
+        self.lb_all_cap = QtWidgets.QLabel(self.all_cap)
+        self.lb_all_cap.setText("Ah")
+        self.all_cap_layout.addWidget(self.lb_all_cap)
+        self.top_qscrollarea_layout.addWidget(self.all_cap, 2, 6, 1, 1)
+
+        self.left_cap = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.left_cap.setTitle("剩余容量")
+        self.left_cap_layout = QtWidgets.QHBoxLayout(self.left_cap)
+        self.lb_left_cap_value = QtWidgets.QLabel(self.left_cap)
+        self.lb_left_cap_value.setText("    ")
+        self.left_cap_layout.addWidget(self.lb_left_cap_value)
+        self.lb_left_cap = QtWidgets.QLabel(self.left_cap)
+        self.lb_left_cap.setText("Ah")
+        self.left_cap_layout.addWidget(self.lb_left_cap)
+        self.top_qscrollarea_layout.addWidget(self.left_cap, 2, 7, 1, 1)
+
+        self.chg_kwh = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.chg_kwh.setTitle("累计充电能量")
+        self.chg_kwh_layout = QtWidgets.QHBoxLayout(self.chg_kwh)
+        self.lb_chg_kwh_value = QtWidgets.QLabel(self.chg_kwh)
+        self.lb_chg_kwh_value.setText("    ")
+        self.chg_kwh_layout.addWidget(self.lb_chg_kwh_value)
+        self.lb_chg_kwh = QtWidgets.QLabel(self.chg_kwh)
+        self.lb_chg_kwh.setText("kWh")
+        self.chg_kwh_layout.addWidget(self.lb_chg_kwh)
+        self.top_qscrollarea_layout.addWidget(self.chg_kwh, 2, 8, 1, 1)
+
+        self.dchg_kwh = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.dchg_kwh.setTitle("累计放电能量")
+        self.dchg_kwh_layout = QtWidgets.QHBoxLayout(self.dchg_kwh)
+        self.lb_dchg_kwh_value = QtWidgets.QLabel(self.dchg_kwh)
+        self.lb_dchg_kwh_value.setText("    ")
+        self.dchg_kwh_layout.addWidget(self.lb_dchg_kwh_value)
+        self.lb_dchg_kwh = QtWidgets.QLabel(self.dchg_kwh)
+        self.lb_dchg_kwh.setText("kWh")
+        self.dchg_kwh_layout.addWidget(self.lb_dchg_kwh)
+        self.top_qscrollarea_layout.addWidget(self.dchg_kwh, 2, 9, 1, 1)
+
+        self.chg_kw = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.chg_kw.setTitle("当前允许充电功率")
+        self.chg_kw_layout = QtWidgets.QHBoxLayout(self.chg_kw)
+        self.lb_chg_kw_value = QtWidgets.QLabel(self.chg_kw)
+        self.lb_chg_kw_value.setText("    ")
+        self.chg_kw_layout.addWidget(self.lb_chg_kw_value)
+        self.lb_chg_kw = QtWidgets.QLabel(self.chg_kw)
+        self.lb_chg_kw.setText("kW")
+        self.chg_kw_layout.addWidget(self.lb_chg_kw)
+        self.top_qscrollarea_layout.addWidget(self.chg_kw, 3, 0, 1, 1)
+
+        self.dchg_kw = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.dchg_kw.setTitle("当前允许放电功率")
+        self.dchg_kw_layout = QtWidgets.QHBoxLayout(self.dchg_kw)
+        self.lb_dchg_kw_value = QtWidgets.QLabel(self.dchg_kw)
+        self.lb_dchg_kw_value.setText("    ")
+        self.dchg_kw_layout.addWidget(self.lb_dchg_kw_value)
+        self.lb_dchg_kw = QtWidgets.QLabel(self.dchg_kw)
+        self.lb_dchg_kw.setText("kW")
+        self.dchg_kw_layout.addWidget(self.lb_dchg_kw)
+        self.top_qscrollarea_layout.addWidget(self.dchg_kw, 3, 1, 1, 1)
+
+        self.max_chg_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.max_chg_vol.setTitle("当前允许最大充电电压")
+        self.max_chg_vol_layout = QtWidgets.QHBoxLayout(self.max_chg_vol)
+        self.lb_max_chg_vol_value = QtWidgets.QLabel(self.max_chg_vol)
+        self.lb_max_chg_vol_value.setText("    ")
+        self.max_chg_vol_layout.addWidget(self.lb_max_chg_vol_value)
+        self.lb_max_chg_vol = QtWidgets.QLabel(self.max_chg_vol)
+        self.lb_max_chg_vol.setText("V")
+        self.max_chg_vol_layout.addWidget(self.lb_max_chg_vol)
+        self.top_qscrollarea_layout.addWidget(self.max_chg_vol, 3, 2, 1, 1)
+
+        self.max_chg_cur = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.max_chg_cur.setTitle("当前允许最大充电电流")
+        self.max_chg_cur_layout = QtWidgets.QHBoxLayout(self.max_chg_cur)
+        self.lb_max_chg_cur_value = QtWidgets.QLabel(self.max_chg_cur)
+        self.lb_max_chg_cur_value.setText("    ")
+        self.max_chg_cur_layout.addWidget(self.lb_max_chg_cur_value)
+        self.lb_max_chg_cur = QtWidgets.QLabel(self.max_chg_cur)
+        self.lb_max_chg_cur.setText("A")
+        self.max_chg_cur_layout.addWidget(self.lb_max_chg_cur)
+        self.top_qscrollarea_layout.addWidget(self.max_chg_cur, 3, 3, 1, 1)
+
+        self.max_dchg_cur = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.max_dchg_cur.setTitle("当前允许最大放电电流")
+        self.max_dchg_cur_layout = QtWidgets.QHBoxLayout(self.max_dchg_cur)
+        self.lb_max_dchg_cur_value = QtWidgets.QLabel(self.max_dchg_cur)
+        self.lb_max_dchg_cur_value.setText("    ")
+        self.max_dchg_cur_layout.addWidget(self.lb_max_dchg_cur_value)
+        self.lb_max_dchg_cur = QtWidgets.QLabel(self.max_dchg_cur)
+        self.lb_max_dchg_cur.setText("A")
+        self.max_dchg_cur_layout.addWidget(self.lb_max_dchg_cur)
+        self.top_qscrollarea_layout.addWidget(self.max_dchg_cur, 3, 4, 1, 1)
+
+        self.max_dchg_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.max_dchg_vol.setTitle("当前允许放电限制电压")
+        self.max_dchg_vol_layout = QtWidgets.QHBoxLayout(self.max_dchg_vol)
+        self.lb_max_dchg_vol_value = QtWidgets.QLabel(self.max_dchg_vol)
+        self.lb_max_dchg_vol_value.setText("    ")
+        self.max_dchg_vol_layout.addWidget(self.lb_max_dchg_vol_value)
+        self.lb_max_dchg_vol = QtWidgets.QLabel(self.max_dchg_vol)
+        self.lb_max_dchg_vol.setText("V")
+        self.max_dchg_vol_layout.addWidget(self.lb_max_dchg_vol)
+
+        self.sum_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.sum_vol.setTitle("单体累加电压和")
+        self.sum_vol_layout = QtWidgets.QHBoxLayout(self.sum_vol)
+        self.lb_sum_vol_value = QtWidgets.QLabel(self.sum_vol)
+        self.lb_sum_vol_value.setText("    ")
+        self.sum_vol_layout.addWidget(self.lb_sum_vol_value)
+        self.lb_sum_vol = QtWidgets.QLabel(self.sum_vol)
+        self.lb_sum_vol.setText("V")
+        self.sum_vol_layout.addWidget(self.lb_sum_vol)
+        self.top_qscrollarea_layout.addWidget(self.sum_vol, 3, 5, 1, 1)
+
+        self.tv_2 = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tv_2.setTitle("总压2")
+        self.tv_2_layout = QtWidgets.QHBoxLayout(self.tv_2)
+        self.lb_tv_2_value = QtWidgets.QLabel(self.tv_2)
+        self.lb_tv_2_value.setText("    ")
+        self.tv_2_layout.addWidget(self.lb_tv_2_value)
+        self.lb_tv_2 = QtWidgets.QLabel(self.tv_2)
+        self.lb_tv_2.setText("V")
+        self.tv_2_layout.addWidget(self.lb_tv_2)
+ 
+
+        self.tv_3 = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.tv_3.setTitle("总压3")
+        self.tv_3_layout = QtWidgets.QHBoxLayout(self.tv_3)
+        self.lb_tv_3_value = QtWidgets.QLabel(self.tv_3)
+        self.lb_tv_3_value.setText("    ")
+        self.tv_3_layout.addWidget(self.lb_tv_3_value)
+        self.lb_tv_3 = QtWidgets.QLabel(self.tv_3)
+        self.lb_tv_3.setText("V")
+        self.tv_3_layout.addWidget(self.lb_tv_3)
+
+        self.left_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.left_energy.setTitle("系统剩余能量")
+        self.left_energy_layout = QtWidgets.QHBoxLayout(self.left_energy)
+        self.lb_left_energy_value = QtWidgets.QLabel(self.left_energy)
+        self.lb_left_energy_value.setText("    ")
+        self.left_energy_layout.addWidget(self.lb_left_energy_value)
+        self.lb_left_energy = QtWidgets.QLabel(self.left_energy)
+        self.lb_left_energy.setText("kWh")
+        self.left_energy_layout.addWidget(self.lb_left_energy)
+        self.top_qscrollarea_layout.addWidget(self.left_energy, 4, 0, 1, 1)
+
+        self.nowday_chg_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.nowday_chg_energy.setTitle("当天累计充电能量")
+        self.nowday_chg_energy_layout = QtWidgets.QHBoxLayout(self.nowday_chg_energy)
+        self.lb_nowday_chg_energy_value = QtWidgets.QLabel(self.nowday_chg_energy)
+        self.lb_nowday_chg_energy_value.setText("    ")
+        self.nowday_chg_energy_layout.addWidget(self.lb_nowday_chg_energy_value)
+        self.lb_nowday_chg_energy = QtWidgets.QLabel(self.nowday_chg_energy)
+        self.lb_nowday_chg_energy.setText("kWh")
+        self.nowday_chg_energy_layout.addWidget(self.lb_nowday_chg_energy)
+        self.top_qscrollarea_layout.addWidget(self.nowday_chg_energy, 4, 1, 1, 1)
+
+        self.nowday_dchg_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.nowday_dchg_energy.setTitle("当天累计放电能量")
+        self.nowday_dchg_energy_layout = QtWidgets.QHBoxLayout(self.nowday_dchg_energy)
+        self.lb_nowday_dchg_energy_value = QtWidgets.QLabel(self.nowday_dchg_energy)
+        self.lb_nowday_dchg_energy_value.setText("    ")
+        self.nowday_dchg_energy_layout.addWidget(self.lb_nowday_dchg_energy_value)
+        self.lb_nowday_dchg_energy = QtWidgets.QLabel(self.nowday_dchg_energy)
+        self.lb_nowday_dchg_energy.setText("kWh")
+        self.nowday_dchg_energy_layout.addWidget(self.lb_nowday_dchg_energy)
+        self.top_qscrollarea_layout.addWidget(self.nowday_dchg_energy, 4, 2, 1, 1)
+
+        self.circle_num = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.circle_num.setTitle("循环次数")
+        self.circle_num_layout = QtWidgets.QHBoxLayout(self.circle_num)
+        self.lb_circle_num_value = QtWidgets.QLabel(self.circle_num)
+        self.lb_circle_num_value.setText("    ")
+        self.circle_num_layout.addWidget(self.lb_circle_num_value)
+        self.lb_circle_num = QtWidgets.QLabel(self.circle_num)
+        self.lb_circle_num.setText("")
+        self.circle_num_layout.addWidget(self.lb_circle_num)
+        self.top_qscrollarea_layout.addWidget(self.circle_num, 4, 3, 1, 1)
+
+        self.gdcy_vol = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.gdcy_vol.setTitle("供电采样电压")
+        self.gdcy_vol_layout = QtWidgets.QHBoxLayout(self.gdcy_vol)
+        self.lb_gdcy_vol_value = QtWidgets.QLabel(self.gdcy_vol)
+        self.lb_gdcy_vol_value.setText("    ")
+        self.gdcy_vol_layout.addWidget(self.lb_gdcy_vol_value)
+        self.lb_gdcy_vol = QtWidgets.QLabel(self.gdcy_vol)
+        self.lb_gdcy_vol.setText("V")
+        self.gdcy_vol_layout.addWidget(self.lb_gdcy_vol)
+        self.top_qscrollarea_layout.addWidget(self.gdcy_vol, 4, 4, 1, 1)
+
+        self.jz_temp_high = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.jz_temp_high.setTitle("最高极柱温度")
+        self.jz_temp_high_layout = QtWidgets.QHBoxLayout(self.jz_temp_high)
+        self.lb_jz_temp_high_value = QtWidgets.QLabel(self.jz_temp_high)
+        self.lb_jz_temp_high_value.setText("    ")
+        self.jz_temp_high_layout.addWidget(self.lb_jz_temp_high_value)
+        self.lb_jz_temp_high = QtWidgets.QLabel(self.jz_temp_high)
+        self.lb_jz_temp_high.setText("℃")
+        self.jz_temp_high_layout.addWidget(self.lb_jz_temp_high)
+
+        self.jz_temp_high_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.jz_temp_high_index.setTitle("最高极柱温度编号")
+        self.jz_temp_high_index_layout = QtWidgets.QHBoxLayout(self.jz_temp_high_index)
+        self.lb_jz_temp_high_index_value = QtWidgets.QLabel(self.jz_temp_high_index)
+        self.lb_jz_temp_high_index_value.setText("    ")
+        self.jz_temp_high_index_layout.addWidget(self.lb_jz_temp_high_index_value)
+        self.lb_jz_temp_high_index = QtWidgets.QLabel(self.jz_temp_high_index)
+        self.lb_jz_temp_high_index.setText("")
+        self.jz_temp_high_index_layout.addWidget(self.lb_jz_temp_high_index)
+
+        self.bcu_temp_high = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.bcu_temp_high.setTitle("最高极柱温度")
+        self.bcu_temp_high_layout = QtWidgets.QHBoxLayout(self.bcu_temp_high)
+        self.lb_bcu_temp_high_value = QtWidgets.QLabel(self.bcu_temp_high)
+        self.lb_bcu_temp_high_value.setText("    ")
+        self.bcu_temp_high_layout.addWidget(self.lb_bcu_temp_high_value)
+        self.lb_bcu_temp_high = QtWidgets.QLabel(self.bcu_temp_high)
+        self.lb_bcu_temp_high.setText("℃")
+        self.bcu_temp_high_layout.addWidget(self.lb_bcu_temp_high)
+
+        self.bcu_temp_high_index = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.bcu_temp_high_index.setTitle("最高极柱温度编号")
+        self.bcu_temp_high_index_layout = QtWidgets.QHBoxLayout(self.bcu_temp_high_index)
+        self.lb_bcu_temp_high_index_value = QtWidgets.QLabel(self.bcu_temp_high_index)
+        self.lb_bcu_temp_high_index_value.setText("    ")
+        self.bcu_temp_high_index_layout.addWidget(self.lb_bcu_temp_high_index_value)
+        self.lb_bcu_temp_high_index = QtWidgets.QLabel(self.bcu_temp_high_index)
+        self.lb_bcu_temp_high_index.setText("")
+        self.bcu_temp_high_index_layout.addWidget(self.lb_bcu_temp_high_index)
+
+        self.mos_temp_1 = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.mos_temp_1.setTitle("MOS温度1")
+        self.mos_temp_1_layout = QtWidgets.QHBoxLayout(self.mos_temp_1)
+        self.lb_mos_temp_1_value = QtWidgets.QLabel(self.mos_temp_1)
+        self.lb_mos_temp_1_value.setText("    ")
+        self.mos_temp_1_layout.addWidget(self.lb_mos_temp_1_value)
+        self.lb_mos_temp_1 = QtWidgets.QLabel(self.mos_temp_1)
+        self.lb_mos_temp_1.setText("℃")
+        self.mos_temp_1_layout.addWidget(self.lb_mos_temp_1)
+
+        self.mos_temp_2 = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.mos_temp_2.setTitle("MOS温度2")
+        self.mos_temp_2_layout = QtWidgets.QHBoxLayout(self.mos_temp_2)
+        self.lb_mos_temp_2_value = QtWidgets.QLabel(self.mos_temp_2)
+        self.lb_mos_temp_2_value.setText("    ")
+        self.mos_temp_2_layout.addWidget(self.lb_mos_temp_2_value)
+        self.lb_mos_temp_2 = QtWidgets.QLabel(self.mos_temp_2)
+        self.lb_mos_temp_2.setText("℃")
+        self.mos_temp_2_layout.addWidget(self.lb_mos_temp_2)
+
+        self.soc_high = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.soc_high.setTitle("最高单体SOC")
+        self.soc_high_layout = QtWidgets.QHBoxLayout(self.soc_high)
+        self.lb_soc_high_value = QtWidgets.QLabel(self.soc_high)
+        self.lb_soc_high_value.setText("    ")
+        self.soc_high_layout.addWidget(self.lb_soc_high_value)
+        self.lb_soc_high = QtWidgets.QLabel(self.soc_high)
+        self.lb_soc_high.setText("")
+        self.soc_high_layout.addWidget(self.lb_soc_high)
+
+        self.soc_low = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.soc_low.setTitle("最低单体SOC")
+        self.soc_low_layout = QtWidgets.QHBoxLayout(self.soc_low)
+        self.lb_soc_low_value = QtWidgets.QLabel(self.soc_low)
+        self.lb_soc_low_value.setText("    ")
+        self.soc_low_layout.addWidget(self.lb_soc_low_value)
+        self.lb_soc_low = QtWidgets.QLabel(self.soc_low)
+        self.lb_soc_low.setText("")
+        self.soc_low_layout.addWidget(self.lb_soc_low)
+
+        self.soc_avg = QtWidgets.QGroupBox(self.top_qscrollarea)
+        self.soc_avg.setTitle("平均单体SOC")
+        self.soc_avg_layout = QtWidgets.QHBoxLayout(self.soc_avg)
+        self.lb_soc_avg_value = QtWidgets.QLabel(self.soc_avg)
+        self.lb_soc_avg_value.setText("    ")
+        self.soc_avg_layout.addWidget(self.lb_soc_avg_value)
+        self.lb_soc_avg = QtWidgets.QLabel(self.soc_avg)
+        self.lb_soc_avg.setText("")
+        self.soc_avg_layout.addWidget(self.lb_soc_avg)
+
+        if SD.CCU_TYPE == 1:
+            self.top_qscrollarea_layout.addWidget(self.tv_2, 3, 6, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.tv_3, 3, 7, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.jz_temp_high, 4, 5, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.jz_temp_high_index, 4, 6, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.bcu_temp_high, 4, 7, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.bcu_temp_high_index, 4, 8, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.mos_temp_1, 4, 9, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.mos_temp_2, 5, 0, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_high, 5, 1, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_low, 5, 2, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_avg, 5, 3, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.max_dchg_vol, 5, 4, 1, 1)
+            self.nom_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+            self.nom_energy.setTitle("系统标称能量")
+            self.nom_energy_layout = QtWidgets.QHBoxLayout(self.nom_energy)
+            self.lb_nom_energy_value = QtWidgets.QLabel(self.nom_energy)
+            self.lb_nom_energy_value.setText("    ")
+            self.nom_energy_layout.addWidget(self.lb_nom_energy_value)
+            self.lb_nom_energy = QtWidgets.QLabel(self.nom_energy)
+            self.lb_nom_energy.setText("kWh")
+            self.nom_energy_layout.addWidget(self.lb_nom_energy)
+            self.top_qscrollarea_layout.addWidget(self.nom_energy, 3, 8, 1, 1)
+
+            self.all_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+            self.all_energy.setTitle("系统总能量")
+            self.all_energy_layout = QtWidgets.QHBoxLayout(self.all_energy)
+            self.lb_all_energy_value = QtWidgets.QLabel(self.all_energy)
+            self.lb_all_energy_value.setText("    ")
+            self.all_energy_layout.addWidget(self.lb_all_energy_value)
+            self.lb_all_energy = QtWidgets.QLabel(self.all_energy)
+            self.lb_all_energy.setText("kWh")
+            self.all_energy_layout.addWidget(self.lb_all_energy)
+            self.top_qscrollarea_layout.addWidget(self.all_energy, 3, 9, 1, 1)
+        else:
+            self.tv_2.setHidden(True)
+            self.tv_3.setHidden(True)
+            self.jz_temp_high.setHidden(True)
+            self.jz_temp_high_index.setHidden(True)
+            self.bcu_temp_high.setHidden(True)
+            self.bcu_temp_high_index.setHidden(True)
+            self.nom_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+            self.nom_energy.setTitle("系统标称能量")
+            self.nom_energy_layout = QtWidgets.QHBoxLayout(self.nom_energy)
+            self.lb_nom_energy_value = QtWidgets.QLabel(self.nom_energy)
+            self.lb_nom_energy_value.setText("    ")
+            self.nom_energy_layout.addWidget(self.lb_nom_energy_value)
+            self.lb_nom_energy = QtWidgets.QLabel(self.nom_energy)
+            self.lb_nom_energy.setText("kWh")
+            self.nom_energy_layout.addWidget(self.lb_nom_energy)
+            self.top_qscrollarea_layout.addWidget(self.nom_energy, 3, 6, 1, 1)
+
+            self.all_energy = QtWidgets.QGroupBox(self.top_qscrollarea)
+            self.all_energy.setTitle("系统总能量")
+            self.all_energy_layout = QtWidgets.QHBoxLayout(self.all_energy)
+            self.lb_all_energy_value = QtWidgets.QLabel(self.all_energy)
+            self.lb_all_energy_value.setText("    ")
+            self.all_energy_layout.addWidget(self.lb_all_energy_value)
+            self.lb_all_energy = QtWidgets.QLabel(self.all_energy)
+            self.lb_all_energy.setText("kWh")
+            self.all_energy_layout.addWidget(self.lb_all_energy)
+            self.top_qscrollarea_layout.addWidget(self.all_energy, 3, 7, 1, 1)
+
+            self.top_qscrollarea_layout.addWidget(self.mos_temp_1, 3, 8, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.mos_temp_2, 3, 9, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_high, 4, 5, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_low, 4, 6, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.soc_avg, 4, 7, 1, 1)
+            self.top_qscrollarea_layout.addWidget(self.max_dchg_vol, 4, 8, 1, 1)
+        self.top_layout.addWidget(self.top_groupbox)
+        self.verticalLayout.addWidget(self.top_widget)

+ 471 - 0
ui/main/under_page.py

@@ -0,0 +1,471 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import os
+from ui.own.frame_theme import MyFrame
+from ui.own.palette_theme import set_edt_bg
+from utils.qt import QtWidgets, QtGui, QIcon, QPixmap, Qt, QColor
+from utils.resource import resource_path
+from utils.globalvar import SD
+
+
+class UnderPage(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        super(UnderPage, self).__init__(parent)
+        self.initUI()
+
+    def initUI(self):
+        self.verticalLayout = QtWidgets.QVBoxLayout(self)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+        self.verticalLayout.setSpacing(0)
+
+        # 设置参数
+        self.under_widget = MyFrame(self)
+        self.under_layout = QtWidgets.QHBoxLayout(self.under_widget)
+        self.under_layout.setContentsMargins(0, 0, 0, 0)
+        self.under_layout.setSpacing(0)
+        self.under_left_groupbox = QtWidgets.QGroupBox(self.under_widget)
+        self.under_left_groupbox.setTitle("运行状态")
+        self.under_left_groupbox_layout = QtWidgets.QGridLayout(self.under_left_groupbox)
+
+        self.lb_status = QtWidgets.QLabel("(灰色:断开/状态不成立 绿色:闭合/状态成立  红色:禁止)")
+        self.under_left_groupbox_layout.addWidget(self.lb_status, 0, 8, 1, 9)
+
+        self.sys_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status.setText("系统状态")
+        self.sys_status.setAlignment(Qt.AlignCenter)
+        self.sys_status.setReadOnly(True)
+        set_edt_bg(self.sys_status, QColor("#99CC99"))
+        self.under_left_groupbox_layout.addWidget(self.sys_status, 1, 0, 1, 2)
+
+        # spacerItem1 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        # self.under_left_groupbox_layout.addItem(spacerItem1)
+
+        self.sys_status_no = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_no.setText("低压上电")
+        self.sys_status_no.setAlignment(Qt.AlignCenter)
+        self.sys_status_no.setReadOnly(True)
+        set_edt_bg(self.sys_status_no, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_no, 1, 3, 1, 2)
+
+        self.sys_status_high_no = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_high_no.setText("待机")
+        self.sys_status_high_no.setAlignment(Qt.AlignCenter)
+        self.sys_status_high_no.setReadOnly(True)
+        set_edt_bg(self.sys_status_high_no, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_high_no, 1, 5, 1, 4)
+
+        # self.sys_status_high_no = QtWidgets.QLineEdit(self.under_left_groupbox)
+        # self.sys_status_high_no.setText("高压待机")
+        # self.sys_status_high_no.setAlignment(Qt.AlignCenter)
+        # self.sys_status_high_no.setReadOnly(True)
+        # set_edt_bg(self.sys_status_high_no, QColor(Qt.gray))
+        # self.under_left_groupbox_layout.addWidget(self.sys_status_high_no, 1, 7, 1, 2)
+
+        self.sys_status_chg = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_chg.setText("充电")
+        self.sys_status_chg.setAlignment(Qt.AlignCenter)
+        self.sys_status_chg.setReadOnly(True)
+        set_edt_bg(self.sys_status_chg, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_chg, 1, 9, 1, 2)
+
+        self.sys_status_dchg = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_dchg.setText("放电")
+        self.sys_status_dchg.setAlignment(Qt.AlignCenter)
+        self.sys_status_dchg.setReadOnly(True)
+        set_edt_bg(self.sys_status_dchg, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_dchg, 1, 11, 1, 2)
+
+        self.sys_status_stop = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_stop.setText("停机")
+        self.sys_status_stop.setAlignment(Qt.AlignCenter)
+        self.sys_status_stop.setReadOnly(True)
+        set_edt_bg(self.sys_status_stop, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_stop, 1, 13, 1, 2)
+
+        self.sys_status_sleep = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.sys_status_sleep.setText("休眠")
+        self.sys_status_sleep.setAlignment(Qt.AlignCenter)
+        self.sys_status_sleep.setReadOnly(True)
+        set_edt_bg(self.sys_status_sleep, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.sys_status_sleep, 1, 15, 1, 2)
+
+        # self.sys_status_nononono = QtWidgets.QLabel("       ")
+        # self.under_left_groupbox_layout.addWidget(self.sys_status_nononono, 0, 9, 1, 1)
+        spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.under_left_groupbox_layout.addItem(spacerItem2)
+
+        # self.up_and_down = QtWidgets.QLineEdit(self.under_left_groupbox)
+        # self.up_and_down.setText("指令")
+        # self.up_and_down.setAlignment(Qt.AlignCenter)
+        # self.up_and_down.setReadOnly(True)
+        # set_edt_bg(self.up_and_down, QColor("#99CC99"))
+        # self.under_left_groupbox_layout.addWidget(self.up_and_down, 2, 0, 1, 2)
+
+        # spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        # self.under_left_groupbox_layout.addItem(spacerItem2)
+
+        # self.sys_up = QtWidgets.QLineEdit(self.under_left_groupbox)
+        # self.sys_up.setText("上电")
+        # self.sys_up.setAlignment(Qt.AlignCenter)
+        # self.sys_up.setReadOnly(True)
+        # set_edt_bg(self.sys_up, QColor(Qt.gray))
+        # self.under_left_groupbox_layout.addWidget(self.sys_up, 2, 3, 1, 3)
+
+        # self.sys_down = QtWidgets.QLineEdit(self.under_left_groupbox)
+        # self.sys_down.setText("下电")
+        # self.sys_down.setAlignment(Qt.AlignCenter)
+        # self.sys_down.setReadOnly(True)
+        # set_edt_bg(self.sys_down, QColor(Qt.gray))
+        # self.under_left_groupbox_layout.addWidget(self.sys_down, 2, 6, 1, 3)
+
+        # spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        # self.under_left_groupbox_layout.addItem(spacerItem2)
+        if SD.CCU_TYPE == 1:
+            self.do_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_status.setText("DO状态")
+            self.do_status.setAlignment(Qt.AlignCenter)
+            self.do_status.setReadOnly(True)
+            set_edt_bg(self.do_status, QColor("#99CC99"))
+            self.under_left_groupbox_layout.addWidget(self.do_status, 3, 0, 1, 3)
+
+            spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+            self.under_left_groupbox_layout.addItem(spacerItem2)
+
+            self.do_1 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_1.setText("主正接触器")
+            self.do_1.setAlignment(Qt.AlignCenter)
+            self.do_1.setReadOnly(True)
+            set_edt_bg(self.do_1, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_1, 3, 3, 1, 3)
+
+            self.do_2 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_2.setText("主负接触器")
+            self.do_2.setAlignment(Qt.AlignCenter)
+            self.do_2.setReadOnly(True)
+            set_edt_bg(self.do_2, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_2, 3, 6, 1, 3)
+
+            self.do_3 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_3.setText("预充接触器")
+            self.do_3.setAlignment(Qt.AlignCenter)
+            self.do_3.setReadOnly(True)
+            set_edt_bg(self.do_3, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_3, 3, 9, 1, 3)
+
+            self.do_4 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_4.setText("中间接触器")
+            self.do_4.setAlignment(Qt.AlignCenter)
+            self.do_4.setReadOnly(True)
+            set_edt_bg(self.do_4, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_4, 3, 12, 1, 3)
+
+            self.do_5 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_5.setText("断路器控制")
+            self.do_5.setAlignment(Qt.AlignCenter)
+            self.do_5.setReadOnly(True)
+            set_edt_bg(self.do_5, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_5, 4, 3, 1, 3)
+
+            self.do_6 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_6.setText("DO6")
+            self.do_6.setAlignment(Qt.AlignCenter)
+            self.do_6.setReadOnly(True)
+            set_edt_bg(self.do_6, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_6, 4, 6, 1, 3)
+
+            self.do_7 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_7.setText("DO7")
+            self.do_7.setAlignment(Qt.AlignCenter)
+            self.do_7.setReadOnly(True)
+            set_edt_bg(self.do_7, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_7, 4, 9, 1, 3)
+
+            self.do_8 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.do_8.setText("DO8")
+            self.do_8.setAlignment(Qt.AlignCenter)
+            self.do_8.setReadOnly(True)
+            set_edt_bg(self.do_8, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.do_8, 4, 12, 1, 3)
+
+
+            self.di_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_status.setText("DI状态")
+            self.di_status.setAlignment(Qt.AlignCenter)
+            self.di_status.setReadOnly(True)
+            set_edt_bg(self.di_status, QColor("#99CC99"))
+            self.under_left_groupbox_layout.addWidget(self.di_status, 5, 0, 1, 3)
+
+            spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+            self.under_left_groupbox_layout.addItem(spacerItem2)
+
+            self.di_1 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_1.setText("DI1")
+            self.di_1.setAlignment(Qt.AlignCenter)
+            self.di_1.setReadOnly(True)
+            set_edt_bg(self.di_1, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_1, 5, 3, 1, 3)
+
+            self.di_2 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_2.setText("DI2")
+            self.di_2.setAlignment(Qt.AlignCenter)
+            self.di_2.setReadOnly(True)
+            set_edt_bg(self.di_2, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_2, 5, 6, 1, 3)
+
+            self.di_3 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_3.setText("DI3")
+            self.di_3.setAlignment(Qt.AlignCenter)
+            self.di_3.setReadOnly(True)
+            set_edt_bg(self.di_3, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_3, 5, 9, 1, 3)
+
+            self.di_4 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_4.setText("DI4")
+            self.di_4.setAlignment(Qt.AlignCenter)
+            self.di_4.setReadOnly(True)
+            set_edt_bg(self.di_4, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_4, 5, 12, 1, 3)
+
+            self.di_5 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_5.setText("DI5")
+            self.di_5.setAlignment(Qt.AlignCenter)
+            self.di_5.setReadOnly(True)
+            set_edt_bg(self.di_5, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_5, 6, 3, 1, 3)
+
+            self.di_6 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_6.setText("DI6")
+            self.di_6.setAlignment(Qt.AlignCenter)
+            self.di_6.setReadOnly(True)
+            set_edt_bg(self.di_6, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_6, 6, 6, 1, 3)
+
+            self.di_7 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_7.setText("DI7")
+            self.di_7.setAlignment(Qt.AlignCenter)
+            self.di_7.setReadOnly(True)
+            set_edt_bg(self.di_7, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_7, 6, 9, 1, 3)
+
+            self.di_8 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.di_8.setText("DI8")
+            self.di_8.setAlignment(Qt.AlignCenter)
+            self.di_8.setReadOnly(True)
+            set_edt_bg(self.di_8, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.di_8, 6, 12, 1, 3)
+        else:
+            # self.sys_sleep = QtWidgets.QLineEdit(self.under_left_groupbox)
+            # self.sys_sleep.setText("休眠")
+            # self.sys_sleep.setAlignment(Qt.AlignCenter)
+            # self.sys_sleep.setReadOnly(True)
+            # set_edt_bg(self.sys_sleep, QColor(Qt.gray))
+            # self.under_left_groupbox_layout.addWidget(self.sys_sleep, 2, 9, 1, 3)
+
+            self.mos_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.mos_status.setText("MOS状态")
+            self.mos_status.setAlignment(Qt.AlignCenter)
+            self.mos_status.setReadOnly(True)
+            set_edt_bg(self.mos_status, QColor("#99CC99"))
+            self.under_left_groupbox_layout.addWidget(self.mos_status, 3, 0, 1, 3)
+
+            spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+            self.under_left_groupbox_layout.addItem(spacerItem2)
+
+            self.mos_chg = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.mos_chg.setText("充电MOS")
+            self.mos_chg.setAlignment(Qt.AlignCenter)
+            self.mos_chg.setReadOnly(True)
+            set_edt_bg(self.mos_chg, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.mos_chg, 3, 3, 1, 3)
+
+            self.mos_dchg = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.mos_dchg.setText("放电MOS")
+            self.mos_dchg.setAlignment(Qt.AlignCenter)
+            self.mos_dchg.setReadOnly(True)
+            set_edt_bg(self.mos_dchg, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.mos_dchg, 3, 6, 1, 3)
+
+            self.mos_pre = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.mos_pre.setText("预充MOS")
+            self.mos_pre.setAlignment(Qt.AlignCenter)
+            self.mos_pre.setReadOnly(True)
+            set_edt_bg(self.mos_pre, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.mos_pre, 3, 9, 1, 3)
+
+            self.fjd_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.fjd_status.setText("干接点状态")
+            self.fjd_status.setAlignment(Qt.AlignCenter)
+            self.fjd_status.setReadOnly(True)
+            set_edt_bg(self.fjd_status, QColor("#99CC99"))
+            self.under_left_groupbox_layout.addWidget(self.fjd_status, 5, 0, 1, 3)
+
+            spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+            self.under_left_groupbox_layout.addItem(spacerItem2)
+
+            self.fjd_1 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.fjd_1.setText("干接点1")
+            self.fjd_1.setAlignment(Qt.AlignCenter)
+            self.fjd_1.setReadOnly(True)
+            set_edt_bg(self.fjd_1, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.fjd_1, 5, 3, 1, 3)
+
+            self.fjd_2 = QtWidgets.QLineEdit(self.under_left_groupbox)
+            self.fjd_2.setText("干接点2")
+            self.fjd_2.setAlignment(Qt.AlignCenter)
+            self.fjd_2.setReadOnly(True)
+            set_edt_bg(self.fjd_2, QColor(Qt.gray))
+            self.under_left_groupbox_layout.addWidget(self.fjd_2, 5, 6, 1, 3)         
+
+        self.chd_dsg_status = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.chd_dsg_status.setText("标志位")
+        self.chd_dsg_status.setAlignment(Qt.AlignCenter)
+        self.chd_dsg_status.setReadOnly(True)
+        set_edt_bg(self.chd_dsg_status, QColor("#99CC99"))
+        self.under_left_groupbox_layout.addWidget(self.chd_dsg_status, 7, 0, 1, 3)
+
+        spacerItem2 = QtWidgets.QSpacerItem(30, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.under_left_groupbox_layout.addItem(spacerItem2)
+
+        self.permit_chg = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.permit_chg.setText("禁止充电")
+        self.permit_chg.setAlignment(Qt.AlignCenter)
+        self.permit_chg.setReadOnly(True)
+        set_edt_bg(self.permit_chg, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.permit_chg, 7, 3, 1, 3)
+
+        self.permit_dchg = QtWidgets.QLineEdit(self.under_left_groupbox)
+        self.permit_dchg.setText("禁止放电")
+        self.permit_dchg.setAlignment(Qt.AlignCenter)
+        self.permit_dchg.setReadOnly(True)
+        set_edt_bg(self.permit_dchg, QColor(Qt.gray))
+        self.under_left_groupbox_layout.addWidget(self.permit_dchg, 7, 6, 1, 3)
+
+        self.under_layout.addWidget(self.under_left_groupbox, 1)
+
+        self.under_right_groupbox = QtWidgets.QGroupBox(self.under_widget)
+        self.under_right_groupbox.setTitle("控制指令")
+        self.under_right_groupbox_layout = QtWidgets.QGridLayout(self.under_right_groupbox)
+
+        self.btn_up = QtWidgets.QPushButton("系统上电")
+        self.under_right_groupbox_layout.addWidget(self.btn_up, 0, 0, 1, 2)
+        self.btn_down = QtWidgets.QPushButton("系统下电")
+        self.under_right_groupbox_layout.addWidget(self.btn_down, 0, 2, 1, 2)
+
+        self.lb_snkz = QtWidgets.QLabel("使能控制")
+        self.under_right_groupbox_layout.addWidget(self.lb_snkz, 0, 4, 1, 1)
+        self.snkz_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.snkz_check_box, 0, 5, 1, 1)
+
+        self.lb_p = QtWidgets.QLabel("主正控制")
+        self.p_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.lb_do7 = QtWidgets.QLabel("干接点1")
+        self.do7_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+
+        self.lb_n = QtWidgets.QLabel("主负控制")
+        self.n_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.lb_do8 = QtWidgets.QLabel("干接点2")
+        self.do8_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+
+        self.lb_center = QtWidgets.QLabel("中间控制")
+        self.center_check_box = QtWidgets.QCheckBox(self.under_right_groupbox) 
+
+        self.lb_dlq = QtWidgets.QLabel("断路器控制")
+        self.dlq_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)  
+
+        self.lb_do6 = QtWidgets.QLabel("DO6")
+        self.do6_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)  
+
+        self.lb_chg_1 = QtWidgets.QLabel("充电控制")
+        self.chg_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.lb_dchg_1 = QtWidgets.QLabel("放电控制")
+        self.dchg_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.lb_gjd_1 = QtWidgets.QLabel("干接点1")
+        self.gjd1_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.lb_gjd2_1 = QtWidgets.QLabel("干接点2")
+        self.gjd2_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+
+
+        if SD.CCU_TYPE == 1:
+            self.chg_check_box.setHidden(True)
+            self.dchg_check_box.setHidden(True)
+            self.gjd1_check_box.setHidden(True)
+            self.gjd2_check_box.setHidden(True)
+            self.under_right_groupbox_layout.addWidget(self.lb_p, 1, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.p_check_box, 1, 1, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.lb_n, 2, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.n_check_box, 2, 1, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.lb_do7, 1, 3, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.do7_check_box, 1, 4, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.lb_do8, 2, 3, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.do8_check_box, 2, 4, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.lb_center, 4, 0, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.center_check_box, 4, 1, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.lb_dlq, 5, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.dlq_check_box, 5, 1, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.lb_do6, 6, 0, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.do6_check_box, 6, 1, 1, 1) 
+        else:
+            self.p_check_box.setHidden(True)
+            self.do7_check_box.setHidden(True)
+            self.n_check_box.setHidden(True)
+            self.do8_check_box.setHidden(True)
+            self.center_check_box.setHidden(True)
+            self.dlq_check_box.setHidden(True)
+            self.do6_check_box.setHidden(True)
+            self.under_right_groupbox_layout.addWidget(self.lb_chg_1, 1, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.chg_check_box, 1, 1, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.lb_dchg_1, 2, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.dchg_check_box, 2, 1, 1, 1)    
+            self.under_right_groupbox_layout.addWidget(self.lb_gjd_1, 4, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.gjd1_check_box, 4, 1, 1, 1) 
+            self.under_right_groupbox_layout.addWidget(self.lb_gjd2_1, 5, 0, 1, 1)
+            self.under_right_groupbox_layout.addWidget(self.gjd2_check_box, 5, 1, 1, 1)  
+
+        self.lb_fault = QtWidgets.QLabel("故障强制释放")
+        self.under_right_groupbox_layout.addWidget(self.lb_fault, 1, 6, 1, 1)
+        self.fault_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.fault_check_box, 1, 7, 1, 1)   
+        self.lb_clear_balance = QtWidgets.QLabel("清空均衡时间")
+        self.under_right_groupbox_layout.addWidget(self.lb_clear_balance, 1, 9, 1, 1)
+        self.clear_balance_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.clear_balance_check_box, 1, 10, 1, 1)   
+
+      
+        self.lb_again = QtWidgets.QLabel("绝缘检测")
+        self.under_right_groupbox_layout.addWidget(self.lb_again, 2, 6, 1, 1)
+        self.again_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.again_check_box, 2, 7, 1, 1)   
+        self.lb_fan = QtWidgets.QLabel("开启风扇")
+        self.under_right_groupbox_layout.addWidget(self.lb_fan, 2, 9, 1, 1)
+        self.fan_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.fan_check_box, 2, 10, 1, 1) 
+
+        self.lb_pre = QtWidgets.QLabel("预充控制")
+        self.under_right_groupbox_layout.addWidget(self.lb_pre, 3, 0, 1, 1)
+        self.pre_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.pre_check_box, 3, 1, 1, 1)      
+        self.lb_again_one = QtWidgets.QLabel("绝缘检测开启一次")
+        self.under_right_groupbox_layout.addWidget(self.lb_again_one, 3, 6, 1, 1)
+        self.again_one_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.again_one_check_box, 3, 7, 1, 1)   
+   
+        self.lb_chg = QtWidgets.QLabel("强制充电指令")
+        self.under_right_groupbox_layout.addWidget(self.lb_chg, 4, 6, 1, 1)
+        self.qiangzhi_chg_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.qiangzhi_chg_check_box, 4, 7, 1, 1)
+   
+        self.lb_sleep = QtWidgets.QLabel("系统休眠指令")
+        self.under_right_groupbox_layout.addWidget(self.lb_sleep, 5, 6, 1, 1)
+        self.sleep_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.sleep_check_box, 5, 7, 1, 1)
+   
+        self.lb_reset = QtWidgets.QLabel("系统复位指令")
+        self.under_right_groupbox_layout.addWidget(self.lb_reset, 6, 6, 1, 1)
+        self.reset_check_box = QtWidgets.QCheckBox(self.under_right_groupbox)
+        self.under_right_groupbox_layout.addWidget(self.reset_check_box, 6, 7, 1, 1)
+
+        self.under_layout.addWidget(self.under_right_groupbox, 1)
+
+        self.verticalLayout.addWidget(self.under_widget)

+ 0 - 0
ui/own/__init__.py


+ 21 - 0
ui/own/frame_theme.py

@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :frame_theme.py
+@时间    :2022/01/22 10:04:48
+@作者    :None
+@版本    :1.0
+@说明    :Frame控件主题
+'''
+
+
+from utils.qt import QFrame
+
+
+class MyFrame(QFrame):
+    def __init__(self, parent=None):
+        super(MyFrame, self).__init__(parent)
+        self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
+        # 设置外线宽度
+        self.setLineWidth(3)
+        self.setMidLineWidth(3)

+ 257 - 0
ui/own/led.py

@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :led.py
+@时间    :2022/01/14 09:31:20
+@作者    :None
+@版本    :2.0
+@说明    :LED灯
+'''
+
+
+# from numpy import array, uint8
+from utils.qt import QApplication, QColor, QSize, QPushButton
+
+
+class Led(QPushButton):
+    black = QColor(0x00, 0x00, 0x00)
+    white = QColor(0xff, 0xff, 0xff)
+    blue = QColor(0x73, 0xce, 0xf4)
+    green = QColor(0xad, 0xff, 0x2f)
+    orange = QColor(0xff, 0xa5, 0x00)
+    purple = QColor(0xaf, 0x00, 0xff)
+    red = QColor(0xf4, 0x37, 0x53)
+    yellow = QColor(0xff, 0xff, 0x00)
+
+    capsule = 1
+    circle = 2
+    rectangle = 3
+
+    def __init__(self, parent, first_color=green, second_color=red, third_color=yellow, off_color=black, shape=circle):
+        super().__init__()
+
+        self._qss = 'QPushButton {{ \
+                                   border: 3px solid lightgray; \
+                                   border-radius: {}px; \
+                                   background-color: \
+                                       QLinearGradient( \
+                                           y1: 0, y2: 1, \
+                                           stop: 0 white, \
+                                           stop: 0.2 #{}, \
+                                           stop: 0.8 #{}, \
+                                           stop: 1 #{} \
+                                       ); \
+                                 }}'
+        self._first_qss = ''
+        self._second_qss = ''
+        self._third_qss = ''
+        self._off_qss = ''
+
+        self._status = 0
+        self._end_radius = 0
+
+        # Properties that will trigger changes on qss.
+        self.__first_color = None
+        self.__second_color = None
+        self.__third_color = None
+        self.__off_color = None
+        self.__shape = None
+        self.__height = 0
+
+        self._first_color = first_color
+        self._second_color = second_color
+        self._third_color = third_color
+        self._off_color = off_color
+        self._shape = shape
+        self._height = self.sizeHint().height()
+
+    # =================================================== Reimplemented Methods
+    def sizeHint(self):
+        res_h = QApplication.desktop().screenGeometry().height()
+        # res_w = QApplication.desktop().screenGeometry().width()
+
+        # res_w, res_h = pyautogui.size()  # Available resolution geometry
+        if self._shape == Led.capsule:
+            base_w = 50
+            base_h = 30
+        elif self._shape == Led.circle:
+            base_w = 30
+            base_h = 30
+        elif self._shape == Led.rectangle:
+            base_w = 40
+            base_h = 30
+
+        width = int(base_w * res_h / 1080)
+        height = int(base_h * res_h / 1080)
+        return QSize(width, height)
+
+    def resizeEvent(self, event):
+        self._height = self.size().height()
+        QPushButton.resizeEvent(self, event)
+
+    def setFixedSize(self, width, height):
+        self._height = height
+        if self._shape == Led.circle:
+            QPushButton.setFixedSize(self, height, height)
+        else:
+            QPushButton.setFixedSize(self, width, height)
+
+    # ============================================================== Properties
+    # 一级故障
+    @property
+    def _first_color(self):
+        return self.__first_color
+
+    @_first_color.setter
+    def _first_color(self, color):
+        self.__first_color = color
+        self._update_first_qss()
+
+    @_first_color.deleter
+    def _first_color(self):
+        del self.__first_color
+
+    # 二级故障
+    @property
+    def _second_color(self):
+        return self.__second_color
+
+    @_second_color.setter
+    def _second_color(self, color):
+        self.__second_color = color
+        self._update_second_qss()
+
+    @_second_color.deleter
+    def _second_color(self):
+        del self.__second_color
+
+    # 三级故障
+    @property
+    def _third_color(self):
+        return self.__third_color
+
+    @_third_color.setter
+    def _third_color(self, color):
+        self.__third_color = color
+        self._update_third_qss()
+
+    @_third_color.deleter
+    def _third_color(self):
+        del self.__third_color
+
+    # 无故障
+    @property
+    def _off_color(self):
+        return self.__off_color
+
+    @_off_color.setter
+    def _off_color(self, color):
+        self.__off_color = color
+        self._update_off_qss()
+
+    @_off_color.deleter
+    def _off_color(self):
+        del self.__off_color
+
+    @property
+    def _shape(self):
+        return self.__shape
+
+    @_shape.setter
+    def _shape(self, shape):
+        self.__shape = shape
+        self._update_end_radius()
+        self._update_first_qss()
+        self._update_second_qss()
+        self._update_third_qss()
+        self._update_off_qss()
+        self.set_status(self._status)
+
+    @_shape.deleter
+    def _shape(self):
+        del self.__shape
+
+    @property
+    def _height(self):
+        return self.__height
+
+    @_height.setter
+    def _height(self, height):
+        self.__height = height
+        self._update_end_radius()
+        self._update_first_qss()
+        self._update_second_qss()
+        self._update_third_qss()
+        self._update_off_qss()
+        self.set_status(self._status)
+
+    @_height.deleter
+    def _height(self):
+        del self.__height
+
+    # ================================================================= Methods
+    def _update_first_qss(self):
+        color, grad = self._get_gradient(self.__first_color)
+        self._first_qss = self._qss.format(self._end_radius, grad, color, color)
+
+    def _update_second_qss(self):
+        color, grad = self._get_gradient(self.__second_color)
+        self._second_qss = self._qss.format(self._end_radius, grad, color, color)
+
+    def _update_third_qss(self):
+        color, grad = self._get_gradient(self.__third_color)
+        self._third_qss = self._qss.format(self._end_radius, grad, color, color)
+
+    def _update_off_qss(self):
+        color, grad = self._get_gradient(self.__off_color)
+        self._off_qss = self._qss.format(self._end_radius, grad, color, color)
+
+    def _get_gradient(self, color):
+        grad = QColor(int((self.white.red() - color.red()) / 2) + color.red(), int((self.white.green() - color.green()) / 2) + color.green(), int((self.white.blue() - color.blue()) / 2) + color.blue())
+        grad = '{:02X}{:02X}{:02X}'.format(grad.red(), grad.green(), grad.blue())
+        color = '{:02X}{:02X}{:02X}'.format(color.red(), color.green(), color.blue())
+        return color, grad
+
+    def _update_end_radius(self):
+        if self.__shape == Led.rectangle:
+            self._end_radius = int(self.__height / 10)
+        else:
+            self._end_radius = int(self.__height / 2)
+
+    def _toggle_first(self):
+        self.setStyleSheet(self._first_qss)
+
+    def _toggle_second(self):
+        self.setStyleSheet(self._second_qss)
+
+    def _toggle_third(self):
+        self.setStyleSheet(self._third_qss)
+
+    def _toggle_off(self):
+        self.setStyleSheet(self._off_qss)
+
+    def set_first_color(self, color):
+        self._first_color = color
+
+    def set_second_color(self, color):
+        self._second_color = color
+
+    def set_third_color(self, color):
+        self._third_color = color
+
+    def set_off_color(self, color):
+        self._off_color = color
+
+    def set_shape(self, shape):
+        self._shape = shape
+
+    def set_status(self, status):
+        self._status = status
+        if self._status == 0:
+            self._toggle_off()
+        elif self._status == 1:
+            self._toggle_first()
+        elif self._status == 2:
+            self._toggle_second()
+        else:
+            self._toggle_third()

+ 63 - 0
ui/own/my_chart_view.py

@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :my_chart_view.py
+@时间    :2022/03/14 12:31:02
+@作者    :None
+@版本    :1.0
+@说明    : 重写QChartView 方法,增加缩放功能
+'''
+
+
+from math import pow
+from utils. qt import Qt, QChartView, QPoint, QPointF
+
+
+class MyChartView(QChartView):
+    m_bMiddleButtonPressed = 0
+    m_oPrePos = QPoint()
+
+    def __init__(self, parent=None):
+        super(MyChartView, self).__init__(parent)
+
+    def mouseMoveEvent(self, event):
+        if self.m_bMiddleButtonPressed:
+            oDeltaPos = event.pos() - self.m_oPrePos
+            self.chart().scroll(-oDeltaPos.x(), 0)
+            self.m_oPrePos = event.pos()
+        super(MyChartView, self).mouseMoveEvent(event)
+
+    def mousePressEvent(self, event):
+        if event.button() == Qt.MiddleButton:
+            self.m_bMiddleButtonPressed = True
+            self.m_oPrePos = event.pos()
+            self.setCursor(Qt.OpenHandCursor)
+        super(MyChartView, self).mousePressEvent(event)
+
+    def mouseReleaseEvent(self, event):
+        if event.button() == Qt.MiddleButton:
+            self.m_bMiddleButtonPressed = False
+            self.setCursor(Qt.ArrowCursor)
+        super(MyChartView, self).mouseReleaseEvent(event)
+
+    def wheelEvent(self, event):
+        # 设置比例
+        rVal = pow(0.999, event.delta())
+        # 1. 读取视图基本信息
+        oPlotAreaRect = self.chart().plotArea()
+        oCenterPoint = oPlotAreaRect.center()
+        # 2. 水平调整
+        oPlotAreaRect.setWidth(oPlotAreaRect.width() * rVal)
+        # 3. 竖直调整
+        oPlotAreaRect.setHeight(oPlotAreaRect.height() * rVal)
+        # 4.1 计算视点,视点不变,围绕中心缩放
+        # QPointF oNewCenterPoint(oCenterPoint);
+        #  4.2 计算视点,让鼠标点击的位置移动到窗口中心
+        # QPointF oNewCenterPoint(pEvent->pos());
+        #  4.3 计算视点,让鼠标点击的位置尽量保持不动(等比换算,存在一点误差)
+        oNewCenterPoint = QPointF(2 * oCenterPoint - event.pos() - (oCenterPoint - event.pos()) / rVal)
+        #  5. 设置视点
+        oPlotAreaRect.moveCenter(oNewCenterPoint)
+        #  6. 提交缩放调整
+        self.chart().zoomIn(oPlotAreaRect)
+        super(MyChartView, self).wheelEvent(event)

+ 87 - 0
ui/own/palette_theme.py

@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :palette_theme.py
+@时间    :2022/01/15 19:42:22
+@作者    :None
+@版本    :1.0
+@说明    :主题
+'''
+
+import os
+from utils.globalvar import SD
+from utils.resource import resource_path
+from utils.qt import QPalette, QFont, QBrush, QPixmap, QColor, QIcon
+
+THEME = 0
+
+
+def set_my_palette(self):
+
+    icon = QIcon()
+    icon.addPixmap(QPixmap(resource_path(os.path.join("assets", "ic_launch.png"))), QIcon.Normal, QIcon.Off)
+    self.setWindowIcon(icon)
+
+    self.setAutoFillBackground(True)
+    palette = QPalette()
+
+    if THEME:
+        # 背景图片
+        palette.setBrush(QPalette.Window, QBrush(QPixmap(resource_path(os.path.join("assets", "background.jpeg")))))
+        # 背景字体
+        palette.setColor(QPalette.WindowText, QColor(255, 255, 255))
+        palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))
+        palette.setColor(QPalette.Button, QColor("#1A1A1A"))
+        palette.setColor(QPalette.Base, QColor("#1A1A1A"))
+        palette.setColor(QPalette.Text, QColor(255, 255, 255))
+        palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255))
+
+    self.setPalette(palette)
+    # 定义字体样式
+    font = QFont('Microsoft YaHei')
+    if SD.HIGH_DPI == 1:
+        font.setPixelSize(17)
+    self.setFont(font)
+
+
+def set_sure_background(self):
+    palette = self.palette()
+    palette.setColor(QPalette.Button, QColor("#99CC99"))
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)
+    self.setFlat(True)
+
+
+def set_edt_bg(self, color):
+    palette = self.palette()
+    palette.setColor(QPalette.Base, color)
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)
+
+
+def set_edt_bg_white(self):
+    palette = self.palette()
+    palette.setColor(QPalette.Base, QColor("#FFFFFF"))
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)
+
+
+def set_tab_bg(self):
+    palette = QPalette()
+    palette.setColor(QPalette.Active, QPalette.Button, QColor(0, 0, 255))
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)
+
+
+def set_table_header_bg(self):
+    palette = QPalette()
+    palette.setColor(QPalette.Button, QColor("#FFA500"))
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)
+
+
+def set_table_line_bg(self):
+    palette = QPalette()
+    palette.setColor(QPalette.Active, QPalette.ColorRole, QColor("#FFA500"))
+    self.setPalette(palette)
+    self.setAutoFillBackground(True)

+ 76 - 0
ui/own/switch_button.py

@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :switch_button.py
+@时间    :2022/01/22 10:05:50
+@作者    :None
+@版本    :1.0
+@说明    :连接开关
+'''
+
+
+from utils.qt import QWidget, Signal, Qt, QRect, QPainter, QFont, QColor, QBrush, QPen
+from utils.globalvar import SD
+
+
+class SwitchButton(QWidget):
+
+    """自定义Switch按钮"""
+    # 信号
+    checkedChanged = Signal(bool)
+
+    def __init__(self, parent=None):
+        super(SwitchButton, self).__init__(parent)
+
+        # 设置无边框和背景透明
+        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
+        self.setAttribute(Qt.WA_TranslucentBackground)
+
+        self.resize(70, 30)
+        self.state = False  # 按钮状态:True表示开,False表示关
+
+    def mousePressEvent(self, event):
+        """鼠标点击事件:用于切换按钮状态"""
+        super(SwitchButton, self).mousePressEvent(event)
+
+        # self.state = False if self.state else True
+        self.state = not self.state
+        # 发射信号
+        self.checkedChanged.emit(self.state)
+
+        self.update()
+
+    def paintEvent(self, event):
+        """绘制按钮"""
+        super(SwitchButton, self).paintEvent(event)
+
+        # 创建绘制器并设置抗锯齿和图片流畅转换
+        painter = QPainter(self)
+        painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
+
+        # 定义字体样式
+        font = QFont('Microsoft YaHei')
+        font.setPixelSize(14)
+        painter.setFont(font)
+
+        # 开关为开的状态
+        if self.state:
+            painter.setPen(Qt.NoPen)
+            brush = QBrush(QColor('#999999'))
+            painter.setBrush(brush)
+            painter.drawRoundedRect(0, 0, self.width(), self.height(), self.height() // 2, self.height() // 2)
+            painter.setPen(Qt.NoPen)
+            brush.setColor(QColor('#006400'))
+            painter.setBrush(brush)
+            painter.drawRoundedRect(43, 3, 24, 24, 12, 12)
+
+        # 开关为关的状态
+        else:
+            painter.setPen(Qt.NoPen)
+            brush = QBrush(QColor('#999999'))
+            painter.setBrush(brush)
+            painter.drawRoundedRect(0, 0, self.width(), self.height(), self.height() // 2, self.height() // 2)
+            painter.setPen(Qt.NoPen)
+            brush.setColor(QColor('#006400'))
+            painter.setBrush(brush)
+            painter.drawRoundedRect(3, 3, 24, 24, 12, 12)

+ 58 - 0
ui/own/troublebar.py

@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :troublebar.py
+@时间    :2022/01/22 10:06:04
+@作者    :None
+@版本    :1.0
+@说明    :故障主题
+'''
+
+
+from utils.qt import QProgressBar, QPainter
+# from random import randint
+
+StyleSheet = """
+/*设置红色进度条*/
+#RedProgressBar {
+    text-align: center; /*进度值居中*/
+}
+#RedProgressBar::chunk {
+    background-color: #F44336;
+}
+#GreenProgressBar {
+    min-height: 12px;
+    max-height: 12px;
+    border-radius: 6px;
+}
+#GreenProgressBar::chunk {
+    border-radius: 6px;
+    background-color: #009688;
+}
+#BlueProgressBar {
+    border: 2px solid #2196F3;/*边框以及边框颜色*/
+    border-radius: 5px;
+    background-color: #E0E0E0;
+}
+BlueProgressBar::chunk {
+    background-color: #2196F3;
+    width: 10px; /*区块宽度*/
+    margin: 0.5px;
+}
+"""
+
+
+class TroubleProgressBar(QProgressBar):
+
+    def __init__(self, parent=None):
+        super(TroubleProgressBar, self).__init__(parent)
+        self.setTextVisible(False)
+        self.setStyleSheet("QProgressBar::chunk{background:qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0.0 green, stop: 0 yellow, stop: 1 red)}")
+
+    def paintEvent(self, event):
+        """绘制按钮"""
+        super(TroubleProgressBar, self).paintEvent(event)
+        # 绘制准备工作,启用反锯齿
+        # 创建绘制器并设置抗锯齿和图片流畅转换
+        painter = QPainter(self)
+        painter.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)

+ 932 - 0
ui/protect.py

@@ -0,0 +1,932 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from utils.qt import QtWidgets, QtCore, Qt, QtGui
+from utils.globalvar import SD
+
+
+class Protect(MyFrame):
+
+    def setupUi(self, Protect):
+
+        self.reg = QtCore.QRegExp('^[\-\+]?\d+(\.\d)?$')
+        self.validator = QtGui.QRegExpValidator(self)
+        self.validator.setRegExp(self.reg)
+
+        self.protect = MyFrame(Protect)
+        self.protect_layout = QtWidgets.QHBoxLayout(self.protect)
+        self.protect_layout.setContentsMargins(5, 5, 5, 5)
+        self.protect_layout.setSpacing(0)
+
+        self.protect_left_groupbox = QtWidgets.QGroupBox(self.protect)
+        self.protect_left_groupbox.setTitle("保护参数"  if SD.SYSTEM_LANGUAGE == 0 else "Protect Param.")
+        self.protect_left_groupbox_layout = QtWidgets.QVBoxLayout(self.protect_left_groupbox)
+
+        self.protect_table = QtWidgets.QTableWidget(self.protect_left_groupbox)
+        self.protect_table.setColumnCount(11)
+
+        self.protect_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+        # 设置只能选择行
+        self.protect_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+
+        self.protect_table.setHorizontalHeaderLabels(["参数名称", "物理值", "单位", "地址", "数据类型", "长度(字节)", "分辨率", "偏移量", "原始值", "最小值", "最大值"])
+
+        # self.protect_table.verticalHeader().setVisible(False)
+        self.protect_table.verticalHeader().setHighlightSections(True)
+        self.protect_table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.protect_table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
+        self.protect_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        self.protect_table.setRowCount(76)
+
+        for i in range(76):
+            item = QtWidgets.QTableWidgetItem("N/A")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 1, item)
+            item = QtWidgets.QTableWidgetItem(str.upper('{:0>4x}'.format(0xA000 + i)))
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 3, item)
+            item = QtWidgets.QTableWidgetItem("uint16")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 4, item)
+            item = QtWidgets.QTableWidgetItem("2")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 5, item)
+            # item = QtWidgets.QTableWidgetItem("1")
+            # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            # self.protect_table.setItem(i, 6, item)
+            item = QtWidgets.QTableWidgetItem("0")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 7, item)
+            item = QtWidgets.QTableWidgetItem("")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 8, item)
+            item = QtWidgets.QTableWidgetItem("")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 9, item)
+            item = QtWidgets.QTableWidgetItem("")
+            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+            self.protect_table.setItem(i, 10, item)
+
+        item = QtWidgets.QTableWidgetItem("单体过压三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(0, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(0, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(0, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体过压二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(1, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(1, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(1, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体过压一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(2, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(2, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(2, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体过压恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(3, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(3, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(3, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体欠压三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(4, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(4, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(4, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体欠压二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(5, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(5, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(5, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体欠压一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(6, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(6, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(6, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体欠压恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(7, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(7, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(7, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体压差三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(8, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(8, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(8, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体压差二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(9, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(9, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(9, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体压差一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(10, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(10, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(10, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单体压差恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(11, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(11, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(11, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压过压三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(12, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(12, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(12, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压过压二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(13, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(13, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(13, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压过压一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(14, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(14, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(14, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压过压恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(15, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(15, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(15, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压欠压三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(16, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(16, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(16, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压欠压二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(17, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(17, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(17, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压欠压一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(18, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(18, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(18, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总压欠压恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(19, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(19, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(19, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电高温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(20, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(20, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(20, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电高温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(21, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(21, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(21, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电高温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(22, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(22, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(22, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电高温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(23, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(23, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(23, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电低温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(24, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(24, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(24, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电低温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(25, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(25, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(25, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电低温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(26, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(26, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(26, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电低温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(27, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(27, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(27, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电高温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(28, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(28, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(28, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电高温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(29, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(29, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(29, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电高温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(30, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(30, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(30, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电高温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(31, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(31, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(31, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电低温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(32, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(32, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(32, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电低温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(33, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(33, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(33, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电低温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(34, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(34, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(34, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电低温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(35, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(35, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(35, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电过流三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(36, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(36, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(36, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电过流二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(37, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(37, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(37, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电过流一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(38, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(38, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(38, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("充电过流恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(39, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(39, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(39, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电过流三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(40, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(40, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(40, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电过流二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(41, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(41, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(41, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电过流一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(42, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(42, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(42, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("放电过流恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(43, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(43, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(43, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("电芯温差三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(44, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(44, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(44, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("电芯温差二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(45, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(45, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(45, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("电芯温差一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(46, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(46, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(46, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("电芯温差恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(47, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(47, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(47, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(48, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(48, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(48, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(49, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(49, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(49, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(50, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(50, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(50, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(51, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(51, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(51, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(52, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(52, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(52, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(53, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(53, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(53, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(54, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(54, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(54, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("MOS高温恢复回差阈值")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(55, 0, item)
+        item = QtWidgets.QTableWidgetItem("℃")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(55, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(55, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("绝缘过低三级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(56, 0, item)
+        item = QtWidgets.QTableWidgetItem("KΩ")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(56, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(56, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("绝缘过低二级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(57, 0, item)
+        item = QtWidgets.QTableWidgetItem("KΩ")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(57, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(57, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("绝缘过低一级告警")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(58, 0, item)
+        item = QtWidgets.QTableWidgetItem("KΩ")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(58, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(58, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("均衡开启电压")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(59, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(59, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(59, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("均衡关闭电压")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(60, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(60, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(60, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("均衡开启压差")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(61, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(61, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(61, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("均衡关闭压差")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(62, 0, item)
+        item = QtWidgets.QTableWidgetItem("mV")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(62, 2, item)
+        item = QtWidgets.QTableWidgetItem("1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(62, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("单次均衡开启时长")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(63, 0, item)
+        item = QtWidgets.QTableWidgetItem("s")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(63, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(63, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("告警判定延时")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(64, 0, item)
+        item = QtWidgets.QTableWidgetItem("s")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(64, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(64, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("告警恢复延时")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(65, 0, item)
+        item = QtWidgets.QTableWidgetItem("s")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(65, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(65, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("当前允许最大充电功率")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(66, 0, item)
+        item = QtWidgets.QTableWidgetItem("kW")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(66, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(66, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("当前允许最大放电功率")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(67, 0, item)
+        item = QtWidgets.QTableWidgetItem("kW")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(67, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(67, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("当前允许最大充电电压")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(68, 0, item)
+        item = QtWidgets.QTableWidgetItem("V")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(68, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(68, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("当前允许最大充电电流")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(69, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(69, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(69, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("当前允许最大放电电流")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(70, 0, item)
+        item = QtWidgets.QTableWidgetItem("A")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(70, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(70, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("标称容量配置")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(71, 0, item)
+        item = QtWidgets.QTableWidgetItem("Ah")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(71, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(71, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("总容量配置")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(72, 0, item)
+        item = QtWidgets.QTableWidgetItem("Ah")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(72, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(72, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("剩余容量配置")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(73, 0, item)
+        item = QtWidgets.QTableWidgetItem("Ah")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(73, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(73, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("累计充电电量")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(74, 0, item)
+        item = QtWidgets.QTableWidgetItem("kWh")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(74, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(74, 6, item)
+
+        item = QtWidgets.QTableWidgetItem("累计放电电量")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(75, 0, item)
+        item = QtWidgets.QTableWidgetItem("kWh")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(75, 2, item)
+        item = QtWidgets.QTableWidgetItem("0.1")
+        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        self.protect_table.setItem(75, 6, item)
+
+        # item = QtWidgets.QTableWidgetItem("单体过压三级告警")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 0, item)
+        # item = QtWidgets.QTableWidgetItem("N/A")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 2, item)
+        # item = QtWidgets.QTableWidgetItem("mV")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 2, item)
+        # item = QtWidgets.QTableWidgetItem("A000")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 5, item)
+        # item = QtWidgets.QTableWidgetItem("uint16")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 5, item)
+        # item = QtWidgets.QTableWidgetItem("2")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 6, item)
+        # item = QtWidgets.QTableWidgetItem("1")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 7, item)
+        # item = QtWidgets.QTableWidgetItem("0")
+        # item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+        # self.protect_table.setItem(0, 8, item)
+        self.protect_table.resizeColumnsToContents()
+
+        self.protect_left_groupbox_layout.addWidget(self.protect_table)
+
+        self.btn_read_param = QtWidgets.QPushButton("读取参数")
+        self.protect_left_groupbox_layout.addWidget(self.btn_read_param)
+
+        self.protect_layout.addWidget(self.protect_left_groupbox, 8)
+
+        self.protect_right_groupbox = QtWidgets.QGroupBox(self.protect)
+        self.protect_right_groupbox.setTitle("修改参数")
+        self.protect_right_groupbox_layout = QtWidgets.QGridLayout(self.protect_right_groupbox)
+
+        self.lb_name = QtWidgets.QLabel("参数名称")
+        self.protect_right_groupbox_layout.addWidget(self.lb_name, 1, 0, 1, 1)
+        self.qline_name = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_name.setAlignment(Qt.AlignCenter)
+        self.qline_name.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_name, 1, 1, 1, 1)
+
+        self.lb_addr = QtWidgets.QLabel("参数地址")
+        self.protect_right_groupbox_layout.addWidget(self.lb_addr, 2, 0, 1, 1)
+        self.qline_addr = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_addr.setAlignment(Qt.AlignCenter)
+        self.qline_addr.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_addr, 2, 1, 1, 1)
+
+        self.lb_data_long = QtWidgets.QLabel("数据长度")
+        self.protect_right_groupbox_layout.addWidget(self.lb_data_long, 3, 0, 1, 1)
+        self.qline_data_long = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_data_long.setAlignment(Qt.AlignCenter)
+        self.qline_data_long.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_data_long, 3, 1, 1, 1)
+
+        self.lb_fbl = QtWidgets.QLabel("分辨率")
+        self.protect_right_groupbox_layout.addWidget(self.lb_fbl, 4, 0, 1, 1)
+        self.qline_fbl = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_fbl.setAlignment(Qt.AlignCenter)
+        self.qline_fbl.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_fbl, 4, 1, 1, 1)
+
+        self.lb_offset = QtWidgets.QLabel("偏移量")
+        self.protect_right_groupbox_layout.addWidget(self.lb_offset, 5, 0, 1, 1)
+        self.qline_offset = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_offset.setAlignment(Qt.AlignCenter)
+        self.qline_offset.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_offset, 5, 1, 1, 1)
+
+        self.lb_dw = QtWidgets.QLabel("数据单位")
+        self.protect_right_groupbox_layout.addWidget(self.lb_dw, 6, 0, 1, 1)
+        self.qline_dw = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_dw.setAlignment(Qt.AlignCenter)
+        self.qline_dw.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_dw, 6, 1, 1, 1)
+
+        self.lb_data = QtWidgets.QLabel("原始值")
+        self.protect_right_groupbox_layout.addWidget(self.lb_data, 7, 0, 1, 1)
+        self.qline_data = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_data.setAlignment(Qt.AlignCenter)
+        self.qline_data.setReadOnly(True)
+        self.protect_right_groupbox_layout.addWidget(self.qline_data, 7, 1, 1, 1)
+
+        self.lb_data_set = QtWidgets.QLabel("物理值")
+        self.protect_right_groupbox_layout.addWidget(self.lb_data_set, 8, 0, 1, 1)
+        self.qline_data_set = QtWidgets.QLineEdit(self.protect_right_groupbox)
+        self.qline_data_set.setAlignment(Qt.AlignCenter)
+        self.qline_data_set.setValidator(self.validator)
+        self.protect_right_groupbox_layout.addWidget(self.qline_data_set, 8, 1, 1, 1)
+
+        self.btn_write_param = QtWidgets.QPushButton("写入参数")
+        self.protect_right_groupbox_layout.addWidget(self.btn_write_param, 9, 0, 1, 2)
+
+        self.btn_exit_param = QtWidgets.QPushButton("退出参数标定")
+        self.protect_right_groupbox_layout.addWidget(self.btn_exit_param, 10, 0, 1, 2)
+
+        self.protect_layout.addWidget(self.protect_right_groupbox, 2)
+
+        QtCore.QMetaObject.connectSlotsByName(Protect)

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 27 - 0
ui/record.py


+ 19 - 0
ui/set.py

@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.own.frame_theme import MyFrame
+from ui.own.palette_theme import set_edt_bg
+from utils.qt import QtWidgets, QtCore, Qt, QColor
+
+
+class Set(MyFrame):
+    def setupUi(self, Set):
+        self.set = MyFrame(Set)
+        self.set_layout = QtWidgets.QHBoxLayout(self.set)
+        self.set_layout.setContentsMargins(5, 5, 5, 5)
+        self.set_layout.setSpacing(0)
+
+     
+        # self.set_layout.addWidget(self.set_right_frame, 1)
+
+        QtCore.QMetaObject.connectSlotsByName(Set)

+ 125 - 0
ui/statusbar.py

@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :statusbar.py
+@时间    :2022/01/22 09:55:34
+@作者    :None
+@版本    :1.0
+@说明    :状态栏页面
+'''
+
+
+from utils.qt import QStatusBar, QLabel, QFrame, QProgressBar, QMetaObject, QCoreApplication, QRadioButton, QButtonGroup, Qt
+from utils.globalvar import SD
+from ui.own.led import Led
+
+
+class UiStatusBar(object):
+    def setupUi(self, bms_status):
+        self.statusbar = QStatusBar()
+
+        # bms软件版本号
+        self.lb_bms_version = QLabel()
+        self.lb_bms_version.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        self.lb_bms_version.setLineWidth(3)
+        self.lb_bms_version.setMidLineWidth(3)
+
+        #本地时间
+        self.lb_local_time = QLabel()
+        self.lb_local_time.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        self.lb_local_time.setLineWidth(3)
+        self.lb_local_time.setMidLineWidth(3)
+
+        # bms连接状态
+        self.label_bms_connect = QLabel()
+        self.label_bms_connect.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        self.label_bms_connect.setLineWidth(3)
+        self.label_bms_connect.setMidLineWidth(3)
+
+        # BMS:SN
+        self.lb_bms_sn = QLabel()
+        self.lb_bms_sn.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        self.lb_bms_sn.setLineWidth(3)
+        self.lb_bms_sn.setMidLineWidth(3)
+
+        self.lb_strech = QLabel("     ")
+
+        self.bms_upgrade_status = QProgressBar()
+        self.bms_upgrade_status.setProperty("value", 0)
+        self.bms_upgrade_status.setVisible(0)
+
+        # self.led_status_normal = Led(self.statusbar)
+        # self.lb_bms_normal = QLabel()
+        # self.lb_bms_normal.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        # self.lb_bms_normal.setLineWidth(3)
+        # self.lb_bms_normal.setMidLineWidth(3)
+        self.qbg_status = QButtonGroup()
+        self.qrb_status_normal = QRadioButton()
+        self.qrb_status_normal.setAttribute(Qt.WA_TransparentForMouseEvents, True)
+        self.qrb_status_normal.setFocusPolicy(Qt.NoFocus)
+        self.qrb_status_warnest = QRadioButton()
+        self.qrb_status_warnest.setAttribute(Qt.WA_TransparentForMouseEvents, True)
+        self.qrb_status_warnest.setFocusPolicy(Qt.NoFocus)
+        self.qrb_status_warner = QRadioButton()
+        self.qrb_status_warner.setAttribute(Qt.WA_TransparentForMouseEvents, True)
+        self.qrb_status_warner.setFocusPolicy(Qt.NoFocus)
+        self.qrb_status_warn = QRadioButton()
+        self.qrb_status_warn.setAttribute(Qt.WA_TransparentForMouseEvents, True)
+        self.qrb_status_warn.setFocusPolicy(Qt.NoFocus)
+        self.qbg_status.addButton(self.qrb_status_normal, 0)
+        self.qbg_status.addButton(self.qrb_status_warnest, 1)
+        self.qbg_status.addButton(self.qrb_status_warner, 2)
+        self.qbg_status.addButton(self.qrb_status_warn, 3)
+        # self.qrb_status_normal.setText("正常")
+        # self.lb_bms_normal = QLabel()
+        # self.lb_bms_normal.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        # self.lb_bms_normal.setLineWidth(3)
+        # self.lb_bms_normal.setMidLineWidth(3)
+
+        # self.led_status_normal = Led(self.statusbar)
+        # self.lb_bms_normal = QLabel()
+        # self.lb_bms_normal.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        # self.lb_bms_normal.setLineWidth(3)
+        # self.lb_bms_normal.setMidLineWidth(3)
+
+        # self.led_status_normal = Led(self.statusbar)
+        # self.lb_bms_normal = QLabel()
+        # self.lb_bms_normal.setFrameStyle(QFrame.Panel | QFrame.Raised)
+        # self.lb_bms_normal.setLineWidth(3)
+        # self.lb_bms_normal.setMidLineWidth(3)
+
+        # 往状态栏中添加组件(stretch应该是拉伸组件宽度)
+        self.statusbar.addWidget(self.lb_bms_version, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addWidget(self.lb_local_time, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addWidget(self.label_bms_connect, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addWidget(self.lb_bms_sn, stretch=0)
+        # self.statusbar.addWidget(self.label_bms_received, stretch=0)
+
+        self.statusbar.addPermanentWidget(self.qrb_status_normal, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addPermanentWidget(self.qrb_status_warnest, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addPermanentWidget(self.qrb_status_warner, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        self.statusbar.addPermanentWidget(self.qrb_status_warn, stretch=0)
+        # self.statusbar.addWidget(self.lb_strech, stretch=0)
+        # self.statusbar.addPermanentWidget(self.lb_bms_normal, stretch=0)
+        self.statusbar.addPermanentWidget(self.bms_upgrade_status, stretch=0)
+
+
+        self.statusbar.setSizeGripEnabled(False)
+
+        self.retranslateUi(bms_status)
+        QMetaObject.connectSlotsByName(bms_status)
+
+    def retranslateUi(self, bms_status):
+        _translate = QCoreApplication.translate
+        self.label_bms_connect.setText(_translate("bms_status", "通讯未连接" if SD.SYSTEM_LANGUAGE == 0 else "Not Connected"))
+        self.lb_bms_sn.setText(_translate("bms_status", "BATSN:EM0123456"))
+        self.qrb_status_normal.setText(_translate("bms_status", "正常" if SD.SYSTEM_LANGUAGE == 0 else "Normal"))
+        self.qrb_status_warnest.setText(_translate("bms_status", "三级告警" if SD.SYSTEM_LANGUAGE == 0 else "Warnest"))
+        self.qrb_status_warner.setText(_translate("bms_status", "二级告警" if SD.SYSTEM_LANGUAGE == 0 else "Warner"))
+        self.qrb_status_warn.setText(_translate("bms_status", "一级告警" if SD.SYSTEM_LANGUAGE == 0 else "Warn/Fault"))

+ 0 - 0
utils/__init__.py


+ 543 - 0
utils/can.py

@@ -0,0 +1,543 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :canConnect.py
+@时间    :2021/12/09 13:47:58
+@作者    :None
+@版本    :1.0
+@说明    :CAN连接驱动
+'''
+
+
+from ctypes.util import find_library
+from sys import platform
+import ctypes
+from ctypes import c_ubyte, c_uint, c_ushort, c_char
+from utils.log_signal import LogSignal
+from utils.resource import resource_path, resource_path_extend
+
+if platform == "win64":
+    zlg_can_dll = resource_path("config\\ControlCAN.dll")
+    ZLGCAN = ctypes.windll.LoadLibrary(zlg_can_dll)
+    pcan_dll = resource_path("config\\PCANBasic.dll")
+    PCAN = ctypes.windll.LoadLibrary(pcan_dll)
+elif platform == "win32":
+    zlg_can_dll = resource_path("config\\ControlCAN.dll")
+    ZLGCAN = ctypes.windll.LoadLibrary(zlg_can_dll)
+    pcan_dll = resource_path("config\\PCANBasic.dll")
+    PCAN = ctypes.windll.LoadLibrary(pcan_dll)
+elif platform == "linux":
+    zlg_can_dll = resource_path("config/linux/libusbcan.so")
+    ZLGCAN = ctypes.cdll.LoadLibrary(zlg_can_dll)
+else:
+    ZLGCAN = ctypes.cdll.LoadLibrary(find_library("libPCBUSB.0.12.1.dylib"))
+    pcan_dll = resource_path("config/libPCBUSB.0.12.1.dylib")
+    PCAN = ctypes.cdll.LoadLibrary(pcan_dll)
+
+ubyte_array = c_ubyte * 8
+ubyte_3array = c_ubyte * 3
+
+# can type
+CANTYPE = {
+    'USBCAN-I': 3,
+    'USBCAN-II': 4,
+}
+
+# can mode
+NORMAL_MODE = 0
+LISTEN_MODE = 1
+
+# filter type
+SINGLE_FILTER = 0
+DOUBLE_FILTER = 1
+
+# status
+STATUS_OK = 1
+
+# sendtype
+SEND_NORMAL = 0
+SEND_SINGLE = 1
+SELF_SEND_RECV = 2
+SELF_SEND_RECV_SINGLE = 3
+
+
+class VCI_INIT_CONFIG(ctypes.Structure):
+    _fields_ = [("AccCode", c_uint),  # 验收码。SJA1000的帧过滤验收码。对经过屏蔽码过滤为“有关位”进行匹配,全部匹配成功后,此帧可以被接收。
+                # 屏蔽码。SJA1000的帧过滤屏蔽码。对接收的CAN帧ID进行过滤,对应位为0的是“有关位”,对应位为1的是“无关位”。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
+                ("AccMask", c_uint),
+                # 保留
+                ("Reserved", c_uint),
+                # 滤波方式
+                ("Filter", c_ubyte),
+                # 波特率定时器 0
+                ("Timing0", c_ubyte),
+                # 波特率定时器 1
+                ("Timing1", c_ubyte),
+                # 模式。=0表示正常模式(相当于正常节点),=1表示只听模式(只接收,不影响总线),=2表示自发自收模式(环回模式)。
+                ("Mode", c_ubyte)
+                ]
+
+
+# VCI_CAN_OBJ结构体是CAN帧结构体,即1个结构体表示一个帧的数据结构。在发送函数VCI_Transmit和接收函数VCI_Receive中,被用来传送CAN信息帧。
+class VCI_CAN_OBJ(ctypes.Structure):
+    _fields_ = [("ID", c_uint),  # 帧ID。32位变量,数据格式为靠右对齐
+                # 设备接收到某一帧的时间标识。时间标示从CAN卡上电开始计时,计时单位为0.1ms。
+                ("TimeStamp", c_uint),
+                # 是否使用时间标识,为1时TimeStamp有效,TimeFlag和TimeStamp只在此帧为接收帧时有意义。
+                ("TimeFlag", c_ubyte),
+                # 发送帧类型。=0时为正常发送(发送失败会自动重发,重发时间为4秒,4秒内没有发出则取消);=1时为单次发送(只发送一次,发送失败不会自动重发,总线只产生一帧数据);其它值无效。
+                ("SendType", c_ubyte),
+                # 是否是远程帧。=0时为为数据帧,=1时为远程帧(数据段空)。
+                ("RemoteFlag", c_ubyte),
+                # 是否是扩展帧。=0时为标准帧(11位ID),=1时为扩展帧(29位ID)。
+                ("ExternFlag", c_ubyte),
+                # 数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节
+                ("DataLen", c_ubyte),
+                ("Data", c_ubyte * 8),
+                # CAN帧的数据。由于CAN规定了最大是8个字节,所以这里预留了8个字节的空间,受DataLen约束。如DataLen定义为3,即Data[0]、Data[1]、Data[2]是有效的
+                ("Reserved", c_ubyte * 3)  # 系统保留
+                ]
+
+
+class PVCI_ERR_INFO(ctypes.Structure):
+    _fields_ = [("ErrorCode", c_uint),
+                ("PassiveErrData", c_ubyte * 3),
+                ("ArLostErrData", c_ubyte)
+                ]
+
+
+baudRateConfig = {
+    '5Kbps': {'time0': 0xBF, 'time1': 0xFF},
+    '10Kbps': {'time0': 0x31, 'time1': 0x1C},
+    '20Kbps': {'time0': 0x18, 'time1': 0x1C},
+    '40Kbps': {'time0': 0x87, 'time1': 0xFF},
+    '50Kbps': {'time0': 0x09, 'time1': 0x1C},
+    '80Kbps': {'time0': 0x83, 'time1': 0xFF},
+    '100Kbps': {'time0': 0x04, 'time1': 0x1C},
+    '125Kbps': {'time0': 0x03, 'time1': 0x1C},
+    '200Kbps': {'time0': 0x81, 'time1': 0xFA},
+    '250Kbps': {'time0': 0x01, 'time1': 0x1C},
+    '400Kbps': {'time0': 0x80, 'time1': 0xFA},
+    '500Kbps': {'time0': 0x00, 'time1': 0x1C},
+    '666Kbps': {'time0': 0x80, 'time1': 0xB6},
+    '800Kbps': {'time0': 0x00, 'time1': 0x16},
+    '1000Kbps': {'time0': 0x00, 'time1': 0x14},
+}
+
+# PCAN
+#///////////////////////////////////////////////////////////
+# Type definitions
+#///////////////////////////////////////////////////////////
+
+TPCANHandle                   = c_ushort    # Represents a PCAN hardware channel handle
+TPCANStatus                   = int         # Represents a PCAN status/error code
+TPCANParameter                = c_ubyte     # Represents a PCAN parameter to be read or set
+TPCANDevice                   = c_ubyte     # Represents a PCAN device
+TPCANMessageType              = c_ubyte     # Represents the type of a PCAN message
+TPCANType                     = c_ubyte     # Represents the type of PCAN hardware to be initialized
+TPCANMode                     = c_ubyte     # Represents a PCAN filter mode
+TPCANBaudrate                 = c_ushort    # Represents a PCAN Baud rate register value
+
+#///////////////////////////////////////////////////////////
+# Value definitions
+#///////////////////////////////////////////////////////////
+
+# Currently defined and supported PCAN channels
+#
+PCAN_NONEBUS                  = TPCANHandle(0x00)  # Undefined/default value for a PCAN bus
+                             
+PCAN_ISABUS1                  = TPCANHandle(0x21)  # PCAN-ISA interface, channel 1
+PCAN_ISABUS2                  = TPCANHandle(0x22)  # PCAN-ISA interface, channel 2
+PCAN_ISABUS3                  = TPCANHandle(0x23)  # PCAN-ISA interface, channel 3
+PCAN_ISABUS4                  = TPCANHandle(0x24)  # PCAN-ISA interface, channel 4
+PCAN_ISABUS5                  = TPCANHandle(0x25)  # PCAN-ISA interface, channel 5
+PCAN_ISABUS6                  = TPCANHandle(0x26)  # PCAN-ISA interface, channel 6
+PCAN_ISABUS7                  = TPCANHandle(0x27)  # PCAN-ISA interface, channel 7
+PCAN_ISABUS8                  = TPCANHandle(0x28)  # PCAN-ISA interface, channel 8
+                             
+PCAN_DNGBUS1                  = TPCANHandle(0x31)  # PCAN-Dongle/LPT interface, channel 1
+                             
+PCAN_PCIBUS1                  = TPCANHandle(0x41)  # PCAN-PCI interface, channel 1
+PCAN_PCIBUS2                  = TPCANHandle(0x42)  # PCAN-PCI interface, channel 2
+PCAN_PCIBUS3                  = TPCANHandle(0x43)  # PCAN-PCI interface, channel 3
+PCAN_PCIBUS4                  = TPCANHandle(0x44)  # PCAN-PCI interface, channel 4
+PCAN_PCIBUS5                  = TPCANHandle(0x45)  # PCAN-PCI interface, channel 5
+PCAN_PCIBUS6                  = TPCANHandle(0x46)  # PCAN-PCI interface, channel 6
+PCAN_PCIBUS7                  = TPCANHandle(0x47)  # PCAN-PCI interface, channel 7
+PCAN_PCIBUS8                  = TPCANHandle(0x48)  # PCAN-PCI interface, channel 8
+PCAN_PCIBUS9                  = TPCANHandle(0x409)  # PCAN-PCI interface, channel 9
+PCAN_PCIBUS10                 = TPCANHandle(0x40A)  # PCAN-PCI interface, channel 10
+PCAN_PCIBUS11                 = TPCANHandle(0x40B)  # PCAN-PCI interface, channel 11
+PCAN_PCIBUS12                 = TPCANHandle(0x40C)  # PCAN-PCI interface, channel 12
+PCAN_PCIBUS13                 = TPCANHandle(0x40D)  # PCAN-PCI interface, channel 13
+PCAN_PCIBUS14                 = TPCANHandle(0x40E)  # PCAN-PCI interface, channel 14
+PCAN_PCIBUS15                 = TPCANHandle(0x40F)  # PCAN-PCI interface, channel 15
+PCAN_PCIBUS16                 = TPCANHandle(0x410)  # PCAN-PCI interface, channel 16
+                             
+PCAN_USBBUS1                  = TPCANHandle(0x51)  # PCAN-USB interface, channel 1
+PCAN_USBBUS2                  = TPCANHandle(0x52)  # PCAN-USB interface, channel 2
+PCAN_USBBUS3                  = TPCANHandle(0x53)  # PCAN-USB interface, channel 3
+PCAN_USBBUS4                  = TPCANHandle(0x54)  # PCAN-USB interface, channel 4
+PCAN_USBBUS5                  = TPCANHandle(0x55)  # PCAN-USB interface, channel 5
+PCAN_USBBUS6                  = TPCANHandle(0x56)  # PCAN-USB interface, channel 6
+PCAN_USBBUS7                  = TPCANHandle(0x57)  # PCAN-USB interface, channel 7
+PCAN_USBBUS8                  = TPCANHandle(0x58)  # PCAN-USB interface, channel 8
+PCAN_USBBUS9                  = TPCANHandle(0x509)  # PCAN-USB interface, channel 9
+PCAN_USBBUS10                 = TPCANHandle(0x50A)  # PCAN-USB interface, channel 10
+PCAN_USBBUS11                 = TPCANHandle(0x50B)  # PCAN-USB interface, channel 11
+PCAN_USBBUS12                 = TPCANHandle(0x50C)  # PCAN-USB interface, channel 12
+PCAN_USBBUS13                 = TPCANHandle(0x50D)  # PCAN-USB interface, channel 13
+PCAN_USBBUS14                 = TPCANHandle(0x50E)  # PCAN-USB interface, channel 14
+PCAN_USBBUS15                 = TPCANHandle(0x50F)  # PCAN-USB interface, channel 15
+PCAN_USBBUS16                 = TPCANHandle(0x510)  # PCAN-USB interface, channel 16
+                             
+PCAN_PCCBUS1                  = TPCANHandle(0x61)  # PCAN-PC Card interface, channel 1
+PCAN_PCCBUS2                  = TPCANHandle(0x62)  # PCAN-PC Card interface, channel 2
+
+PCAN_LANBUS1                  = TPCANHandle(0x801)  # PCAN-LAN interface, channel 1
+PCAN_LANBUS2                  = TPCANHandle(0x802)  # PCAN-LAN interface, channel 2
+PCAN_LANBUS3                  = TPCANHandle(0x803)  # PCAN-LAN interface, channel 3
+PCAN_LANBUS4                  = TPCANHandle(0x804)  # PCAN-LAN interface, channel 4
+PCAN_LANBUS5                  = TPCANHandle(0x805)  # PCAN-LAN interface, channel 5
+PCAN_LANBUS6                  = TPCANHandle(0x806)  # PCAN-LAN interface, channel 6
+PCAN_LANBUS7                  = TPCANHandle(0x807)  # PCAN-LAN interface, channel 7
+PCAN_LANBUS8                  = TPCANHandle(0x808)  # PCAN-LAN interface, channel 8
+PCAN_LANBUS9                  = TPCANHandle(0x809)  # PCAN-LAN interface, channel 9
+PCAN_LANBUS10                 = TPCANHandle(0x80A)  # PCAN-LAN interface, channel 10
+PCAN_LANBUS11                 = TPCANHandle(0x80B)  # PCAN-LAN interface, channel 11
+PCAN_LANBUS12                 = TPCANHandle(0x80C)  # PCAN-LAN interface, channel 12
+PCAN_LANBUS13                 = TPCANHandle(0x80D)  # PCAN-LAN interface, channel 13
+PCAN_LANBUS14                 = TPCANHandle(0x80E)  # PCAN-LAN interface, channel 14
+PCAN_LANBUS15                 = TPCANHandle(0x80F)  # PCAN-LAN interface, channel 15
+PCAN_LANBUS16                 = TPCANHandle(0x810)  # PCAN-LAN interface, channel 16
+
+# Represent the PCAN error and status codes 
+#
+PCAN_ERROR_OK                 = TPCANStatus(0x00000)  # No error 
+PCAN_ERROR_XMTFULL            = TPCANStatus(0x00001)  # Transmit buffer in CAN controller is full
+PCAN_ERROR_OVERRUN            = TPCANStatus(0x00002)  # CAN controller was read too late
+PCAN_ERROR_BUSLIGHT           = TPCANStatus(0x00004)  # Bus error: an error counter reached the 'light' limit
+PCAN_ERROR_BUSHEAVY           = TPCANStatus(0x00008)  # Bus error: an error counter reached the 'heavy' limit
+PCAN_ERROR_BUSWARNING         = TPCANStatus(PCAN_ERROR_BUSHEAVY) # Bus error: an error counter reached the 'warning' limit
+PCAN_ERROR_BUSPASSIVE         = TPCANStatus(0x40000)  # Bus error: the CAN controller is error passive
+PCAN_ERROR_BUSOFF             = TPCANStatus(0x00010)  # Bus error: the CAN controller is in bus-off state
+PCAN_ERROR_ANYBUSERR          = TPCANStatus(PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE) # Mask for all bus errors
+PCAN_ERROR_QRCVEMPTY          = TPCANStatus(0x00020)  # Receive queue is empty
+PCAN_ERROR_QOVERRUN           = TPCANStatus(0x00040)  # Receive queue was read too late
+PCAN_ERROR_QXMTFULL           = TPCANStatus(0x00080)  # Transmit queue is full
+PCAN_ERROR_REGTEST            = TPCANStatus(0x00100)  # Test of the CAN controller hardware registers failed (no hardware found)
+PCAN_ERROR_NODRIVER           = TPCANStatus(0x00200)  # Driver not loaded
+PCAN_ERROR_HWINUSE            = TPCANStatus(0x00400)  # Hardware already in use by a Net
+PCAN_ERROR_NETINUSE           = TPCANStatus(0x00800)  # A Client is already connected to the Net
+PCAN_ERROR_ILLHW              = TPCANStatus(0x01400)  # Hardware handle is invalid
+PCAN_ERROR_ILLNET             = TPCANStatus(0x01800)  # Net handle is invalid
+PCAN_ERROR_ILLCLIENT          = TPCANStatus(0x01C00)  # Client handle is invalid
+PCAN_ERROR_ILLHANDLE          = TPCANStatus(PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT) # Mask for all handle errors
+PCAN_ERROR_RESOURCE           = TPCANStatus(0x02000)  # Resource (FIFO, Client, timeout) cannot be created
+PCAN_ERROR_ILLPARAMTYPE       = TPCANStatus(0x04000)  # Invalid parameter
+PCAN_ERROR_ILLPARAMVAL        = TPCANStatus(0x08000)  # Invalid parameter value
+PCAN_ERROR_UNKNOWN            = TPCANStatus(0x10000)  # Unknown error
+PCAN_ERROR_ILLDATA            = TPCANStatus(0x20000)  # Invalid data, function, or action
+PCAN_ERROR_ILLMODE            = TPCANStatus(0x80000)  # Driver object state is wrong for the attempted operation
+PCAN_ERROR_CAUTION            = TPCANStatus(0x2000000)# An operation was successfully carried out, however, irregularities were registered
+PCAN_ERROR_INITIALIZE         = TPCANStatus(0x4000000)# Channel is not initialized [Value was changed from 0x40000 to 0x4000000]
+PCAN_ERROR_ILLOPERATION       = TPCANStatus(0x8000000)# Invalid operation [Value was changed from 0x80000 to 0x8000000]
+
+# PCAN devices
+#
+PCAN_NONE                     = TPCANDevice(0x00)  # Undefined, unknown or not selected PCAN device value
+PCAN_PEAKCAN                  = TPCANDevice(0x01)  # PCAN Non-PnP devices. NOT USED WITHIN PCAN-Basic API
+PCAN_ISA                      = TPCANDevice(0x02)  # PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus
+PCAN_DNG                      = TPCANDevice(0x03)  # PCAN-Dongle
+PCAN_PCI                      = TPCANDevice(0x04)  # PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express
+PCAN_USB                      = TPCANDevice(0x05)  # PCAN-USB and PCAN-USB Pro
+PCAN_PCC                      = TPCANDevice(0x06)  # PCAN-PC Card
+PCAN_VIRTUAL                  = TPCANDevice(0x07)  # PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API
+PCAN_LAN                      = TPCANDevice(0x08)  # PCAN Gateway devices
+
+# PCAN parameters
+#
+PCAN_DEVICE_ID                 = TPCANParameter(0x01)  # Device identifier parameter
+PCAN_5VOLTS_POWER              = TPCANParameter(0x02)  # 5-Volt power parameter
+PCAN_RECEIVE_EVENT             = TPCANParameter(0x03)  # PCAN receive event handler parameter
+PCAN_MESSAGE_FILTER            = TPCANParameter(0x04)  # PCAN message filter parameter
+PCAN_API_VERSION               = TPCANParameter(0x05)  # PCAN-Basic API version parameter
+PCAN_CHANNEL_VERSION           = TPCANParameter(0x06)  # PCAN device channel version parameter
+PCAN_BUSOFF_AUTORESET          = TPCANParameter(0x07)  # PCAN Reset-On-Busoff parameter
+PCAN_LISTEN_ONLY               = TPCANParameter(0x08)  # PCAN Listen-Only parameter
+PCAN_LOG_LOCATION              = TPCANParameter(0x09)  # Directory path for log files
+PCAN_LOG_STATUS                = TPCANParameter(0x0A)  # Debug-Log activation status
+PCAN_LOG_CONFIGURE             = TPCANParameter(0x0B)  # Configuration of the debugged information (LOG_FUNCTION_***)
+PCAN_LOG_TEXT                  = TPCANParameter(0x0C)  # Custom insertion of text into the log file
+PCAN_CHANNEL_CONDITION         = TPCANParameter(0x0D)  # Availability status of a PCAN-Channel
+PCAN_HARDWARE_NAME             = TPCANParameter(0x0E)  # PCAN hardware name parameter
+PCAN_RECEIVE_STATUS            = TPCANParameter(0x0F)  # Message reception status of a PCAN-Channel
+PCAN_CONTROLLER_NUMBER         = TPCANParameter(0x10)  # CAN-Controller number of a PCAN-Channel
+PCAN_TRACE_LOCATION            = TPCANParameter(0x11)  # Directory path for PCAN trace files
+PCAN_TRACE_STATUS              = TPCANParameter(0x12)  # CAN tracing activation status
+PCAN_TRACE_SIZE                = TPCANParameter(0x13)  # Configuration of the maximum file size of a CAN trace
+PCAN_TRACE_CONFIGURE           = TPCANParameter(0x14)  # Configuration of the trace file storing mode (TRACE_FILE_***)
+PCAN_CHANNEL_IDENTIFYING       = TPCANParameter(0x15)  # Physical identification of a USB based PCAN-Channel by blinking its associated LED
+PCAN_CHANNEL_FEATURES          = TPCANParameter(0x16)  # Capabilities of a PCAN device (FEATURE_***)
+PCAN_BITRATE_ADAPTING          = TPCANParameter(0x17)  # Using of an existing bit rate (PCAN-View connected to a channel)
+PCAN_BITRATE_INFO              = TPCANParameter(0x18)  # Configured bit rate as Btr0Btr1 value
+PCAN_BITRATE_INFO_FD           = TPCANParameter(0x19)  # Configured bit rate as TPCANBitrateFD string
+PCAN_BUSSPEED_NOMINAL          = TPCANParameter(0x1A)  # Configured nominal CAN Bus speed as Bits per seconds
+PCAN_BUSSPEED_DATA             = TPCANParameter(0x1B)  # Configured CAN data speed as Bits per seconds
+PCAN_IP_ADDRESS                = TPCANParameter(0x1C)  # Remote address of a LAN channel as string in IPv4 format
+PCAN_LAN_SERVICE_STATUS        = TPCANParameter(0x1D)  # Status of the Virtual PCAN-Gateway Service
+PCAN_ALLOW_STATUS_FRAMES       = TPCANParameter(0x1E)  # Status messages reception status within a PCAN-Channel
+PCAN_ALLOW_RTR_FRAMES          = TPCANParameter(0x1F)  # RTR messages reception status within a PCAN-Channel
+PCAN_ALLOW_ERROR_FRAMES        = TPCANParameter(0x20)  # Error messages reception status within a PCAN-Channel
+PCAN_INTERFRAME_DELAY          = TPCANParameter(0x21)  # Delay, in microseconds, between sending frames
+PCAN_ACCEPTANCE_FILTER_11BIT   = TPCANParameter(0x22)  # Filter over code and mask patterns for 11-Bit messages
+PCAN_ACCEPTANCE_FILTER_29BIT   = TPCANParameter(0x23)  # Filter over code and mask patterns for 29-Bit messages
+PCAN_IO_DIGITAL_CONFIGURATION  = TPCANParameter(0x24)  # Output mode of 32 digital I/O pin of a PCAN-USB Chip. 1: Output-Active 0 : Output Inactive
+PCAN_IO_DIGITAL_VALUE          = TPCANParameter(0x25)  # Value assigned to a 32 digital I/O pins of a PCAN-USB Chip
+PCAN_IO_DIGITAL_SET            = TPCANParameter(0x26)  # Value assigned to a 32 digital I/O pins of a PCAN-USB Chip - Multiple digital I/O pins to 1 = High
+PCAN_IO_DIGITAL_CLEAR          = TPCANParameter(0x27)  # Clear multiple digital I/O pins to 0
+PCAN_IO_ANALOG_VALUE           = TPCANParameter(0x28)  # Get value of a single analog input pin
+PCAN_FIRMWARE_VERSION          = TPCANParameter(0x29)  # Get the version of the firmware used by the device associated with a PCAN-Channel
+PCAN_ATTACHED_CHANNELS_COUNT   = TPCANParameter(0x2A)  # Get the amount of PCAN channels attached to a system
+PCAN_ATTACHED_CHANNELS         = TPCANParameter(0x2B)  # Get information about PCAN channels attached to a system
+PCAN_ALLOW_ECHO_FRAMES         = TPCANParameter(0x2C)  # Echo messages reception status within a PCAN-Channel
+PCAN_DEVICE_PART_NUMBER        = TPCANParameter(0x2D)  # Get the part number associated to a device
+
+# DEPRECATED parameters
+#
+PCAN_DEVICE_NUMBER             = PCAN_DEVICE_ID        # DEPRECATED. Use PCAN_DEVICE_ID instead
+
+# PCAN parameter values
+#
+PCAN_PARAMETER_OFF            = int(0x00)  # The PCAN parameter is not set (inactive)
+PCAN_PARAMETER_ON             = int(0x01)  # The PCAN parameter is set (active)
+PCAN_FILTER_CLOSE             = int(0x00)  # The PCAN filter is closed. No messages will be received
+PCAN_FILTER_OPEN              = int(0x01)  # The PCAN filter is fully opened. All messages will be received
+PCAN_FILTER_CUSTOM            = int(0x02)  # The PCAN filter is custom configured. Only registered messages will be received
+PCAN_CHANNEL_UNAVAILABLE      = int(0x00)  # The PCAN-Channel handle is illegal, or its associated hardware is not available
+PCAN_CHANNEL_AVAILABLE        = int(0x01)  # The PCAN-Channel handle is available to be connected (PnP Hardware: it means furthermore that the hardware is plugged-in)
+PCAN_CHANNEL_OCCUPIED         = int(0x02)  # The PCAN-Channel handle is valid, and is already being used
+PCAN_CHANNEL_PCANVIEW         = PCAN_CHANNEL_AVAILABLE | PCAN_CHANNEL_OCCUPIED  # The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect
+                              
+LOG_FUNCTION_DEFAULT          = int(0x00)   # Logs system exceptions / errors
+LOG_FUNCTION_ENTRY            = int(0x01)   # Logs the entries to the PCAN-Basic API functions 
+LOG_FUNCTION_PARAMETERS       = int(0x02)   # Logs the parameters passed to the PCAN-Basic API functions 
+LOG_FUNCTION_LEAVE            = int(0x04)   # Logs the exits from the PCAN-Basic API functions 
+LOG_FUNCTION_WRITE            = int(0x08)   # Logs the CAN messages passed to the CAN_Write function
+LOG_FUNCTION_READ             = int(0x10)   # Logs the CAN messages received within the CAN_Read function
+LOG_FUNCTION_ALL              = int(0xFFFF) # Logs all possible information within the PCAN-Basic API functions
+                              
+TRACE_FILE_SINGLE             = int(0x00)  # A single file is written until it size reaches PAN_TRACE_SIZE
+TRACE_FILE_SEGMENTED          = int(0x01)  # Traced data is distributed in several files with size PAN_TRACE_SIZE
+TRACE_FILE_DATE               = int(0x02)  # Includes the date into the name of the trace file
+TRACE_FILE_TIME               = int(0x04)  # Includes the start time into the name of the trace file
+TRACE_FILE_OVERWRITE          = int(0x80)  # Causes the overwriting of available traces (same name)
+TRACE_FILE_DATA_LENGTH        = int(0x100) # Causes using the data length column ('l') instead of the DLC column ('L') in the trace file
+                              
+FEATURE_FD_CAPABLE            = int(0x01)  # Device supports flexible data-rate (CAN-FD)
+FEATURE_DELAY_CAPABLE         = int(0x02)  # Device supports a delay between sending frames (FPGA based USB devices)
+FEATURE_IO_CAPABLE            = int(0x04)  # Device supports I/O functionality for electronic circuits (USB-Chip devices)
+                              
+SERVICE_STATUS_STOPPED        = int(0x01)  # The service is not running
+SERVICE_STATUS_RUNNING        = int(0x04)  # The service is running
+
+# Other constants
+#
+MAX_LENGTH_HARDWARE_NAME      = int(33)    # Maximum length of the name of a device: 32 characters + terminator
+MAX_LENGTH_VERSION_STRING     = int(256)   # Maximum length of a version string: 255 characters + terminator
+                              
+# PCAN message types          
+#                             
+PCAN_MESSAGE_STANDARD         = TPCANMessageType(0x00)  # The PCAN message is a CAN Standard Frame (11-bit identifier)
+PCAN_MESSAGE_RTR              = TPCANMessageType(0x01)  # The PCAN message is a CAN Remote-Transfer-Request Frame
+PCAN_MESSAGE_EXTENDED         = TPCANMessageType(0x02)  # The PCAN message is a CAN Extended Frame (29-bit identifier)
+PCAN_MESSAGE_FD               = TPCANMessageType(0x04)  # The PCAN message represents a FD frame in terms of CiA Specs
+PCAN_MESSAGE_BRS              = TPCANMessageType(0x08)  # The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate)
+PCAN_MESSAGE_ESI              = TPCANMessageType(0x10)  # The PCAN message represents a FD error state indicator(CAN FD transmitter was error active)
+PCAN_MESSAGE_ECHO             = TPCANMessageType(0x20)  # The PCAN message represents an echo CAN Frame
+PCAN_MESSAGE_ERRFRAME         = TPCANMessageType(0x40)  # The PCAN message represents an error frame
+PCAN_MESSAGE_STATUS           = TPCANMessageType(0x80)  # The PCAN message represents a PCAN status message
+
+# LookUp Parameters
+#
+LOOKUP_DEVICE_TYPE            = b"devicetype"           # Lookup channel by Device type (see PCAN devices e.g. PCAN_USB)
+LOOKUP_DEVICE_ID              = b"deviceid"             # Lookup channel by device id
+LOOKUP_CONTROLLER_NUMBER      = b"controllernumber"     # Lookup channel by CAN controller 0-based index
+LOOKUP_IP_ADDRESS             = b"ipaddress"            # Lookup channel by IP address (LAN channels only)
+
+# Frame Type / Initialization Mode
+#
+PCAN_MODE_STANDARD            = PCAN_MESSAGE_STANDARD  
+PCAN_MODE_EXTENDED            = PCAN_MESSAGE_EXTENDED  
+
+# Baud rate codes = BTR0/BTR1 register values for the CAN controller.
+# You can define your own Baud rate with the BTROBTR1 register.
+# Take a look at www.peak-system.com for our free software "BAUDTOOL" 
+# to calculate the BTROBTR1 register for every bit rate and sample point.
+#
+PCAN_BAUD_1M                  = TPCANBaudrate(0x0014) #   1 MBit/s
+PCAN_BAUD_800K                = TPCANBaudrate(0x0016) # 800 kBit/s
+PCAN_BAUD_500K                = TPCANBaudrate(0x001C) # 500 kBit/s
+PCAN_BAUD_250K                = TPCANBaudrate(0x011C) # 250 kBit/s
+PCAN_BAUD_125K                = TPCANBaudrate(0x031C) # 125 kBit/s
+PCAN_BAUD_100K                = TPCANBaudrate(0x432F) # 100 kBit/s
+PCAN_BAUD_95K                 = TPCANBaudrate(0xC34E) #  95,238 kBit/s
+PCAN_BAUD_83K                 = TPCANBaudrate(0x852B) #  83,333 kBit/s
+PCAN_BAUD_50K                 = TPCANBaudrate(0x472F) #  50 kBit/s
+PCAN_BAUD_47K                 = TPCANBaudrate(0x1414) #  47,619 kBit/s
+PCAN_BAUD_33K                 = TPCANBaudrate(0x8B2F) #  33,333 kBit/s
+PCAN_BAUD_20K                 = TPCANBaudrate(0x532F) #  20 kBit/s
+PCAN_BAUD_10K                 = TPCANBaudrate(0x672F) #  10 kBit/s
+PCAN_BAUD_5K                  = TPCANBaudrate(0x7F7F) #   5 kBit/s
+
+# Supported Non-PnP Hardware types
+#
+PZLGCAN_ISA                 = TPCANType(0x01)  # PCAN-ISA 82C200
+PZLGCAN_ISA_SJA             = TPCANType(0x09)  # PCAN-ISA SJA1000
+PZLGCAN_ISA_PHYTEC          = TPCANType(0x04)  # PHYTEC ISA 
+PZLGCAN_DNG                 = TPCANType(0x02)  # PCAN-Dongle 82C200
+PZLGCAN_DNG_EPP             = TPCANType(0x03)  # PCAN-Dongle EPP 82C200
+PZLGCAN_DNG_SJA             = TPCANType(0x05)  # PCAN-Dongle SJA1000
+PZLGCAN_DNG_SJA_EPP         = TPCANType(0x06)  # PCAN-Dongle EPP SJA1000
+ 
+# Represents a PCAN message
+#
+class TPCANMsg (ctypes.Structure):
+    """
+    Represents a PCAN message
+    """
+    _fields_ = [ ("ID",      c_uint),           # 11/29-bit message identifier
+                 ("MSGTYPE", TPCANMessageType), # Type of the message
+                 ("LEN",     c_ubyte),          # Data Length Code of the message (0..8)
+                 ("DATA",    c_ubyte * 8) ]     # Data of the message (DATA[0]..DATA[7])
+
+# Represents a timestamp of a received PCAN message
+# Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow
+#
+class TPCANTimestamp (ctypes.Structure):
+    """
+    Represents a timestamp of a received PCAN message
+    Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow
+    """
+    _fields_ = [ ("millis",          c_uint),    # Base-value: milliseconds: 0.. 2^32-1
+                 ("millis_overflow", c_ushort),  # Roll-arounds of millis
+                 ("micros",          c_ushort) ] # Microseconds: 0..999
+
+
+class MessageDeal:
+    def __init__(self):
+        self.can_connect = 0
+
+    def set_can_board(self, can_type, canIndex, canChannel, canBaudrate):
+        if can_type == 0:
+            self.canType = CANTYPE['USBCAN-II']
+            self.can_connect = 0
+        else:
+            self.canType = PCAN_USBBUS1
+            self.can_connect = 1
+
+        self.canIndex = canIndex
+        self.canChannel = canChannel
+        self.canBaudrate = canBaudrate
+
+    def open_device(self):
+        if self.can_connect:
+            if self.canBaudrate == "125Kbps":
+                ret = PCAN.CAN_Initialize(self.canType, PCAN_BAUD_125K ,0,0,0)
+            elif self.canBaudrate == "250Kbps":
+                ret = PCAN.CAN_Initialize(self.canType, PCAN_BAUD_250K ,0,0,0)
+            else:
+                ret = PCAN.CAN_Initialize(self.canType, PCAN_BAUD_500K ,0,0,0)
+            if TPCANStatus(ret) != PCAN_ERROR_OK:
+                return False
+            return True
+        else:
+            if (STATUS_OK != ZLGCAN.VCI_OpenDevice(self.canType, self.canChannel, self.canChannel)):
+                return False 
+            _vci_initconfig = VCI_INIT_CONFIG(0x00000000, 0xFFFFFFFF, 0, DOUBLE_FILTER,
+                                          baudRateConfig[self.canBaudrate]['time0'],
+                                          baudRateConfig[self.canBaudrate]['time1'],
+                                          NORMAL_MODE)
+            if (STATUS_OK != ZLGCAN.VCI_InitCAN(self.canType, self.canIndex, self.canChannel, ctypes.byref(_vci_initconfig))):
+                return False
+
+            if (STATUS_OK != ZLGCAN.VCI_StartCAN(self.canType, self.canIndex, self.canChannel)):
+                return False
+            
+            return True
+
+    def get_undeal_number(self):
+        if self.can_connect:
+            return 1
+        else:
+            return ZLGCAN.VCI_GetReceiveNum(self.canType, self.canIndex, self.canChannel)
+
+    def receive(self, number=1):
+        if self.can_connect:
+            msg = TPCANMsg()
+            timestamp = TPCANTimestamp()
+            res = PCAN.CAN_Read(self.canType,ctypes.byref(msg),ctypes.byref(timestamp))
+            if (res != PCAN_ERROR_QRCVEMPTY):
+                return 1, msg.ID, msg.DATA
+            else:
+                return 0, 0, 0
+        else:
+            objs = (VCI_CAN_OBJ * number)()
+            ret = ZLGCAN.VCI_Receive(self.canType, self.canIndex, self.canChannel, ctypes.byref(objs), number, 10)
+            if (ret > 0):
+                for i in range(0, ret):
+                    return 1, objs[i].ID, objs[i].Data
+            else:
+                return 0, 0, 0      
+
+
+    def send(self, ID, data, data_len=8):
+        if self.can_connect:
+            msg = TPCANMsg()
+            msg.ID = ID
+            msg.LEN = data_len
+            if (ID > 0x7FF):
+                msg.MSGTYPE = PCAN_MESSAGE_EXTENDED
+            else:
+                msg.MSGTYPE = PCAN_MESSAGE_STANDARD
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+
+            msg.DATA = (c_ubyte * 8)(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7])
+            send_status = PCAN.CAN_Write(self.canType,ctypes.byref(msg))
+            if (TPCANStatus(send_status) != PCAN_ERROR_OK):
+                return False
+            else:
+                return True
+        else:
+            vci_can_obj = VCI_CAN_OBJ()
+            vci_can_obj.ID = ID
+            vci_can_obj.DataLen = data_len
+            vci_can_obj.SendType = SEND_NORMAL
+            if (ID > 0x7FF):
+                vci_can_obj.ExternFlag = 1
+            else:
+                vci_can_obj.ExternFlag = 0
+            vci_can_obj.RemoteFlag = 0
+
+            if len(data) < 8:
+                data += (8 - len(data)) * [0]
+
+            vci_can_obj.Data = (c_ubyte * 8)(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7])
+            ret = ZLGCAN.VCI_Transmit(self.canType, self.canIndex, self.canChannel, ctypes.byref(vci_can_obj), 1)
+            if ret != STATUS_OK:
+                return False
+            else:
+                return True
+
+    def read_err_info(self):
+        errInfo = PVCI_ERR_INFO(0, ubyte_3array(0, 0, 0), 0)
+        ZLGCAN.VCI_ReadErrInfo(self.canType, self.canIndex, self.canChannel, ctypes.byref(errInfo))
+        LogSignal.print_log_signal().log_emit(errInfo.ErrorCode, errInfo.PassiveErrData[0], errInfo.PassiveErrData[1], errInfo.PassiveErrData[2], errInfo.ArLostErrData)
+
+    def close_can(self):
+        if self.can_connect:
+            PCAN.CAN_Uninitialize(self.canType)
+        else:
+            ZLGCAN.VCI_ClearBuffer(self.canType, self.canIndex, self.canChannel)
+            ZLGCAN.VCI_CloseDevice(self.canType, self.canIndex)

+ 32 - 0
utils/delay.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :delay.py
+@时间    :2022/02/17 15:37:43
+@作者    :None
+@版本    :1.0
+@说明    :精确到ms延迟函数
+'''
+
+
+import sys
+import ctypes
+from time import sleep
+
+
+def m_delay(ms):
+    if sys.platform == "darwin" or sys.platform == "linux":
+        sleep(ms / 1000)
+    elif sys.platform == "win32" or sys.platform == "win64":
+        stop_value = ctypes.c_longlong(0)
+        start_value = ctypes.c_longlong(0)
+        freq = ctypes.c_longlong(0)
+        n = 0
+        ctypes.windll.kernel32.QueryPerformanceFrequency(ctypes.byref(freq))
+        count = ms * freq.value / 1000
+        ctypes.windll.kernel32.QueryPerformanceCounter(ctypes.byref(start_value))
+        while n < count:
+            ctypes.windll.kernel32.QueryPerformanceCounter(ctypes.byref(stop_value))
+            n = stop_value.value - start_value.value
+    else:
+        sleep(ms / 1000)

+ 42 - 0
utils/globalvar.py

@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :globalvar.py
+@时间    :2022/01/22 10:11:23
+@作者    :None
+@版本    :1.0
+@说明    :全局变量
+'''
+from utils.qt import QMutex, QSemaphore
+from utils.can import MessageDeal
+
+
+class SD:
+
+    MAJOR_VERSION_NUMBER = 0
+    # 子版本号
+    MINOR_VERSION_NUMBER = 0
+    # 修正版本号
+    REVISION_NUMBER = 0
+
+    CAN_TYPE = 0
+
+    # 加载CAN连接驱动
+    CAN_CONTROL = MessageDeal()
+
+    CAN_ON_OFF = 0
+    # 工商业储能 or 户储
+    CCU_TYPE = 0
+
+    BCU_ID = 1
+
+    # 主机列表
+    BCU_LIST = [0 for i in range(15)]
+    BCU_LIFE_STATE = [0 for i in range(15)]
+
+    SYSTEM_LANGUAGE = 0
+
+    HIGH_DPI = 0
+
+    START_RUN = False
+

+ 43 - 0
utils/hex_bit.py

@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :hexBit.py
+@时间    :2021/12/09 13:48:58
+@作者    :None
+@版本    :1.0
+@说明    :获取位的值
+'''
+
+
+def a_bit(data, i):
+    if i == 1:
+        return data & 0x01
+    if i == 2:
+        return (data & 0x02) >> 1
+    if i == 3:
+        return (data & 0x04) >> 2
+    if i == 4:
+        return (data & 0x08) >> 3
+    if i == 5:
+        return (data & 0x10) >> 4
+    if i == 6:
+        return (data & 0x20) >> 5
+    if i == 7:
+        return (data & 0x40) >> 6
+    if i == 8:
+        return (data & 0x80) >> 7
+
+
+def hex_bcd(data):
+    s = data // 16
+    g = data % 16
+    c = s * 10 + g
+    return str(c)
+
+
+def bcd_hex(data):
+    int_data = int(data)
+    s = int_data // 10
+    g = int_data % 10
+    c = s * 16 + g
+    return c

+ 28 - 0
utils/log_signal.py

@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :log_signal.py
+@时间    :2022/02/17 15:37:11
+@作者    :None
+@版本    :1.0
+@说明    : 日志打印实例/单例模式
+'''
+
+from utils.qt import Signal, QObject
+
+
+class LogSignal(QObject):
+    instance = None
+    signal = Signal(str)
+
+    @classmethod
+    def print_log_signal(cls):
+        if cls.instance:
+            return cls.instance
+        else:
+            obj = cls()
+            cls.instance = obj
+            return cls.instance
+
+    def log_emit(self, data):
+        self.signal.emit(data)

+ 66 - 0
utils/qt.py

@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :qt.py
+@时间    :2022/02/21 16:48:46
+@作者    :None
+@版本    :1.0
+@说明    : pyqt和pyside2兼容包
+'''
+
+
+QT_CHOSE = 1
+if QT_CHOSE:
+    # PySide2
+    from PySide2 import (  # noqa F401
+        QtGui, QtWidgets, QtCore
+    )
+    from PySide2.QtWidgets import (  # noqa F401
+        QMainWindow, QDesktopWidget, QStyleFactory, QWidget, QFrame,
+        QApplication, QSizePolicy, QHBoxLayout, QVBoxLayout, QGridLayout,
+        QLabel, QPushButton, QRadioButton, QButtonGroup, QLineEdit, QProgressBar, QComboBox, QLCDNumber,
+        QMessageBox, QFileDialog, QPlainTextEdit, QStatusBar, QGroupBox, QTabBar,
+        QTabWidget, QTableWidget, QAbstractItemView, QCheckBox, QHeaderView,
+        QStyle, QStyleOptionButton, QTableWidgetItem, QSpacerItem, QStackedWidget
+    )
+    from PySide2.QtGui import (  # noqa F401
+        QGuiApplication, QPalette, QPainter, QColor, QPen,
+        QLinearGradient, QFont, QBrush, QPixmap, QIcon, QRegExpValidator, QKeySequence
+    )
+    from PySide2.QtCore import (  # noqa F401
+        QObject, QCoreApplication, QStandardPaths, QMetaObject, Qt,
+        QPoint, QRect, QRectF, QPointF, QDateTime, QTimer, QSize,
+        QThread, QMutex, QSemaphore, QRegExp, QModelIndex, Signal, Slot
+    )
+    from PySide2.QtCharts import QtCharts
+    QChartView = QtCharts.QChartView
+    QChart = QtCharts.QChart
+    QLineSeries = QtCharts.QLineSeries
+    QCategoryAxis = QtCharts.QCategoryAxis
+    QValueAxis = QtCharts.QValueAxis
+    QLegendMarker = QtCharts.QLegendMarker
+else:
+    # PyQt5
+    from PyQt5 import (  # noqa F401
+        QtGui, QtWidgets, QtCore, QtChart
+    )
+    from PyQt5.QtWidgets import (  # noqa F401
+        QMainWindow, QDesktopWidget, QStyleFactory, QWidget, QFrame,
+        QApplication, QSizePolicy, QHBoxLayout, QVBoxLayout, QGridLayout,
+        QLabel, QPushButton, QRadioButton, QButtonGroup, QLineEdit, QProgressBar, QComboBox, QLCDNumber,
+        QMessageBox, QFileDialog, QPlainTextEdit, QStatusBar, QGroupBox, QTabBar,
+        QTabWidget, QTableWidget, QAbstractItemView, QCheckBox, QHeaderView,
+        QStyle, QStyleOptionButton, QTableWidgetItem, QSpacerItem, QStackedWidget
+    )
+    from PyQt5.QtGui import (  # noqa F401
+        QGuiApplication, QPalette, QPainter, QColor, QPen,
+        QLinearGradient, QFont, QBrush, QPixmap, QIcon, QRegExpValidator, QKeySequence
+    )
+    from PyQt5.QtCore import (  # noqa F401
+        QObject, QCoreApplication, QStandardPaths, QMetaObject, Qt, QRect, QRectF,
+        QPoint, QPointF, QDateTime, QTimer, QSize,
+        QThread, QMutex, QSemaphore, QRegExp, QModelIndex, pyqtSignal as Signal, pyqtSlot as Slot
+    )
+    from PyQt5.QtChart import (  # noqa F401
+        QChartView, QLineSeries, QChart, QCategoryAxis, QValueAxis, QLegendMarker
+    )

+ 27 - 0
utils/resource.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :resourcePath.py
+@时间    :2021/12/09 13:49:58
+@作者    :None
+@版本    :1.0
+@说明    :资源文件路径配置
+'''
+
+
+from os import path
+import sys
+from sys import path as spath
+
+
+def resource_path(relative_path):
+    try:
+        base_path = sys._MEIPASS
+    except Exception:
+        base_path = path.abspath(".")
+    return path.join(base_path, relative_path)
+
+
+def resource_path_extend(relative_path):
+    spath.append(path.abspath(relative_path))
+    print(sys.path)

+ 0 - 0
widget/__init__.py


+ 32 - 0
widget/bms_balance.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.balance import Balance
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Balance(Balance, MyFrame):
+
+    balance_control_signal = Signal(int, int, int)
+
+    def __init__(self, parent=None):
+        super(Win_Balance, self).__init__(parent)
+        self.setupUi(self)
+
+
+        for i in range(15):
+            for j in range(72):
+                # self.balance_control_qscrollarea_layout.itemAtPosition(j + 1, i).widget().layout().itemAt(1).widget().stateChanged.connect(lambda state = self.balance_control_qscrollarea_layout.itemAtPosition(j + 1, i).widget().layout().itemAt(1).widget(), cmu_id = i + 1, cell_id = j + 1: self._balance_ctl(state, cmu_id, cell_id))
+                self.balance_control_qscrollarea_layout.itemAtPosition(i, j + 1).widget().layout().itemAt(1).widget().stateChanged.connect(lambda state = self.balance_control_qscrollarea_layout.itemAtPosition(i, j + 1).widget().layout().itemAt(1).widget(), cmu_id = i + 1, cell_id = j + 1: self._balance_ctl(state, cmu_id, cell_id))    
+
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")
+
+
+    def _balance_ctl(self, state, cmu_id, cell_id):
+        # print(cmu_id, cell_id, state)
+        self.balance_control_signal.emit(cmu_id, cell_id, state)

+ 43 - 0
widget/bms_cell.py

@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.cell import Cell
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QLineSeries, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Cell(Cell, MyFrame):
+
+    cell_vol_signal = Signal(int)
+    cell_temp_signal = Signal(int)
+    jz_temp_signal = Signal(int)
+    bcu_temp_signal = Signal(int)
+    mos_temp_signal = Signal(int)
+
+    def __init__(self, parent=None):
+        super(Win_Cell, self).__init__(parent)
+        self.setupUi(self)
+        
+        if SD.CCU_TYPE == 1:
+            self.btn_cell_vol.clicked.connect(self._cell_vol)
+            self.btn_cell_temp.clicked.connect(self._cell_temp)
+            self.btn_jz_temp.clicked.connect(self._jz_temp)
+            self.btn_bcu_temp.clicked.connect(self._bcu_temp)
+
+    def _cell_vol(self):
+        self.cell_vol_signal.emit(0)
+    
+    def _cell_temp(self):
+        self.cell_temp_signal.emit(1)
+
+    def _jz_temp(self):
+        self.jz_temp_signal.emit(2)
+
+    def _bcu_temp(self):
+        self.bcu_temp_signal.emit(3)
+
+    def _mos_temp(self):
+        self.mos_temp_signal.emit(4)

+ 15 - 0
widget/bms_double_ccu.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from ui.double_ccu import DoubleCcu
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QLineSeries, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Double_Ccu(DoubleCcu, MyFrame):
+
+    def __init__(self, parent=None):
+        super(Win_Double_Ccu, self).__init__(parent)
+        self.setupUi(self)

+ 33 - 0
widget/bms_download.py

@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.download import Download
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Download(Download, MyFrame):
+    bms_sn_signal = Signal()
+    bat_sn_signal = Signal()
+
+    def __init__(self, parent=None):
+        super(Win_Download, self).__init__(parent)
+        self.setupUi(self)
+
+        self.btn_bms_sn.clicked.connect(self._bms_sn)
+        self.btn_battery_sn.clicked.connect(self._battery_sn)
+
+    def _bms_sn(self):
+        self.bms_sn_signal.emit()
+
+    def _battery_sn(self):
+        self.bat_sn_signal.emit()
+
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")
+
+    def index_error(self):
+        QMessageBox.critical(self, "错误的SN" if SD.SYSTEM_LANGUAGE == 0 else "SN error", "SN不符!" if SD.SYSTEM_LANGUAGE == 0 else "SN not aviable!")

+ 46 - 0
widget/bms_hard.py

@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.hard import Hard
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+from functools import partial
+
+class Win_Hard(Hard, MyFrame):
+    rtc_update_signal = Signal()
+
+    def __init__(self, parent=None):
+        super(Win_Hard, self).__init__(parent)
+        self.setupUi(self)
+
+        self.btn_rtc.clicked.connect(self._rtc_update)
+
+        for i in range(64):
+                self.hard_table.cellWidget(i, 2).editingFinished.connect(partial(self._set_diff, i))
+       
+    def _rtc_update(self):
+         self.rtc_update_signal.emit()
+
+    def _set_diff(self, i):
+        try:
+            diff = int(float(self.hard_table.cellWidget(i, 2).text())) - int(self.hard_table.item(i, 3).text())
+            
+            self.hard_table.item(i, 4).setText(str(diff))
+            # if int(self.hard_table.item(i, 2).text()) <= int(float(self.hard_table.cellWidget(i, 1).text())) <= int(self.hard_table.item(i, 3).text()):
+            #     return
+            # else:
+            #     QMessageBox.critical(self, "失败" if SD.SYSTEM_LANGUAGE == 0 else "Error", "参数无效!" if SD.SYSTEM_LANGUAGE == 0 else "Invalid value!")
+            #     self.hard_table.cellWidget(i, 1).setText("")
+            #     self.hard_table.cellWidget(i, 1).setFocus()
+            #     return
+        except BaseException:
+            # QMessageBox.critical(self, "失败" if SD.SYSTEM_LANGUAGE == 0 else "Error", "参数无效!" if SD.SYSTEM_LANGUAGE == 0 else "Invalid value!")
+            # self.hard_table.cellWidget(i, 1).setText("")
+            # self.hard_table.cellWidget(i, 1).setFocusPolicy(Qt.StrongFocus)
+            return
+        
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")

+ 194 - 0
widget/bms_home.py

@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :bms_home.py
+@时间    :2021/12/09 13:33:56
+@作者    :None
+@版本    :1.0
+@说明    :主页面逻辑
+'''
+
+
+from utils.globalvar import SD
+from ui.home import UiBmsHomePage
+from utils.hex_bit import bcd_hex
+from utils.log_signal import LogSignal
+from utils.qt import QMainWindow, Qt, QStyle, QMessageBox, QGuiApplication, QTimer, QDateTime, Signal
+
+
+class Win_GotionBMS(UiBmsHomePage, QMainWindow):
+    main_control_signal = Signal(int)
+    cell_inf_signal = Signal(int)
+    double_ccu_signal = Signal(int)
+    protect_inf_signal = Signal(int)
+    hard_cali_signal = Signal(int)
+    balance_inf_signal = Signal(int)
+    data_inf_signal = Signal(int)
+    download_signal = Signal(int)
+    set_inf_signal = Signal(int)
+    bcu_online_list_signal = Signal(list)
+
+    can_start_signal = Signal()
+    can_stop_signal = Signal()
+    cut_start_signal = Signal()
+    
+    def __init__(self, parent=None):
+        super(Win_GotionBMS, self).__init__(parent)
+        self.setupUi(self)
+
+        self.btn_main_control.clicked.connect(self._main_control)
+        self.btn_cell_inf.clicked.connect(self._cell_inf)
+        self.btn_double_ccu.clicked.connect(self._double_ccu)
+        self.btn_protect_inf.clicked.connect(self._protect_inf)
+        self.btn_hard_cali.clicked.connect(self._hard_cali)
+        self.btn_balance_inf.clicked.connect(self._balance_inf)
+        self.btn_data_inf.clicked.connect(self._data_inf)
+        self.btn_download.clicked.connect(self._download)
+        self.btn_set_inf.clicked.connect(self._set_inf)
+        self.btn_start.clicked.connect(self._can_start)
+        self.btn_stop.clicked.connect(self._can_stop)
+        self.btn_cut.clicked.connect(self._app_cut)
+        
+        self.cb_bcu.currentIndexChanged.connect(self._bcu_masterid_set)
+        self.cb_bmu.currentIndexChanged.connect(self._bmu_id_set)
+    
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")
+
+    def _main_control(self):
+        self.main_control_signal.emit(0)
+    
+    def _cell_inf(self):
+        self.cell_inf_signal.emit(1)
+
+    def _double_ccu(self):
+        self.double_ccu_signal.emit(2)
+
+    def _protect_inf(self):
+        self.protect_inf_signal.emit(3)
+
+    def _hard_cali(self):
+        self.hard_cali_signal.emit(4)
+
+    def _balance_inf(self):
+        self.balance_inf_signal.emit(5)
+
+    def _data_inf(self):
+        self.data_inf_signal.emit(6)
+
+    def _download(self):
+        self.download_signal.emit(7)
+
+    def _set_inf(self):
+        self.set_inf_signal.emit(8)
+
+    def _can_start(self):
+        self.can_start_signal.emit()
+
+    def _can_stop(self):
+        self.can_stop_signal.emit()
+
+    def _app_cut(self):
+        self.cut_start_signal.emit()
+        
+    def _bcu_masterid_set(self):
+        SD.BCU_ID = int(self.cb_bcu.currentIndex() +  1)
+
+    def _bmu_id_set(self):
+        int(self.cb_bmu.currentIndex() +  1)
+
+    def _bcu_connect_get(self, data):
+        bcu_on_line = ["BCU1", "BCU2", "BCU3", "BCU4", "BCU5", "BCU6", "BCU7", "BCU8", "BCU9", "BCU10", "BCU11", "BCU12", "BCU13", "BCU14", "BCU15"]
+        bcu_on_line_set = []
+        if data[0] == 1:
+            bcu_on_line[0] = "BCU1"
+        else:
+            bcu_on_line[0] = ""
+
+        if data[1] == 1:
+            bcu_on_line[1] = "BCU2"
+        else:
+            bcu_on_line[1] = ""
+
+        if data[2] == 1:
+            bcu_on_line[2] = "BCU3"
+        else:
+            bcu_on_line[2] = ""
+
+        if data[3] == 1:
+            bcu_on_line[3] = "BCU4"
+        else:
+            bcu_on_line[3] = ""
+
+        if data[4] == 1:
+            bcu_on_line[4] = "BCU5"
+        else:
+            bcu_on_line[4] = ""
+
+        if data[5] == 1:
+            bcu_on_line[5] = "BCU6"
+        else:
+            bcu_on_line[5] = ""
+
+        if data[6] == 1:
+            bcu_on_line[6] = "BCU7"
+        else:
+            bcu_on_line[6] = ""
+
+        if data[7] == 1:
+            bcu_on_line[7] = "BCU8"
+        else:
+            bcu_on_line[7] = ""
+
+        if data[8] == 1:
+            bcu_on_line[8] = "BCU9"
+        else:
+            bcu_on_line[8] = ""
+
+        if data[9] == 1:
+            bcu_on_line[9] = "BCU10"
+        else:
+            bcu_on_line[9] = ""
+
+        if data[10] == 1:
+            bcu_on_line[10] = "BCU11"
+        else:
+            bcu_on_line[10] = ""
+
+        if data[11] == 1:
+            bcu_on_line[11] = "BCU12"
+        else:
+            bcu_on_line[11] = ""
+        
+        if data[12] == 1:
+            bcu_on_line[12] = "BCU13"
+        else:
+            bcu_on_line[12] = ""
+
+        if data[13] == 1:
+            bcu_on_line[13] = "BCU14"
+        else:
+            bcu_on_line[13] = ""
+
+        if data[14] == 1:
+            bcu_on_line[14] = "BCU15"
+        else:
+            bcu_on_line[14] = ""
+
+        for a in list(bcu_on_line):
+            if a != "":
+                bcu_on_line_set.append(a)
+        self.edt_online.setText('、'.join([i for i in list(bcu_on_line_set)]))
+    
+    
+    # 居中显示
+    def center(self):
+        # 新方法
+        self.setGeometry(
+            QStyle.alignedRect(
+                Qt.LeftToRight,
+                Qt.AlignCenter,
+                self.size(),
+                QGuiApplication.primaryScreen().availableGeometry(),
+            ),
+        )

+ 63 - 0
widget/bms_login.py

@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :bms_login.py
+@时间    :2022/01/03 09:35:16
+@作者    :None
+@版本    :1.0
+@说明    :登录逻辑
+'''
+
+
+from ui.login import UiBmsLoginPage
+from ui.own.frame_theme import MyFrame
+from utils.qt import QMessageBox, Qt, Signal, Slot
+from utils.globalvar import SD
+
+
+class Win_Login(UiBmsLoginPage, MyFrame):
+    # 信号传递
+    login_signal = Signal()
+    cancel_signal = Signal()
+    home_show_signal = Signal()
+    language_signal = Signal(int)
+
+    def __init__(self, parent=None):
+        super(Win_Login, self).__init__(parent)
+        self.setupUi(self)
+
+    @Slot()
+    def on_btn_login_clicked(self):
+        self.login_signal.emit()
+
+    @Slot()
+    def on_edt_password_returnPressed(self):
+        self.login_signal.emit()
+
+    @Slot()
+    def on_btn_cancel_clicked(self):
+        self.cancel_signal.emit()
+
+    @Slot(int)
+    def on_language_currentIndexChanged(self, index):
+        self.language_signal.emit(index)
+
+    def on_success(self):
+        SD.CCU_TYPE = self.cb_prj.currentIndex()
+        self.can_type = self.cb_con_type.currentIndex()
+        self._can_index = self.cb_index.currentText()
+        self._can_channel = self.cb_channel.currentText()
+        self._can_baudrate = self.cb_baudrate.currentText()
+
+        SD.CAN_TYPE = self.can_type
+        can_index = int(self._can_index)
+        can_channel = int(self._can_channel)
+        can_baudrate = self._can_baudrate
+
+        SD.CAN_CONTROL.set_can_board(SD.CAN_TYPE, can_index, can_channel, can_baudrate)
+
+        self.home_show_signal.emit()
+        self.close()
+
+    def on_error(self):
+        QMessageBox.critical(self, "登录失败" if SD.SYSTEM_LANGUAGE == 0 else "Login Error", "帐号密码错误" if SD.SYSTEM_LANGUAGE == 0 else "UserName or Pwd Error!")

+ 167 - 0
widget/bms_main.py

@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.main.main import Main
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Main(Main, MyFrame):
+
+    up_signal = Signal()
+    down_signal = Signal()
+    controll_signal = Signal(int)
+    do1_signal = Signal(int)
+    do2_signal = Signal(int)
+    do3_signal = Signal(int)
+    do4_signal = Signal(int)
+    do5_signal = Signal(int)
+    do6_signal = Signal(int)
+    do7_signal = Signal(int)
+    do8_signal = Signal(int)
+
+    fault_release_signal = Signal(int)
+    jy_signal = Signal(int)
+    jy_one_signal = Signal(int)
+    chg_mos_signal = Signal(int)
+    dchg_mos_signal = Signal(int)
+    pre_mos_signal = Signal(int)
+    gjd1_signal = Signal(int)
+    gjd2_signal = Signal(int)
+    chg_signal = Signal(int)
+    sleep_signal = Signal(int)
+    reset_signal = Signal(int)
+    clear_balance_signal = Signal(int)
+    fan_signal = Signal(int)
+
+    def __init__(self, parent=None):
+        super(Win_Main, self).__init__(parent)
+        self.setupUi(self)
+
+        self.under_widget.btn_up.clicked.connect(self._sys_up)
+        self.under_widget.btn_down.clicked.connect(self._sys_down)
+        self.under_widget.snkz_check_box.stateChanged.connect(self._controll_sys)
+        self.under_widget.p_check_box.stateChanged.connect(self._do1)
+        self.under_widget.n_check_box.stateChanged.connect(self._do2)
+        self.under_widget.pre_check_box.stateChanged.connect(self._do3)
+        self.under_widget.center_check_box.stateChanged.connect(self._do4)
+        self.under_widget.dlq_check_box.stateChanged.connect(self._do5)
+        self.under_widget.do6_check_box.stateChanged.connect(self._do6)
+        self.under_widget.do7_check_box.stateChanged.connect(self._do7)
+        self.under_widget.do8_check_box.stateChanged.connect(self._do8)
+
+        self.under_widget.fault_check_box.stateChanged.connect(self._fault)
+        self.under_widget.again_check_box.stateChanged.connect(self._against)
+        self.under_widget.again_one_check_box.stateChanged.connect(self._again_one)
+        self.under_widget.chg_check_box.stateChanged.connect(self._chg)
+        self.under_widget.dchg_check_box.stateChanged.connect(self._dchg)
+        self.under_widget.pre_check_box.stateChanged.connect(self._pre)
+        self.under_widget.gjd1_check_box.stateChanged.connect(self._gjd1)
+        self.under_widget.gjd2_check_box.stateChanged.connect(self._gjd2)
+        self.under_widget.qiangzhi_chg_check_box.stateChanged.connect(self._qiangzhi_chg)
+        self.under_widget.sleep_check_box.stateChanged.connect(self._sleep)
+        self.under_widget.reset_check_box.stateChanged.connect(self._reset)
+        self.under_widget.clear_balance_check_box.stateChanged.connect(self._clear)
+        self.under_widget.fan_check_box.stateChanged.connect(self._fan)
+
+
+    def _sys_up(self):
+        self.up_signal.emit()
+
+
+    def _sys_down(self):
+        self.down_signal.emit()
+
+
+    def _controll_sys(self, data):
+        self.controll_signal.emit(data)
+
+
+    def _do1(self, data):
+        self.do1_signal.emit(data)
+
+
+    def _do2(self, data):
+        self.do2_signal.emit(data)
+
+
+    def _do3(self, data):
+        self.do3_signal.emit(data)
+
+
+    def _do4(self, data):
+        self.do4_signal.emit(data)
+
+
+    def _do5(self, data):
+        self.do5_signal.emit(data)
+
+
+    def _do6(self, data):
+        self.do6_signal.emit(data)
+
+
+    def _do7(self, data):
+        self.do7_signal.emit(data)
+
+
+    def _do8(self, data):
+        self.do8_signal.emit(data)        
+
+
+    def _fault(self, data):
+        self.fault_release_signal.emit(data)
+
+
+    def _against(self, data):
+        self.jy_signal.emit(data)
+
+
+    def _again_one(self, data):
+        self.jy_one_signal.emit(data)
+
+
+    def _chg(self, data):
+        self.chg_mos_signal.emit(data)
+
+
+    def _dchg(self, data):
+        self.dchg_mos_signal.emit(data)
+
+
+    def _pre(self, data):
+        self.pre_mos_signal.emit(data)
+
+
+    def _gjd1(self, data):
+        self.gjd1_signal.emit(data)
+
+
+    def _gjd2(self, data):
+        self.gjd2_signal.emit(data)
+
+
+    def _qiangzhi_chg(self, data):
+        self.chg_signal.emit(data)
+
+
+    def _sleep(self, data):
+        self.sleep_signal.emit(data)
+
+
+    def _reset(self, data):
+        self.reset_signal.emit(data)
+
+    def _clear(self, data):
+        self.clear_balance_signal.emit(data)
+
+
+    def _fan(self, data):
+        self.fan_signal.emit(data)
+
+
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")

+ 60 - 0
widget/bms_protect.py

@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.protect import Protect
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Protect(Protect, MyFrame):
+
+    # 信号传递
+    on_read_param_signal = Signal()
+    on_write_param_signal = Signal()
+    on_exit_param_signal = Signal()
+
+    def __init__(self, parent=None):
+        super(Win_Protect, self).__init__(parent)
+        self.setupUi(self)
+
+        self.btn_read_param.clicked.connect(self.on_btn_read_param)
+        self.btn_write_param.clicked.connect(self.on_btn_write_param)
+        self.btn_exit_param.clicked.connect(self.on_btn_exit_param)
+        self.protect_table.itemClicked.connect(self._param_item_clicked)
+        self.qline_data_set.returnPressed.connect(self._protect_data_changed)
+
+
+    def on_btn_read_param(self):
+        self.on_read_param_signal.emit()
+
+
+    def on_btn_write_param(self):
+        self.on_write_param_signal.emit()
+
+    def on_btn_exit_param(self):
+        self.on_exit_param_signal.emit()
+
+    def _protect_data_changed(self):
+        value = (float(self.qline_data_set.text()) - float(self.qline_offset.text()))/float(self.qline_fbl.text())
+        self.qline_data.setText(str(value))
+
+
+    def _param_item_clicked(self, index):
+        self.qline_name.setText(self.protect_table.item(index.row(), 0).text())
+        self.qline_addr.setText(self.protect_table.item(index.row(), 3).text())
+        self.qline_data_long.setText(self.protect_table.item(index.row(), 5).text())
+        self.qline_fbl.setText(self.protect_table.item(index.row(), 6).text())
+        self.qline_offset.setText(self.protect_table.item(index.row(), 7).text())
+        self.qline_dw.setText(self.protect_table.item(index.row(), 2).text())
+        self.qline_data.setText(self.protect_table.item(index.row(), 8).text())
+        self.qline_data_set.setText(self.protect_table.item(index.row(), 1).text())
+
+
+    def set_error(self):
+        QMessageBox.critical(self, "错误" if SD.SYSTEM_LANGUAGE == 0 else "Error", "参数无效!" if SD.SYSTEM_LANGUAGE == 0 else "Param Error!")
+
+    def can_connect_error(self):
+        QMessageBox.critical(self, "连接状态" if SD.SYSTEM_LANGUAGE == 0 else "Connect State", "CAN 连接失败!" if SD.SYSTEM_LANGUAGE == 0 else "CAN Connect Error!")

+ 16 - 0
widget/bms_record.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.record import Record
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QLineSeries, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Record(Record, MyFrame):
+
+    def __init__(self, parent=None):
+        super(Win_Record, self).__init__(parent)
+        self.setupUi(self)

+ 16 - 0
widget/bms_set.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.set import Set
+from ui.own.frame_theme import MyFrame
+from ui.own.my_chart_view import MyChartView
+from utils.globalvar import SD
+from utils.qt import QLineSeries, QChart, QValueAxis, QHBoxLayout, QPainter, Qt, Signal, Slot, QLegendMarker
+
+
+class Win_Set(Set, MyFrame):
+
+    def __init__(self, parent=None):
+        super(Win_Set, self).__init__(parent)
+        self.setupUi(self)

+ 49 - 0
widget/bms_status_bar.py

@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+
+from ui.own.frame_theme import MyFrame
+from ui.statusbar import UiStatusBar
+from utils.globalvar import SD
+from utils.qt import QMessageBox, QFileDialog, QTimer, QDateTime
+
+
+class Win_Bms_Status_Bar(UiStatusBar, MyFrame):
+    def __init__(self, parent=None):
+        super(Win_Bms_Status_Bar, self).__init__(parent)
+        self.setupUi(self)
+        self.lb_bms_version.setText("V" + ''.join((str(SD.MAJOR_VERSION_NUMBER), '.', str(SD.MINOR_VERSION_NUMBER))))
+
+        self.timer = QTimer()
+        self.timer.timeout.connect(self._show_local_data_time)
+        self.timer.start(1000)
+        self._show_local_data_time()
+
+    def _show_local_data_time(self):
+        dataTime = QDateTime.currentDateTime()
+        text = dataTime.toString("yyyy-MM-dd HH:mm:ss")
+        self.lb_local_time.setText(text)
+
+    def bms_error(self):
+        QMessageBox.warning(self, "警告" if SD.SYSTEM_LANGUAGE == 0 else "Warning", "请连接BMS!" if SD.SYSTEM_LANGUAGE == 0 else "No BMS!")
+
+    def h86_error(self):
+        QMessageBox.critical(self, "错误" if SD.SYSTEM_LANGUAGE == 0 else "Error", "不是标准的h86文件!" if SD.SYSTEM_LANGUAGE == 0 else "H86 Error!")
+
+    def hex_error(self):
+        QMessageBox.critical(self, "错误" if SD.SYSTEM_LANGUAGE == 0 else "Error", "不是标准的hex文件!" if SD.SYSTEM_LANGUAGE == 0 else "Hex Error!")
+
+    def s19_error(self):
+        QMessageBox.critical(self, "错误" if SD.SYSTEM_LANGUAGE == 0 else "Error", "不是标准的s19文件!" if SD.SYSTEM_LANGUAGE == 0 else "S19 Error!")
+
+    def bmu_can_file(self):
+        return QFileDialog.getOpenFileName(self, "选取文件" if SD.SYSTEM_LANGUAGE == 0 else "Chose File", SD.FILE_PATH, "Text Files (*.hex)")
+
+    def ccu_can_file(self):
+        return QFileDialog.getOpenFileName(self, "选取文件" if SD.SYSTEM_LANGUAGE == 0 else "Chose File", SD.FILE_PATH, "Text Files (*.h86 , *.hex , *.s19)")
+
+    def bams_can_file(self):
+        return QFileDialog.getOpenFileName(self, "选取文件" if SD.SYSTEM_LANGUAGE == 0 else "Chose File", SD.FILE_PATH, "Text Files (*.hex)")
+
+    def bams_net_file(self):
+        return QFileDialog.getOpenFileName(self, "选取文件" if SD.SYSTEM_LANGUAGE == 0 else "Chose File", SD.FILE_PATH, "Text Files (*.bin)")

+ 0 - 0
worker/__init__.py


+ 388 - 0
worker/bms_work.py

@@ -0,0 +1,388 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@文件    :ccuWork.py
+@时间    :2021/12/09 08:31:48
+@作者    :None
+@版本    :1.0
+@说明    :二级BMS工作线程
+'''
+
+from utils.delay import m_delay
+from utils.globalvar import SD
+from utils.hex_bit import hex_bcd
+from utils.log_signal import LogSignal
+from utils.qt import QObject, Signal, QDateTime
+
+
+class BmsSend(QObject):
+
+    def __init__(self):
+        super(BmsSend, self).__init__()
+        self.page = 1
+
+    def send(self):
+        i = 0
+        while SD.START_RUN:
+            if SD.FRAM_READ_START:
+                if SD.FRAM_SEND_PAGE:
+                    self._fram_read(self.page)
+                    self.page += 1
+                    SD.FRAM_SEND_PAGE = False
+                else:
+                    if SD.FRAM_DELAY_TIME < 10000:
+                        m_delay(1)
+                        SD.FRAM_DELAY_TIME = SD.FRAM_DELAY_TIME + 1
+                    else:
+                        LogSignal.print_log_signal().log_emit("BCMU 铁电数据接收超时重发!" if SD.SYSTEM_LANGUAGE == 0 else "BCMU Fram Timeout!")
+                        self.page -= 1
+                        SD.FRAM_SEND_PAGE = True
+            else:
+                if SD.CCU_CHIP == 0 or SD.CCU_CHIP == 1:
+                    self._run_old()
+                elif SD.CCU_CHIP == 2:
+                    self._run_new(i)
+                    m_delay(100)
+                    self._run_relay(i)
+                    i = i + 1
+                    if i == 256:
+                        i = 0
+                if SD.LIFE_CTL == 2:
+                    self._life_date()
+                m_delay(1000)
+
+    def _fram_read(self, page):
+        data = []
+        if len(data) < 8:
+            data += (8 - len(data)) * [0]
+        data[0] = 0x01
+        data[1] = page & 0xFF
+        data[2] = (page & 0xFF00) >> 8
+        data[3] = 0x01
+        data[4] = 0xFF
+        data[5] = 0xFF
+        data[6] = 0xFF
+        data[7] = 0xFF
+        SD.CAN_CONTROL.send(0x1801B1C1, data, extern_flag=True)
+
+    def _run_old(self):
+        if SD.CCU_CHIP == 0:
+            id = 0x18F403F0
+        elif SD.CCU_CHIP == 1:
+            id = 0x18F403F0 | ((SD.BCU_ID & 0xF0) << 8) | (SD.BCU_ID & 0xF)
+        SD.CAN_CONTROL.send(id, [0x52, 0x55, 0x4E, 0, 0, 0, 0, 0xF5], extern_flag=True)
+
+    def _run_new(self, i):
+        data = []
+        if len(data) < 8:
+            data += (8 - len(data)) * [0]
+        data[0] = 2
+        data[1] = SD.SINGLE_ACQUISITION_OR_BALANCE
+        data[6] = i
+        data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+
+        SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x0020, data, extern_flag=True)
+
+    def _run_relay(self, i):
+        data = []
+        if len(data) < 8:
+            data += (8 - len(data)) * [0]
+        data[0] = 4
+        data[6] = i
+        data[7] = data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6]
+
+        SD.CAN_CONTROL.send((0x18 << 24) | (SD.BCU_ID << 16) | 0x0020, data, extern_flag=True)
+
+    def _life_date(self):
+        data = []
+        if len(data) < 8:
+            data += (8 - len(data)) * [0x00]
+        SD.CAN_CONTROL.send(0x18FF0000, data, extern_flag=True)
+
+
+class BmsReceived(QObject):
+
+    to_show_masterid_signal = Signal(int)
+    to_show_0000_signal = Signal(object)
+    to_show_0001_signal = Signal(object)
+    to_show_0002_signal = Signal(object)
+    to_show_0003_signal = Signal(object)
+    to_show_0004_signal = Signal(object)
+    to_show_0005_signal = Signal(object)
+    to_show_0006_signal = Signal(object)
+    to_show_0007_signal = Signal(object)
+    to_show_0008_signal = Signal(object)
+    to_show_0009_signal = Signal(object)
+    to_show_000A_signal = Signal(object)
+    to_show_000B_signal = Signal(object)
+    to_show_000C_signal = Signal(object)
+    to_show_000D_signal = Signal(object)
+    to_show_000E_signal = Signal(object)
+    to_show_000F_signal = Signal(object)
+    to_show_0010_signal = Signal(object)
+    to_show_0011_signal = Signal(object)
+    to_show_0012_signal = Signal(object)
+    to_show_0013_signal = Signal(object)
+    to_show_0014_signal = Signal(object)
+    to_show_0015_signal = Signal(object)
+    to_show_0016_signal = Signal(object)
+    to_show_0017_signal = Signal(object)
+    to_show_0018_signal = Signal(object)
+    to_show_0019_signal = Signal(object)
+    to_show_001A_signal = Signal(object)
+    to_show_001B_signal = Signal(object)
+    to_show_001C_signal = Signal(object)
+    to_show_001D_signal = Signal(object)
+    to_show_001E_signal = Signal(object)
+    to_show_001F_signal = Signal(object)
+    to_show_0020_signal = Signal(object)
+    to_show_0021_signal = Signal(object)
+    to_show_0022_signal = Signal(object)
+    to_show_0023_signal = Signal(object)
+
+    def __init__(self):
+        super(BmsReceived, self).__init__()
+
+        self.dantidianya = [0 for i in range(10000)]
+        self.dantiwendu = [0 for i in range(10000)]
+        self.masterVersion = ["" for i in range(18)]
+        self.fram_param = ["" for i in range(24)]
+        self.single_low_vol_x = ""
+        self.single_high_temp_x = ""
+
+    # 接收数据
+    def received(self):
+        while SD.CAN_ON_OFF:
+            result = SD.CAN_CONTROL.receive()
+            if (result[1]):
+                # ID主机号识别
+                if result[1] & 0xFFFF == 1:
+                    self.to_show_masterid_signal.emit((result[1] >> 16) & 0xFF)
+                # 0001
+                if result[1] == 0x18000000 | (SD.BCU_ID << 16):
+                    self.to_show_0000_signal.emit(result[2])
+                # 0001
+                if result[1] == 0x18000001 | (SD.BCU_ID << 16):
+                    self.to_show_0001_signal.emit(result[2])
+                # 0002  
+                elif result[1] == 0x18000002 | (SD.BCU_ID << 16):
+                    self.to_show_0002_signal.emit(result[2])
+                # 0003
+                elif result[1] == 0x18000003 | (SD.BCU_ID << 16):
+                    self.to_show_0003_signal.emit(result[2])
+                # 0004  
+                elif result[1] == 0x18000004 | (SD.BCU_ID << 16):
+                    self.to_show_0004_signal.emit(result[2])
+                # 0005
+                elif result[1] == 0x18000005 | (SD.BCU_ID << 16):
+                    self.to_show_0005_signal.emit(result[2])
+                # 0006  
+                elif result[1] == 0x18000006 | (SD.BCU_ID << 16):
+                    self.to_show_0006_signal.emit(result[2])
+                # 0007
+                elif result[1] == 0x18000007 | (SD.BCU_ID << 16):
+                    self.to_show_0007_signal.emit(result[2])
+                # 0008
+                elif result[1] == 0x18000008 | (SD.BCU_ID << 16):
+                    self.to_show_0008_signal.emit(result[2])
+                # 0009
+                elif result[1] == 0x18000009 | (SD.BCU_ID << 16):
+                    self.to_show_0009_signal.emit(result[2])
+                # 000A
+                elif result[1] == 0x1800000A | (SD.BCU_ID << 16):
+                    self.to_show_000A_signal.emit(result[2])
+                # 000B
+                elif result[1] == 0x1800000B | (SD.BCU_ID << 16):
+                    self.to_show_000B_signal.emit(result[2])
+                # 000C 
+                elif result[1] == 0x1800000C | (SD.BCU_ID << 16):
+                    self.to_show_000C_signal.emit(result[2])
+                # 000D
+                elif result[1] == 0x1800000D | (SD.BCU_ID << 16):
+                    self.to_show_000D_signal.emit(result[2])
+                # 000E
+                elif result[1] == 0x1800000E | (SD.BCU_ID << 16):
+                    self.to_show_000E_signal.emit(result[2])
+                # 000F
+                elif result[1] == 0x1800000F | (SD.BCU_ID << 16):
+                    self.to_show_000F_signal.emit(result[2])
+                # 0010
+                elif result[1] == 0x18000010 | (SD.BCU_ID << 16):
+                    self.to_show_0010_signal.emit(result[2])
+                # 0011
+                elif result[1] == 0x18000011 | (SD.BCU_ID << 16):
+                    self.to_show_0011_signal.emit(result[2])
+                # 0012
+                elif result[1] == 0x18000012 | (SD.BCU_ID << 16):
+                    self.to_show_0012_signal.emit(result[2])
+                # 0013
+                elif result[1] == 0x18000013 | (SD.BCU_ID << 16):
+                    self.to_show_0013_signal.emit(result[2])
+                # 0014
+                elif result[1] == 0x18000014 | (SD.BCU_ID << 16):
+                    self.to_show_0014_signal.emit(result[2])
+                # 0015
+                elif result[1] == 0x18000015 | (SD.BCU_ID << 16):
+                    self.to_show_0015_signal.emit(result[2])
+                # 0016
+                elif result[1] == 0x18000016 | (SD.BCU_ID << 16):
+                    self.to_show_0016_signal.emit(result[2])
+                # 0017
+                elif result[1] == 0x18000017 | (SD.BCU_ID << 16):
+                    self.to_show_0017_signal.emit(result[2])
+                # 0018
+                elif result[1] == 0x18000018 | (SD.BCU_ID << 16):
+                    self.to_show_0018_signal.emit(result[2])
+                # 0019
+                elif result[1] == 0x18000019 | (SD.BCU_ID << 16):
+                    self.to_show_0019_signal.emit(result[2])
+                # 001A
+                elif result[1] == 0x1800001A | (SD.BCU_ID << 16):
+                    self.to_show_001A_signal.emit(result[2])
+                # 001B
+                elif result[1] == 0x1800001B | (SD.BCU_ID << 16):
+                    self.to_show_001B_signal.emit(result[2])
+                # 001C
+                elif result[1] == 0x1800001C | (SD.BCU_ID << 16):
+                    self.to_show_001C_signal.emit(result[2])
+                # 001D
+                elif result[1] == 0x1800001D | (SD.BCU_ID << 16):
+                    self.to_show_001D_signal.emit(result[2])
+                # 001E
+                elif result[1] == 0x1800001E | (SD.BCU_ID << 16):
+                    self.to_show_001E_signal.emit(result[2])
+                # 001F
+                elif result[1] == 0x1800001F | (SD.BCU_ID << 16):
+                    self.to_show_001F_signal.emit(result[2])
+                # 0020
+                elif result[1] == 0x18000020 | (SD.BCU_ID << 16):
+                    self.to_show_0020_signal.emit(result[2])
+                # 0021
+                elif result[1] == 0x18000021 | (SD.BCU_ID << 16):
+                    self.to_show_0021_signal.emit(result[2])
+                # 0022
+                elif result[1] == 0x18000022 | (SD.BCU_ID << 16):
+                    self.to_show_0022_signal.emit(result[2])
+                # 0023
+                elif result[1] == 0x18000023 | (SD.BCU_ID << 16):
+                    self.to_show_0023_signal.emit(result[2])
+                    
+    # # 接收数据
+    # def received(self):
+    #     while SD.CAN_ON_OFF:
+    #         restNum = SD.CAN_CONTROL.get_undeal_number()
+    #         if restNum <= 0:
+    #             continue
+    #         revRet = SD.CAN_CONTROL.receive()
+    #         for i in revRet:
+    #             print(i)
+    #             if int(i.RemoteFlag) == 0:
+    #                 print(i.ID)
+    #                 # ID主机号识别
+    #                 if i.ID & 0xFFFF == 1:
+    #                     self.to_show_masterid_signal.emit((i.ID >> 16) & 0xFF)
+    #                 # 0001
+    #                 if i.ID == 0x18000001 | (SD.BCU_ID << 16):
+    #                     self.to_show_0001_signal.emit(i.Data)
+    #                 # 0002  
+    #                 elif i.ID == 0x18000002 | (SD.BCU_ID << 16):
+    #                     self.to_show_0002_signal.emit(i.Data)
+    #                 # 0003
+    #                 elif i.ID == 0x18000003 | (SD.BCU_ID << 16):
+    #                     self.to_show_0003_signal.emit(i.Data)
+    #                 # 0004  
+    #                 elif i.ID == 0x18000004 | (SD.BCU_ID << 16):
+    #                     self.to_show_0004_signal.emit(i.Data)
+    #                 # 0005
+    #                 elif i.ID == 0x18000005 | (SD.BCU_ID << 16):
+    #                     self.to_show_0005_signal.emit(i.Data)
+    #                 # 0006  
+    #                 elif i.ID == 0x18000006 | (SD.BCU_ID << 16):
+    #                     self.to_show_0006_signal.emit(i.Data)
+    #                 # 0007
+    #                 elif i.ID == 0x18000007 | (SD.BCU_ID << 16):
+    #                     self.to_show_0007_signal.emit(i.Data)
+    #                 # 0008
+    #                 elif i.ID == 0x18000008 | (SD.BCU_ID << 16):
+    #                     self.to_show_0008_signal.emit(i.Data)
+    #                 # 0009
+    #                 elif i.ID == 0x18000009 | (SD.BCU_ID << 16):
+    #                     self.to_show_0009_signal.emit(i.Data)
+    #                 # 000A
+    #                 elif i.ID == 0x1800000A | (SD.BCU_ID << 16):
+    #                     self.to_show_000A_signal.emit(i.Data)
+    #                 # 000B
+    #                 elif i.ID == 0x1800000B | (SD.BCU_ID << 16):
+    #                     self.to_show_000B_signal.emit(i.Data)
+    #                 # 000C 
+    #                 elif i.ID == 0x1800000C | (SD.BCU_ID << 16):
+    #                     self.to_show_000C_signal.emit(i.Data)
+    #                 # 000D
+    #                 elif i.ID == 0x1800000D | (SD.BCU_ID << 16):
+    #                     self.to_show_000D_signal.emit(i.Data)
+    #                 # 000E
+    #                 elif i.ID == 0x1800000E | (SD.BCU_ID << 16):
+    #                     self.to_show_000E_signal.emit(i.Data)
+    #                 # 000F
+    #                 elif i.ID == 0x1800000F | (SD.BCU_ID << 16):
+    #                     self.to_show_000F_signal.emit(i.Data)
+    #                 # 0010
+    #                 elif i.ID == 0x18000010 | (SD.BCU_ID << 16):
+    #                     self.to_show_0010_signal.emit(i.Data)
+    #                 # 0011
+    #                 elif i.ID == 0x18000011 | (SD.BCU_ID << 16):
+    #                     self.to_show_0011_signal.emit(i.Data)
+    #                 # 0012
+    #                 elif i.ID == 0x18000012 | (SD.BCU_ID << 16):
+    #                     self.to_show_0012_signal.emit(i.Data)
+    #                 # 0013
+    #                 elif i.ID == 0x18000013 | (SD.BCU_ID << 16):
+    #                     self.to_show_0013_signal.emit(i.Data)
+    #                 # 0014
+    #                 elif i.ID == 0x18000014 | (SD.BCU_ID << 16):
+    #                     self.to_show_0014_signal.emit(i.Data)
+    #                 # 0015
+    #                 elif i.ID == 0x18000015 | (SD.BCU_ID << 16):
+    #                     self.to_show_0015_signal.emit(i.Data)
+    #                 # 0016
+    #                 elif i.ID == 0x18000016 | (SD.BCU_ID << 16):
+    #                     self.to_show_0016_signal.emit(i.Data)
+    #                 # 0017
+    #                 elif i.ID == 0x18000017 | (SD.BCU_ID << 16):
+    #                     self.to_show_0017_signal.emit(i.Data)
+    #                 # 0018
+    #                 elif i.ID == 0x18000018 | (SD.BCU_ID << 16):
+    #                     self.to_show_0018_signal.emit(i.Data)
+    #                 # 0019
+    #                 elif i.ID == 0x18000019 | (SD.BCU_ID << 16):
+    #                     self.to_show_0019_signal.emit(i.Data)
+    #                 # 001A
+    #                 elif i.ID == 0x1800001A | (SD.BCU_ID << 16):
+    #                     self.to_show_001A_signal.emit(i.Data)
+    #                 # 001B
+    #                 elif i.ID == 0x1800001B | (SD.BCU_ID << 16):
+    #                     self.to_show_001B_signal.emit(i.Data)
+    #                 # 001C
+    #                 elif i.ID == 0x1800001C | (SD.BCU_ID << 16):
+    #                     self.to_show_001C_signal.emit(i.Data)
+    #                 # 001D
+    #                 elif i.ID == 0x1800001D | (SD.BCU_ID << 16):
+    #                     self.to_show_001D_signal.emit(i.Data)
+    #                 # 001E
+    #                 elif i.ID == 0x1800001E | (SD.BCU_ID << 16):
+    #                     self.to_show_001E_signal.emit(i.Data)
+    #                 # 001F
+    #                 elif i.ID == 0x1800001F | (SD.BCU_ID << 16):
+    #                     self.to_show_001F_signal.emit(i.Data)
+    #                 # 0020
+    #                 elif i.ID == 0x18000020 | (SD.BCU_ID << 16):
+    #                     self.to_show_0020_signal.emit(i.Data)
+    #                 # 0021
+    #                 elif i.ID == 0x18000021 | (SD.BCU_ID << 16):
+    #                     self.to_show_0021_signal.emit(i.Data)
+    #                 # 0022
+    #                 elif i.ID == 0x18000022 | (SD.BCU_ID << 16):
+    #                     self.to_show_0022_signal.emit(i.Data)
+    #                 # 0023
+    #                 elif i.ID == 0x18000023 | (SD.BCU_ID << 16):
+    #                     self.to_show_0023_signal.emit(i.Data)

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů