Compare commits

..

No commits in common. "main" and "feat/vision" have entirely different histories.

445 changed files with 6564 additions and 184 deletions

View File

@ -1 +0,0 @@
{"rev":[1,0],"vid":2410270,"id":{"mdns":"wled-9986c8","name":"cps-warnlight-wled1","inv":"Light","sui":false},"nw":{"espnow":false,"linked_remote":"","ins":[{"ssid":"cpsWlan24GHz","pskl":10,"ip":[0,0,0,0],"gw":[0,0,0,0],"sn":[255,255,255,0]}],"dns":[10,71,1,1]},"ap":{"ssid":"wled_warnLight-AP","pskl":8,"chan":1,"hide":0,"behav":0,"ip":[4,3,2,1]},"wifi":{"sleep":false,"phy":false,"txpwr":78},"hw":{"led":{"total":18,"maxpwr":850,"ledma":0,"cct":false,"cr":false,"ic":false,"cb":0,"fps":42,"rgbwm":255,"ld":true,"ins":[{"start":0,"len":6,"pin":[16],"order":0,"rev":false,"skip":0,"type":22,"ref":false,"rgbwm":0,"freq":0,"maxpwr":283,"ledma":55},{"start":6,"len":6,"pin":[17],"order":0,"rev":false,"skip":0,"type":22,"ref":false,"rgbwm":0,"freq":0,"maxpwr":283,"ledma":55},{"start":12,"len":6,"pin":[18],"order":0,"rev":false,"skip":0,"type":22,"ref":false,"rgbwm":0,"freq":0,"maxpwr":283,"ledma":55}]},"com":[],"btn":{"max":4,"pull":true,"ins":[{"type":2,"pin":[0],"macros":[0,0,0]},{"type":0,"pin":[-1],"macros":[0,0,0]},{"type":0,"pin":[-1],"macros":[0,0,0]},{"type":0,"pin":[-1],"macros":[0,0,0]}],"tt":32,"mqtt":true},"ir":{"pin":-1,"type":0,"sel":true},"relay":{"pin":-1,"rev":false,"odrain":false},"baud":1152,"if":{"i2c-pin":[-1,-1],"spi-pin":[-1,-1,-1]}},"light":{"scale-bri":100,"pal-mode":0,"aseg":true,"gc":{"bri":1,"col":2.8,"val":2.8},"tr":{"mode":true,"fx":true,"dur":7,"pal":false,"rpc":5,"hrp":true},"nl":{"mode":1,"dur":60,"tbri":0,"macro":0}},"def":{"ps":4,"on":true,"bri":128},"if":{"sync":{"port0":21324,"port1":65506,"espnow":false,"recv":{"bri":true,"col":true,"fx":true,"pal":true,"grp":1,"seg":false,"sb":false},"send":{"en":false,"dir":false,"btn":false,"va":false,"hue":true,"grp":1,"ret":0}},"nodes":{"list":true,"bcast":true},"live":{"en":true,"mso":false,"rlm":true,"port":5568,"mc":false,"dmx":{"uni":1,"seqskip":false,"e131prio":0,"addr":1,"dss":0,"mode":4},"timeout":25,"maxbri":false,"no-gc":true,"offset":0},"va":{"alexa":false,"macros":[0,0],"p":0},"mqtt":{"en":true,"broker":"10.71.1.103","port":1883,"user":"cpsMqtt","pskl":10,"cid":"WLED-9986c8","rtn":false,"topics":{"device":"wled/9986c8","group":"wled/all"}},"hue":{"en":false,"id":1,"iv":25,"recv":{"on":true,"bri":true,"col":true},"ip":[10,71,1,0]},"ntp":{"en":false,"host":"0.wled.pool.ntp.org","tz":0,"offset":0,"ampm":false,"ln":0,"lt":0}},"ol":{"clock":0,"cntdwn":false,"min":0,"max":29,"o12pix":0,"o5m":false,"osec":false,"osb":false},"timers":{"cntdwn":{"goal":[20,1,1,0,0,0],"macro":0},"ins":[]},"ota":{"lock":false,"lock-wifi":false,"pskl":7,"aota":true},"um":{"AudioReactive":{"enabled":false,"add-palettes":false,"analogmic":{"pin":-1},"digitalmic":{"type":1,"pin":[32,15,14,-1]},"config":{"squelch":10,"gain":60,"AGC":0},"frequency":{"scale":3},"dynamics":{"limiter":true,"rise":80,"fall":1400},"sync":{"port":11988,"mode":0}}}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,950 @@
# -*- 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
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
# db_config = {
# 'user': 'dbUser',
# 'password': 'dbPassword',
# 'host': '127.0.0.1', # 'host': 'localhost',
# 'database': 'projectGeislinger',
# 'port': 3306 # Standard port for MariaDB
# }
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': '127.0.0.1', # 'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
#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/
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):
#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)
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 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
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 objectTypeDetectionThread(self, auftragsnummer):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
# 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()
'''
# 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]])
# 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.")
# 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
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):
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()
'''
# 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
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([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
# 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
# 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)
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")
#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)
'''
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:"))
# 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)
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.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:"))
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)
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
# 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())
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
# 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
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:
'''
# 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))
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):
#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.")
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
'''
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.")
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()
'''
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
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.")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

View File

@ -0,0 +1,751 @@
# -*- 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.
##########Es muss noch überprüft werden, ob der PC mit der Waage überhaupt verbunden ist
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject
import serial
import binascii
import math
import mariadb
import time
import threading
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
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):
#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)
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 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
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 objectTypeDetectionThread(self, auftragsnummer):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
# 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()
'''
# 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]])
# 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.")
# 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
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):
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()
'''
# 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
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([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
# 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
# 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)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.auftragsnummer = ""
self.teileZuViel = 0 # 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(1090, 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")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 300, 661, 192))
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(6)
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)
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, 150, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 460, 161, 25))
self.checkWaageBtn.setObjectName("checkWaageBtn")
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 500, 161, 25))
self.stopLoopBtn.setObjectName("stopLoopBtn")
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
self.waageTareBtn.setGeometry(QtCore.QRect(700, 100, 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.BezeichnungLabel.setObjectName("BezeichnungLabel")
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
self.teileZuVielLabel.setGeometry(QtCore.QRect(700, 350, 350, 17))
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(700, 370, 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)
'''
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setVerticalHeaderItem(0,item)
'''
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)
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"))
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:"))
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.thread = QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.worker.objectDetectionFinishedSignal.connect(self.objectTypeDetectionFinished)
self.worker.waageStoppedSignal.connect(self.threadStopped)
self.worker.stopLoopSignal.connect(lambda status: setattr(self.worker, 'stopLoop', status))
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("clickedCheckboxTrue")
else:
print("clickedCheckboxFalse")
def getRowNr(self, posNr):
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())
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
# 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, rowID,r,g,b):
self.AuftragsdetailsTable.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 1).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 2).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 3).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 4).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.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
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:
'''
# 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))
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)
counter = counter +1
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
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
self.worker.stopLoopSignal.emit(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.worker.stopLoopSignal.emit(False)
# überprüfen, ob ein Bauteiltyp gesetzt wurde
if(self.checkPosNrEmpty()==True):
print("Das Pos.-Nr.-Feld ist leer.")
return
if(self.AuftragsdetailsTable.item(0,0) == None):
print("Der Auftrag muss zuerst geladen werden.")
return
# den GUI Wert von Textfeld TeileZuViel in die Variable schreiben
self.teileZuViel = int(float(self.teileZuVielTxtFeld.toPlainText()))
self.teileZuVielTxtFeld.setText(str(self.teileZuViel))
#übernehmen der BauteilID aus dem Feld Pos.-Nr
einzelteilID = int(self.PosNrTxtFeld.toPlainText())
#zum setzen den Farbe der gesamten Reihe auf Orange
self.setRowColor(self.getRowNr(einzelteilID),255,165,0)
# den Thread starten, welcher die Bauteilanzahl überprüft
self.worker.checkWaageStartSignal.connect(self.worker.checkWaageThread)
self.worker.checkWaageUpdateSignal.connect(self.checkWaageUpdate)
self.worker.checkWaageFinishedSignal.connect(self.checkWaageFinished)
self.thread.started.connect(lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer))
self.thread.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.getRowNr(einzelteilID),0,255,0) #zum setzen den Farbe der gesamten Reihe auf Grün
# den Thread beenden
self.thread.quit()
self.thread.wait()
try:
self.thread.started.disconnect(lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer)) # 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.") # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
# GUI updaten
#self.updateGUI()
def objectTypeDetection(self):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
'''
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.worker.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.")
return
# speichert den Wert, welcher im Textfeld steht in Variablen im Code
self.setAuftragsnummer()
# starten des Threats, welcher den Bauteiltyp zurück gibt
self.worker.objectDetectionStartSignal.connect(self.worker.objectTypeDetectionThread)
self.thread.started.connect(lambda: self.worker.objectDetectionStartSignal.emit(self.auftragsnummer))
self.thread.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.getRowNr(einzelteilID),255,165,0)
# den Thread beenden
self.thread.quit()
self.thread.wait()
try:
self.thread.started.disconnect() # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
except:
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
if(einzelteilID > 0):
self.setRowColor(self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
# den Thread beenden
self.thread.quit()
self.thread.wait()
try:
self.thread.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.")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

View File

@ -0,0 +1,823 @@
# -*- 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
from PyQt5.QtWidgets import QApplication, QComboBox
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject
from PyQt5.QtGui import QColor
import serial
import binascii
import math
import mariadb
import time
import threading
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': '127.0.0.1', # 'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
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):
#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)
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 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
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 objectTypeDetectionThread(self, auftragsnummer):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
# 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()
'''
# 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]])
# 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.")
# 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
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):
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()
'''
# 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
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([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
# 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
# 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)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.auftragsnummer = ""
self.teileZuViel = 0 # 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(1090, 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")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 300, 661, 192))
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)
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, 150, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 460, 161, 25))
self.checkWaageBtn.setObjectName("checkWaageBtn")
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 500, 161, 25))
self.stopLoopBtn.setObjectName("stopLoopBtn")
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
self.waageTareBtn.setGeometry(QtCore.QRect(700, 100, 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.BezeichnungLabel.setObjectName("BezeichnungLabel")
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
self.teileZuVielLabel.setGeometry(QtCore.QRect(700, 350, 350, 17))
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(700, 370, 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(700, 10, 151, 23))
self.checkBox.setObjectName("checkBox")
#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)
'''
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)
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"))
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:"))
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)
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 getRowNr(self, posNr):
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())
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
# 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, rowID,r,g,b):
self.AuftragsdetailsTable.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 1).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 2).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 3).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 4).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.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
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:
'''
# 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))
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
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(row,255,255,255)
if(color_index == 2):
self.setRowColor(row,255,165,0)
if(color_index == 3):
self.setRowColor(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 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.")
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.getRowNr(einzelteilID),255,165,0)
# 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.getRowNr(einzelteilID),0,255,0) #zum setzen den Farbe der gesamten Reihe auf Grün
# 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
'''
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.")
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.getRowNr(einzelteilID),255,165,0)
# den Thread beenden
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
if(einzelteilID > 0):
self.setRowColor(self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
# 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.")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -23,18 +23,25 @@ import mariadb
import time import time
import threading import threading
from lib.CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
import cv2 import cv2
import os import os
import lib.sainsmartrelay as sainsmartrelay import sainsmartrelay
import lib.wledControl as wledControl
# db_config = {
# 'user': 'dbUser',
# 'password': 'dbPassword',
# 'host': '127.0.0.1', # 'host': 'localhost',
# 'database': 'projectGeislinger',
# 'port': 3306 # Standard port for MariaDB
# }
db_config = { db_config = {
'user': 'dbUser', 'user': 'dbUser',
'password': 'dbPassword', 'password': 'dbPassword',
'host': '127.0.0.1', # 'host': 'localhost', changed because more compatible 'host': '127.0.0.1', # 'host': 'localhost',
'database': 'projectGeislinger', 'database': 'projectGeislinger',
'port': 3306 # Standard port for MariaDB 'port': 3306 # Standard port for MariaDB
} }
@ -55,8 +62,6 @@ except serial.SerialException:
#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 #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) # 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/ # 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 waageEingeschwungen = False
@ -456,7 +461,7 @@ class Ui_MainWindow(object):
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.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") self.graphicsView.setObjectName("graphicsView")
# relay control buttons # relay control
self.startSpotlightBtn = QtWidgets.QPushButton(self.centralwidget) 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.setGeometry(QtCore.QRect(700+200, int(1080/2)+100, 161, 25)) #int(1080/2)+100
self.startSpotlightBtn.setObjectName("startSpotlightBtn") self.startSpotlightBtn.setObjectName("startSpotlightBtn")
@ -464,18 +469,6 @@ class Ui_MainWindow(object):
self.stopSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+150, 161, 25)) self.stopSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+150, 161, 25))
self.stopSpotlightBtn.setObjectName("stopSpotlightBtn") 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))
#self.myTestLambda = lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer) #self.myTestLambda = lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer)
''' '''
@ -579,16 +572,10 @@ class Ui_MainWindow(object):
# self.camWorkFlowcheckBox.clicked.connect(self.onCheckboxCheck) # self.camWorkFlowcheckBox.clicked.connect(self.onCheckboxCheck)
self.modelComboBox self.modelComboBox
# relay control buttons # relay control
self.startSpotlightBtn.setText(_translate("MainWindow", "Turn on light")) self.startSpotlightBtn.setText(_translate("MainWindow", "Turn on light"))
self.stopSpotlightBtn.setText(_translate("MainWindow", "Turn off 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 last LED"))
def mousePressEvent(self, event): def mousePressEvent(self, event):
@ -1072,8 +1059,8 @@ class CameraStreamApp(QtWidgets.QMainWindow):
self.yolo_stream.cap.release() self.yolo_stream.cap.release()
event.accept() event.accept()
# new class for light control # new class for relay control
class LightControl(QtWidgets.QMainWindow): class RelayControl(QtWidgets.QMainWindow):
def __init__(self, ui): def __init__(self, ui):
super().__init__() super().__init__()
self.ui = ui self.ui = ui
@ -1082,13 +1069,6 @@ class LightControl(QtWidgets.QMainWindow):
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off) self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
self.r = sainsmartrelay.SainsmartRelay() self.r = sainsmartrelay.SainsmartRelay()
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.w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
def spot_on(self): def spot_on(self):
print("Turn on light clicked") print("Turn on light clicked")
self.r.turn_on(1) self.r.turn_on(1)
@ -1099,23 +1079,27 @@ class LightControl(QtWidgets.QMainWindow):
def red_on(self): def red_on(self):
print("Red light is on") print("Red light is on")
self.w.switch_to_red() self.r.turn_on(2)
def red_off(self):
print("Red light is off")
self.r.turn_off(2)
def yellow_on(self): def yellow_on(self):
print("Yellow light is on") print("Yellow light is on")
self.w.switch_to_yellow() self.r.turn_on(3)
def yellow_off(self):
print("Yellow light is off")
self.r.turn_off(3)
def green_on(self): def green_on(self):
print("Green light is on") print("Green light is on")
self.w.switch_to_green() self.r.turn_on(4)
def leds_off(self): def green_off(self):
print("LEDs are off") print("Green light is off")
self.w.turn_off_all() self.r.turn_off(4)
def leds_blink(self):
print("Previous color is blinking")
self.w.change_effect()
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
@ -1126,8 +1110,8 @@ if __name__ == "__main__":
# Initialize the CameraStreamApp with the UI # Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui) camera_app = CameraStreamApp(ui)
# initialize light control app # initialize relay app
light_app = LightControl(ui) relay_app = RelayControl(ui)
MainWindow.show() MainWindow.show()
sys.exit(app.exec_()) sys.exit(app.exec_())

222
bjoerntest2.py Normal file
View File

@ -0,0 +1,222 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'testbjoern2.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# 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.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
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(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(800, 280, 256, 192))
self.graphicsView.setObjectName("graphicsView")
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.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"))
item = self.AuftragsdetailsTable.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "T1"))
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", "Menge"))
item = self.AuftragsdetailsTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "Lgort"))
__sortingEnabled = self.AuftragsdetailsTable.isSortingEnabled()
self.AuftragsdetailsTable.setSortingEnabled(False)
item = self.AuftragsdetailsTable.item(0, 0)
item.setText(_translate("MainWindow", "I1"))
self.AuftragsdetailsTable.setSortingEnabled(__sortingEnabled)
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.bauteiltypTextbox.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
import sys
import cv2
#from PyQt5 import QtCore, QtWidgets, QtGui
class CameraStreamApp(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
# OpenCV video capture (0 for the default camera)
self.cap = None # Initialize capture as None (stream starts on button click)
# Timer for updating the frame
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_frame)
def initUI(self):
self.setWindowTitle("Camera Stream")
# Create a QGraphicsView widget
self.graphicsView = QtWidgets.QGraphicsView(self)
self.graphicsView.setGeometry(QtCore.QRect(50, 50, 640, 480))
self.graphicsView.setObjectName("graphicsView")
# Create a QGraphicsScene to hold the frame
self.scene = QtWidgets.QGraphicsScene()
self.graphicsView.setScene(self.scene)
# Create a button to start the camera stream
self.startButton = QtWidgets.QPushButton('Start Camera', self)
self.startButton.setGeometry(QtCore.QRect(50, 550, 120, 40)) # Position the button below the view
self.startButton.clicked.connect(self.start_camera)
# Show the main window
self.setGeometry(100, 100, 800, 600)
self.show()
def start_camera(self):
# Start OpenCV video capture (only if not already started)
if self.cap is None:
self.cap = cv2.VideoCapture(0)
if not self.cap.isOpened():
print("Error: Unable to open the camera.")
return
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
def update_frame(self):
if self.cap:
ret, frame = self.cap.read() # Capture frame from the camera
if ret:
# Convert the frame from BGR (OpenCV format) to RGB
frame = cv2.cvtColor(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)
# Update the scene with the new pixmap
self.scene.clear()
self.scene.addPixmap(pixmap)
def closeEvent(self, event):
# Release the camera when the application is closed
if self.cap is not None:
self.cap.release()
event.accept()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

181
bjoerntest3.py Normal file
View File

@ -0,0 +1,181 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(800, 280, 256, 192))
self.graphicsView.setObjectName("graphicsView")
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.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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
class CameraStreamApp(QtWidgets.QMainWindow):
def __init__(self, ui):
super().__init__()
self.ui = ui
self.cap = None # Initialize capture as None (stream starts on button click)
# Timer for updating the frame
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_frame)
# Set up the camera stream button
self.ui.btn1.clicked.connect(self.start_camera)
# Set up the graphics view and scene
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
def start_camera(self):
# Start OpenCV video capture (only if not already started)
if self.cap is None:
self.cap = cv2.VideoCapture(0)
if not self.cap.isOpened():
print("Error: Unable to open the camera.")
return
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
# def update_frame(self):
# if self.cap:
# ret, frame = self.cap.read() # Capture frame from the camera
# if ret:
# # Convert the frame from BGR (OpenCV format) to RGB
# frame = cv2.cvtColor(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)
# # Update the scene with the new pixmap
# self.scene.clear()
# self.scene.addPixmap(pixmap)
def update_frame(self):
if self.cap:
ret, frame = self.cap.read() # Capture frame from the camera
if ret:
# Convert the frame from BGR (OpenCV format) to RGB
frame = cv2.cvtColor(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.cap is not None:
self.cap.release()
event.accept()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

154
bjoerntest4.py Normal file
View File

@ -0,0 +1,154 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(800, 280, 256, 192))
self.graphicsView.setObjectName("graphicsView")
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.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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
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)
self.ui.btn1.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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 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:
# Convert the frame from BGR (OpenCV format) to RGB
frame = cv2.cvtColor(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()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

159
bjoerntest5.py Normal file
View File

@ -0,0 +1,159 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(800, 280, 256, 192))
self.graphicsView.setObjectName("graphicsView")
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.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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
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)
self.ui.btn1.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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 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) # might change nomenclature later?
# 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()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

138
bjoerntest6.py Normal file
View File

@ -0,0 +1,138 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# Create a vertical layout
self.layout = QtWidgets.QVBoxLayout(self.centralwidget)
# Add your widgets to the layout
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
self.layout.addWidget(self.AuftragsdetailsTable)
self.label = QtWidgets.QLabel(self.centralwidget)
self.layout.addWidget(self.label)
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.layout.addWidget(self.textEdit)
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.layout.addWidget(self.bauteilTypBtn)
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.layout.addWidget(self.bauteiltypTextbox)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.layout.addWidget(self.label_3)
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.layout.addWidget(self.label_4)
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.layout.addWidget(self.textEdit_3)
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.layout.addWidget(self.checkBox)
# Create the QGraphicsView
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.layout.addWidget(self.graphicsView)
# Add a button to the layout
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.layout.addWidget(self.btn1)
# Set the layout for the central widget
self.centralwidget.setLayout(self.layout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
MainWindow.setStatusBar(self.statusbar)
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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
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)
self.ui.btn1.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
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:
# Process frame via YOLO model
processed_frame = self.yolo_stream.process_frame(frame)
# Convert the frame from BGR (OpenCV format) to RGB
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()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

142
bjoerntest7.py Normal file
View File

@ -0,0 +1,142 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# Create a horizontal layout for the main window
self.layout = QtWidgets.QHBoxLayout(self.centralwidget)
# Left Column (Can be empty or have some widgets)
self.left_column = QtWidgets.QWidget(self.centralwidget)
self.left_layout = QtWidgets.QVBoxLayout(self.left_column)
# You can add more widgets to the left column here if needed
self.label = QtWidgets.QLabel("Left Column (Empty)", self.left_column)
self.left_layout.addWidget(self.label)
# Add left column widget to the main layout
self.layout.addWidget(self.left_column)
# Right Column
self.right_column = QtWidgets.QWidget(self.centralwidget)
self.right_layout = QtWidgets.QVBoxLayout(self.right_column)
# Add your widgets to the right layout
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.right_column)
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
self.right_layout.addWidget(self.AuftragsdetailsTable)
self.textEdit = QtWidgets.QTextEdit(self.right_column)
self.right_layout.addWidget(self.textEdit)
self.bauteilTypBtn = QtWidgets.QPushButton("Bauteiltype erkennen", self.right_column)
self.right_layout.addWidget(self.bauteilTypBtn)
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.right_column)
self.right_layout.addWidget(self.bauteiltypTextbox)
self.label_3 = QtWidgets.QLabel("Bezeichnung", self.right_column)
self.right_layout.addWidget(self.label_3)
self.label_4 = QtWidgets.QLabel("Pos.-Nr:", self.right_column)
self.right_layout.addWidget(self.label_4)
self.textEdit_3 = QtWidgets.QTextEdit(self.right_column)
self.right_layout.addWidget(self.textEdit_3)
self.checkBox = QtWidgets.QCheckBox("Bauteiltype locked", self.right_column)
self.right_layout.addWidget(self.checkBox)
# Create the QGraphicsView
self.graphicsView = QtWidgets.QGraphicsView(self.right_column)
self.right_layout.addWidget(self.graphicsView)
# Add right column widget to the main layout
self.layout.addWidget(self.right_column)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
# Add more translations as needed
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)
self.ui.bauteilTypBtn.clicked.connect(self.start_camera) # Connect the button to start the camera
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
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:
# Process frame via YOLO model
processed_frame = self.yolo_stream.process_frame(frame)
# Convert the frame from BGR (OpenCV format) to RGB
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()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

159
bjoerntest8.py Normal file
View File

@ -0,0 +1,159 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import sys
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
font.setPointSize(8)
item.setFont(font)
self.AuftragsdetailsTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(1100, 20, int(640*1.2), int(480*1.2))) # position and size of camera frame
self.graphicsView.setObjectName("graphicsView")
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.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.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
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)
self.ui.btn1.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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 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) # might change nomenclature later?
# 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()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
# Initialize the CameraStreamApp with the UI
camera_app = CameraStreamApp(ui)
MainWindow.show()
sys.exit(app.exec_())

910
bjoerntest9.py Normal file
View File

@ -0,0 +1,910 @@
# -*- 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
from PyQt5.QtWidgets import QApplication, QComboBox
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject
from PyQt5.QtGui import QColor
import serial
import binascii
import math
import mariadb
import time
import threading
from CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
import cv2
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': '127.0.0.1', # 'host': 'localhost',
'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()
# # Konfiguration der seriellen Schnittstelle
# ser = serial.Serial('/dev/ttyUSB0', 9600)
# Configuration of the serial port
try:
ser = serial.Serial('/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-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.")
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):
#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)
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 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
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 objectTypeDetectionThread(self, auftragsnummer):
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
# 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()
'''
# 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]])
# 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.")
# 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
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):
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()
'''
# 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
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([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
# 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
# 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)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.auftragsnummer = ""
self.teileZuViel = 0 # 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(1090, 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")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 300, 661, 192))
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)
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, 150, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 460, 161, 25))
self.checkWaageBtn.setObjectName("checkWaageBtn")
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 500, 161, 25))
self.stopLoopBtn.setObjectName("stopLoopBtn")
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
self.waageTareBtn.setGeometry(QtCore.QRect(700, 100, 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.BezeichnungLabel.setObjectName("BezeichnungLabel")
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
self.teileZuVielLabel.setGeometry(QtCore.QRect(700, 350, 350, 17))
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(700, 370, 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(700, 10, 151, 23))
self.checkBox.setObjectName("checkBox")
# button and checkbox for camera workflow + graphicsview widget
self.startCamBtn = QtWidgets.QPushButton(self.centralwidget)
self.startCamBtn.setGeometry(QtCore.QRect(900, 45, 161, 25))
self.startCamBtn.setObjectName("startCamBtn")
self.stopCamBtn = QtWidgets.QPushButton(self.centralwidget)
self.stopCamBtn.setGeometry(QtCore.QRect(900, 45+25, 161, 25))
self.stopCamBtn.setObjectName("stopCamBtn")
self.camWorkFlowcheckBox = QtWidgets.QCheckBox(self.centralwidget)
self.camWorkFlowcheckBox.setGeometry(QtCore.QRect(900, 10, 151, 23))
self.camWorkFlowcheckBox.setObjectName("camWorkFlowcheckBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(1100, 20, int(640*1.2), int(480*1.2))) # position and size of camera frame
self.graphicsView.setObjectName("graphicsView")
#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)
'''
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)
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"))
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:"))
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)
# 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)
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 getRowNr(self, posNr):
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())
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
# 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, rowID,r,g,b):
self.AuftragsdetailsTable.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 1).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 2).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 3).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.item(rowID, 4).setBackground(QtGui.QColor(r,g,b))
self.AuftragsdetailsTable.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
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:
'''
# 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))
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
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(row,255,255,255)
if(color_index == 2):
self.setRowColor(row,255,165,0)
if(color_index == 3):
self.setRowColor(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 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.")
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.getRowNr(einzelteilID),255,165,0)
# 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.getRowNr(einzelteilID),0,255,0) #zum setzen den Farbe der gesamten Reihe auf Grün
# 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
'''
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.")
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.getRowNr(einzelteilID),255,165,0)
# den Thread beenden
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
if(einzelteilID > 0):
self.setRowColor(self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
# 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)
self.ui.startCamBtn.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
self.scene = QtWidgets.QGraphicsScene(self)
self.ui.graphicsView.setScene(self.scene)
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 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) # might change nomenclature later?
# 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()
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)
MainWindow.show()
sys.exit(app.exec_())

