update: delete unnecessary files
This commit is contained in:
parent
d89ae03a64
commit
b452a3df74
298
workflow.py
298
workflow.py
@ -1,14 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'test.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
########## beim Static workflow funktionieren die Threads ab dem zweiten nicht mehr
|
||||
|
||||
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@ -31,6 +20,12 @@ import os
|
||||
import lib.sainsmartrelay as sainsmartrelay
|
||||
import lib.wledControl as wledControl
|
||||
|
||||
|
||||
# ## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser -> Farben Drop Down
|
||||
|
||||
|
||||
# ## Aufsetzen der Datenbank und Waagenverbindung
|
||||
# # Definieren der Datenbankverbindung
|
||||
db_config = {
|
||||
'user': 'dbUser',
|
||||
'password': 'dbPassword',
|
||||
@ -39,11 +34,24 @@ db_config = {
|
||||
'port': 3306 # Standard port for MariaDB
|
||||
}
|
||||
|
||||
# # Establishing the connection
|
||||
# conn = mariadb.connect(**db_config)
|
||||
# # Create a cursor to execute queries
|
||||
# cursor = conn.cursor()
|
||||
|
||||
# Establishing the connection
|
||||
try:
|
||||
# Attempt to establish the connection
|
||||
conn = mariadb.connect(**db_config)
|
||||
print("Database connection established successfully.")
|
||||
|
||||
# Create a cursor to execute queries
|
||||
cursor = conn.cursor()
|
||||
except mariadb.Error as e:
|
||||
# Handle connection errors
|
||||
print(f"Error connecting to the database: {e}")
|
||||
conn = None
|
||||
cursor = None
|
||||
|
||||
|
||||
# Configuration of the serial port
|
||||
try:
|
||||
@ -52,34 +60,8 @@ try:
|
||||
except serial.SerialException:
|
||||
ser = None
|
||||
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.")
|
||||
#ser = serial.Serial('/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0', 9600) #dadurch garantiert immer die gleiche Schnittstelle verwendet
|
||||
# und nicht die Schnittstelle, welche die Bezeichnung ttyUSB0 verwendet (welche sich ändern könnte)
|
||||
# um die ID der USB-Schnittstelle heraus zu finden im Terminal folgendes eingeben: ls -l /dev/serial/by-id/
|
||||
# addition: now 2 ESP32 are used: 1 for reading the scale and 1 for controlling the led light. Problem is they both use the same id so
|
||||
# physical port is selected instead.
|
||||
|
||||
|
||||
waageEingeschwungen = False
|
||||
|
||||
|
||||
def wahrscheinlichkeitsDichte(x,mue, var):
|
||||
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet
|
||||
standardabweichung = var**0.5
|
||||
|
||||
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||||
|
||||
return result
|
||||
|
||||
def calcWahrscheinlichkeitFromDichte(x,mue, var):
|
||||
# in der Funktion wird die Wahrscheinlichkeit via der Wahrscheinlichkeitsdichte berechnet, indem das Verhältnis aus der dem Bauteil zugehörigen Wahrscheinlichkeitsdichte zu der maximalen Wahrscheinlichkeitsdichte berechnet wird
|
||||
p1 = wahrscheinlichkeitsDichte(x,mue, var)
|
||||
p_max = wahrscheinlichkeitsDichte(mue,mue, var)
|
||||
|
||||
return p1/p_max
|
||||
|
||||
|
||||
|
||||
#class Worker(QThread):
|
||||
# die Workerklasse ist dazu da die Schleifen - in welchen der Bauteiltyp erkannt wird und die Anzahl der Bauteile, welche auf der Waage liegen - in einem seperaten Thread auszuführen, um ein Blockieren des Mainthreads zu verhindern
|
||||
class Worker(QObject):
|
||||
#progress = pyqtSignal(int)
|
||||
objectDetectionStartSignal = pyqtSignal(str)
|
||||
@ -92,6 +74,7 @@ class Worker(QObject):
|
||||
waageStoppedSignal = pyqtSignal(int)
|
||||
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
||||
|
||||
waageEingeschwungen = False
|
||||
stopLoop = False
|
||||
btTypeIsSet = False
|
||||
correctBtNr = False
|
||||
@ -103,7 +86,7 @@ class Worker(QObject):
|
||||
|
||||
|
||||
def getDataOfArticleType(self, allArticles, articleType):
|
||||
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||
''' die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück '''
|
||||
for i in allArticles:
|
||||
if i[1] == articleType:
|
||||
return i
|
||||
@ -113,26 +96,27 @@ class Worker(QObject):
|
||||
def waageNichtEingeschwungenOutput(self):
|
||||
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||
|
||||
def wahrscheinlichkeitsDichte(self, x,mue, var):
|
||||
''' in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet '''
|
||||
standardabweichung = var**0.5
|
||||
|
||||
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||||
|
||||
return result
|
||||
|
||||
def readWaage(self):
|
||||
# in folgender Funktion wird die Waage ausgelesen
|
||||
|
||||
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe
|
||||
|
||||
''' in folgender Funktion wird die Waage ausgelesen '''
|
||||
|
||||
if ser.is_open == False:
|
||||
ser.open()
|
||||
|
||||
|
||||
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||||
ser.write(b'getWeight\n')
|
||||
#ser.write(b'tare\n')
|
||||
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||||
|
||||
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||||
lenString = len(serialString)-1
|
||||
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||||
#print("ist eingeschwungen") #Debuggingausgabe
|
||||
waageEingeschwungen = True
|
||||
else:
|
||||
print("die Waage ist noch nicht eingeschwungen")
|
||||
@ -144,17 +128,13 @@ class Worker(QObject):
|
||||
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||||
intString = intString + i
|
||||
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||||
## Waage auslesen - ENDE
|
||||
|
||||
ser.close()
|
||||
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||
|
||||
return waageEingeschwungen, intString
|
||||
|
||||
def objectTypeDetectionThread(self, auftragsnummer):
|
||||
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||
|
||||
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
|
||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
||||
|
||||
# Parameterdefinition
|
||||
propDensVect = []
|
||||
@ -174,16 +154,9 @@ class Worker(QObject):
|
||||
cursor.execute(sql_query)
|
||||
auftragEinzelteilDaten = cursor.fetchall()
|
||||
|
||||
'''
|
||||
# Display data #Debugausgabe
|
||||
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||
for row in auftragEinzelteilDaten:
|
||||
print(row)
|
||||
'''
|
||||
|
||||
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
||||
for row in auftragEinzelteilDaten:
|
||||
propDensVect.append([wahrscheinlichkeitsDichte(float(intString),float(row[6]), float(row[7])), row[1], row[5]])
|
||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),float(row[6]), float(row[7])), row[1], row[5]])
|
||||
|
||||
# Jenen Eintrag des propDensVect raussuchen, welcher die größte Wahrscheinlichkeitsdichte beinhaltet
|
||||
maxpropDens = 0
|
||||
@ -201,14 +174,6 @@ class Worker(QObject):
|
||||
else:
|
||||
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
||||
|
||||
# Wahrscheinlichkeit berechnen, dass das angegebene Bauteil auch wirklich diesem entspricht
|
||||
prop = 0
|
||||
for row in auftragEinzelteilDaten:
|
||||
if row[1] == einzelteilID:
|
||||
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6]), float(row[7]))
|
||||
break
|
||||
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||
|
||||
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
||||
self.btTypeIsSet = True
|
||||
|
||||
@ -219,6 +184,7 @@ class Worker(QObject):
|
||||
self.waageStoppedSignal.emit(einzelteilID)
|
||||
|
||||
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
||||
''' in dieser Funktion wird die Stückzahl der Bauteile, welche auf der Waage liegen, berechnet '''
|
||||
|
||||
self.correctBtNr = False
|
||||
prevAnzahl = 0
|
||||
@ -238,14 +204,6 @@ class Worker(QObject):
|
||||
cursor.execute(sql_query)
|
||||
auftragDaten = cursor.fetchall()
|
||||
|
||||
'''
|
||||
# Display data - zum Debuggen
|
||||
print("Ausgabe der Auftragsdetails:")
|
||||
print("id|EinzelteilID|Auftragsnummer|Anzahl")
|
||||
for row in auftragDaten:
|
||||
print(row)
|
||||
'''
|
||||
|
||||
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
||||
anzBauteile_soll = 0
|
||||
idVorhanden = False
|
||||
@ -267,7 +225,7 @@ class Worker(QObject):
|
||||
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
||||
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
||||
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
||||
propDensVect.append([wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
||||
|
||||
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
||||
maxpropDens = 0
|
||||
@ -280,14 +238,6 @@ class Worker(QObject):
|
||||
if prevAnzahl != anzahl:
|
||||
prevAnzahl = anzahl
|
||||
|
||||
# Die Wahrscheinlichkeit berechnen, dass das obige Ergebnis auch dem Bauteil entspricht
|
||||
if anzahl > 0:
|
||||
for row in auftragDaten:
|
||||
if row[1] == einzelteilID:
|
||||
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6])*anzahl, float(row[7])*anzahl)
|
||||
break
|
||||
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||
|
||||
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
||||
if (anzahl == anzBauteile_soll):
|
||||
self.correctBtNr = True
|
||||
@ -307,8 +257,7 @@ class Worker(QObject):
|
||||
self.waageStoppedSignal.emit(einzelteilID)
|
||||
|
||||
|
||||
|
||||
|
||||
## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
self.auftragsnummer = ""
|
||||
@ -316,7 +265,6 @@ class Ui_MainWindow(object):
|
||||
self.correctBtNr = False
|
||||
self.btTypeIsSet = False
|
||||
|
||||
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(1400, 675)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
@ -476,16 +424,6 @@ class Ui_MainWindow(object):
|
||||
self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.blinkLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+300, 161, 25))
|
||||
|
||||
#self.myTestLambda = lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer)
|
||||
|
||||
'''
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setVerticalHeaderItem(0,item)
|
||||
'''
|
||||
|
||||
# Maximize the window on startup
|
||||
MainWindow.showMaximized()
|
||||
|
||||
@ -520,8 +458,6 @@ class Ui_MainWindow(object):
|
||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
|
||||
item.setText(_translate("MainWindow", "ToDo:"))
|
||||
|
||||
# Befüllen der Arbeisschritttabelle mit Text
|
||||
#item = self.ArbeitsschrittTable.
|
||||
# Ein neues QTableWidgetItem erstellen und den Text setzen
|
||||
item = QtWidgets.QTableWidgetItem("Auftrag laden")
|
||||
self.ArbeitsschrittTable.setItem(0, 0, item)
|
||||
@ -539,19 +475,10 @@ class Ui_MainWindow(object):
|
||||
self.ArbeitsschrittTable.setItem(3, 0, item)
|
||||
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
|
||||
#self.ArbeitsschrittTable.item(0,0).setText("test")
|
||||
|
||||
#einzelteilID = int(self.AuftragsdetailsTable.item(i,0).text())
|
||||
#self.PosNrTxtFeld.setText(str(self.AuftragsdetailsTable.item(i,0).text()))
|
||||
#self.bauteiltypTextbox.setText(str(self.AuftragsdetailsTable.item(i,2).text()))
|
||||
|
||||
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
||||
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
||||
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
||||
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
||||
#self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
#item = self.AuftragsdetailsTable.verticalHeaderItem(0)
|
||||
#item.setText(_translate("MainWindow", "test"))
|
||||
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
||||
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
||||
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
||||
@ -573,10 +500,8 @@ class Ui_MainWindow(object):
|
||||
|
||||
# new camera workflow
|
||||
self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
|
||||
# self.startCamBtn.clicked.connect(self.startCamBtnClicked)
|
||||
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
|
||||
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
|
||||
# self.camWorkFlowcheckBox.clicked.connect(self.onCheckboxCheck)
|
||||
self.modelComboBox
|
||||
|
||||
# relay control buttons
|
||||
@ -588,23 +513,20 @@ class Ui_MainWindow(object):
|
||||
self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED"))
|
||||
self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED"))
|
||||
self.offLightBtn.setText(_translate("MainWindow", "Turn off all LEDs"))
|
||||
self.blinkLightBtn.setText(_translate("MainWindow", "Blink last LED"))
|
||||
|
||||
self.blinkLightBtn.setText(_translate("MainWindow", "Blink Yellow LED"))
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
print("Das MainWindow wurde angeklickt.")
|
||||
self.setFocus()
|
||||
super().mousePressEvent(event)
|
||||
|
||||
|
||||
def onTareClick(self):
|
||||
#Tarieren der Waage
|
||||
''' Tarieren der Waage '''
|
||||
if ser.is_open == False:
|
||||
ser.open()
|
||||
ser.write(b'tare\n')
|
||||
ser.close()
|
||||
|
||||
|
||||
def onCheckboxCheck(self):
|
||||
if self.checkBox.isChecked() == True:
|
||||
print("static workflow activated")
|
||||
@ -621,9 +543,6 @@ class Ui_MainWindow(object):
|
||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
||||
return i
|
||||
# brauche ich hier vermutlich nicht mehr - ist in den Worker Thread kopiert worden
|
||||
def waageNichtEingeschwungenOutput(self):
|
||||
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||
|
||||
def onTableCellClick(self):
|
||||
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
||||
@ -648,71 +567,21 @@ class Ui_MainWindow(object):
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# eventuell benötigt man die Funktion hier nicht mehr, da sie zu den Threads kopiert wurde
|
||||
def getDataOfArticleType(self, allArticles, articleType):
|
||||
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||
for i in allArticles:
|
||||
if i[1] == articleType:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def updateGUI(self):
|
||||
self.PosNrLabel.repaint() #GUI aktualisieren
|
||||
QApplication.processEvents() #GUI aktualisieren
|
||||
|
||||
|
||||
def setRowColor(self, tableObject, rowID,r,g,b):
|
||||
for col in range(tableObject.columnCount()-1):
|
||||
tableObject.item(rowID, col).setBackground(QtGui.QColor(r,g,b))
|
||||
'''
|
||||
die alte Version der Programmierung
|
||||
tableObject.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
|
||||
tableObject.item(rowID, 1).setBackground(QtGui.QColor(r,g,b))
|
||||
tableObject.item(rowID, 2).setBackground(QtGui.QColor(r,g,b))
|
||||
tableObject.item(rowID, 3).setBackground(QtGui.QColor(r,g,b))
|
||||
tableObject.item(rowID, 4).setBackground(QtGui.QColor(r,g,b))
|
||||
tableObject.item(rowID, 5).setBackground(QtGui.QColor(r,g,b))
|
||||
'''
|
||||
|
||||
#wird hier vermutlich nicht mehr benötigt - wurde in die Workerklasse kopiert
|
||||
def readWaage(self):
|
||||
# in folgender Funktion wird die Waage ausgelesen
|
||||
|
||||
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe
|
||||
self.checkPosNrEmpty()
|
||||
|
||||
if ser.is_open == False:
|
||||
ser.open()
|
||||
|
||||
|
||||
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||||
ser.write(b'getWeight\n')
|
||||
#ser.write(b'tare\n')
|
||||
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||||
|
||||
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||||
lenString = len(serialString)-1
|
||||
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||||
#print("ist eingeschwungen") #Debuggingausgabe
|
||||
waageEingeschwungen = True
|
||||
else:
|
||||
print("die Waage ist noch nicht eingeschwungen")
|
||||
waageEingeschwungen = False
|
||||
|
||||
#aus dem String werden alle Zeichen, welche nicht zur Darstellung der Zahl benötigt werden entfernt
|
||||
intString = ""
|
||||
for i in serialString:
|
||||
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||||
intString = intString + i
|
||||
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||||
## Waage auslesen - ENDE
|
||||
|
||||
ser.close()
|
||||
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||
|
||||
return waageEingeschwungen, intString
|
||||
# # call change led color
|
||||
# Check if the 'w' object already exists
|
||||
# hier könnte noch nachgearbeitet werden
|
||||
if not hasattr(self, 'w'):
|
||||
w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
||||
w.connect()
|
||||
w.map_color_to_led([r,g,b])
|
||||
|
||||
def auftragsBtnClicked(self):
|
||||
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
||||
@ -731,16 +600,7 @@ class Ui_MainWindow(object):
|
||||
print("Fehler in der Datenbankabfrage.")
|
||||
|
||||
|
||||
|
||||
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
||||
'''
|
||||
# Display data
|
||||
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||
for row in auftragEinzelteilDaten:
|
||||
if str(row[2]) == self.auftragsnummer:
|
||||
print("passt")
|
||||
print(row)
|
||||
'''
|
||||
|
||||
### die Auftragsdaten in die Tabelle laden
|
||||
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
||||
@ -787,7 +647,6 @@ class Ui_MainWindow(object):
|
||||
self.bauteiltypTextbox.setText("")
|
||||
self.PosNrTxtFeld.setText("")
|
||||
|
||||
|
||||
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
|
||||
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
||||
|
||||
@ -800,7 +659,7 @@ class Ui_MainWindow(object):
|
||||
self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
|
||||
|
||||
def stopLoopClicked(self):
|
||||
# damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert
|
||||
''' damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert '''
|
||||
if hasattr(self, 'objectDetectionWorker'):
|
||||
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
||||
|
||||
@ -808,20 +667,15 @@ class Ui_MainWindow(object):
|
||||
self.checkWaageWorker.stopLoopSignal.emit(True)
|
||||
|
||||
def checkFinished(self):
|
||||
#die Funktion geht alle Zeilen der Auftragsliste durch und schaut, ob die richtige Anzahl an Teilen vorhanden sind
|
||||
''' die Funktion geht alle Zeilen der Auftragsliste durch und schaut, ob die richtige Anzahl an Teilen vorhanden sind '''
|
||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def checkWaage(self):
|
||||
#print("Running in thread:", threading.current_thread().name) # Debuggingausgabe
|
||||
QApplication.processEvents()
|
||||
|
||||
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||
#self.checkWaageWorker.stopLoopSignal.emit(False)
|
||||
|
||||
# überprüfen, ob der Auftrag geladen wurde
|
||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||
print("Der Auftrag muss zuerst geladen werden.")
|
||||
@ -910,22 +764,13 @@ class Ui_MainWindow(object):
|
||||
#self.updateGUI()
|
||||
|
||||
def objectTypeDetection(self):
|
||||
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
||||
|
||||
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
||||
if self.checkBox.isChecked() == True:
|
||||
self.checkWaage()
|
||||
return
|
||||
|
||||
'''
|
||||
if(self.checkPosNrEmpty()==True):
|
||||
print("Das Pos.-Nr.-Feld ist leer.")
|
||||
return
|
||||
'''
|
||||
|
||||
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||
#self.objectDetectionWorker.stopLoopSignal.emit(False)
|
||||
|
||||
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||
print("Der Auftrag muss zuerst geladen werden.")
|
||||
@ -949,7 +794,7 @@ class Ui_MainWindow(object):
|
||||
self.objectDetectionThread.start()
|
||||
|
||||
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
||||
# wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden
|
||||
''' wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden '''
|
||||
|
||||
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
||||
self.PosNrTxtFeld.setText(str(rowData[1]))
|
||||
@ -965,20 +810,12 @@ class Ui_MainWindow(object):
|
||||
self.objectDetectionThread.quit()
|
||||
self.objectDetectionThread.wait()
|
||||
|
||||
'''
|
||||
try:
|
||||
self.objectDetectionThread.started.disconnect() # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
|
||||
except:
|
||||
print(f"Error while disconnecting: {e}")
|
||||
print("Disconnecting the thread did not work.")
|
||||
'''
|
||||
|
||||
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
||||
self.updateGUI()
|
||||
self.checkWaage()
|
||||
|
||||
def threadStopped(self, einzelteilID):
|
||||
# wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0
|
||||
''' wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0 '''
|
||||
if self.checkFinished() == False:
|
||||
if(einzelteilID > 0):
|
||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
||||
@ -996,7 +833,6 @@ class Ui_MainWindow(object):
|
||||
self.checkWaageThread.wait()
|
||||
print("Der CheckWaage-Thread wurde beendet.")
|
||||
|
||||
|
||||
# new class for Camera Object detection with YOLOv8
|
||||
class CameraStreamApp(QtWidgets.QMainWindow):
|
||||
def __init__(self, ui):
|
||||
@ -1048,7 +884,7 @@ class CameraStreamApp(QtWidgets.QMainWindow):
|
||||
|
||||
# Convert the frame from BGR (OpenCV format) to RGB
|
||||
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB) # might change nomenclature later?
|
||||
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
||||
|
||||
# Convert the frame to QImage
|
||||
h, w, ch = frame.shape
|
||||
@ -1078,16 +914,30 @@ class LightControl(QtWidgets.QMainWindow):
|
||||
super().__init__()
|
||||
self.ui = ui
|
||||
|
||||
# init relay control
|
||||
self.ui.startSpotlightBtn.clicked.connect(self.spot_on)
|
||||
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
|
||||
self.r = sainsmartrelay.SainsmartRelay()
|
||||
|
||||
# init led control
|
||||
self.ui.redLightBtn.clicked.connect(self.red_on)
|
||||
self.ui.yellowLightBtn.clicked.connect(self.yellow_on)
|
||||
self.ui.greenLightBtn.clicked.connect(self.green_on)
|
||||
self.ui.offLightBtn.clicked.connect(self.leds_off)
|
||||
self.ui.blinkLightBtn.clicked.connect(self.leds_blink)
|
||||
self.ui.blinkLightBtn.clicked.connect(self.blink_yellow)
|
||||
self.w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
||||
self.w.connect()
|
||||
#self.w.switch_to_green() # at appstart the light is green
|
||||
self.w.blink_green() # and switches to green blinking until the workflow gets started successfully#
|
||||
|
||||
# Connect app exit signal to the cleanup method
|
||||
app.aboutToQuit.connect(self.cleanup)
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up resources and switch off LEDs."""
|
||||
print("Cleaning up resources and switching off LEDs")
|
||||
self.leds_off() # Turn off LEDs
|
||||
self.w.disconnect() # Disconnect WLED controller
|
||||
|
||||
def spot_on(self):
|
||||
print("Turn on light clicked")
|
||||
@ -1113,9 +963,17 @@ class LightControl(QtWidgets.QMainWindow):
|
||||
print("LEDs are off")
|
||||
self.w.turn_off_all()
|
||||
|
||||
def leds_blink(self):
|
||||
print("Previous color is blinking")
|
||||
self.w.change_effect()
|
||||
def blink_yellow(self):
|
||||
print("Yellow color is blinking")
|
||||
self.w.blink_yellow()
|
||||
|
||||
def blink_red(self):
|
||||
print("Red color is blinking")
|
||||
self.w.blink_red()
|
||||
|
||||
def blink_green(self):
|
||||
print("Green color is blinking")
|
||||
self.w.blink_green()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
1012
workflow2.py
1012
workflow2.py
File diff suppressed because it is too large
Load Diff
991
workflow3.py
991
workflow3.py
@ -1,991 +0,0 @@
|
||||
|
||||
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import QApplication, QComboBox
|
||||
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject, Qt
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
import serial
|
||||
import binascii
|
||||
import math
|
||||
import mariadb
|
||||
import time
|
||||
import threading
|
||||
|
||||
from lib.CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
|
||||
import cv2
|
||||
|
||||
import os
|
||||
|
||||
import lib.sainsmartrelay as sainsmartrelay
|
||||
import lib.wledControl as wledControl
|
||||
|
||||
|
||||
# ## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser -> Farben Drop Down
|
||||
|
||||
|
||||
# ## Aufsetzen der Datenbank und Waagenverbindung
|
||||
# # Definieren der Datenbankverbindung
|
||||
db_config = {
|
||||
'user': 'dbUser',
|
||||
'password': 'dbPassword',
|
||||
'host': '127.0.0.1', # 'host': 'localhost', changed because more compatible
|
||||
'database': 'projectGeislinger',
|
||||
'port': 3306 # Standard port for MariaDB
|
||||
}
|
||||
|
||||
# # Establishing the connection
|
||||
# conn = mariadb.connect(**db_config)
|
||||
# # Create a cursor to execute queries
|
||||
# cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
# Attempt to establish the connection
|
||||
conn = mariadb.connect(**db_config)
|
||||
print("Database connection established successfully.")
|
||||
|
||||
# Create a cursor to execute queries
|
||||
cursor = conn.cursor()
|
||||
except mariadb.Error as e:
|
||||
# Handle connection errors
|
||||
print(f"Error connecting to the database: {e}")
|
||||
conn = None
|
||||
cursor = None
|
||||
|
||||
|
||||
# Configuration of the serial port
|
||||
try:
|
||||
ser = serial.Serial('/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:3:1.0-port0', 9600)
|
||||
print("Serial port connected successfully.")
|
||||
except serial.SerialException:
|
||||
ser = None
|
||||
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.")
|
||||
|
||||
# die Workerklasse ist dazu da die Schleifen - in welchen der Bauteiltyp erkannt wird und die Anzahl der Bauteile, welche auf der Waage liegen - in einem seperaten Thread auszuführen, um ein Blockieren des Mainthreads zu verhindern
|
||||
class Worker(QObject):
|
||||
#progress = pyqtSignal(int)
|
||||
objectDetectionStartSignal = pyqtSignal(str)
|
||||
objectDetectionFinishedSignal = pyqtSignal(int, object)
|
||||
|
||||
checkWaageStartSignal = pyqtSignal(int, int, str)
|
||||
checkWaageUpdateSignal = pyqtSignal(int, int)
|
||||
checkWaageFinishedSignal = pyqtSignal(int)
|
||||
|
||||
waageStoppedSignal = pyqtSignal(int)
|
||||
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
||||
|
||||
waageEingeschwungen = False
|
||||
stopLoop = False
|
||||
btTypeIsSet = False
|
||||
correctBtNr = False
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super(Worker, self).__init__()
|
||||
stopLoop = False
|
||||
|
||||
|
||||
def getDataOfArticleType(self, allArticles, articleType):
|
||||
''' die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück '''
|
||||
for i in allArticles:
|
||||
if i[1] == articleType:
|
||||
return i
|
||||
|
||||
return -1
|
||||
|
||||
def waageNichtEingeschwungenOutput(self):
|
||||
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||
|
||||
def wahrscheinlichkeitsDichte(self, x,mue, var):
|
||||
''' in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet '''
|
||||
standardabweichung = var**0.5
|
||||
|
||||
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||||
|
||||
return result
|
||||
|
||||
def readWaage(self):
|
||||
''' in folgender Funktion wird die Waage ausgelesen '''
|
||||
|
||||
if ser.is_open == False:
|
||||
ser.open()
|
||||
|
||||
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||||
ser.write(b'getWeight\n')
|
||||
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||||
|
||||
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||||
lenString = len(serialString)-1
|
||||
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||||
waageEingeschwungen = True
|
||||
else:
|
||||
print("die Waage ist noch nicht eingeschwungen")
|
||||
waageEingeschwungen = False
|
||||
|
||||
#aus dem String werden alle Zeichen, welche nicht zur Darstellung der Zahl benötigt werden entfernt
|
||||
intString = ""
|
||||
for i in serialString:
|
||||
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||||
intString = intString + i
|
||||
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||||
|
||||
ser.close()
|
||||
|
||||
return waageEingeschwungen, intString
|
||||
|
||||
def objectTypeDetectionThread(self, auftragsnummer):
|
||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
||||
|
||||
# Parameterdefinition
|
||||
propDensVect = []
|
||||
|
||||
self.btTypeIsSet = False
|
||||
|
||||
while(self.btTypeIsSet == False and self.stopLoop == False):
|
||||
|
||||
# Auslesen der Waage
|
||||
waageEingeschwungen, intString = self.readWaage()
|
||||
if waageEingeschwungen == False:
|
||||
self.waageNichtEingeschwungenOutput()
|
||||
else:
|
||||
|
||||
# Datenbankabfrage
|
||||
sql_query = "SELECT Auftraege.id, EinzelteilID, Auftragsnummer, Anzahl, Einzelteile.id, Bezeichnung, CAST(projectGeislinger.Einzelteile.GewichtMittelwert AS CHAR), CAST(projectGeislinger.Einzelteile.GewichtVarianz AS CHAR) FROM projectGeislinger.Auftraege, projectGeislinger.Einzelteile where projectGeislinger.Auftraege.EinzelteilID = projectGeislinger.Einzelteile.id AND projectGeislinger.Auftraege.Auftragsnummer = " + auftragsnummer
|
||||
cursor.execute(sql_query)
|
||||
auftragEinzelteilDaten = cursor.fetchall()
|
||||
|
||||
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
||||
for row in auftragEinzelteilDaten:
|
||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),float(row[6]), float(row[7])), row[1], row[5]])
|
||||
|
||||
# Jenen Eintrag des propDensVect raussuchen, welcher die größte Wahrscheinlichkeitsdichte beinhaltet
|
||||
maxpropDens = 0
|
||||
einzelteilID = 0
|
||||
rowData = None
|
||||
for row in propDensVect:
|
||||
if row[0] > maxpropDens:
|
||||
maxpropDens = row[0]
|
||||
einzelteilID = row[1]
|
||||
rowData = row
|
||||
|
||||
# überprüfen, ob das aufliegende Bauteil in der Auftragstabelle vorhanden ist
|
||||
if(einzelteilID == 0):
|
||||
print("Es wurde kein Bauteil aus der Auftragsliste (Tabelle) erkannt.")
|
||||
else:
|
||||
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
||||
|
||||
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
||||
self.btTypeIsSet = True
|
||||
|
||||
if(self.stopLoop == False):
|
||||
# ein Signal zurück an den MainThreat senden, mit den Infos/Ergebnissen, der Typenbestimmung
|
||||
self.objectDetectionFinishedSignal.emit(einzelteilID, rowData)
|
||||
else:
|
||||
self.waageStoppedSignal.emit(einzelteilID)
|
||||
|
||||
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
||||
''' in dieser Funktion wird die Stückzahl der Bauteile, welche auf der Waage liegen, berechnet '''
|
||||
|
||||
self.correctBtNr = False
|
||||
prevAnzahl = 0
|
||||
anzahl = 0
|
||||
einzelteilID = einzelteilID
|
||||
|
||||
while (self.correctBtNr == False and self.stopLoop == False):
|
||||
|
||||
#überprüfen, ob die Waage eingeschwungen ist (und damit korrekte Ergebnisse liefert)
|
||||
waageEingeschwungen, intString = self.readWaage()
|
||||
if waageEingeschwungen == False:
|
||||
self.waageNichtEingeschwungenOutput()
|
||||
else:
|
||||
|
||||
# Datenbankabfrage - holen der Auftrags- und Bauteilinfos
|
||||
sql_query = "SELECT Auftraege.id, EinzelteilID, Auftragsnummer, Anzahl, Einzelteile.id, Bezeichnung, CAST(projectGeislinger.Einzelteile.GewichtMittelwert AS CHAR), CAST(projectGeislinger.Einzelteile.GewichtVarianz AS CHAR) FROM projectGeislinger.Auftraege, projectGeislinger.Einzelteile where projectGeislinger.Auftraege.EinzelteilID = projectGeislinger.Einzelteile.id AND projectGeislinger.Auftraege.Auftragsnummer = " + auftragsnummer
|
||||
cursor.execute(sql_query)
|
||||
auftragDaten = cursor.fetchall()
|
||||
|
||||
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
||||
anzBauteile_soll = 0
|
||||
idVorhanden = False
|
||||
|
||||
for row in auftragDaten:
|
||||
if row[1] == einzelteilID:
|
||||
anzBauteile_soll = row[3]
|
||||
idVorhanden = True
|
||||
|
||||
if(idVorhanden == False):
|
||||
print("Die gewählte Pos.Nr ist nicht in der Auftragsliste (Tabelle) vorhanden.")
|
||||
return
|
||||
|
||||
# Berechnen der Wahrscheinlichkeitsdichten - der Betrag aller Wahrscheinlichkeitsdichten werden im propDensVect gespeichert
|
||||
propDensVect = []
|
||||
articleData = self.getDataOfArticleType(auftragDaten, einzelteilID)
|
||||
for i in range(1,anzBauteile_soll+teileZuViel+1):
|
||||
# Mathematische Sätze, auf welchen die Berechnung basiert:
|
||||
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
||||
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
||||
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
||||
|
||||
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
||||
maxpropDens = 0
|
||||
for row in propDensVect:
|
||||
if row[0] > maxpropDens:
|
||||
maxpropDens = row[0]
|
||||
anzahl = row[1]
|
||||
|
||||
# damit nur etwas gemacht wird (zb ein Updatesignal an den Hauptthread zurücksenden), wenn sich die berechnete Anzahl ändert
|
||||
if prevAnzahl != anzahl:
|
||||
prevAnzahl = anzahl
|
||||
|
||||
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
||||
if (anzahl == anzBauteile_soll):
|
||||
self.correctBtNr = True
|
||||
|
||||
# Konsolenausgabe
|
||||
if maxpropDens > 0:
|
||||
print("Bei der Anzahl" , anzahl , "des Bauteiltypes", einzelteilID, ",wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
||||
self.checkWaageUpdateSignal.emit(einzelteilID, anzahl)
|
||||
|
||||
else:
|
||||
print("Von der ausgewählten Bauteiltype liegt die berechnete Wahrscheinlichkeit bei 0, dass zwischen 0 und", anzBauteile_soll+teileZuViel, "Bauteilen auf der Waage liegen.")
|
||||
print("Falls die korrekte Anzhl an Bauteilen auf der Waage liegt, könnte der Fehler in einer falschen Kalibrierung der Waage liegen (TARE).")
|
||||
|
||||
if(self.stopLoop == False):
|
||||
self.checkWaageFinishedSignal.emit(einzelteilID)
|
||||
else:
|
||||
self.waageStoppedSignal.emit(einzelteilID)
|
||||
|
||||
|
||||
## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
self.auftragsnummer = ""
|
||||
self.teileZuViel = 100 # Anzahl an Bauteilen, welche zu viel drinnen sein können - der Parameter kann selbst gesetzt werden #####
|
||||
self.correctBtNr = False
|
||||
self.btTypeIsSet = False
|
||||
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(1400, 675)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.btn1.setGeometry(QtCore.QRect(700, 45, 111, 25))
|
||||
self.btn1.setObjectName("btn1")
|
||||
# Tabelle zur Darstellung der Auftragsdetails
|
||||
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
|
||||
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 100, 661, 400))
|
||||
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
|
||||
self.AuftragsdetailsTable.setColumnCount(7)
|
||||
self.AuftragsdetailsTable.setRowCount(0)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(0, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(1, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(2, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(3, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(5, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(4, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(6, item)
|
||||
|
||||
# Tabelle zur Darstellung der Arbeitsschritte
|
||||
self.ArbeitsschrittTable = QtWidgets.QTableWidget(self.centralwidget)
|
||||
self.ArbeitsschrittTable.setGeometry(QtCore.QRect(1000, 50, 395, 400))
|
||||
self.ArbeitsschrittTable.setObjectName("AuftragsdetailsTable")
|
||||
self.ArbeitsschrittTable.setColumnCount(2)
|
||||
self.ArbeitsschrittTable.setRowCount(4)
|
||||
self.ArbeitsschrittTable.setColumnWidth(0, 100)
|
||||
self.ArbeitsschrittTable.setColumnWidth(1, 280)
|
||||
self.ArbeitsschrittTable.setRowHeight(0, 80)
|
||||
self.ArbeitsschrittTable.setRowHeight(1, 180)
|
||||
self.ArbeitsschrittTable.setRowHeight(2, 50)
|
||||
self.ArbeitsschrittTable.setRowHeight(3, 50)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.ArbeitsschrittTable.setHorizontalHeaderItem(0, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
item.setFont(font)
|
||||
self.ArbeitsschrittTable.setHorizontalHeaderItem(1, item)
|
||||
|
||||
self.label = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label.setGeometry(QtCore.QRect(500, 20, 121, 17))
|
||||
self.label.setObjectName("label")
|
||||
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.textEdit.setGeometry(QtCore.QRect(450, 40, 221, 31))
|
||||
self.textEdit.setObjectName("textEdit")
|
||||
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.bauteilTypBtn.setGeometry(QtCore.QRect(700, 100, 161, 25))
|
||||
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
|
||||
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 150, 161, 25))
|
||||
self.checkWaageBtn.setObjectName("checkWaageBtn")
|
||||
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 350, 161, 25))
|
||||
self.stopLoopBtn.setObjectName("stopLoopBtn")
|
||||
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.waageTareBtn.setGeometry(QtCore.QRect(700, 400, 161, 25))
|
||||
self.waageTareBtn.setObjectName("waageTareBtn")
|
||||
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.bauteiltypTextbox.setGeometry(QtCore.QRect(700, 290, 221, 31))
|
||||
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
|
||||
self.BezeichnungLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
self.BezeichnungLabel.setGeometry(QtCore.QRect(700, 270, 181, 20))
|
||||
self.BezeichnungLabel.setObjectName("BezeichnungLabel")
|
||||
self.PosNrLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
self.PosNrLabel.setGeometry(QtCore.QRect(700, 200, 67, 17))
|
||||
self.PosNrLabel.setObjectName("PosNrLabel")
|
||||
self.PosNrTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.PosNrTxtFeld.setGeometry(QtCore.QRect(700, 220, 191, 31))
|
||||
self.PosNrTxtFeld.setObjectName("PosNrTxtFeld")
|
||||
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
self.teileZuVielLabel.setGeometry(QtCore.QRect(1000, 560, 350, 17))
|
||||
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
|
||||
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(1000, 580, 191, 31))
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1090, 22))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow.setStatusBar(self.statusbar)
|
||||
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.checkBox.setGeometry(QtCore.QRect(1000, 480, 151, 23))
|
||||
self.checkBox.setObjectName("checkBox")
|
||||
self.checkBoxAutoTare = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.checkBoxAutoTare.setGeometry(QtCore.QRect(1000, 520, 180, 23))
|
||||
self.checkBoxAutoTare.setObjectName("checkBoxAutoTare")
|
||||
|
||||
# button and checkbox for camera workflow + graphicsview widget
|
||||
self.camWorkFlowcheckBox = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.camWorkFlowcheckBox.setGeometry(QtCore.QRect(700, int(1080/2), 151, 23))
|
||||
self.camWorkFlowcheckBox.setObjectName("camWorkFlowcheckBox")
|
||||
self.modelComboBox = QtWidgets.QComboBox(self.centralwidget)
|
||||
self.modelComboBox.setGeometry(QtCore.QRect(700, int(1080/2)+50, 161, 25))
|
||||
self.modelComboBox.setObjectName("modelComboBox")
|
||||
self.startCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.startCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
||||
self.startCamBtn.setObjectName("startCamBtn")
|
||||
self.stopCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.stopCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+150, 161, 25))
|
||||
self.stopCamBtn.setObjectName("stopCamBtn")
|
||||
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
|
||||
self.graphicsView.setGeometry(QtCore.QRect(10, int(1080/2), 661, int(480*1.05))) # position and size of camera frame # int(640*1.05)
|
||||
self.graphicsView.setObjectName("graphicsView")
|
||||
|
||||
# relay control buttons
|
||||
self.startSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.startSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
||||
self.startSpotlightBtn.setObjectName("startSpotlightBtn")
|
||||
self.stopSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.stopSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+150, 161, 25))
|
||||
self.stopSpotlightBtn.setObjectName("stopSpotlightBtn")
|
||||
|
||||
# led control buttons
|
||||
self.redLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.redLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+100, 161, 25))
|
||||
self.yellowLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.yellowLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+150, 161, 25))
|
||||
self.greenLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.greenLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+200, 161, 25))
|
||||
self.offLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.offLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+250, 161, 25))
|
||||
self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.blinkLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+300, 161, 25))
|
||||
|
||||
# Maximize the window on startup
|
||||
MainWindow.showMaximized()
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||
self.btn1.setText(_translate("MainWindow", "load Auftrag"))
|
||||
self.btn1.clicked.connect(self.auftragsBtnClicked)
|
||||
|
||||
# Tabelle zur Darstellung der Auftragsdetails
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(0)
|
||||
item.setText(_translate("MainWindow", "Pos.-Nr"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(1)
|
||||
item.setText(_translate("MainWindow", "Matnr mit hoechster Version"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(2)
|
||||
item.setText(_translate("MainWindow", "Bezeichnung + Werkstoff"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(3)
|
||||
item.setText(_translate("MainWindow", "Soll-Menge"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(4)
|
||||
item.setText(_translate("MainWindow", "Ist-Menge"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(5)
|
||||
item.setText(_translate("MainWindow", "Lgort"))
|
||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(6)
|
||||
item.setText(_translate("MainWindow", "set Farbe"))
|
||||
|
||||
# Tabelle zur Darstellung der Arbeitsschritte
|
||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(0)
|
||||
item.setText(_translate("MainWindow", "Arbeitsschritt"))
|
||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
|
||||
item.setText(_translate("MainWindow", "ToDo:"))
|
||||
|
||||
# Ein neues QTableWidgetItem erstellen und den Text setzen
|
||||
item = QtWidgets.QTableWidgetItem("Auftrag laden")
|
||||
self.ArbeitsschrittTable.setItem(0, 0, item)
|
||||
item = QtWidgets.QTableWidgetItem("--> Auftragsnummer eingeben \n--> \"load Auftrag\" Buttonclick")
|
||||
self.ArbeitsschrittTable.setItem(0, 1, item)
|
||||
item = QtWidgets.QTableWidgetItem("Bauteiltyp erkennen")
|
||||
self.ArbeitsschrittTable.setItem(1, 0, item)
|
||||
item = QtWidgets.QTableWidgetItem("visuell: \n--> ein Bauteil in die Kamera halten\n\nWaage: \n--> ein Bauteil auf die Waage legen\n--> \"Bauteiltyp erkennen\" Buttonclick\n\nmanuell:\n--> Bauteiltypen auswählen\n-->\"ckeck Waage\" Button click")
|
||||
self.ArbeitsschrittTable.setItem(1, 1, item)
|
||||
item = QtWidgets.QTableWidgetItem("Bauteilanzahl erkennen")
|
||||
self.ArbeitsschrittTable.setItem(2, 0, item)
|
||||
item = QtWidgets.QTableWidgetItem("--> Bauteile auflegen")
|
||||
self.ArbeitsschrittTable.setItem(2, 1, item)
|
||||
item = QtWidgets.QTableWidgetItem("Prozess beendet")
|
||||
self.ArbeitsschrittTable.setItem(3, 0, item)
|
||||
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
|
||||
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
||||
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
||||
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
||||
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
||||
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
||||
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
||||
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
||||
self.teileZuVielTxtFeld.setText(str(self.teileZuViel))
|
||||
self.checkWaageBtn.setText(_translate("MainWindow", "check Waage"))
|
||||
self.checkWaageBtn.clicked.connect(self.checkWaage)
|
||||
self.stopLoopBtn.setText(_translate("MainWindow", "stop loop"))
|
||||
self.stopLoopBtn.clicked.connect(self.stopLoopClicked)
|
||||
self.waageTareBtn.setText(_translate("MainWindow", "Waage tarieren"))
|
||||
self.waageTareBtn.clicked.connect(self.onTareClick)
|
||||
self.checkBox.setText(_translate("MainWindow", "static workflow"))
|
||||
self.checkBox.clicked.connect(self.onCheckboxCheck)
|
||||
self.checkBoxAutoTare.setText(_translate("MainWindow", "automatisches Tarieren"))
|
||||
self.checkBoxAutoTare.clicked.connect(self.autoTareCheck)
|
||||
|
||||
self.setRowColor(self.ArbeitsschrittTable, 0,255,165,0) # zum setzen der ersten Spalte der Arbeitsschrittetabelle auf orange
|
||||
self.checkBoxAutoTare.setCheckState(Qt.Checked)
|
||||
self.checkBox.setCheckState(Qt.Unchecked)
|
||||
|
||||
# new camera workflow
|
||||
self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
|
||||
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
|
||||
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
|
||||
self.modelComboBox
|
||||
|
||||
# relay control buttons
|
||||
self.startSpotlightBtn.setText(_translate("MainWindow", "Turn on light"))
|
||||
self.stopSpotlightBtn.setText(_translate("MainWindow", "Turn off light"))
|
||||
|
||||
# led control buttons
|
||||
self.redLightBtn.setText(_translate("MainWindow", "Turn on red LED"))
|
||||
self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED"))
|
||||
self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED"))
|
||||
self.offLightBtn.setText(_translate("MainWindow", "Turn off all LEDs"))
|
||||
self.blinkLightBtn.setText(_translate("MainWindow", "Blink Yellow LED"))
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
print("Das MainWindow wurde angeklickt.")
|
||||
self.setFocus()
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def onTareClick(self):
|
||||
''' Tarieren der Waage '''
|
||||
if ser.is_open == False:
|
||||
ser.open()
|
||||
ser.write(b'tare\n')
|
||||
ser.close()
|
||||
|
||||
def onCheckboxCheck(self):
|
||||
if self.checkBox.isChecked() == True:
|
||||
print("static workflow activated")
|
||||
else:
|
||||
print("static workflow deactivated")
|
||||
|
||||
def autoTareCheck(self):
|
||||
if self.checkBoxAutoTare.isChecked() == True:
|
||||
print("automatisches Tarieren ist aktiviert")
|
||||
else:
|
||||
print("automatisches Tarieren ist deaktiviert")
|
||||
|
||||
def getRowNr(self, posNr):
|
||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
||||
return i
|
||||
|
||||
def onTableCellClick(self):
|
||||
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
||||
self.bauteiltypTextbox.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),2).text())
|
||||
|
||||
def setAuftragsnummer(self):
|
||||
self.auftragsnummer = self.textEdit.toPlainText()
|
||||
if(not self.auftragsnummer):
|
||||
self.auftragsnummer = ""
|
||||
self.textEdit.setText("")
|
||||
|
||||
def checkAuftragsnummerEmpty(self):
|
||||
if self.auftragsnummer == "":
|
||||
print("Das Auftragsnummernfeld ist leer.")
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def checkPosNrEmpty(self):
|
||||
if self.PosNrTxtFeld.toPlainText() == "":
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def updateGUI(self):
|
||||
self.PosNrLabel.repaint() #GUI aktualisieren
|
||||
QApplication.processEvents() #GUI aktualisieren
|
||||
|
||||
def setRowColor(self, tableObject, rowID,r,g,b):
|
||||
for col in range(tableObject.columnCount()-1):
|
||||
tableObject.item(rowID, col).setBackground(QtGui.QColor(r,g,b))
|
||||
|
||||
# # call change led color
|
||||
# Check if the 'w' object already exists
|
||||
# hier könnte noch nachgearbeitet werden
|
||||
if not hasattr(self, 'w'):
|
||||
w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
||||
w.connect()
|
||||
w.map_color_to_led([r,g,b])
|
||||
|
||||
def auftragsBtnClicked(self):
|
||||
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
||||
auftragEinzelteilDaten = []
|
||||
|
||||
self.setAuftragsnummer()
|
||||
if(not self.checkAuftragsnummerEmpty()):
|
||||
|
||||
sql_query = "SELECT Auftraege.id, EinzelteilID, Auftragsnummer, Anzahl, Einzelteile.id, Bezeichnung, CAST(projectGeislinger.Einzelteile.GewichtMittelwert AS CHAR), CAST(projectGeislinger.Einzelteile.GewichtVarianz AS CHAR) FROM projectGeislinger.Auftraege, projectGeislinger.Einzelteile where projectGeislinger.Auftraege.EinzelteilID = projectGeislinger.Einzelteile.id AND projectGeislinger.Auftraege.Auftragsnummer = " + self.auftragsnummer
|
||||
try:
|
||||
cursor.execute(sql_query)
|
||||
# Fetch results
|
||||
auftragEinzelteilDaten = cursor.fetchall()
|
||||
databaseQueryWorking = True
|
||||
except:
|
||||
print("Fehler in der Datenbankabfrage.")
|
||||
|
||||
|
||||
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
||||
|
||||
### die Auftragsdaten in die Tabelle laden
|
||||
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
counter = 0
|
||||
for row in auftragEinzelteilDaten:
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 0, self.item)
|
||||
self.item.setText(str(row[1]))
|
||||
self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsEditable)
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 1, self.item)
|
||||
self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsEditable)
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 2, self.item)
|
||||
self.item.setText(str(row[5]))
|
||||
self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsEditable)
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 3, self.item)
|
||||
self.item.setText(str(row[3]))
|
||||
self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsEditable)
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 4, self.item)
|
||||
self.item.setText(str("0"))
|
||||
self.item = QtWidgets.QTableWidgetItem()
|
||||
self.AuftragsdetailsTable.setItem(counter, 5, self.item)
|
||||
self.item.setFlags(self.item.flags() & ~QtCore.Qt.ItemIsEditable)
|
||||
|
||||
# Dropdown für Farben in die 6. Spalte einfügen
|
||||
#self.item = QtWidgets.QTableWidgetItem()
|
||||
#self.AuftragsdetailsTable.setItem(counter, 6, self.item)
|
||||
combo = QComboBox()
|
||||
combo.addItems(["Farbe", "Weiß", "Orange", "Grün"])
|
||||
combo.currentIndexChanged.connect(lambda index, rowId =counter: self.change_row_color(rowId, index))
|
||||
self.AuftragsdetailsTable.setCellWidget(counter, 6, combo)
|
||||
counter = counter +1
|
||||
|
||||
self.setRowColor(self.ArbeitsschrittTable, 0,0,255,0) #zum setzen der ersten Zeile der Auftragstabelle auf grün
|
||||
self.setRowColor(self.ArbeitsschrittTable, 1,255,165,0) #zum setzen der zweiten Zeile der Auftragstabelle auf orange
|
||||
self.setRowColor(self.ArbeitsschrittTable, 2,255,255,255) #zum setzen der dritten Zeile der Auftragstabelle auf weiß
|
||||
self.setRowColor(self.ArbeitsschrittTable, 3,255,255,255) #zum setzen der vierten Zeile der Auftragstabelle auf weiß
|
||||
|
||||
# setzen der beiden Felder auf einen leeren String, um Fehler zu Vermeiden, wenn ein neuer Auftrag geladen wird
|
||||
self.bauteiltypTextbox.setText("")
|
||||
self.PosNrTxtFeld.setText("")
|
||||
|
||||
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
|
||||
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
||||
|
||||
def change_row_color(self, row, color_index):
|
||||
if(color_index == 1):
|
||||
self.setRowColor(self.AuftragsdetailsTable, row,255,255,255)
|
||||
if(color_index == 2):
|
||||
self.setRowColor(self.AuftragsdetailsTable, row,255,165,0)
|
||||
if(color_index == 3):
|
||||
self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
|
||||
|
||||
def stopLoopClicked(self):
|
||||
''' damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert '''
|
||||
if hasattr(self, 'objectDetectionWorker'):
|
||||
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
||||
|
||||
if hasattr(self, 'checkWaageWorker'):
|
||||
self.checkWaageWorker.stopLoopSignal.emit(True)
|
||||
|
||||
def checkFinished(self):
|
||||
''' die Funktion geht alle Zeilen der Auftragsliste durch und schaut, ob die richtige Anzahl an Teilen vorhanden sind '''
|
||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
|
||||
return False
|
||||
return True
|
||||
|
||||
def checkWaage(self):
|
||||
QApplication.processEvents()
|
||||
|
||||
# überprüfen, ob der Auftrag geladen wurde
|
||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||
print("Der Auftrag muss zuerst geladen werden.")
|
||||
return
|
||||
|
||||
# überprüfen, ob ein Bauteiltyp gesetzt wurde
|
||||
if(self.checkPosNrEmpty()==True and self.checkBox.isChecked() == False):
|
||||
print("Das Pos.-Nr.-Feld ist leer.")
|
||||
return
|
||||
|
||||
# den GUI Wert von Textfeld TeileZuViel in die Variable schreiben
|
||||
self.teileZuViel = int(float(self.teileZuVielTxtFeld.toPlainText()))
|
||||
self.teileZuVielTxtFeld.setText(str(self.teileZuViel))
|
||||
|
||||
einzelteilID = -1 # Initialisieren der Variable mit einem Defaultwert, welcher nie eingenommen werden können sollte
|
||||
if (self.checkBox.isChecked() == False):
|
||||
#übernehmen der BauteilID aus dem Feld Pos.-Nr - wenn der Workflow dynamisch gewählt wurde
|
||||
einzelteilID = int(self.PosNrTxtFeld.toPlainText())
|
||||
else:
|
||||
# wenn der Workflow statisch gesetzt wurde, dann soll das erste Item aus der Auftragsliste geladen werden, von welchem noch nicht genug Bauteile auf der Waage liegen
|
||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
|
||||
einzelteilID = int(self.AuftragsdetailsTable.item(i,0).text())
|
||||
self.PosNrTxtFeld.setText(str(self.AuftragsdetailsTable.item(i,0).text()))
|
||||
self.bauteiltypTextbox.setText(str(self.AuftragsdetailsTable.item(i,2).text()))
|
||||
break
|
||||
|
||||
if einzelteilID == -1:
|
||||
# den Thread beenden
|
||||
self.checkWaageThread.quit()
|
||||
self.checkWaageThread.wait()
|
||||
try:
|
||||
self.checkWaageThread.started.disconnect() # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
|
||||
print("Der Thread wurde beendet.")
|
||||
except:
|
||||
print("Disconnecting the thread did not work.")
|
||||
return
|
||||
|
||||
|
||||
#zum setzen den Farbe der gesamten Reihe auf Orange
|
||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,165,0)
|
||||
self.setRowColor(self.ArbeitsschrittTable, 1,0,255,0) # zum setzen der zweiten Spalte der Arbeitsschrittetabelle auf grün
|
||||
self.setRowColor(self.ArbeitsschrittTable, 2,255,165,0) # zum setzen der dritten Spalte der Arbeitsschrittetabelle auf orange
|
||||
|
||||
# den Thread starten, welcher die Bauteilanzahl überprüft
|
||||
self.checkWaageWorker = Worker()
|
||||
self.checkWaageThread = QThread()
|
||||
|
||||
self.checkWaageWorker.moveToThread(self.checkWaageThread)
|
||||
|
||||
self.checkWaageWorker.checkWaageStartSignal.connect(self.checkWaageWorker.checkWaageThread)
|
||||
self.checkWaageWorker.checkWaageUpdateSignal.connect(self.checkWaageUpdate)
|
||||
self.checkWaageWorker.checkWaageFinishedSignal.connect(self.checkWaageFinished)
|
||||
self.checkWaageWorker.waageStoppedSignal.connect(self.threadStopped)
|
||||
self.checkWaageWorker.stopLoopSignal.connect(lambda status: setattr(self.checkWaageWorker, 'stopLoop', status)) #wird fürs aktive Stoppen des Threads benötigt
|
||||
|
||||
self.checkWaageThread.started.connect(lambda: self.checkWaageWorker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer))
|
||||
self.checkWaageThread.start()
|
||||
|
||||
def checkWaageUpdate(self, einzelteilID, anzahl):
|
||||
# die Funktion updated die (vom Thread) berechnete Bauteilanzahl in der GUI
|
||||
self.AuftragsdetailsTable.item(self.getRowNr(einzelteilID), 4).setText(str(anzahl)) # in die Tabelle die Anzahl an berechneten Bauteilen reinschreiben
|
||||
|
||||
def checkWaageFinished(self, einzelteilID):
|
||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),0,255,0) #zum setzen den Farbe der gesamten Reihe auf Grün
|
||||
|
||||
if self.checkFinished(): # wenn alle Bauteile auf der Waage liegen, soll folgender Code ausgeführt werden
|
||||
self.setRowColor(self.ArbeitsschrittTable, 2,0,255,0) # zum setzen der zweiten Spalte der Arbeitsschrittetabelle auf orange
|
||||
self.setRowColor(self.ArbeitsschrittTable, 3,0,255,0) # zum setzen der dritten Spalte der Arbeitsschrittetabelle auf weiß
|
||||
else: # wenn noch nicht alle Bauteile des Auftrags auf der Waage liegen, soll folgernder Code ausgeführt werden
|
||||
self.setRowColor(self.ArbeitsschrittTable, 1,255,165,0) # zum setzen der zweiten Spalte der Arbeitsschrittetabelle auf orange
|
||||
self.setRowColor(self.ArbeitsschrittTable, 2,255,255,255) # zum setzen der dritten Spalte der Arbeitsschrittetabelle auf weiß
|
||||
if self.checkBoxAutoTare.isChecked():
|
||||
self.onTareClick()
|
||||
|
||||
# den Thread beenden
|
||||
self.checkWaageThread.quit()
|
||||
self.checkWaageThread.wait()
|
||||
|
||||
# auch wenn die Länge der Liste überschritten wurde
|
||||
# wenn der statische Workflow aktiviert ist, dann soll die checkwaage-funktion erneut aufgerufen werden
|
||||
if(self.checkBox.isChecked() == True):
|
||||
self.checkWaage()
|
||||
|
||||
# GUI updaten
|
||||
#self.updateGUI()
|
||||
|
||||
def objectTypeDetection(self):
|
||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
||||
|
||||
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
||||
if self.checkBox.isChecked() == True:
|
||||
self.checkWaage()
|
||||
return
|
||||
|
||||
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||
print("Der Auftrag muss zuerst geladen werden.")
|
||||
return
|
||||
|
||||
# speichert den Wert, welcher im Textfeld steht in Variablen im Code
|
||||
self.setAuftragsnummer()
|
||||
|
||||
# starten des Threats, welcher den Bauteiltyp zurück gibt
|
||||
self.objectDetectionWorker = Worker()
|
||||
self.objectDetectionThread = QThread()
|
||||
|
||||
self.objectDetectionWorker.moveToThread(self.objectDetectionThread)
|
||||
|
||||
self.objectDetectionWorker.objectDetectionStartSignal.connect(self.objectDetectionWorker.objectTypeDetectionThread)
|
||||
self.objectDetectionWorker.objectDetectionFinishedSignal.connect(self.objectTypeDetectionFinished)
|
||||
self.objectDetectionWorker.waageStoppedSignal.connect(self.threadStopped)
|
||||
self.objectDetectionWorker.stopLoopSignal.connect(lambda status: setattr(self.objectDetectionWorker, 'stopLoop', status)) #wird fürs aktive Stoppen des Threads benötigt
|
||||
|
||||
self.objectDetectionThread.started.connect(lambda: self.objectDetectionWorker.objectDetectionStartSignal.emit(self.auftragsnummer))
|
||||
self.objectDetectionThread.start()
|
||||
|
||||
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
||||
''' wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden '''
|
||||
|
||||
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
||||
self.PosNrTxtFeld.setText(str(rowData[1]))
|
||||
self.bauteiltypTextbox.setText(rowData[2])
|
||||
|
||||
# setzt den Boolean, um aus der Schleife raus zu gehen
|
||||
self.btTypeIsSet = True
|
||||
|
||||
#zum setzen den Farbe der gesamten Reihe auf Orange
|
||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,165,0)
|
||||
|
||||
# den Thread beenden
|
||||
self.objectDetectionThread.quit()
|
||||
self.objectDetectionThread.wait()
|
||||
|
||||
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
||||
self.updateGUI()
|
||||
self.checkWaage()
|
||||
|
||||
def threadStopped(self, einzelteilID):
|
||||
''' wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0 '''
|
||||
if self.checkFinished() == False:
|
||||
if(einzelteilID > 0):
|
||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
||||
self.setRowColor(self.ArbeitsschrittTable, 2,255,255,255)
|
||||
self.setRowColor(self.ArbeitsschrittTable, 1,255,165,0)
|
||||
|
||||
# den Thread beenden
|
||||
if hasattr(self, 'objectDetectionThread'):
|
||||
self.objectDetectionThread.quit()
|
||||
self.objectDetectionThread.wait()
|
||||
print("Der ObjektDetection-Thread wurde beendet.")
|
||||
|
||||
if hasattr(self, 'checkWaageThread'):
|
||||
self.checkWaageThread.quit()
|
||||
self.checkWaageThread.wait()
|
||||
print("Der CheckWaage-Thread wurde beendet.")
|
||||
|
||||
# new class for Camera Object detection with YOLOv8
|
||||
class CameraStreamApp(QtWidgets.QMainWindow):
|
||||
def __init__(self, ui):
|
||||
super().__init__()
|
||||
self.ui = ui
|
||||
self.yolo_stream = None # Initialize YOLOv8CameraStream as None
|
||||
self.timer = QtCore.QTimer(self)
|
||||
self.timer.timeout.connect(self.update_frame)
|
||||
|
||||
# Populate the model dropdown menu
|
||||
self.populate_model_dropdown()
|
||||
|
||||
self.ui.startCamBtn.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
|
||||
self.ui.stopCamBtn.clicked.connect(self.stop_camera) # start camera if button LoadAuftrag is clicked
|
||||
self.scene = QtWidgets.QGraphicsScene(self)
|
||||
self.ui.graphicsView.setScene(self.scene)
|
||||
|
||||
def populate_model_dropdown(self):
|
||||
"""Populate the dropdown menu with model files from the models directory."""
|
||||
models_dir = "models"
|
||||
model_files = [f for f in os.listdir(models_dir) if f.endswith(".pt")]
|
||||
self.ui.modelComboBox.clear()
|
||||
self.ui.modelComboBox.addItems(model_files)
|
||||
|
||||
def start_camera(self):
|
||||
# Start the YOLOv8 camera stream (only if not already started)
|
||||
if self.yolo_stream is None:
|
||||
self.yolo_stream = YOLOv8CameraStream(model_path="models/yolov8m_seg_e300.pt", logging_level="high")
|
||||
# self.yolo_stream.start() # Start the YOLOv8 stream
|
||||
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
|
||||
|
||||
def stop_camera(self):
|
||||
# Stop the camera stream and processing
|
||||
if self.yolo_stream is not None:
|
||||
self.timer.stop() # Stop the timer
|
||||
self.yolo_stream.cap.release() # Release the camera resource
|
||||
self.yolo_stream = None # Reset the YOLOv8 stream object
|
||||
self.scene.clear() # Clear the displayed frame from the graphicsView
|
||||
print("Camera stream stopped and resources released.")
|
||||
|
||||
def update_frame(self):
|
||||
# Update the frame from YOLOv8 stream
|
||||
if self.yolo_stream:
|
||||
ret, frame = self.yolo_stream.cap.read() # Capture frame from YOLOv8 stream
|
||||
|
||||
if ret:
|
||||
# new part including processing via yolo model
|
||||
processed_frame = self.yolo_stream.process_frame(frame)
|
||||
|
||||
# Convert the frame from BGR (OpenCV format) to RGB
|
||||
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
||||
|
||||
# Convert the frame to QImage
|
||||
h, w, ch = frame.shape
|
||||
bytes_per_line = ch * w
|
||||
qt_image = QtGui.QImage(frame.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
|
||||
|
||||
# Add the QImage to a QPixmap
|
||||
pixmap = QtGui.QPixmap.fromImage(qt_image)
|
||||
|
||||
# Get the size of the graphicsView and scale the pixmap to fit
|
||||
view_size = self.ui.graphicsView.size()
|
||||
scaled_pixmap = pixmap.scaled(view_size, QtCore.Qt.KeepAspectRatio)
|
||||
|
||||
# Update the scene with the scaled pixmap
|
||||
self.scene.clear()
|
||||
self.scene.addPixmap(scaled_pixmap)
|
||||
|
||||
def closeEvent(self, event):
|
||||
# Release the camera when the application is closed
|
||||
if self.yolo_stream is not None:
|
||||
self.yolo_stream.cap.release()
|
||||
event.accept()
|
||||
|
||||
# new class for light control
|
||||
class LightControl(QtWidgets.QMainWindow):
|
||||
def __init__(self, ui):
|
||||
super().__init__()
|
||||
self.ui = ui
|
||||
|
||||
# init relay control
|
||||
self.ui.startSpotlightBtn.clicked.connect(self.spot_on)
|
||||
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
|
||||
self.r = sainsmartrelay.SainsmartRelay()
|
||||
|
||||
# init led control
|
||||
self.ui.redLightBtn.clicked.connect(self.red_on)
|
||||
self.ui.yellowLightBtn.clicked.connect(self.yellow_on)
|
||||
self.ui.greenLightBtn.clicked.connect(self.green_on)
|
||||
self.ui.offLightBtn.clicked.connect(self.leds_off)
|
||||
self.ui.blinkLightBtn.clicked.connect(self.blink_yellow)
|
||||
self.w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
||||
self.w.connect()
|
||||
#self.w.switch_to_green() # at appstart the light is green
|
||||
self.w.blink_green() # and switches to green blinking until the workflow gets started successfully#
|
||||
|
||||
# Connect app exit signal to the cleanup method
|
||||
app.aboutToQuit.connect(self.cleanup)
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up resources and switch off LEDs."""
|
||||
print("Cleaning up resources and switching off LEDs")
|
||||
self.leds_off() # Turn off LEDs
|
||||
self.w.disconnect() # Disconnect WLED controller
|
||||
|
||||
def spot_on(self):
|
||||
print("Turn on light clicked")
|
||||
self.r.turn_on(1)
|
||||
|
||||
def spot_off(self):
|
||||
print("Turn off light clicked")
|
||||
self.r.turn_off(1)
|
||||
|
||||
def red_on(self):
|
||||
print("Red light is on")
|
||||
self.w.switch_to_red()
|
||||
|
||||
def yellow_on(self):
|
||||
print("Yellow light is on")
|
||||
self.w.switch_to_yellow()
|
||||
|
||||
def green_on(self):
|
||||
print("Green light is on")
|
||||
self.w.switch_to_green()
|
||||
|
||||
def leds_off(self):
|
||||
print("LEDs are off")
|
||||
self.w.turn_off_all()
|
||||
|
||||
def blink_yellow(self):
|
||||
print("Yellow color is blinking")
|
||||
self.w.blink_yellow()
|
||||
|
||||
def blink_red(self):
|
||||
print("Red color is blinking")
|
||||
self.w.blink_red()
|
||||
|
||||
def blink_green(self):
|
||||
print("Green color is blinking")
|
||||
self.w.blink_green()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
MainWindow = QtWidgets.QMainWindow()
|
||||
ui = Ui_MainWindow()
|
||||
ui.setupUi(MainWindow)
|
||||
|
||||
# Initialize the CameraStreamApp with the UI
|
||||
camera_app = CameraStreamApp(ui)
|
||||
# initialize light control app
|
||||
light_app = LightControl(ui)
|
||||
|
||||
MainWindow.show()
|
||||
sys.exit(app.exec_())
|
Loading…
Reference in New Issue
Block a user