update: delete unnecessary files

This commit is contained in:
Your Name 2024-12-02 08:17:02 +01:00
parent d89ae03a64
commit b452a3df74
3 changed files with 84 additions and 2229 deletions

View File

@ -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 QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
@ -31,6 +20,12 @@ import os
import lib.sainsmartrelay as sainsmartrelay import lib.sainsmartrelay as sainsmartrelay
import lib.wledControl as wledControl 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 = { db_config = {
'user': 'dbUser', 'user': 'dbUser',
'password': 'dbPassword', 'password': 'dbPassword',
@ -39,11 +34,24 @@ db_config = {
'port': 3306 # Standard port for MariaDB '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) conn = mariadb.connect(**db_config)
print("Database connection established successfully.")
# Create a cursor to execute queries # Create a cursor to execute queries
cursor = conn.cursor() 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 # Configuration of the serial port
try: try:
@ -52,34 +60,8 @@ try:
except serial.SerialException: except serial.SerialException:
ser = None ser = None
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.") 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.
# 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
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):
class Worker(QObject): class Worker(QObject):
#progress = pyqtSignal(int) #progress = pyqtSignal(int)
objectDetectionStartSignal = pyqtSignal(str) objectDetectionStartSignal = pyqtSignal(str)
@ -92,6 +74,7 @@ class Worker(QObject):
waageStoppedSignal = pyqtSignal(int) waageStoppedSignal = pyqtSignal(int)
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf) stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
waageEingeschwungen = False
stopLoop = False stopLoop = False
btTypeIsSet = False btTypeIsSet = False
correctBtNr = False correctBtNr = False
@ -103,7 +86,7 @@ class Worker(QObject):
def getDataOfArticleType(self, allArticles, articleType): 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: for i in allArticles:
if i[1] == articleType: if i[1] == articleType:
return i return i
@ -113,26 +96,27 @@ class Worker(QObject):
def waageNichtEingeschwungenOutput(self): def waageNichtEingeschwungenOutput(self):
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.") 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): def readWaage(self):
# in folgender Funktion wird die Waage ausgelesen ''' 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
if ser.is_open == False: if ser.is_open == False:
ser.open() ser.open()
#an die Waage den Befehl senden, dass sie ausgelesen werden soll #an die Waage den Befehl senden, dass sie ausgelesen werden soll
ser.write(b'getWeight\n') 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 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 # wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
lenString = len(serialString)-1 lenString = len(serialString)-1
if serialString[lenString] == "g" and serialString[lenString-1] == "k": if serialString[lenString] == "g" and serialString[lenString-1] == "k":
#print("ist eingeschwungen") #Debuggingausgabe
waageEingeschwungen = True waageEingeschwungen = True
else: else:
print("die Waage ist noch nicht eingeschwungen") 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": 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 intString = intString + i
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg") print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
## Waage auslesen - ENDE
ser.close() ser.close()
#print("connection is open: ", ser.is_open) #Debuggingausgabe
return waageEingeschwungen, intString return waageEingeschwungen, intString
def objectTypeDetectionThread(self, auftragsnummer): def objectTypeDetectionThread(self, auftragsnummer):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt ''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
# Parameterdefinition # Parameterdefinition
propDensVect = [] propDensVect = []
@ -174,16 +154,9 @@ class Worker(QObject):
cursor.execute(sql_query) cursor.execute(sql_query)
auftragEinzelteilDaten = cursor.fetchall() 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 # in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
for row in auftragEinzelteilDaten: 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 # Jenen Eintrag des propDensVect raussuchen, welcher die größte Wahrscheinlichkeitsdichte beinhaltet
maxpropDens = 0 maxpropDens = 0
@ -201,14 +174,6 @@ class Worker(QObject):
else: else:
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.") 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 # den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
self.btTypeIsSet = True self.btTypeIsSet = True
@ -219,6 +184,7 @@ class Worker(QObject):
self.waageStoppedSignal.emit(einzelteilID) self.waageStoppedSignal.emit(einzelteilID)
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer): def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
''' in dieser Funktion wird die Stückzahl der Bauteile, welche auf der Waage liegen, berechnet '''
self.correctBtNr = False self.correctBtNr = False
prevAnzahl = 0 prevAnzahl = 0
@ -238,14 +204,6 @@ class Worker(QObject):
cursor.execute(sql_query) cursor.execute(sql_query)
auftragDaten = cursor.fetchall() 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 #auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
anzBauteile_soll = 0 anzBauteile_soll = 0
idVorhanden = False 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 # 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 mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz 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 # durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
maxpropDens = 0 maxpropDens = 0
@ -280,14 +238,6 @@ class Worker(QObject):
if prevAnzahl != anzahl: if prevAnzahl != anzahl:
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 # wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
if (anzahl == anzBauteile_soll): if (anzahl == anzBauteile_soll):
self.correctBtNr = True self.correctBtNr = True
@ -307,8 +257,7 @@ class Worker(QObject):
self.waageStoppedSignal.emit(einzelteilID) self.waageStoppedSignal.emit(einzelteilID)
## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
self.auftragsnummer = "" self.auftragsnummer = ""
@ -316,7 +265,6 @@ class Ui_MainWindow(object):
self.correctBtNr = False self.correctBtNr = False
self.btTypeIsSet = False self.btTypeIsSet = False
MainWindow.setObjectName("MainWindow") MainWindow.setObjectName("MainWindow")
MainWindow.resize(1400, 675) MainWindow.resize(1400, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget = QtWidgets.QWidget(MainWindow)
@ -476,16 +424,6 @@ class Ui_MainWindow(object):
self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget) self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget)
self.blinkLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+300, 161, 25)) 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 # Maximize the window on startup
MainWindow.showMaximized() MainWindow.showMaximized()
@ -520,8 +458,6 @@ class Ui_MainWindow(object):
item = self.ArbeitsschrittTable.horizontalHeaderItem(1) item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "ToDo:")) item.setText(_translate("MainWindow", "ToDo:"))
# Befüllen der Arbeisschritttabelle mit Text
#item = self.ArbeitsschrittTable.
# Ein neues QTableWidgetItem erstellen und den Text setzen # Ein neues QTableWidgetItem erstellen und den Text setzen
item = QtWidgets.QTableWidgetItem("Auftrag laden") item = QtWidgets.QTableWidgetItem("Auftrag laden")
self.ArbeitsschrittTable.setItem(0, 0, item) self.ArbeitsschrittTable.setItem(0, 0, item)
@ -539,19 +475,10 @@ class Ui_MainWindow(object):
self.ArbeitsschrittTable.setItem(3, 0, item) self.ArbeitsschrittTable.setItem(3, 0, item)
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers) 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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen")) self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection) self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick) 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.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:")) self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:")) self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
@ -573,10 +500,8 @@ class Ui_MainWindow(object):
# new camera workflow # new camera workflow
self.startCamBtn.setText(_translate("MainWindow", "Start Camera")) self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
# self.startCamBtn.clicked.connect(self.startCamBtnClicked)
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera")) self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow")) self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
# self.camWorkFlowcheckBox.clicked.connect(self.onCheckboxCheck)
self.modelComboBox self.modelComboBox
# relay control buttons # relay control buttons
@ -588,23 +513,20 @@ class Ui_MainWindow(object):
self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED")) self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED"))
self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED")) self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED"))
self.offLightBtn.setText(_translate("MainWindow", "Turn off all LEDs")) 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): def mousePressEvent(self, event):
print("Das MainWindow wurde angeklickt.") print("Das MainWindow wurde angeklickt.")
self.setFocus() self.setFocus()
super().mousePressEvent(event) super().mousePressEvent(event)
def onTareClick(self): def onTareClick(self):
#Tarieren der Waage ''' Tarieren der Waage '''
if ser.is_open == False: if ser.is_open == False:
ser.open() ser.open()
ser.write(b'tare\n') ser.write(b'tare\n')
ser.close() ser.close()
def onCheckboxCheck(self): def onCheckboxCheck(self):
if self.checkBox.isChecked() == True: if self.checkBox.isChecked() == True:
print("static workflow activated") print("static workflow activated")
@ -621,9 +543,6 @@ class Ui_MainWindow(object):
for i in range(0,self.AuftragsdetailsTable.rowCount()): for i in range(0,self.AuftragsdetailsTable.rowCount()):
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)): if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
return i 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): def onTableCellClick(self):
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text()) self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
@ -648,71 +567,21 @@ class Ui_MainWindow(object):
else: else:
return False 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): def updateGUI(self):
self.PosNrLabel.repaint() #GUI aktualisieren self.PosNrLabel.repaint() #GUI aktualisieren
QApplication.processEvents() #GUI aktualisieren QApplication.processEvents() #GUI aktualisieren
def setRowColor(self, tableObject, rowID,r,g,b): def setRowColor(self, tableObject, rowID,r,g,b):
for col in range(tableObject.columnCount()-1): for col in range(tableObject.columnCount()-1):
tableObject.item(rowID, col).setBackground(QtGui.QColor(r,g,b)) 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 # # call change led color
def readWaage(self): # Check if the 'w' object already exists
# in folgender Funktion wird die Waage ausgelesen # hier könnte noch nachgearbeitet werden
if not hasattr(self, 'w'):
#print("connection is open: ", ser.is_open) #Debuggingausgabe w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe w.connect()
self.checkPosNrEmpty() w.map_color_to_led([r,g,b])
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
def auftragsBtnClicked(self): def auftragsBtnClicked(self):
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet 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.") print("Fehler in der Datenbankabfrage.")
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0: 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 ### die Auftragsdaten in die Tabelle laden
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten)) self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
@ -787,7 +647,6 @@ class Ui_MainWindow(object):
self.bauteiltypTextbox.setText("") self.bauteiltypTextbox.setText("")
self.PosNrTxtFeld.setText("") self.PosNrTxtFeld.setText("")
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0): elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.") 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) self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
def stopLoopClicked(self): 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'): if hasattr(self, 'objectDetectionWorker'):
self.objectDetectionWorker.stopLoopSignal.emit(True) self.objectDetectionWorker.stopLoopSignal.emit(True)
@ -808,20 +667,15 @@ class Ui_MainWindow(object):
self.checkWaageWorker.stopLoopSignal.emit(True) self.checkWaageWorker.stopLoopSignal.emit(True)
def checkFinished(self): 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()): for i in range(0,self.AuftragsdetailsTable.rowCount()):
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text(): if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
return False return False
return True return True
def checkWaage(self): def checkWaage(self):
#print("Running in thread:", threading.current_thread().name) # Debuggingausgabe
QApplication.processEvents() 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 # überprüfen, ob der Auftrag geladen wurde
if(self.AuftragsdetailsTable.item(0,0) == None): if(self.AuftragsdetailsTable.item(0,0) == None):
print("Der Auftrag muss zuerst geladen werden.") print("Der Auftrag muss zuerst geladen werden.")
@ -910,22 +764,13 @@ class Ui_MainWindow(object):
#self.updateGUI() #self.updateGUI()
def objectTypeDetection(self): 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 # 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: if self.checkBox.isChecked() == True:
self.checkWaage() self.checkWaage()
return 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 # überprüfen, ob der Auftrag in die Tabelle geladen wurde
if(self.AuftragsdetailsTable.item(0,0) == None): if(self.AuftragsdetailsTable.item(0,0) == None):
print("Der Auftrag muss zuerst geladen werden.") print("Der Auftrag muss zuerst geladen werden.")
@ -949,7 +794,7 @@ class Ui_MainWindow(object):
self.objectDetectionThread.start() self.objectDetectionThread.start()
def objectTypeDetectionFinished(self, einzelteilID, rowData): 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 # Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
self.PosNrTxtFeld.setText(str(rowData[1])) self.PosNrTxtFeld.setText(str(rowData[1]))
@ -965,20 +810,12 @@ class Ui_MainWindow(object):
self.objectDetectionThread.quit() self.objectDetectionThread.quit()
self.objectDetectionThread.wait() 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 # wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
self.updateGUI() self.updateGUI()
self.checkWaage() self.checkWaage()
def threadStopped(self, einzelteilID): 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 self.checkFinished() == False:
if(einzelteilID > 0): 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.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() self.checkWaageThread.wait()
print("Der CheckWaage-Thread wurde beendet.") print("Der CheckWaage-Thread wurde beendet.")
# new class for Camera Object detection with YOLOv8 # new class for Camera Object detection with YOLOv8
class CameraStreamApp(QtWidgets.QMainWindow): class CameraStreamApp(QtWidgets.QMainWindow):
def __init__(self, ui): def __init__(self, ui):
@ -1048,7 +884,7 @@ class CameraStreamApp(QtWidgets.QMainWindow):
# Convert the frame from BGR (OpenCV format) to RGB # Convert the frame from BGR (OpenCV format) to RGB
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 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 # Convert the frame to QImage
h, w, ch = frame.shape h, w, ch = frame.shape
@ -1078,16 +914,30 @@ class LightControl(QtWidgets.QMainWindow):
super().__init__() super().__init__()
self.ui = ui self.ui = ui
# init relay control
self.ui.startSpotlightBtn.clicked.connect(self.spot_on) self.ui.startSpotlightBtn.clicked.connect(self.spot_on)
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off) self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
self.r = sainsmartrelay.SainsmartRelay() self.r = sainsmartrelay.SainsmartRelay()
# init led control
self.ui.redLightBtn.clicked.connect(self.red_on) self.ui.redLightBtn.clicked.connect(self.red_on)
self.ui.yellowLightBtn.clicked.connect(self.yellow_on) self.ui.yellowLightBtn.clicked.connect(self.yellow_on)
self.ui.greenLightBtn.clicked.connect(self.green_on) self.ui.greenLightBtn.clicked.connect(self.green_on)
self.ui.offLightBtn.clicked.connect(self.leds_off) 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 = 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): def spot_on(self):
print("Turn on light clicked") print("Turn on light clicked")
@ -1113,9 +963,17 @@ class LightControl(QtWidgets.QMainWindow):
print("LEDs are off") print("LEDs are off")
self.w.turn_off_all() self.w.turn_off_all()
def leds_blink(self): def blink_yellow(self):
print("Previous color is blinking") print("Yellow color is blinking")
self.w.change_effect() 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__": if __name__ == "__main__":
import sys import sys

File diff suppressed because it is too large Load Diff

View File

@ -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_())