47
mariadb-test.py Normal file
View File

@ -0,0 +1,47 @@
import mariadb
import sys
# # Database connection parameters
# host = "127.0.0.1" # host = "localhost" # or the IP of the machine if accessed remotely
# port = 3306
# user = "root"
# password = "my-secret-pw" # Update with your password
# database = "mydatabase" # Replace with your actual database name
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': '127.0.0.1', # 'host': 'localhost',
'database': 'projectGeislinger',
'port': 3306 # Standard port for MariaDB
}
try:
# Establish a connection
# conn = mariadb.connect(
# user=user,
# password=password,
# host=host,
# port=port,
# database=database
# )
conn = mariadb.connect(**db_config)
print("Connection successful!")
# Create a cursor object
cur = conn.cursor()
# Example query
cur.execute("SELECT VERSION()")
result = cur.fetchone()
print(f"MariaDB version: {result[0]}")
except mariadb.Error as e:
print(f"Error connecting to MariaDB: {e}")
sys.exit(1)
finally:
if conn:
conn.close()

301
readScale.py Normal file
View File

@ -0,0 +1,301 @@
import serial
import binascii
import math
import mariadb
import copy
# aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse)
# das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
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 wahrscheinlichkeitsDichteMultipVar(waageMessung, numberObjectList, results):
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable waageMessung für eine bestimmte Normalverteilung berechnet
# Mathematische Sätze, auf welchen die Berechnung basiert:
# seien X1,..., Xn unabhängige Zufallsvariablen mit Dichten f1,..., fn, dann hat X = (X1,...,Xn) die gemeinsame Dichte f(x1,...,xn) = f1(x1) * ... + fn(xn)
# 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
result = 0
# Berechnung vom Gesamtmittelwert
mueGes = 0
for i in range(0, len(numberObjectList)):
mueGes = mueGes + numberObjectList[i] * results[i][2]
# Berechnung von der Gesamtvarianz (var = sigma^2)
varGes = 0
for i in range(0, len(numberObjectList)):
varGes = varGes + numberObjectList[i] * results[i][3]
# Berechnung der Wahrscheinlichkeitsdichte
standardabweichungGes = varGes**0.5
result = 1/(standardabweichungGes * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((waageMessung-mueGes)/standardabweichungGes)**2)
return result
# die Funktion kann man vermutlich rauslöschen
def numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2):
for i in range(1,10000):
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
return i
else:
return -1
def sumMaxWeightObjects(objectType, numberObjectList, results):
sum = 0
# die Anzahl an Bauteilen, welche dem Objekttypen zugeordnet sind, sollen nicht mit dazugerechnet werden
for i in range(objectType+1, len(numberObjectList)):
# eigentlich müsste man nur mit 3 multiplizieren, um 99,7% der Bauteile im Bereich zu haben - das gilt aber nur für eine gültige Normalverteilung
#sum = sum + numberObjectList[i] * (results[i][2] + 3 * math.sqrt(results[i][3]))
sum = sum + numberObjectList[i] * (results[i][2])
return sum
def numberPossibleObjects(objectType, numberObjectList, results, messungWaage):
# der objectType definiert, welcher der Objekte das Anschauungsobjekt ist
# wenn nur ein Objekt darauf gelegt wird, welches nicht vom Typen des Anschauungsobjektes ist, dann wird 1 zurück gegeben
#print(results[objectType][2]-10*math.sqrt(results[objectType][3]))
#print((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/results[objectType][2])
# wenn kein Gewicht auf der Waage liegt, dann soll -1 zurück gegeben werden.
if messungWaage <= 0:
return -1
#print(results[objectType][2])
#print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3]))))
#print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]-3*math.sqrt(results[objectType][3]))))
#zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3])))
zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]))
for i in range(1,10000):
if zwischenSumme <= 0: #in diesem Fall wird das gesamte Gewicht der Messung durch Objekte eines anderen Typen "aufgebraucht"
return 0
if i > zwischenSumme:
return i # i entspricht beim returnen der Anzahl der möglichen Objekte
def anzBauteileCountFunction(numberObjectList):
counter = 0
for i in range(0,len(numberObjectList)):
if numberObjectList[i] > 0:
counter = counter + 1
return counter
"""
for i in range(1,10000):
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
return i
else:
return -1
"""
def main():
print("connection is open: ", ser.is_open)
print("port to which it is connected: ", ser.portstr)
#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")
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")
# wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden
if( waageEingeschwungen == True and float(intString)>0):
# Define the SQL query
sql_query = "SELECT * FROM projectGeislinger.Einzelteile"
# Execute the query
cursor.execute(sql_query)
# Fetch results
results = cursor.fetchall()
# Display data
print("Ausgabe der Daten der Datenbank:")
for row in results:
print(row)
anzBauteiltypen = len(results)
anzBauteile = anzBauteiltypen * [0] # erstellt eine Liste, in welcher die Anzahl der Bauteiltypen gespeichert ist, welche für die weiteren Schleifen verwendet wird
wahrscheinleichkeitsMatrix = []
# Berechnen der Anzahl an Objekten
for i in range(0, anzBauteiltypen):
#bauteilTypCounter = i+1 #zum hochzählen der Anzahlen der Bauteiltypen nach der k-Schleife
while(True):
if i<(anzBauteiltypen-1): # wenn i die letzte Spalte der Bauteiltypenmatrix ist, dann soll der Teil übersprungen werden
for k in range(0, 10000):
anzBauteile[i+1] = k
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
if nrObjects == -1 or nrObjects == 0:
break
anzBauteile[i] = nrObjects
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
# da die Berechnete Anzahl an möglichen Messobjekten um 0 bis +1 um den "wahren" Wert schwankt, wird in der Folge auch die Wahrscheinlichkeit mit einer um 1 verringerten Bauteilanzahl berechnet (sollte diese größer als 1 sein)
if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1):
anzBauteile = anzBauteile[:]
anzBauteile[i] = anzBauteile[i]-1
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
anzBauteile[i+1] = 0
elif i == (anzBauteiltypen-1):
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
if nrObjects == -1 or nrObjects == 0:
break
anzBauteile[i] = nrObjects
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1):
anzBauteile = anzBauteile[:]
anzBauteile[i] = anzBauteile[i]-1
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
if i >= (anzBauteiltypen-2): #wenn der Fall eintritt, dann wurden alle Fälle überprüft -> dadurch kann die i-Schleife in die letzte Runde gehen, kann das Programm sich ganz beenden
anzBauteile[i] = 0
break
for m in range(i+2,anzBauteiltypen):
anzBauteile[m] = anzBauteile[m] + 1
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
if nrObjects >= 1:
break
elif nrObjects < 1 and m == (anzBauteiltypen-1) :
break
else:
anzBauteile[m] = 0
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
if (nrObjects == -1 or nrObjects == 0):
anzBauteile[anzBauteiltypen-1] = 0
anzBauteile[i] = 0
break
# Suchen der höchsten Wahrscheinlichkeitsdichte
countMaxPropDensity = 0
maxPropDensity = 0
#print(wahrscheinleichkeitsMatrix[0][0])
for i in range(0, len(wahrscheinleichkeitsMatrix)):
if(wahrscheinleichkeitsMatrix[i][0] > maxPropDensity):
maxPropDensity = wahrscheinleichkeitsMatrix[i][0]
countMaxPropDensity = i
if wahrscheinleichkeitsMatrix[i][0] >0:
print(wahrscheinleichkeitsMatrix[i])
print(wahrscheinleichkeitsMatrix[countMaxPropDensity][0])
# die Bauteilkombination mit der höchsten Wahrscheinlichkeitsdichte ausgeben
for i in range(0, len(wahrscheinleichkeitsMatrix[0][1])):
print("Bauteiltyp: ", results[i][1]," Anzahl: ", wahrscheinleichkeitsMatrix[countMaxPropDensity][1][i])
#nrObjects = numberPossibleObjects(0, anzBauteile, results, float(intString))
#print("number objects: ", nrObjects-1)
"""
for i in range(3,0,-1):
numberOfSmallObjects = numberSmallerObjects(1, float(intString),results[4][2], results[3][2], math.sqrt(results[3][3]))
print("number of smaller objects: ", numberOfSmallObjects-1)
"""
"""
# in der Folge wird nun berechnet, welcher Normalverteilung die Messung am ehesten entspricht
dBId = 0
maxPropDensity = 0
for row in results:
propDens = wahrscheinlichkeitsDichte(float(intString) ,row[2], row[3])
if propDens > maxPropDensity:
maxPropDensity = propDens
dBId = row[0]
#Ausgabe des Bauteiltypen, welchem die Messung am ehesten entspricht
for row in results:
if row[0] == dBId:
print(row[1])
#propDens = wahrscheinlichkeitsDichte(0.042 ,results[0][2], results[0][3])
#print(propDens)
"""
ser.close()
print("connection is open: ", ser.is_open)
if __name__ == "__main__":
main()

