text: # -*- coding: utf-8 -*-
  """
  This module is full of dialog code(Are all based on QDialog)
  class:
      SetTimeDialog: Let the user enter the time
      WIFIDialog: Let the user enter SSID and password
      resultDialog: Tell the user about the results after performing the task
      RootDialog: UI interface in brush mode
  
      myDialog: A simple dialog box example
      MainWindow: Used for debugging dialogs
  """
  import sys
  import socket
  import hashlib
  from PySide2.QtCore import *
  from PySide2.QtWidgets import *
  from PySide2 import QtCore, QtGui, QtWidgets
  from tcp_server import SeverThreadForQT
  from lan_ewlink_api import *
  
  
  class SetTimeDialog(QDialog):
      """
      Let the user enter the time
      You can pass in the parameters in the initialization, the dialog box will be displayed,
      if not set all will be displayed as the default value
  
      function
          __init__: The UI that depicts the dialog box
                _________________ X
               | ( )ON   ( )OFF   |
               | min：————— |
               | sec：————— |
               | ( )+0.5s ( )0s   |
               --------------------
          rbclicked:
      """
  
      def __init__(self, parent=None, **reserved_vrg):
          super(SetTimeDialog, self).__init__(parent)
          if "min" in reserved_vrg:
              min = str(reserved_vrg["min"])
              sec = str(reserved_vrg["sec"])
              pulse = reserved_vrg["pulse"]
              sec_sta = reserved_vrg["sec_sta"]
          else:
              min = "59"
              sec = "59"
              sec_sta = True
              pulse = True
          # Sets the title and size of the dialog box
          self.setWindowTitle('Inching Settings')
          self.resize(200, 200)
          # Set the window to modal, and the user can only return to the main
          # interface after closing the popover
          self.setWindowModality(Qt.ApplicationModal)
          # Table layout used to layout QLabel and QLineEdit and QSpinBox
          grid = QGridLayout()
          self.rb01 = QRadioButton('Inching ON', self)
          self.rb02 = QRadioButton('Inching OFF', self)
          self.bg0 = QButtonGroup(self)
          self.bg0.addButton(self.rb01, 11)
          self.bg0.addButton(self.rb02, 12)
          if pulse:
              self.rb01.setChecked(True)
              self.set_sta = True
          else:
              self.rb02.setChecked(True)
              self.set_sta = False
  
          self.bg0.buttonClicked.connect(self.rbclicked)
          grid.addWidget(self.rb01, 0, 0, 1, 1)
          grid.addWidget(self.rb02, 0, 1, 1, 1)
  
          grid.addWidget(QLabel(u'mins(number)', parent=self), 1, 0, 1, 1)
          self.minute = QLineEdit(parent=self)
          self.minute.setText(min)
          grid.addWidget(self.minute, 1, 1, 1, 1)
          grid.addWidget(QLabel(u'sces(number)', parent=self), 2, 0, 1, 1)
          self.second = QLineEdit(parent=self)
          self.second.setText(sec)
          grid.addWidget(self.second, 2, 1, 1, 1)
  
          self.rb11 = QRadioButton('+0.5s', self)
          self.rb12 = QRadioButton('+0s', self)
          self.bg1 = QButtonGroup(self)
          self.bg1.addButton(self.rb11, 21)
          self.bg1.addButton(self.rb12, 22)
          grid.addWidget(self.rb11, 3, 0, 1, 1)
          grid.addWidget(self.rb12, 3, 1, 1, 1)
          if sec_sta:
              self.rb11.setChecked(True)
              self.second_point = True
          else:
              self.rb12.setChecked(True)
              self.second_point = False
          self.bg1.buttonClicked.connect(self.rbclicked)
  
          grid.addWidget(
              QLabel(
                  u'Inching duration range is 0:0.5 ~ 59:59.5\n with the interval of 0.5 sec.',
                  parent=self),
              4,
              0,
              2,
              2)
          # Create ButtonBox, and the user confirms and cancels
          buttonbox = QDialogButtonBox(parent=self)
          buttonbox.setOrientation(Qt.Horizontal)  # Set to horizontal
          buttonbox.setStandardButtons(
              QDialogButtonBox.Cancel | QDialogButtonBox.Ok)  # Ok and cancel two buttons
          # Connect the signal to the slot
          buttonbox.accepted.connect(self.accept)
          buttonbox.rejected.connect(self.reject)
          # Vertical layout, layout tables and buttons
          layout = QVBoxLayout()
          # Add the table layout you created earlier
          layout.addLayout(grid)
          # Put a space object to beautify the layout
          spacer_item = QSpacerItem(
              20, 48, QSizePolicy.Minimum, QSizePolicy.Expanding)
          layout.addItem(spacer_item)
          # ButtonBox
          layout.addWidget(buttonbox)
          self.setLayout(layout)
  
      def rbclicked(self):
          """
          Process radio check boxes
          :return:
          """
          print("sender")
          if self.bg0.checkedId() == 11:
              print("11")
              self.set_sta = True
          elif self.bg0.checkedId() == 12:
              print("12")
              self.set_sta = False
          else:
              # self.info1 = False
              pass
          if self.bg1.checkedId() == 21:
              print("21")
              self.second_point = True
          elif self.bg1.checkedId() == 22:
              print("22")
              self.second_point = False
          else:
              self.second_point = False
  
      def minute(self):
          """
          View the number of minutes the user entered
          :return:str
          """
          return self.minute.text()
  
      def second(self):
          """
          View the number of seconds the user entered
          :return: str
          """
          return self.second.text()
  
      def all_time(self):
          """
          Calculate all times entered by the user
          :return: int (Number of milliseconds)
          """
          input_min = self.minute.text()
          input_sec = self.second.text()
          if (input_sec.isdigit())and(input_min.isdigit()):
              min = int(input_min)
              sec = int(input_sec)
              print(min, sec)
              all_time = min * 60000 + sec * 1000
              if self.second_point:
                  all_time += 500
              if not (499 < all_time < 3600000):
                  all_time = 0
          else:
              return 0
          return all_time
  
  
  class WIFIDialog(QDialog):
      """
      Let the user enter the SSID and password for wifi
      """
  
      def __init__(self, parent=None):
          super(WIFIDialog, self).__init__(parent)
          # Sets the title and size of the dialog box
          self.setWindowTitle('Connect to a new WIFI')
          self.resize(200, 100)
          # Set the window to modal, and the user can only close the main
          # interface after closing the popover
          self.setWindowModality(Qt.ApplicationModal)
          # Table layout used to layout QLabel and QLineEdit and QSpinBox
          grid = QGridLayout()
          grid.addWidget(QLabel(u'SSID', parent=self), 0, 0, 1, 1)
          self.SSIDName = QLineEdit(parent=self)
          self.SSIDName.setText("SSID")
          grid.addWidget(self.SSIDName, 0, 1, 1, 1)
          grid.addWidget(QLabel(u'password', parent=self), 1, 0, 1, 1)
          self.WIFIpassword = QLineEdit(parent=self)
          self.WIFIpassword.setText("password")
          grid.addWidget(self.WIFIpassword, 1, 1, 1, 1)
          grid.addWidget(
              QLabel(
                  u'Please enter the SSID and password of the new wifi your device will connect.After connected,\n the '
                  u'device will no longer be on this LAN and info in the list will be refreshed in 5 mins.',
                  parent=self),
              2,
              0,
              2,
              2)
          # Create ButtonBox, and the user confirms and cancels
          buttonbox = QDialogButtonBox(parent=self)
          buttonbox.setOrientation(Qt.Horizontal)
          buttonbox.setStandardButtons(
              QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
          buttonbox.accepted.connect(self.accept)
          buttonbox.rejected.connect(self.reject)
          # Vertical layout, layout tables and buttons
          layout = QVBoxLayout()
          # Add the table layout you created earlier
          layout.addLayout(grid)
          # Put a space object to beautify the layout
          spacer = QSpacerItem(
              20, 48, QSizePolicy.Minimum, QSizePolicy.Expanding)
          layout.addItem(spacer)
          # ButtonBox
          layout.addWidget(buttonbox)
          self.setLayout(layout)
  
      def name(self):
          """
          :return: (str)SSID of user input
          """
          return self.SSIDName.text()
  
      def password(self):
          """
          :return:(str)WIFI password of user input
          """
          return self.WIFIpassword.text()
  
  
  class resultDialog(QDialog):
      """
      Result dialog box, Used to display the results after execution
      __init__(**info)
              info{id: successful/failure}
  
      """
  
      def __init__(self, parent=None, **info):
          super(resultDialog, self).__init__(parent)
          print("后：%s" % str(info["info"]))
          all_info = info["info"]
          self.setWindowTitle('result')
          self.resize(200, 100)
          self.setWindowModality(Qt.ApplicationModal)
          grid = QGridLayout()
          num = 0
          for x in all_info.keys():
              print(x)
              sub_name = QLabel(parent=self)
              sub_name.setText(x)
              grid.addWidget(sub_name, num, 0, 1, 1)
              sub_ret = QLabel(parent=self)
              sub_ret.setText(all_info[x])
              grid.addWidget(sub_ret, num, 1, 1, 1)
              num += 1
          buttonbox = QDialogButtonBox(parent=self)
          buttonbox.setOrientation(Qt.Horizontal)
          buttonbox.setStandardButtons(
              QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
          buttonbox.accepted.connect(self.accept)
          buttonbox.rejected.connect(self.reject)
          layout = QVBoxLayout()
          layout.addLayout(grid)
          spacerItem = QSpacerItem(
              20, 48, QSizePolicy.Minimum, QSizePolicy.Expanding)
          layout.addItem(spacerItem)
          layout.addWidget(buttonbox)
          self.setLayout(layout)
  
  
  class myDialog(QDialog):
      """
      An example of a dialog box
      """
  
      def __init__(self, parent=None):
          super(myDialog, self).__init__(parent)
          # Sets the title and size of the dialog box
          self.setWindowTitle('myDialog')
          self.resize(200, 100)
          # Set the window to modal, and the user can only close the main
          # interface after closing the popover
          self.setWindowModality(Qt.ApplicationModal)
          # Table layout used to layout QLabel and QLineEdit and QSpinBox
          grid = QGridLayout()
          grid.addWidget(QLabel(u'SSID', parent=self), 0, 0, 1, 1)
          self.SSIDName = QLineEdit(parent=self)
          self.SSIDName.setText("wifi")
          grid.addWidget(self.SSIDName, 0, 1, 1, 1)
          grid.addWidget(QLabel(u'password', parent=self), 1, 0, 1, 1)
          self.WIFIpassword = QLineEdit(parent=self)
          self.WIFIpassword.setText("password")
          grid.addWidget(self.WIFIpassword, 1, 1, 1, 1)
          grid.addWidget(QLabel(u'password', parent=self), 2, 0, 2, 2)
          # Create ButtonBox, and the user confirms and cancels
          buttonbox = QDialogButtonBox(parent=self)
          buttonbox.setOrientation(Qt.Horizontal)
          buttonbox.setStandardButtons(
              QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
          buttonbox.accepted.connect(self.accept)
          buttonbox.rejected.connect(self.reject)
          # Vertical layout, layout tables and buttons
          layout = QVBoxLayout()
          # Add the table layout you created earlier
          layout.addLayout(grid)
          # Put a space object to beautify the layout
          spacerItem = QSpacerItem(
              20, 48, QSizePolicy.Minimum, QSizePolicy.Expanding)
          layout.addItem(spacerItem)
          # ButtonBox
          layout.addWidget(buttonbox)
          self.setLayout(layout)
  
      def name(self):
          return self.SSIDName.text()
  
      def password(self):
          return self.WIFIpassword.text()
  
  
  class RootDialog(QDialog):
      """
      Root main interface window( All device information)
      1.Create server thread(Wait for the device to get the data)
      2.Send the unlock command to the device
      """
  
      def __init__(self, parent=None, **ccs):
          super(RootDialog, self).__init__(parent)
          self.file_flg = False
          self.dev_flg = False
          print(str(ccs))
          if "b" not in ccs:
              self.all_sub = []
          else:
              self.all_sub = ccs["b"]
          # Sets the title and size of the dialog box
          self.setWindowTitle('Root')
          self.resize(445, 302)
          # Set the window to modal, and the user can only close the main
          # interface after closing the popover
          self.setWindowModality(Qt.ApplicationModal)
          # Table layout used to layout QLabel and QLineEdit and QSpinBox
          self.gridLayoutWidget = QtWidgets.QWidget(self)
          self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 1, 431, 291))
          self.gridLayoutWidget.setObjectName("gridLayoutWidget")
          self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
          self.gridLayout.setContentsMargins(0, 0, 0, 0)
          self.gridLayout.setVerticalSpacing(6)
          self.gridLayout.setObjectName("gridLayout")
          self.lineEdit_firmware = QtWidgets.QLineEdit(self.gridLayoutWidget)
          self.lineEdit_firmware.setObjectName("lineEdit_firmware")
          self.gridLayout.addWidget(self.lineEdit_firmware, 1, 1, 1, 1)
          self.horizontalLayout = QtWidgets.QHBoxLayout()
          self.horizontalLayout.setObjectName("horizontalLayout")
          self.pB_OK = QtWidgets.QPushButton(self.gridLayoutWidget)
          self.pB_OK.setObjectName("pB_OK")
          self.horizontalLayout.addWidget(self.pB_OK)
          self.pB_Cencel = QtWidgets.QPushButton(self.gridLayoutWidget)
          self.pB_Cencel.setObjectName("pB_Cencel")
          self.horizontalLayout.addWidget(self.pB_Cencel)
          self.gridLayout.addLayout(self.horizontalLayout, 5, 1, 1, 2)
          self.root_progressBar = QtWidgets.QProgressBar(self.gridLayoutWidget)
          self.root_progressBar.setProperty("value", 0)
          self.root_progressBar.setObjectName("root_progressBar")
          self.gridLayout.addWidget(self.root_progressBar, 6, 1, 1, 2)
          self.pB_import_firmware = QtWidgets.QPushButton(self.gridLayoutWidget)
          self.pB_import_firmware.setObjectName("pB_import_firmware")
          self.gridLayout.addWidget(self.pB_import_firmware, 1, 2, 1, 1)
          self.label_3 = QtWidgets.QLabel(self.gridLayoutWidget)
          self.label_3.setObjectName("label_3")
          self.gridLayout.addWidget(self.label_3, 4, 0, 1, 1)
          self.label = QtWidgets.QLabel(self.gridLayoutWidget)
          self.label.setObjectName("label")
          self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
          self.label_4 = QtWidgets.QLabel(self.gridLayoutWidget)
          self.label_4.setObjectName("label_4")
          self.gridLayout.addWidget(self.label_4, 6, 0, 1, 1)
          self.textBrowser = QtWidgets.QTextBrowser(self.gridLayoutWidget)
          sizePolicy = QtWidgets.QSizePolicy(
              QtWidgets.QSizePolicy.Preferred,
              QtWidgets.QSizePolicy.Preferred)
          sizePolicy.setHorizontalStretch(0)
          sizePolicy.setVerticalStretch(0)
          sizePolicy.setHeightForWidth(
              self.textBrowser.sizePolicy().hasHeightForWidth())
          self.textBrowser.setSizePolicy(sizePolicy)
          self.textBrowser.setObjectName("textBrowser")
          self.gridLayout.addWidget(self.textBrowser, 4, 1, 1, 2)
          self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget)
          self.label_2.setObjectName("label_2")
          self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
          self.pB_get_device = QtWidgets.QPushButton(self.gridLayoutWidget)
          self.pB_get_device.setObjectName("pB_get_device")
          self.gridLayout.addWidget(self.pB_get_device, 2, 2, 1, 1)
          self.cBox_Dev = QtWidgets.QComboBox(self.gridLayoutWidget)
          self.cBox_Dev.setObjectName("cBox_Dev")
          self.gridLayout.addWidget(self.cBox_Dev, 2, 1, 1, 1)
          self.label_5 = QtWidgets.QLabel(self.gridLayoutWidget)
          font = QtGui.QFont()
          font.setPointSize(14)
          self.label_5.setFont(font)
          self.label_5.setLayoutDirection(QtCore.Qt.LeftToRight)
          self.label_5.setAlignment(QtCore.Qt.AlignCenter)
          self.label_5.setObjectName("label_5")
          self.gridLayout.addWidget(self.label_5, 0, 0, 1, 3)
          self.retranslateUi()
          self.fresh_box()
          # Connect the signal to the slot
          self.cBox_Dev.currentIndexChanged.connect(self.select_port)
          self.pB_get_device.clicked.connect(self.fresh_box)
          self.pB_import_firmware.clicked.connect(self.choose_img)
          self.pB_OK.clicked.connect(self.start_root)
          self.pB_Cencel.clicked.connect(self.reject)
  
      def retranslateUi(self):
          self.setWindowTitle(QtWidgets.QApplication.translate(
              "Dialog", "DIY Flash Firmware TOOL", None, -1))
          self.pB_OK.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "OK", None, -1))
          self.pB_Cencel.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Cancel", None, -1))
          self.pB_import_firmware.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Import firmware", None, -1))
          self.label_3.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", " Warning ", None, -1))
          self.label.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Firmware", None, -1))
          self.label_4.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Progress", None, -1))
          self.textBrowser.setHtml(
              QtWidgets.QApplication.translate(
                  "Dialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                  "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                  "p, li { white-space: pre-wrap; }\n"
                  "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                  "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:11pt;\">Flashing firmware will void your warranty.By clicking \'OK\',you accept voiding the warranty on this device. To avoid bricking, do not power off,restart the device,disconnect it from network, restart LAN router, change IP or port on your PC or close this program during installation. </span></p></body></html>", None, -1))
          self.label_2.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Device", None, -1))
          self.pB_get_device.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "Flash device list", None, -1))
          self.label_5.setText(
              QtWidgets.QApplication.translate(
                  "Dialog", "DIY Flash Firmware TOOL", None, -1))
  
      def fresh_box(self):
          """
          Refresh device options
          :return: None
          """
          self.dev_flg = False
          self.cBox_Dev.clear()
          print(self.all_sub)
          if len(self.all_sub) <= 0:
              QMessageBox.critical(
                  "Unable to find device, please exit retry", 10000)
              print("Unable to find device, please exit retry")
          else:
              for x in self.all_sub:
                  self.cBox_Dev.addItems([x])
  
      def check_port(self):
          """
          Test which ports are available[80, 1080, 8888, 6666, 9999]
          :return: (int)Available ports
          """
          port_number = [80, 1080, 8888, 6666, 9999]
          for index in port_number:
              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              result = sock.connect_ex(('127.0.0.1', index))
              sock.close()
              if result == 0:
                  print("Port %d is open" % index)
              else:
                  print("Port %d is not open" % index)
                  return index
          return 0
  
      def choose_img(self):
          """
          Select the firmware
                  Select the firmware, copy the user's firmware to the current working directory,
                  and calculate the SHA256 value of the file, and verify whether the file is Dout,
                  and the firmware size is less than 508k,
                  and whether it is a ".bin "file
          :return:
          """
          dlg = QFileDialog()
          dlg.setFileMode(QFileDialog.AnyFile)
          dlg.setFilter(QDir.Files)
          if dlg.exec_():
              filenames = dlg.selectedFiles()
              imgfile = filenames[0]
              self.lineEdit_firmware.clear()
              # whether it is a ".bin "file
              if ".bin" not in imgfile:
                  QMessageBox.information(
                      self,
                      "ERROR",
                      "The firmware selected is not a bin file",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
                  return
              #
              if self.get_file_to_work(imgfile):
                  try:
                      with open("itead.bin", 'rb') as file_obj:
                          self.img = file_obj.read()
                          print(type(self.img))
                          print(len(self.img))
                          sha256 = hashlib.sha256(self.img)
                          self.imgsha256 = sha256.hexdigest()
                          print(self.imgsha256)
                          self.lineEdit_firmware.setText(imgfile)
                          self.file_flg = True
                  except BaseException:
                      print("unknown err")
              else:
                  QMessageBox.information(
                      self,
                      "ERROR",
                      "Firmware file cannot be greater than 508k; The firmware must be Dout",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
  
      def get_file_to_work(self, bin_file):
          """
          calculate the SHA256 value of the file, and verify whether the file is Dout,
          and the firmware size is less than 508k,
          """
          try:
              with open(bin_file, 'rb') as file_obj:
                  b = bytearray(file_obj.read())
                  if (b[2] == 3)and(len(b) < 508000):
                      file_obj.seek(0, 0)
                      img = file_obj.read()
                  else:
                      return False
          except BaseException:
              print("unknown err")
              return False
          bin_obj = open("itead.bin", 'wb')
          bin_obj.write(img)
          return True
  
      def select_port(self):
          """
          Confirm the selected user
          :return:
          """
          id = self.cBox_Dev.currentText()
          if len(id) <= 1:
              return
          self.dev_flg = True
          new = "The currently selected device id is" + id
          QMessageBox.information(
              self,
              "tips",
              new,
              QMessageBox.Yes,
              QMessageBox.Yes)
          self.sub_id = [id]
  
      def start_root(self):
          # Check if conditions are met
          if not self.file_flg:
              QMessageBox.information(
                  self,
                  "Insufficient conditions",
                  "Missing firmware file！",
                  QMessageBox.Yes,
                  QMessageBox.Yes)
              return
          if not self.dev_flg:
              QMessageBox.information(
                  self,
                  "Insufficient conditions",
                  "No device selected yet！",
                  QMessageBox.Yes,
                  QMessageBox.Yes)
              return
          # Create a QT thread to transfer firmware to the device
          myport = self.check_port()
          myaddr = self.get_dev_ip_for_lan()
          # print("Host information：",myname,myaddr,str(myport))
          print("Server initialization complete")
          self.control_server_Thread = SeverThreadForQT(
              server_port=myport, server_ip=myaddr)
          # Lock button
          self.pB_get_device.setDisabled(1)
          self.pB_import_firmware.setDisabled(1)
          self.pB_OK.setDisabled(1)
          self.pB_Cencel.setDisabled(1)
          # Send an unlocked device upgrade
          self.send_unlock(self.sub_id, self.imgsha256, myaddr, myport)
  
      def get_host_ip(self):
          """
          Query the native IP address
          :return: ip
          """
          try:
              s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
              s.connect(('8.8.8.8', 80))
              ip = s.getsockname()[0]
          except BaseException:
              s.close()
              return self.getText()
          finally:
              s.close()
          return ip
  
      def get_dev_ip_for_lan(self):
          """
          Query the native IP address
          :return: ip
          """
          try:
              myname = socket.getfqdn(socket.gethostname())
              myaddr = socket.gethostbyname_ex(myname)
              print(myaddr)
              all_adds = myaddr[2]
              print("self.all_sub", self.all_sub)
              sub_info = self.all_sub[self.sub_id[0]]
              sub_ip = sub_info["ip"]
              for x in all_adds:
                  print(x)
                  if x[:10] in sub_ip[:10]:
                      return x
              return all_adds[0]
          except BaseException:
              return self.get_host_ip()
  
      def send_unlock(self, sub_id, sha256, sever_ip, sever_port):
          """
          Send the unlock command to the device
          :param sub_id: The device ID number to unlock
          :param sha256: The SHA256 value of the firmware
          :param sever_ip: The IP address of the server
          :param sever_port: Server port
          :return:
          """
          print("unlock SUB：", sub_id)
          dicta = {"info": self.all_sub, "select_name_list": sub_id}
          pass
          dicta["command_num"] = 7
          vrg = {}
          command_vrg = {}
          pass
          command_vrg["sha256sum"] = sha256
          command_vrg["sever_ip"] = sever_ip
          command_vrg["sever_port"] = sever_port
          vrg["command_vrg"] = command_vrg
          dicta["command_vrg"] = vrg
          self.myThread = ThreadForQT(parent=None, **dicta)
          self.myThread.run_test_Thread.connect(self.do_unlock_result)
          self.myThread.start()
  
      def do_unlock_result(self, result_str):
          """
          To understand the return value of the lock instruction
          :param result_str: Unlock the message sent by the thread
          :return:
          """
          if "END" in result_str:
              # self.ui.pushButton.setDisabled(0)
              return
          result_list = result_str.split("\n")
          print("The return value is received：", result_list)
          if result_list[1] is "0":
              # Perform an
              self.control_server_Thread.ota_state_Thread.connect(
                  self.updata_ota)
              self.control_server_Thread.start()
          else:
              # Send unlocking failure (prompt for network connection)(close the
              # server)
              QMessageBox.information(
                  self,
                  "Send unlock failed",
                  "Please check your network connection and retry.！",
                  QMessageBox.Yes,
                  QMessageBox.Yes)
  
      def getText(self):
          """
          When the IP address cannot be automatically obtained by the user's computer,
          the IP address will be manually entered by the user to create the server
          :return: str The IP address entered by the user
          """
          text, okPressed = QInputDialog.getText(
              self, "not find ip ", "Your PC ip:", QLineEdit.Normal, "")
          if okPressed and text != '':
              print(text)
              return text
  
      def updata_ota(self, result_new):
          """
          Process information for server threads
          :param result_new: Message from the server thread
          :return:
          """
          result_vrg = result_new.split("\n")
          print(result_vrg)
          result_num = int(result_vrg[2].split(".")[0])
          if "get" in result_vrg:
              self.root_progressBar.setProperty("value", result_num)
          elif "post" in result_vrg:
              print("The return value is received：", str(result_num))
              self.pB_get_device.setDisabled(0)
              self.pB_import_firmware.setDisabled(0)
              self.pB_OK.setDisabled(0)
              self.pB_Cencel.setDisabled(0)
              if result_num == 0:
                  # Prompt upgrade successful
                  QMessageBox.information(
                      self,
                      "Data sent successfully",
                      "Please wait for the device to restart.\nDo not power off or restart the device manually, \
                      but you may close this window now. ",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
              elif result_num == 1:
                  # Prompt upgrade failed
                  QMessageBox.information(
                      self,
                      "error",
                      "Please wait for the device to restart！",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
              elif result_num == 404:
                  # Prompt upgrade failed
                  QMessageBox.information(
                      self,
                      "error",
                      "Data download error 404！",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
              elif result_num == 406:
                  # Prompt upgrade failed
                  QMessageBox.information(
                      self,
                      "error",
                      "Upgrade failed！",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
              elif result_num == 409:
                  # Prompt upgrade failed
                  QMessageBox.information(
                      self,
                      "error",
                      "Data verification failed！",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
              elif result_num == 410:
                  # Prompt upgrade failed
                  QMessageBox.information(
                      self,
                      "error",
                      "Device error！",
                      QMessageBox.Yes,
                      QMessageBox.Yes)
          elif "ERR" in result_vrg:
              self.pB_Cencel.setDisabled(0)
              QMessageBox.information(
                  self,
                  "!!!!!!!!!!",
                  "Please make sure the connection between the device and your PC is working correctly.\
                  (Don\'t power off or restart the device, close the upgrade window, or change the IP \
                  or port on your PC)！",
                  QMessageBox.Yes,
                  QMessageBox.Yes)
  
  
  class MainWindow(QMainWindow):
      """
      Single-module debugging classes
      """
  
      def __init__(self, parent=None):
          super(MainWindow, self).__init__(parent)
          # Sets the title and size of the main window
          self.setWindowTitle('The main window')
          self.resize(400, 300)
          # Create button
          self.btn = QPushButton(self)
          self.btn.setText('Popup dialog')
          self.btn.move(50, 50)
          self.btn.clicked.connect(self.show_dialog1)
  
      def show_dialog1(self):
          all_dev = ["First", "second", "third", "more"]
          self.dialog = RootDialog(b=all_dev)
          self.dialog.show()
          ret = self.dialog.exec_()
          print(ret)
          if ret:
              print(self.dialog.name())
              print(self.dialog.password())
          self.dialog.destroy()
  
      def show_WIFIDialog(self):
          self.dialog = WIFIDialog()
          self.dialog.show()
          ret = self.dialog.exec_()
          print(ret)
          if ret:
              print(self.dialog.name())
              print(self.dialog.password())
          self.dialog.destroy()
  
      def show_dialog(self):
          self.dialog = SetTimeDialog()
          self.dialog.show()
          ret = self.dialog.exec_()
          print("ret:", ret)
          if ret:
              print(self.dialog.all_time())
          self.dialog.destroy()
  
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
      demo = MainWindow()
      demo.show()
      sys.exit(app.exec_())
  