Final goyda
This commit is contained in:
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
@ -169,11 +169,20 @@ class ControllerInterface:
|
|||||||
error(e)
|
error(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def sendPacketWithResponse(self, command_code: int, target: tuple, data: list, throw_if_error=False) -> list:
|
def sendPacketWithResponse(self, command_code: int, target: tuple, data: list, throw_if_error=False, retry=2) -> list:
|
||||||
try:
|
try:
|
||||||
|
for i in range(retry):
|
||||||
|
debug(f'Try #{i}')
|
||||||
self.controller.sendRequest(command_code, target, data)
|
self.controller.sendRequest(command_code, target, data)
|
||||||
self.controller.packet_id = (self.controller.packet_id + 1) % 255
|
self.controller.packet_id = (self.controller.packet_id + 1) % 255
|
||||||
return self.controller.readData()
|
res = self.controller.readData()
|
||||||
|
debug(f'Read data: {res}')
|
||||||
|
if res:
|
||||||
|
return res
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
debug(f'Failed after {retry} tries')
|
||||||
|
return []
|
||||||
except SerialException or IndexError as e:
|
except SerialException or IndexError as e:
|
||||||
error(e)
|
error(e)
|
||||||
if throw_if_error:
|
if throw_if_error:
|
||||||
@ -280,7 +289,7 @@ class ControllerInterface:
|
|||||||
if not mode:
|
if not mode:
|
||||||
return []
|
return []
|
||||||
modes.append(mode)
|
modes.append(mode)
|
||||||
time.sleep(0.05)
|
time.sleep(0.1) # TODO CHECK
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for m in modes:
|
for m in modes:
|
||||||
|
485
final.py
Normal file
485
final.py
Normal file
@ -0,0 +1,485 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from logging import debug, info
|
||||||
|
from threading import Timer
|
||||||
|
|
||||||
|
from PyQt6 import QtCore, QtWidgets, QtGui
|
||||||
|
from PyQt6.QtCore import QRegularExpression
|
||||||
|
from PyQt6.QtGui import QRegularExpressionValidator
|
||||||
|
|
||||||
|
import controller.controller_reifined as controller
|
||||||
|
from all import Ui_Controller
|
||||||
|
|
||||||
|
|
||||||
|
class Window(QtWidgets.QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
QtWidgets.QMainWindow.__init__(self)
|
||||||
|
|
||||||
|
self.ui = Ui_Controller()
|
||||||
|
self.ui.setupUi(self)
|
||||||
|
|
||||||
|
self.controller = controller.ControllerInterface(controller.ControllerRefined(0xFFFFFFFFFFFF, 0x112233445542))
|
||||||
|
self.device = ""
|
||||||
|
|
||||||
|
# dev selection
|
||||||
|
self.hoverFilter = self.ComboBoxHoverEventFilter(self.ui.DeviceSelection, self.refreshDeviceList)
|
||||||
|
self.connected = False
|
||||||
|
|
||||||
|
# object containers
|
||||||
|
self.currentFields = [self.ui.Current1Field, self.ui.Current2Field, self.ui.Current3Field, self.ui.Current4Field]
|
||||||
|
self.voltageFields = [self.ui.Voltage1Field, self.ui.Voltage2Field, self.ui.Voltage3Field, self.ui.Voltage4Field]
|
||||||
|
|
||||||
|
# qt styles
|
||||||
|
self.redLineEdit = "QLineEdit { background: rgb(255, 0, 0); selection-background-color: rgb(111, 136, 222); }"
|
||||||
|
self.disLineEdit = "QLineEdit { background: rgb(117, 116, 114); selection-background-color: rgb(117, 116, 114); }"
|
||||||
|
self.defLineEdit = "QLineEdit {}"
|
||||||
|
self.redCombobox = "QComboBox { background: rgb(255, 0, 0); selection-background-color: rgb(111, 136, 222); }"
|
||||||
|
self.defCombobox = "QComboBox {}"
|
||||||
|
|
||||||
|
# Other state vars
|
||||||
|
self.last_click_time = 0
|
||||||
|
self.savedStatus = ""
|
||||||
|
self.modes = []
|
||||||
|
|
||||||
|
# Mode table fields
|
||||||
|
self.imageDialog = None
|
||||||
|
self.imageLabel = None
|
||||||
|
self.pixmap = None
|
||||||
|
|
||||||
|
|
||||||
|
# connect signals and validation
|
||||||
|
self.connectMethods()
|
||||||
|
self.applyValidators()
|
||||||
|
|
||||||
|
def connectMethods(self):
|
||||||
|
self.ui.DeviceSelection.activated.connect(self.deviceSelectionCallback)
|
||||||
|
self.ui.DeviceSelection.installEventFilter(self.hoverFilter)
|
||||||
|
self.ui.Read.clicked.connect(self.readCallback)
|
||||||
|
self.ui.Write.clicked.connect(self.writeCallback)
|
||||||
|
self.ui.ModeInfo.clicked.connect(self.showModeTable)
|
||||||
|
|
||||||
|
def applyValidators(self):
|
||||||
|
# 1 - 511
|
||||||
|
self.ui.DmxAddressField.setValidator(QRegularExpressionValidator(QRegularExpression("^([1-9]|[1-9][0-9]|[1-4][0-9]{2}|50[0-9]|511)$")))
|
||||||
|
|
||||||
|
# 100 - 2550
|
||||||
|
for f in self.currentFields:
|
||||||
|
f.setValidator(QRegularExpressionValidator(
|
||||||
|
QRegularExpression("^(?:[1-9][0-9]{2}|1[0-9]{3}|2[0-4][0-9]{2}|25[0-4][0-9]|2550)$")))
|
||||||
|
|
||||||
|
# 2 - 60
|
||||||
|
for f in self.voltageFields:
|
||||||
|
f.setValidator(QRegularExpressionValidator(
|
||||||
|
QRegularExpression("^(?:[2-9]|[1-5][0-9]|60)$")))
|
||||||
|
|
||||||
|
# 5 - 255
|
||||||
|
self.ui.PowerField.setValidator(QRegularExpressionValidator(
|
||||||
|
QRegularExpression("^(?:[5-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")))
|
||||||
|
|
||||||
|
def resetAllStyles(self) -> None:
|
||||||
|
for f in self.currentFields:
|
||||||
|
f.setStyleSheet(self.defLineEdit)
|
||||||
|
for f in self.voltageFields:
|
||||||
|
f.setStyleSheet(self.defLineEdit)
|
||||||
|
|
||||||
|
self.ui.ModeSelection.setStyleSheet(self.defCombobox)
|
||||||
|
self.ui.PDop.setStyleSheet(self.defLineEdit)
|
||||||
|
self.ui.DmxAddressField.setStyleSheet(self.defLineEdit)
|
||||||
|
|
||||||
|
def clearAllFields(self) -> None:
|
||||||
|
self.ui.DmxAddressField.clear()
|
||||||
|
self.ui.ModeSelection.clear()
|
||||||
|
|
||||||
|
for f in self.currentFields:
|
||||||
|
f.setText("")
|
||||||
|
f.setReadOnly(False)
|
||||||
|
|
||||||
|
for f in self.voltageFields:
|
||||||
|
f.setText("")
|
||||||
|
f.setReadOnly(False)
|
||||||
|
|
||||||
|
self.ui.PowerField.setText("")
|
||||||
|
self.ui.PowerField.setReadOnly(False)
|
||||||
|
|
||||||
|
def resetStatus(self) -> None:
|
||||||
|
self.setStatus(self.savedStatus)
|
||||||
|
|
||||||
|
def setStatus(self, text: str) -> None:
|
||||||
|
print(text)
|
||||||
|
self.ui.Status.setText(text)
|
||||||
|
|
||||||
|
app.processEvents()
|
||||||
|
|
||||||
|
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 setText(self, field, text) -> None:
|
||||||
|
field.setReadOnly(False)
|
||||||
|
field.setStyleSheet(self.defLineEdit)
|
||||||
|
field.setText(text)
|
||||||
|
|
||||||
|
def setReadonly(self, fields: list) -> None:
|
||||||
|
for f in fields:
|
||||||
|
f.setReadOnly(True)
|
||||||
|
f.setStyleSheet(self.disLineEdit)
|
||||||
|
|
||||||
|
def setCurrents(self, currents: list) -> None:
|
||||||
|
for i, f in enumerate(self.currentFields):
|
||||||
|
self.setText(f, str(currents[i] * 10))
|
||||||
|
|
||||||
|
def getCurrents(self) -> list:
|
||||||
|
currents = []
|
||||||
|
for f in self.currentFields:
|
||||||
|
currents.append(int(f.text()) if f.text() != "" else 0)
|
||||||
|
return currents
|
||||||
|
|
||||||
|
def setVoltages(self, voltages: list) -> None:
|
||||||
|
for i, f in enumerate(self.voltageFields):
|
||||||
|
self.setText(f, str(int(voltages[i] * 0.235)))
|
||||||
|
|
||||||
|
def getVoltages(self) -> list:
|
||||||
|
voltages = []
|
||||||
|
for f in self.voltageFields:
|
||||||
|
voltages.append(int(f.text()) if f.text() != "" else 0)
|
||||||
|
return voltages
|
||||||
|
|
||||||
|
def setPower(self, power: int) -> None:
|
||||||
|
self.setText(self.ui.PowerField, str(power))
|
||||||
|
|
||||||
|
def connectionLost(self) -> None:
|
||||||
|
self.controller.close()
|
||||||
|
self.setStatus('Пожалуйста, выберите порт')
|
||||||
|
self.setTempStatus(f'Подключение к {self.controller.controller.ser.port} потеряно!', 2)
|
||||||
|
self.resetAllStyles()
|
||||||
|
self.clearAllFields()
|
||||||
|
self.ui.DeviceSelection.clear() # Manually clear device selection combobox
|
||||||
|
|
||||||
|
def determine_capabilities(self, readModes=True) -> tuple[bool, tuple]:
|
||||||
|
# 1.1
|
||||||
|
self.setStatus(f'Чтение адреса {self.controller.controller.ser.port}...')
|
||||||
|
address = self.controller.readAddress()
|
||||||
|
if address == -1:
|
||||||
|
self.setStatus(f'Ошибка чтения адреса {self.controller.controller.ser.port}')
|
||||||
|
return False, ()
|
||||||
|
|
||||||
|
# 1.2
|
||||||
|
self.setStatus(f'Чтение режима {self.controller.controller.ser.port}...')
|
||||||
|
dev_info = self.controller.readDeviceInfo()
|
||||||
|
debug(dev_info)
|
||||||
|
if not dev_info:
|
||||||
|
self.setStatus(f'Ошибка чтения режима {self.controller.controller.ser.port}')
|
||||||
|
return False, ()
|
||||||
|
|
||||||
|
# 1.2 (after all)
|
||||||
|
if readModes:
|
||||||
|
self.modes = []
|
||||||
|
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:
|
||||||
|
return False, ()
|
||||||
|
|
||||||
|
self.modes.append(mode)
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
# 1.3
|
||||||
|
self.setStatus(f'Чтение токов {self.controller.controller.ser.port}...')
|
||||||
|
currents = self.controller.readCurrents()
|
||||||
|
|
||||||
|
# 1.4
|
||||||
|
self.setStatus(f'Чтение эл. параметров {self.controller.controller.ser.port}...')
|
||||||
|
powers = self.controller.readPowers()
|
||||||
|
return True, (address, dev_info, self.modes, currents, powers)
|
||||||
|
|
||||||
|
def readData(self, connecting=False) -> bool:
|
||||||
|
self.connected, data = self.determine_capabilities()
|
||||||
|
if not self.connected:
|
||||||
|
self.setStatus(f'{"Не удалось подключиться" if connecting else "Потеряно подключение"} к {self.device}')
|
||||||
|
self.ui.DeviceSelection.clear()
|
||||||
|
self.controller.close()
|
||||||
|
return False
|
||||||
|
|
||||||
|
address, dev_info, self.modes, currents, powers = data
|
||||||
|
self.setStatus(f'Выбранный порт: {self.device}')
|
||||||
|
self.ui.DmxAddressField.setText(str(address))
|
||||||
|
|
||||||
|
self.ui.ModeSelection.setStyleSheet(self.defCombobox)
|
||||||
|
self.ui.ModeSelection.clear()
|
||||||
|
mode_names = []
|
||||||
|
for index, m in enumerate(self.modes):
|
||||||
|
mode_names.append(f'{index + 1}:{m[1]}')
|
||||||
|
|
||||||
|
self.ui.ModeSelection.addItems(mode_names)
|
||||||
|
self.ui.ModeSelection.setCurrentText(mode_names[dev_info[1] - 1])
|
||||||
|
|
||||||
|
if currents:
|
||||||
|
self.setCurrents(currents)
|
||||||
|
else:
|
||||||
|
self.setReadonly(self.currentFields)
|
||||||
|
|
||||||
|
if powers:
|
||||||
|
self.setVoltages(powers[4:8])
|
||||||
|
self.setPower(powers[8])
|
||||||
|
else:
|
||||||
|
self.setReadonly([*self.voltageFields, self.ui.PowerField])
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def writeData(self) -> None:
|
||||||
|
success, data = self.determine_capabilities(readModes=False)
|
||||||
|
if not success:
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
|
||||||
|
address, dev_info, _, currents, powers = data
|
||||||
|
|
||||||
|
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 currents:
|
||||||
|
self.setStatus(f'Запись токов в {self.controller.controller.ser.port}...')
|
||||||
|
currents_controller = [int(self.getCurrents()[i] * 0.1) for i in range(4)]
|
||||||
|
if not self.controller.writeCurrents(currents_controller):
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
|
||||||
|
if powers:
|
||||||
|
currents = self.getCurrents()
|
||||||
|
voltages = self.getVoltages()
|
||||||
|
# FIX ROUNDING ISSUE
|
||||||
|
for i in range(4):
|
||||||
|
voltages[i] = voltages[i] + 1
|
||||||
|
|
||||||
|
p_poss = int(self.ui.PowerField.text())
|
||||||
|
p_max = powers[17]
|
||||||
|
|
||||||
|
pwm_max = int.from_bytes([powers[15], powers[16]], byteorder='big')
|
||||||
|
|
||||||
|
currents_ma = [currents[i] * 0.001 for i in range(4)]
|
||||||
|
|
||||||
|
currents_controller = [int(currents[i] * 0.1) for i in range(4)]
|
||||||
|
voltages_controller = [int(voltages[i] / 0.235) for i in range(4)]
|
||||||
|
|
||||||
|
powers = [currents_ma[i] * voltages[i] for i in range(4)]
|
||||||
|
p_sum = sum(powers)
|
||||||
|
ka = [powers[i] / p_sum for i in range(4)]
|
||||||
|
km = min(p_poss / p_sum, 1)
|
||||||
|
Amax = int(km * pwm_max)
|
||||||
|
kn = [min(int(ka[i] * 256), 255) for i in range(4)]
|
||||||
|
|
||||||
|
info(f'Currents: {currents}')
|
||||||
|
info(f'Currents controller: {currents_controller}')
|
||||||
|
info(f'Currents ma: {currents_ma}')
|
||||||
|
info(f'Voltages: {voltages}')
|
||||||
|
info(f'Voltages controller: {voltages_controller}')
|
||||||
|
info(f'Powers: {powers}')
|
||||||
|
info(f'Power sum: {p_sum}')
|
||||||
|
info(f'Ka: {ka}')
|
||||||
|
info(f'Km: {km}')
|
||||||
|
info(f'Pmax: {p_max}')
|
||||||
|
info(f'Pext: {p_poss}')
|
||||||
|
info(f'PwmMax: {pwm_max}')
|
||||||
|
info(f'Amax: {Amax}')
|
||||||
|
info(f'Kn: {kn}')
|
||||||
|
|
||||||
|
self.setStatus(f'Запись эл. параметров в {self.controller.controller.ser.port}...')
|
||||||
|
if not self.controller.writePowers(currents_controller, voltages_controller, p_poss, kn, Amax):
|
||||||
|
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())
|
||||||
|
voltages_save = []
|
||||||
|
for entry in self.voltageFields:
|
||||||
|
voltages_save.append(entry.text())
|
||||||
|
p_poss_save = self.ui.PowerField.text()
|
||||||
|
|
||||||
|
self.setStatus(f'Чтение адреса: {self.controller.controller.ser.port}...')
|
||||||
|
dmx_real = self.controller.readAddress()
|
||||||
|
if dmx_real == -1:
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setStatus(f'Чтение режима: {self.controller.controller.ser.port}...')
|
||||||
|
dev_info = self.controller.readDeviceInfo()
|
||||||
|
if not dev_info:
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
pers_real = f'{dev_info[1]}:{self.modes[dev_info[1] - 1][1]}'
|
||||||
|
|
||||||
|
currents_real = []
|
||||||
|
if currents:
|
||||||
|
self.setStatus(f'Чтение токов: {self.controller.controller.ser.port}...')
|
||||||
|
currents_real = [a * 10 for a in self.controller.readCurrents()]
|
||||||
|
if not currents_real:
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
|
||||||
|
voltages_real = []
|
||||||
|
p_poss_real = 0
|
||||||
|
if powers:
|
||||||
|
self.setStatus(f'Чтение эл. параметров: {self.controller.controller.ser.port}...')
|
||||||
|
powers_real = self.controller.readPowers()
|
||||||
|
if not powers_real:
|
||||||
|
self.connectionLost()
|
||||||
|
return
|
||||||
|
|
||||||
|
voltages_real = [int(powers_real[4 + i] * 0.235) for i in range(4)]
|
||||||
|
p_poss_real = powers_real[8]
|
||||||
|
if not currents:
|
||||||
|
currents_real = powers_real[0:4]
|
||||||
|
|
||||||
|
print(f'Save: {dmx_save}, {pers_save}, {currents_save}, {voltages_save}, {p_poss_save}')
|
||||||
|
print(f'Real: {dmx_real}, {pers_real}, {currents_real}, {voltages_real}, {p_poss_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:
|
||||||
|
if currents_save[index] == "" or int(currents_save[index]) != currents_real[index]:
|
||||||
|
failed = True
|
||||||
|
print(f'Failed current: {index}')
|
||||||
|
self.currentFields[index].setStyleSheet(self.redLineEdit)
|
||||||
|
else:
|
||||||
|
self.currentFields[index].setStyleSheet(self.defLineEdit)
|
||||||
|
if powers:
|
||||||
|
if voltages_save[index] == "" or int(voltages_save[index]) != voltages_save[index]:
|
||||||
|
failed = True
|
||||||
|
print(f'Failed voltage: {index}')
|
||||||
|
self.voltageFields[index].setStyleSheet(self.redLineEdit)
|
||||||
|
else:
|
||||||
|
self.voltageFields[index].setStyleSheet(self.defLineEdit)
|
||||||
|
if powers:
|
||||||
|
if p_poss_save != p_poss_real:
|
||||||
|
failed = True
|
||||||
|
self.ui.PowerField.setStyleSheet(self.redLineEdit)
|
||||||
|
else:
|
||||||
|
self.ui.PowerField.setStyleSheet(self.defLineEdit)
|
||||||
|
|
||||||
|
self.setStatus(f'Выбранный порт: {self.controller.controller.ser.port}')
|
||||||
|
if failed:
|
||||||
|
self.setTempStatus('Обнаружены ошибки, повторите запись', 1)
|
||||||
|
else:
|
||||||
|
self.setTempStatus('Проверка прошла успешно', 1)
|
||||||
|
|
||||||
|
def deviceSelectionCallback(self, deviceIndex: int):
|
||||||
|
self.resetAllStyles()
|
||||||
|
self.clearAllFields()
|
||||||
|
|
||||||
|
self.device = self.ui.DeviceSelection.itemText(deviceIndex)
|
||||||
|
|
||||||
|
self.connected = False
|
||||||
|
self.controller.close()
|
||||||
|
|
||||||
|
self.setStatus(f'Подключение к {self.device}...')
|
||||||
|
self.controller.connect(self.device)
|
||||||
|
self.readData(connecting=True)
|
||||||
|
|
||||||
|
def readCallback(self):
|
||||||
|
if time.time() - self.last_click_time < 1:
|
||||||
|
return
|
||||||
|
self.last_click_time = time.time()
|
||||||
|
|
||||||
|
if self.connected:
|
||||||
|
if self.readData():
|
||||||
|
self.setStatus(f'Выбранный порт: {self.controller.controller.ser.port}')
|
||||||
|
self.setTempStatus(f'Данные прочитаны, порт: {self.controller.controller.ser.port}', 1)
|
||||||
|
else:
|
||||||
|
self.setTempStatus('Порт не выбран!', 1)
|
||||||
|
|
||||||
|
def writeCallback(self):
|
||||||
|
if time.time() - self.last_click_time < 2:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.last_click_time = time.time()
|
||||||
|
|
||||||
|
if self.connected:
|
||||||
|
self.writeData()
|
||||||
|
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 showModeTable(self) -> None:
|
||||||
|
self.pixmap = QtGui.QPixmap("../table.png")
|
||||||
|
debug(self.pixmap.width())
|
||||||
|
|
||||||
|
self.imageDialog = QtWidgets.QDialog()
|
||||||
|
self.imageDialog.resize(self.pixmap.width(), self.pixmap.height())
|
||||||
|
self.imageLabel = QtWidgets.QLabel(self.imageDialog)
|
||||||
|
self.imageLabel.resize(self.pixmap.width(), self.pixmap.height())
|
||||||
|
self.imageLabel.setPixmap(self.pixmap)
|
||||||
|
self.imageDialog.exec()
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
# 2, 37, 33, 60
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logs() -> None:
|
||||||
|
os.makedirs("logs", exist_ok=True)
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||||
|
handlers=[
|
||||||
|
logging.FileHandler(f'./logs/{datetime.now().strftime("%Y%m%d-%H%M%S")}.log'),
|
||||||
|
logging.StreamHandler()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
setup_logs()
|
||||||
|
window = Window()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
sys.exit(app.exec())
|
4
main.py
4
main.py
@ -321,5 +321,5 @@ def stress_test() -> None:
|
|||||||
tests.start()
|
tests.start()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
start_ui()
|
#start_ui()
|
||||||
# stress_test()
|
stress_test()
|
11
tests.py
11
tests.py
@ -14,7 +14,7 @@ import controller.controller_reifined as c
|
|||||||
def setup_logs() -> None:
|
def setup_logs() -> None:
|
||||||
os.makedirs("logs", exist_ok=True)
|
os.makedirs("logs", exist_ok=True)
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.DEBUG,
|
||||||
format="%(asctime)s [%(levelname)s] %(message)s",
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||||
handlers=[
|
handlers=[
|
||||||
logging.FileHandler(f'./logs/{datetime.now().strftime("%Y%m%d-%H%M%S")}.log'),
|
logging.FileHandler(f'./logs/{datetime.now().strftime("%Y%m%d-%H%M%S")}.log'),
|
||||||
@ -93,6 +93,11 @@ def start() -> None:
|
|||||||
# )
|
# )
|
||||||
batch_test(
|
batch_test(
|
||||||
[
|
[
|
||||||
|
(test_power_write, 30, 2),
|
||||||
|
(test_dev_info_read, 10, 0),
|
||||||
|
(test_mode_read, 10, 0),
|
||||||
|
|
||||||
|
(test_dev_info_write, 30, 1),
|
||||||
(test_address_read, 30, 0),
|
(test_address_read, 30, 0),
|
||||||
(test_address_write, 30, 1),
|
(test_address_write, 30, 1),
|
||||||
(test_dev_info_write, 30, 2),
|
(test_dev_info_write, 30, 2),
|
||||||
@ -296,7 +301,6 @@ def test_power_write(controller: c.ControllerInterface) -> bool:
|
|||||||
random.randint(voltage_min, voltage_max),
|
random.randint(voltage_min, voltage_max),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
currents_ma = [currents[i] * 0.001 for i in range(4)]
|
currents_ma = [currents[i] * 0.001 for i in range(4)]
|
||||||
|
|
||||||
currents_controller = [int(currents[i] * 0.1) for i in range(4)]
|
currents_controller = [int(currents[i] * 0.1) for i in range(4)]
|
||||||
@ -307,7 +311,7 @@ def test_power_write(controller: c.ControllerInterface) -> bool:
|
|||||||
ka = [powers[i] / p_sum for i in range(4)]
|
ka = [powers[i] / p_sum for i in range(4)]
|
||||||
km = min(p_poss / p_sum, 1)
|
km = min(p_poss / p_sum, 1)
|
||||||
Amax = int(km * pwm_max)
|
Amax = int(km * pwm_max)
|
||||||
kn = [min(int(ka[i] * 256), 255) for i in range(4)] # TODO check if 255
|
kn = [min(int(ka[i] * 256), 255) for i in range(4)]
|
||||||
|
|
||||||
info(f'Currents: {currents}')
|
info(f'Currents: {currents}')
|
||||||
info(f'Currents controller: {currents_controller}')
|
info(f'Currents controller: {currents_controller}')
|
||||||
@ -355,4 +359,3 @@ def test_power_write(controller: c.ControllerInterface) -> bool:
|
|||||||
error('Failed to read powers')
|
error('Failed to read powers')
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"currents.ui",
|
"currents.ui",
|
||||||
"question mark.png",
|
"question mark.png",
|
||||||
"power.ui",
|
"power.ui",
|
||||||
"all.ui"
|
"all.ui",
|
||||||
|
"table.ui"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 15.0.0, 2025-01-30T19:27:19. -->
|
<!-- Written by QtCreator 15.0.0, 2025-02-05T21:57:59. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
19
ui/ControllerUI/table.ui
Normal file
19
ui/ControllerUI/table.ui
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Reference in New Issue
Block a user