138
readScale_Stand01.07.py Normal file
View File

@ -0,0 +1,138 @@
import serial
import binascii
import math
import mariadb
# aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse)
# das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
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 numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2):
for i in range(1,10000):
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
print((messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1)
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
return i
else:
return -1
def main():
print("connection is open: ", ser.is_open)
print("port to which it is connected: ", ser.portstr)
#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")
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")
# wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden
if( waageEingeschwungen == True):
# Define the SQL query
sql_query = "SELECT * FROM projectGeislinger.Einzelteile"
# Execute the query
cursor.execute(sql_query)
# Fetch results
results = cursor.fetchall()
# Display data
print("Ausgabe der Daten der Datenbank:")
for row in results:
print(row)
# in der Folge wird nun berechnet, welcher Normalverteilung die Messung am ehesten entspricht
dBId = 0
maxPropDensity = 0
for row in results:
propDens = wahrscheinlichkeitsDichte(float(intString) ,row[2], row[3])
if propDens > maxPropDensity:
maxPropDensity = propDens
dBId = row[0]
#Ausgabe des Bauteiltypen, welchem die Messung am ehesten entspricht
for row in results:
if row[0] == dBId:
print(row[1])
#propDens = wahrscheinlichkeitsDichte(0.042 ,results[0][2], results[0][3])
#print(propDens)
ser.close()
print("connection is open: ", ser.is_open)
if __name__ == "__main__":
main()

206
readScale_Stand1708.py Normal file
View File

@ -0,0 +1,206 @@
import serial
import binascii
import math
import mariadb
# aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse)
# das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden
db_config = {
'user': 'dbUser',
'password': 'dbPassword',
'host': 'localhost',
'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()
# Konfiguration der seriellen Schnittstelle
ser = serial.Serial('/dev/ttyUSB0', 9600)
waageEingeschwungen = False
def getDataOfArticleType(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 getDataOfArticleNotType(allArticles, articleType):
# die Funktion geht die Liste mit allen Artikeln durch und gibt jene Einträge, welche nicht mit dem "articleTypen" übereinstimmt zurück
returnMatrix = []
for i in allArticles:
if i[1] != articleType:
returnMatrix.append(i)
return returnMatrix
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 generateArticleProbabilities(articleType, allArticles, n, x, numberOfOtherTypes, measuredWeight):
# es fehtl noch eine Datavariable, welche die Daten der Datenbank beinhaltet
# articleType ... die Artikeltype, welche erwartet wird (also für welche n+x überprüft wird)
# n ... Anzahl der Artikel, welche laut dem Auftrag vorhanden sein sollten
# x ... Anzahl der Artikel vom Artikeltypen des Auftrages, welche über der Anzahl n noch überprüft werden sollen
# numberofOtherTypes ... Anzahl an Artikeln, welch von anderen Typen überprüft werden sollen
# measuredWeight ... das Gewicht, welches von der Waage gemessen wird
# über alle Möglichkeiten drüberiterieren, die Wahrscheinlichkeitsdichte für diese berechnen und in einer Matrix speichern.
# in der Folge werden die artikelbezogenen Daten in einer Matrix zusammengefasst
articleData = getDataOfArticleType(allArticles, articleType)
if articleData == -1:
return -1
otherArticleData = getDataOfArticleNotType(allArticles, articleType)
#print("AData: ", articleData)
print("NArticleData: ", otherArticleData)
#print(wahrscheinlichkeitsDichte(measuredWeight, articleData[1], articleData[2]))
articleProbMatix = []
for i in range(numberOfOtherTypes+1):
for j in range(n+x):
anzArtikelToCheck = j+1
propDensity = wahrscheinlichkeitsDichte(measuredWeight*anzArtikelToCheck, articleData[2], articleData[3])
print(propDensity)
return 0
'''
def numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2):
for i in range(1,10000):
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
print((messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1)
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
return i
else:
return -1
'''
def main():
print("connection is open: ", ser.is_open)
print("port to which it is connected: ", ser.portstr)
#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")
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")
# wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden
if( waageEingeschwungen == True):
# new SWL-Query
sql_query = "SELECT * FROM projectGeislinger.Auftraege, projectGeislinger.Einzelteile where projectGeislinger.Auftraege.EinzelteilID = projectGeislinger.Einzelteile.id "
# Execute the query
cursor.execute(sql_query)
# Fetch results
auftragDaten = cursor.fetchall()
# Display data
print("Ausgabe der Daten der Datenbank:")
for row in auftragDaten:
print(row)
# Define the SQL query
sql_query = "SELECT * FROM projectGeislinger.Einzelteile"
# Execute the query
cursor.execute(sql_query)
# Fetch results
einzelteile = cursor.fetchall()
# Display data
print("Ausgabe der Daten der Datenbank:")
for row in einzelteile:
print(row)
#print(einzelteile)
#
selectedRow = 0 #diese wird durch die GUI vorgegeben, oder automatische ausgewählt
artikelBezeichnung = auftragDaten[selectedRow][5]
# 10 Anzahl laut Auftrag, 3, Anzahl darüber, 1 Anzahl anderer Typ
generateArticleProbabilities(artikelBezeichnung, einzelteile, 2, 0,1, float(intString))
ser.close()
print("connection is open: ", ser.is_open)
if __name__ == "__main__":
main()

134
readme.md
View File

@ -1,134 +0,0 @@
# CPS Geislinger Packaging Assistant Workflow
Dieses Repository enthält die Software und Dokumentation für den **CPS Geislinger Packaging Assistant**, ein System, das Mitarbeiter beim Einpacken von Aufträgen unterstützt. Es kombiniert eine Waage und eine Kamera, um Bauteile automatisch zu erkennen, die Stückzahl zu prüfen und den Verpackungsprozess effizienter zu gestalten.
---
## Inhaltsverzeichnis
1. [Ordnerstruktur](#ordnerstruktur)
2. [Systemanforderungen](#systemanforderungen)
3. [Installation](#installation)
4. [Anwendung](#anwendung)
- [Programmstart](#programmstart)
- [Arbeitsablauf](#arbeitsablauf)
5. [Fehlerbehebung](#fehlerbehebung)
6. [Kontakt](#kontakt)
---
## Ordnerstruktur
Die Dateien und Ordner sind wie folgt strukturiert:
- **`workflow.py`**: Hauptprogramm zur Steuerung des Systems.
- **`readme.md`**: Diese Anleitung.
- **`environment.yaml`**: Conda-Umgebungskonfigurationsdatei.
- **`compose.yml`**: Docker Compose Datei für lokale Tests mit MariaDB.
- **`.gitignore`**: Einstellungen für Git, um unnötige Dateien auszuschließen.
- **`doc/`**: Zusätzliche Dokumentation.
- **`ESP32/`**: Firmwaredateien für den ESP32-Hilfscontroller.
- **`lib/`**: Lokale Python-Bibliotheken.
- **`models/`**: Machine Learning-Modelle für die Bauteilerkennung.
- **`pyqt_project/`**: Projektdateien für die Benutzeroberfläche (erstellt mit Qt Designer).
---
## Systemanforderungen
- **Betriebssystem**: Ubuntu 24.04 oder kompatibel.
- **Python-Version**: Python 3.10 oder höher.
- **Abhängigkeiten**:
- Conda oder Miniforge zur Verwaltung von Python-Bibliotheken.
- Docker und Docker Compose (optional für lokale Tests mit MariaDB).
- **Hardware**:
- Eine Waage mit USB-/serieller Verbindung.
- Eine Kamera für die Bauteilerkennung.
- Ein ESP32-Mikrocontroller als Hilfsgerät.
---
## Installation
Falls das System nicht vorinstalliert ist, folgen Sie diesen Schritten:
### 1. Conda-Umgebung erstellen
Installieren Sie die Conda-Abhängigkeiten, indem Sie die `environment.yaml` Datei nutzen:
```bash
conda env create -n geislinger -f environment.yaml
```
### 2. Conda-Umgebung aktivieren
Setzen Sie die erstellte Umgebung als Standardumgebung, indem Sie in der Datei ~/.bashrc folgendes hinzufügen:
> conda activate geislinger
Alternativ können Sie die Umgebung vor jedem Programmstart manuell aktivieren:
```bash
conda activate geislinger
```
### 3. Optional: MariaDB-Testumgebung starten
Falls Sie die Datenbank lokal testen möchten, starten Sie Docker Compose im Projektordner:
```bash
docker-compose up -d
```
### 4. Software für USB Relay Board installieren
https://github.com/scheiber-sa/sainsmartUsbRelay
## Anwendung
### Programmstart
Starten Sie das Hauptprogramm aus dem Projektordner mit:
```bash
python3 workflow.py
```
Die Benutzeroberfläche wird gestartet und alle Geräte (Waage, Kamera, ESP32) werden automatisch initialisiert.
### Arbeitsablauf
1. Auftrag laden
Geben Sie die Auftragsnummer in das entsprechende Feld ein und laden Sie die Auftragsdaten.
2. Bauteilerkennung
Wählen Sie das Bauteil manuell aus oder lassen Sie es automatisch durch die Kamera und Waage bestimmen.
3. Bestücken
Legen Sie die Teile auf, bis die Waage die gewünschte Stückzahl bestätigt.
4. Weiterverpacken
Wiederholen Sie den Vorgang für alle Bauteile im Auftrag.
5. Auftragsabschluss
Sobald alle Bauteile verpackt sind, schließen Sie den Auftrag ab.
## Fehlerbehebung
- Geräte werden nicht erkannt:
Stellen Sie sicher, dass alle Geräte korrekt verbunden sind und überprüfen Sie die Konfiguration.
- Waage zeigt falsche Werte:
Kalibrieren Sie die Waage erneut gemäß der Dokumentation.
- Fehlerhafte Bauteilerkennung:
Stellen Sie sicher, dass die Kamera sauber ist und die Beleuchtung ausreichend ist. Prüfen Sie auch, ob das entsprechende Modell in models/ geladen wurde.
- Datenbankfehler:
Vergewissern Sie sich, dass MariaDB läuft und die Zugangsdaten korrekt in der Konfiguration hinterlegt sind.
## Kontakt
Für weitere Unterstützung oder Fragen wenden Sie sich bitte an:
- E-Mail: clemens.fritze@unileoben.ac.at
- Telefon:
- Dokumentation: Weitere Informationen finden Sie im Ordner doc/.
Dieses Projekt wurde entwickelt, um die Effizienz und Genauigkeit im Verpackungsprozess zu steigern und die Arbeitsbelastung der Mitarbeiter zu reduzieren. Vielen Dank für die Nutzung des CPS Geislinger Packaging Assistant!

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

230
test.ui Normal file
View File

@ -0,0 +1,230 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<height>675</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="btn1">
<property name="geometry">
<rect>
<x>900</x>
<y>80</y>
<width>111</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>load Auftrag</string>
</property>
</widget>
<widget class="QTableWidget" name="AuftragsdetailsTable">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>661</width>
<height>192</height>
</rect>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<row>
<property name="text">
<string>T1</string>
</property>
</row>
<column>
<property name="text">
<string>Pos.-Nr</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Matnr mit hoechster Version</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Bezeichnung + Werkstoff</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Menge</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Lgort</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>I1</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>900</x>
<y>20</y>
<width>121</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Auftragsnummer:</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>860</x>
<y>40</y>
<width>221</width>
<height>31</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QPushButton" name="bauteilTypBtn">
<property name="geometry">
<rect>
<x>450</x>
<y>350</y>
<width>161</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Bauteiltype erkennen</string>
</property>
</widget>
<widget class="QTextEdit" name="bauteiltypTextbox">
<property name="geometry">
<rect>
<x>620</x>
<y>350</y>
<width>221</width>
<height>31</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>640</x>
<y>330</y>
<width>181</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Bezeichnung</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>910</x>
<y>330</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Pos.-Nr:</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_3">
<property name="geometry">
<rect>
<x>850</x>
<y>350</y>
<width>191</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>460</x>
<y>420</y>
<width>151</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Bauteiltype locked</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

274
test2.ui.py Normal file
View File

@ -0,0 +1,274 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1374</width>
<height>725</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="enabled">
<bool>true</bool>
</property>
<widget class="QTableWidget" name="AuftragsdetailsTable">
<property name="geometry">
<rect>
<x>30</x>
<y>200</y>
<width>591</width>
<height>371</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<row>
<property name="text">
<string>T1</string>
</property>
</row>
<column>
<property name="text">
<string>Pos.-Nr</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Matnr mit hoechster Version</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Bezeichnung + Werkstoff</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Menge</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Lgort</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>I1</string>
</property>
</item>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>9</x>
<y>9</y>
<width>611</width>
<height>151</height>
</rect>
</property>
<property name="title">
<string>Bauteile</string>
</property>
<widget class="QFrame" name="frame">
<property name="geometry">
<rect>
<x>170</x>
<y>30</y>
<width>221</width>
<height>71</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QTextEdit" name="bauteiltypTextbox">
<property name="geometry">
<rect>
<x>31</x>
<y>34</y>
<width>269</width>
<height>76</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>31</x>
<y>11</y>
<width>73</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Bezeichnung</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>420</x>
<y>40</y>
<width>171</width>
<height>71</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Pos.-Nr:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit_3"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>161</width>
<height>81</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="bauteilTypBtn">
<property name="text">
<string>Bauteiltype erkennen</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Bauteiltype locked</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>640</x>
<y>20</y>
<width>351</width>
<height>571</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Auftrag</string>
</property>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>10</x>
<y>32</y>
<width>331</width>
<height>481</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Auftragsnummer:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn1">
<property name="text">
<string>load Auftrag</string>
</property>
</widget>
</item>
<item>
<widget class="QGraphicsView" name="graphicsView"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

130
test_ui.py Normal file
View File

@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/bjoern/git/GeislingerProject/test.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# 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.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
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(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(450, 350, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(620, 350, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(640, 330, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(910, 330, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(850, 350, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(460, 420, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
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.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"))
item = self.AuftragsdetailsTable.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "T1"))
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", "Menge"))
item = self.AuftragsdetailsTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "Lgort"))
__sortingEnabled = self.AuftragsdetailsTable.isSortingEnabled()
self.AuftragsdetailsTable.setSortingEnabled(False)
item = self.AuftragsdetailsTable.item(0, 0)
item.setText(_translate("MainWindow", "I1"))
self.AuftragsdetailsTable.setSortingEnabled(__sortingEnabled)
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Ubuntu\'; font-size:11pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.bauteiltypTextbox.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Ubuntu\'; font-size:11pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))

189
testbjoern.py Normal file
View File

@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test2.ui.py'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# 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.
from PyQt5 import QtCore, QtGui, QtWidgets
import signal
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1374, 725)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setEnabled(True)
self.centralwidget.setObjectName("centralwidget")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(30, 200, 591, 371))
self.AuftragsdetailsTable.setAutoFillBackground(False)
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
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(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox.setGeometry(QtCore.QRect(9, 9, 611, 151))
self.groupBox.setObjectName("groupBox")
self.frame = QtWidgets.QFrame(self.groupBox)
self.frame.setGeometry(QtCore.QRect(170, 30, 221, 71))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.frame)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(31, 34, 269, 76))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.frame)
self.label_3.setGeometry(QtCore.QRect(31, 11, 73, 17))
self.label_3.setObjectName("label_3")
self.widget = QtWidgets.QWidget(self.groupBox)
self.widget.setGeometry(QtCore.QRect(420, 40, 171, 71))
self.widget.setObjectName("widget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label_4 = QtWidgets.QLabel(self.widget)
self.label_4.setObjectName("label_4")
self.verticalLayout_2.addWidget(self.label_4)
self.textEdit_3 = QtWidgets.QTextEdit(self.widget)
self.textEdit_3.setObjectName("textEdit_3")
self.verticalLayout_2.addWidget(self.textEdit_3)
self.widget1 = QtWidgets.QWidget(self.groupBox)
self.widget1.setGeometry(QtCore.QRect(20, 40, 161, 81))
self.widget1.setObjectName("widget1")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget1)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.bauteilTypBtn = QtWidgets.QPushButton(self.widget1)
self.bauteilTypBtn.setCheckable(False)
self.bauteilTypBtn.setAutoDefault(False)
self.bauteilTypBtn.setDefault(False)
self.bauteilTypBtn.setFlat(False)
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.verticalLayout_3.addWidget(self.bauteilTypBtn)
self.checkBox = QtWidgets.QCheckBox(self.widget1)
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.verticalLayout_3.addWidget(self.checkBox)
self.widget2 = QtWidgets.QWidget(self.centralwidget)
self.widget2.setGeometry(QtCore.QRect(640, 20, 351, 571))
self.widget2.setObjectName("widget2")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget2)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.groupBox_2 = QtWidgets.QGroupBox(self.widget2)
self.groupBox_2.setObjectName("groupBox_2")
self.widget3 = QtWidgets.QWidget(self.groupBox_2)
self.widget3.setGeometry(QtCore.QRect(10, 32, 331, 481))
self.widget3.setObjectName("widget3")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.widget3)
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.label = QtWidgets.QLabel(self.widget3)
self.label.setObjectName("label")
self.verticalLayout_4.addWidget(self.label)
self.btn1 = QtWidgets.QPushButton(self.widget3)
self.btn1.setObjectName("btn1")
self.verticalLayout_4.addWidget(self.btn1)
self.graphicsView = QtWidgets.QGraphicsView(self.widget3)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout_4.addWidget(self.graphicsView)
self.verticalLayout.addWidget(self.groupBox_2)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.AuftragsdetailsTable.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "T1"))
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", "Menge"))
item = self.AuftragsdetailsTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "Lgort"))
__sortingEnabled = self.AuftragsdetailsTable.isSortingEnabled()
self.AuftragsdetailsTable.setSortingEnabled(False)
item = self.AuftragsdetailsTable.item(0, 0)
item.setText(_translate("MainWindow", "I1"))
self.AuftragsdetailsTable.setSortingEnabled(__sortingEnabled)
self.groupBox.setTitle(_translate("MainWindow", "Bauteile"))
self.bauteiltypTextbox.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))
self.groupBox_2.setTitle(_translate("MainWindow", "Auftrag"))
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.btn1.setText(_translate("MainWindow", "load Auftrag"))
def signal_handler(sig, frame):
QtWidgets.QApplication.quit()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
# Handle Ctrl+C (SIGINT) to close the application
signal.signal(signal.SIGINT, signal_handler)
# Create a timer that runs in the background to process signals
timer = QtCore.QTimer()
timer.start(100) # Timer set to trigger every 100 ms
timer.timeout.connect(lambda: None) # No-op to keep the event loop running
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

246
testbjoern2.ui Normal file
View File

@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<height>675</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="btn1">
<property name="geometry">
<rect>
<x>900</x>
<y>80</y>
<width>111</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>load Auftrag</string>
</property>
</widget>
<widget class="QTableWidget" name="AuftragsdetailsTable">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>661</width>
<height>192</height>
</rect>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<row>
<property name="text">
<string>T1</string>
</property>
</row>
<column>
<property name="text">
<string>Pos.-Nr</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Matnr mit hoechster Version</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Bezeichnung + Werkstoff</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Menge</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<column>
<property name="text">
<string>Lgort</string>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>I1</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>900</x>
<y>20</y>
<width>121</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Auftragsnummer:</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>860</x>
<y>40</y>
<width>221</width>
<height>31</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QPushButton" name="bauteilTypBtn">
<property name="geometry">
<rect>
<x>60</x>
<y>340</y>
<width>161</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Bauteiltype erkennen</string>
</property>
</widget>
<widget class="QTextEdit" name="bauteiltypTextbox">
<property name="geometry">
<rect>
<x>230</x>
<y>340</y>
<width>221</width>
<height>31</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>250</x>
<y>320</y>
<width>181</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Bezeichnung</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>520</x>
<y>320</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Pos.-Nr:</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_3">
<property name="geometry">
<rect>
<x>460</x>
<y>340</y>
<width>191</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>70</x>
<y>410</y>
<width>151</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Bauteiltype locked</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
<widget class="QGraphicsView" name="graphicsView">
<property name="geometry">
<rect>
<x>800</x>
<y>280</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

139
testbjoern2_ui.py Normal file
View File

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/bjoern/git/GeislingerProject/testbjoern2.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# 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.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1090, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
self.btn1.setGeometry(QtCore.QRect(900, 80, 111, 25))
self.btn1.setObjectName("btn1")
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 10, 661, 192))
self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
self.AuftragsdetailsTable.setColumnCount(5)
self.AuftragsdetailsTable.setRowCount(1)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setVerticalHeaderItem(0, item)
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(4, item)
item = QtWidgets.QTableWidgetItem()
self.AuftragsdetailsTable.setItem(0, 0, item)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(900, 20, 121, 17))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(860, 40, 221, 31))
self.textEdit.setObjectName("textEdit")
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
self.bauteilTypBtn.setGeometry(QtCore.QRect(60, 340, 161, 25))
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
self.bauteiltypTextbox.setGeometry(QtCore.QRect(230, 340, 221, 31))
self.bauteiltypTextbox.setObjectName("bauteiltypTextbox")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(250, 320, 181, 20))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(520, 320, 67, 17))
self.label_4.setObjectName("label_4")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(460, 340, 191, 31))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(70, 410, 151, 23))
self.checkBox.setChecked(False)
self.checkBox.setObjectName("checkBox")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(800, 280, 256, 192))
self.graphicsView.setObjectName("graphicsView")
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.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"))
item = self.AuftragsdetailsTable.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "T1"))
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", "Menge"))
item = self.AuftragsdetailsTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "Lgort"))
__sortingEnabled = self.AuftragsdetailsTable.isSortingEnabled()
self.AuftragsdetailsTable.setSortingEnabled(False)
item = self.AuftragsdetailsTable.item(0, 0)
item.setText(_translate("MainWindow", "I1"))
self.AuftragsdetailsTable.setSortingEnabled(__sortingEnabled)
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"))
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltype erkennen"))
self.bauteiltypTextbox.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"))
self.label_3.setText(_translate("MainWindow", "Bezeichnung"))
self.label_4.setText(_translate("MainWindow", "Pos.-Nr:"))
self.checkBox.setText(_translate("MainWindow", "Bauteiltype locked"))

Some files were not shown because too many files have changed in this diff Show More