307 lines
11 KiB
Python
307 lines
11 KiB
Python
import time
|
||
from threading import Timer
|
||
|
||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||
from ui import Ui_Controller
|
||
|
||
import controller.controller_reifined as controller
|
||
|
||
class Window(QtWidgets.QMainWindow):
|
||
def __init__(self):
|
||
QtWidgets.QMainWindow.__init__(self)
|
||
self.ui = Ui_Controller()
|
||
self.ui.setupUi(self)
|
||
|
||
# controller
|
||
self.controller = controller.ControllerInterface(controller.ControllerRefined(0xFFFFFFFFFFFF, 0x112233445542))
|
||
|
||
# dev selection
|
||
self.hoverFilter = self.ComboBoxHoverEventFilter(self.ui.DeviceSelection, self.refreshDeviceList)
|
||
self.connected = False
|
||
|
||
# qt styles
|
||
self.redLineEdit = "QLineEdit { background: rgb(255, 0, 0); selection-background-color: rgb(111, 136, 222); }"
|
||
self.defLineEdit = "QLineEdit { }"
|
||
|
||
# button click times
|
||
self.last_click_time = 0
|
||
|
||
self.savedStatus = ""
|
||
|
||
# object containers
|
||
self.currentFields = [
|
||
self.ui.Current1Field,
|
||
self.ui.Current2Field,
|
||
self.ui.Current3Field,
|
||
self.ui.Current4Field,
|
||
]
|
||
|
||
# modes, currents, etc
|
||
self.modes = []
|
||
|
||
# connect signals
|
||
self.connectMethods()
|
||
|
||
def resetAllStyles(self) -> None:
|
||
for f in self.currentFields:
|
||
f.setStyleSheet(self.defLineEdit)
|
||
|
||
def clearAllFields(self) -> None:
|
||
for f in self.currentFields:
|
||
f.setText("")
|
||
self.ui.ModeSelection.clear()
|
||
self.ui.DmxAddressField.clear()
|
||
|
||
def resetStatus(self) -> None:
|
||
self.setStatus(self.savedStatus)
|
||
|
||
def setStatus(self, text: str) -> None :
|
||
print(text)
|
||
self.ui.Status.setText(text)
|
||
self.repaint()
|
||
|
||
def setTempStatus(self, new_status: str, reset_time: float) -> None:
|
||
if self.ui.Status.text() != new_status:
|
||
self.savedStatus = self.ui.Status.text()
|
||
self.setStatus(new_status)
|
||
Timer(reset_time, self.resetStatus).start()
|
||
|
||
def deviceSelected(self, deviceIndex: int):
|
||
device = self.ui.DeviceSelection.itemText(deviceIndex)
|
||
self.connected = False
|
||
self.resetAllStyles()
|
||
self.clearAllFields()
|
||
|
||
self.setStatus(f'Подключение к {device}...')
|
||
|
||
self.controller.close()
|
||
self.controller.connect(device)
|
||
|
||
print(device)
|
||
|
||
if self.readControllerCurrentsAndData():
|
||
self.setStatus(f'Выбранный порт: {device}')
|
||
self.connected = True
|
||
else:
|
||
self.setStatus(f'Не удалось подключиться к {device}')
|
||
self.ui.DeviceSelection.clear()
|
||
self.connected = False
|
||
self.controller.close()
|
||
|
||
def connectionLost(self) -> None:
|
||
self.controller.close()
|
||
self.setStatus('Пожалуйста, выберите порт')
|
||
self.setTempStatus(f'Подключение к {self.controller.controller.ser.port} потеряно!', 2)
|
||
self.resetAllStyles()
|
||
self.ui.DeviceSelection.clear()
|
||
self.clearAllFields()
|
||
|
||
def readControllerCurrentsAndData(self) -> bool:
|
||
self.setStatus(f'Чтение токов {self.controller.controller.ser.port}...')
|
||
values = self.controller.readCurrents()
|
||
|
||
if not values:
|
||
for f in self.currentFields:
|
||
f.setStyleSheet(self.redLineEdit)
|
||
else:
|
||
for i, f in enumerate(self.currentFields):
|
||
f.setStyleSheet(self.defLineEdit)
|
||
f.setText(str(values[i] * 10))
|
||
|
||
self.setStatus(f'Чтение адреса {self.controller.controller.ser.port}...')
|
||
address = self.controller.readAddress()
|
||
print(f'Address {address}')
|
||
|
||
if address == -1:
|
||
self.ui.DmxAddressField.setStyleSheet(self.redLineEdit)
|
||
else:
|
||
self.ui.DmxAddressField.setStyleSheet(self.defLineEdit)
|
||
self.ui.DmxAddressField.setText(str(address))
|
||
|
||
self.modes = []
|
||
|
||
self.setStatus(f'Чтение режимов {self.controller.controller.ser.port}...')
|
||
dev_info = self.controller.readDeviceInfo()
|
||
print(f'Dev info: {dev_info}')
|
||
if dev_info:
|
||
mode_count = dev_info[2]
|
||
for index in range(mode_count):
|
||
self.setStatus(f'Чтение режима {index + 1} {self.controller.controller.ser.port}...')
|
||
mode = self.controller.readMode(index)
|
||
if not mode:
|
||
self.modes = []
|
||
break
|
||
self.modes.append(mode)
|
||
time.sleep(0.05)
|
||
|
||
print(f'Dev info: {dev_info}')
|
||
if not self.modes:
|
||
self.ui.ModeSelection.clear()
|
||
self.ui.ModeSelection.setCurrentText('ERROR')
|
||
else:
|
||
self.ui.ModeSelection.setStyleSheet('QComboBox {}')
|
||
self.ui.ModeSelection.clear()
|
||
|
||
for m in self.modes:
|
||
self.ui.ModeSelection.addItem(m[1])
|
||
|
||
mode_names = []
|
||
for index, m in enumerate(self.modes):
|
||
mode_names.append(f'{index + 1}:{m[1]}')
|
||
|
||
self.ui.ModeSelection.clear()
|
||
self.ui.ModeSelection.addItems(mode_names)
|
||
self.ui.ModeSelection.setCurrentText(mode_names[dev_info[1] - 1])
|
||
else:
|
||
self.ui.ModeSelection.setStyleSheet(
|
||
'QComboBox { background: rgb(255, 0, 0); selection-background-color: rgb(111, 136, 222); }')
|
||
|
||
return values or address != -1 or self.modes
|
||
|
||
def writeCurrentsAddressAndMode(self) -> None:
|
||
toWrite = []
|
||
for f in self.currentFields:
|
||
x = f.text()
|
||
if x != "":
|
||
toWrite.append(int(x) // 10)
|
||
else:
|
||
toWrite.append(0)
|
||
|
||
(self.
|
||
setStatus(f'Запись токов в {self.controller.controller.ser.port}...'))
|
||
print(f'Writing... {toWrite}')
|
||
if not self.controller.writeCurrents(toWrite):
|
||
self.connectionLost()
|
||
return
|
||
|
||
self.setStatus(f'Запись адреса в {self.controller.controller.ser.port}...')
|
||
if self.ui.DmxAddressField.text() != "" and not self.controller.writeAddress(int(self.ui.DmxAddressField.text())):
|
||
self.connectionLost()
|
||
return
|
||
|
||
self.setStatus(f'Запись режима в {self.controller.controller.ser.port}...')
|
||
if not self.controller.writeMode(self.ui.ModeSelection.currentIndex() + 1):
|
||
self.connectionLost()
|
||
return
|
||
|
||
if not self.ui.Check.isChecked():
|
||
self.setStatus(f'Выбранный порт: {self.controller.controller.ser.port}')
|
||
self.setTempStatus(f'Данные были записаны в {self.controller.controller.ser.port}', 1)
|
||
else:
|
||
time.sleep(0.5)
|
||
dmx_save = self.ui.DmxAddressField.text()
|
||
pers_save = self.ui.ModeSelection.currentText()
|
||
currents_save = []
|
||
for entry in self.currentFields:
|
||
currents_save.append(entry.text())
|
||
|
||
self.setStatus(f'Чтение адреса: {self.controller.controller.ser.port}...')
|
||
dmx_real = self.controller.readAddress()
|
||
|
||
self.setStatus(f'Чтение режима: {self.controller.controller.ser.port}...')
|
||
dev_info = self.controller.readDeviceInfo()
|
||
|
||
self.setStatus(f'Чтение токов: {self.controller.controller.ser.port}...')
|
||
time.sleep(1)
|
||
|
||
currents_real = self.controller.readCurrents()
|
||
print(f'Save: {dmx_save}, {pers_save}, {currents_save}')
|
||
print(f'Real: {dmx_real}, {dev_info}, {currents_real}')
|
||
if dmx_real == -1 or not dev_info or not currents_real:
|
||
self.connectionLost()
|
||
return
|
||
|
||
pers_real = f'{dev_info[1]}:{self.modes[dev_info[1] - 1][1]}'
|
||
print(f'Pers real: {pers_real}')
|
||
failed = False
|
||
if dmx_save == "" or int(dmx_save) != dmx_real:
|
||
failed = True
|
||
self.ui.DmxAddressField.setStyleSheet(self.redLineEdit)
|
||
else:
|
||
self.ui.DmxAddressField.setStyleSheet(self.defLineEdit)
|
||
|
||
if pers_save != pers_real:
|
||
failed = True
|
||
self.ui.ModeSelection.clear()
|
||
self.ui.ModeSelection.setStyleSheet('QComboBox { background: rgb(255, 0, 0); selection-background-color: rgb(111, 136, 222); }')
|
||
else:
|
||
self.ui.ModeSelection.setStyleSheet('QComboBox {}')
|
||
|
||
for index in range(4):
|
||
if currents_save[index] == "" or int(currents_save[index]) != currents_real[index] * 10:
|
||
failed = True
|
||
print(f'Failed current: {index}')
|
||
self.currentFields[index].setStyleSheet(self.redLineEdit)
|
||
else:
|
||
self.currentFields[index].setStyleSheet(self.defLineEdit)
|
||
|
||
self.setStatus(f'Выбранный порт: {self.controller.controller.ser.port}')
|
||
if failed:
|
||
self.setTempStatus('Обнаружены ошибки, повторите запись', 1)
|
||
else:
|
||
self.setTempStatus('Проверка прошла успешно', 1)
|
||
|
||
def refreshDeviceList(self):
|
||
selected = self.ui.DeviceSelection.currentText()
|
||
self.ui.DeviceSelection.clear()
|
||
self.ui.DeviceSelection.addItems(self.controller.readComPorts())
|
||
self.ui.DeviceSelection.setCurrentText(selected)
|
||
|
||
def readCallback(self) -> None:
|
||
if time.time() - self.last_click_time < 1:
|
||
return
|
||
|
||
self.last_click_time = time.time()
|
||
|
||
if self.connected:
|
||
if not self.readControllerCurrentsAndData():
|
||
self.connectionLost()
|
||
return
|
||
|
||
self.setStatus(f'Выбранный порт: {self.controller.controller.ser.port}')
|
||
self.setTempStatus(f'Данные прочитаны, порт: {self.controller.controller.ser.port}', 1)
|
||
else:
|
||
self.setTempStatus('Порт не выбран!', 1)
|
||
|
||
def writeCallback(self) -> None:
|
||
if time.time() - self.last_click_time < 2:
|
||
return
|
||
|
||
self.last_click_time = time.time()
|
||
|
||
if self.connected:
|
||
self.writeCurrentsAddressAndMode()
|
||
else:
|
||
self.setTempStatus('Порт не выбран!', 1)
|
||
|
||
def connectMethods(self):
|
||
self.ui.DeviceSelection.activated.connect(self.deviceSelected)
|
||
self.ui.DeviceSelection.installEventFilter(self.hoverFilter)
|
||
self.ui.Read.clicked.connect(self.readCallback)
|
||
self.ui.Write.clicked.connect(self.writeCallback)
|
||
|
||
class ComboBoxHoverEventFilter(QtCore.QObject):
|
||
def __init__(self, parent, onEnter):
|
||
super().__init__(parent)
|
||
self.parent = parent
|
||
self.onEnter = onEnter
|
||
|
||
def eventFilter(self, obj, event):
|
||
if event.type() == QtCore.QEvent.Type.Enter:
|
||
self.onEnter()
|
||
return super().eventFilter(obj, event)
|
||
|
||
def start_ui() -> None:
|
||
import sys
|
||
app = QtWidgets.QApplication(sys.argv)
|
||
window = Window()
|
||
window.show()
|
||
sys.exit(app.exec())
|
||
|
||
def stress_test() -> None:
|
||
import tests
|
||
tests.start()
|
||
|
||
if __name__ == '__main__':
|
||
# start_ui()
|
||
stress_test() |