Compare commits
No commits in common. "main" and "feat/vision" have entirely different histories.
main
...
feat/visio
@ -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}}}}
|
|
@ -1,3 +1,14 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'test.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.9
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
########## beim Static workflow funktionieren die Threads ab dem zweiten nicht mehr
|
||||||
|
|
||||||
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -12,56 +23,57 @@ import mariadb
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from lib.CameraStream import YOLOv8CameraStream # Import the YOLOv8CameraStream class
|
|
||||||
import cv2
|
|
||||||
|
|
||||||
import os
|
# db_config = {
|
||||||
|
# 'user': 'dbUser',
|
||||||
|
# 'password': 'dbPassword',
|
||||||
|
# 'host': '127.0.0.1', # 'host': 'localhost',
|
||||||
|
# 'database': 'projectGeislinger',
|
||||||
|
# 'port': 3306 # Standard port for MariaDB
|
||||||
|
# }
|
||||||
|
|
||||||
import lib.sainsmartrelay as sainsmartrelay
|
|
||||||
import lib.wledControl as wledControl
|
|
||||||
|
|
||||||
|
|
||||||
# ## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser -> Farben Drop Down
|
|
||||||
|
|
||||||
|
|
||||||
# ## Aufsetzen der Datenbank und Waagenverbindung
|
|
||||||
# # Definieren der Datenbankverbindung
|
|
||||||
db_config = {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
# # Establishing the connection
|
|
||||||
# conn = mariadb.connect(**db_config)
|
|
||||||
# # Create a cursor to execute queries
|
|
||||||
# cursor = conn.cursor()
|
|
||||||
|
|
||||||
try:
|
# Establishing the connection
|
||||||
# Attempt to establish the connection
|
conn = mariadb.connect(**db_config)
|
||||||
conn = mariadb.connect(**db_config)
|
# Create a cursor to execute queries
|
||||||
print("Database connection established successfully.")
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# Create a cursor to execute queries
|
# Konfiguration der seriellen Schnittstelle
|
||||||
cursor = conn.cursor()
|
ser = serial.Serial('/dev/ttyUSB0', 9600)
|
||||||
except mariadb.Error as e:
|
#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
|
||||||
# Handle connection errors
|
# und nicht die Schnittstelle, welche die Bezeichnung ttyUSB0 verwendet (welche sich ändern könnte)
|
||||||
print(f"Error connecting to the database: {e}")
|
# um die ID der USB-Schnittstelle heraus zu finden im Terminal folgendes eingeben: ls -l /dev/serial/by-id/
|
||||||
conn = None
|
|
||||||
cursor = None
|
|
||||||
|
|
||||||
|
|
||||||
# Configuration of the serial port
|
waageEingeschwungen = False
|
||||||
try:
|
|
||||||
ser = serial.Serial('/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:3:1.0-port0', 9600)
|
|
||||||
print("Serial port connected successfully.")
|
|
||||||
except serial.SerialException:
|
|
||||||
ser = None
|
|
||||||
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.")
|
|
||||||
|
|
||||||
# die Workerklasse ist dazu da die Schleifen - in welchen der Bauteiltyp erkannt wird und die Anzahl der Bauteile, welche auf der Waage liegen - in einem seperaten Thread auszuführen, um ein Blockieren des Mainthreads zu verhindern
|
|
||||||
|
def wahrscheinlichkeitsDichte(x,mue, var):
|
||||||
|
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet
|
||||||
|
standardabweichung = var**0.5
|
||||||
|
|
||||||
|
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def calcWahrscheinlichkeitFromDichte(x,mue, var):
|
||||||
|
# in der Funktion wird die Wahrscheinlichkeit via der Wahrscheinlichkeitsdichte berechnet, indem das Verhältnis aus der dem Bauteil zugehörigen Wahrscheinlichkeitsdichte zu der maximalen Wahrscheinlichkeitsdichte berechnet wird
|
||||||
|
p1 = wahrscheinlichkeitsDichte(x,mue, var)
|
||||||
|
p_max = wahrscheinlichkeitsDichte(mue,mue, var)
|
||||||
|
|
||||||
|
return p1/p_max
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#class Worker(QThread):
|
||||||
class Worker(QObject):
|
class Worker(QObject):
|
||||||
#progress = pyqtSignal(int)
|
#progress = pyqtSignal(int)
|
||||||
objectDetectionStartSignal = pyqtSignal(str)
|
objectDetectionStartSignal = pyqtSignal(str)
|
||||||
@ -74,7 +86,6 @@ class Worker(QObject):
|
|||||||
waageStoppedSignal = pyqtSignal(int)
|
waageStoppedSignal = pyqtSignal(int)
|
||||||
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
||||||
|
|
||||||
waageEingeschwungen = False
|
|
||||||
stopLoop = False
|
stopLoop = False
|
||||||
btTypeIsSet = False
|
btTypeIsSet = False
|
||||||
correctBtNr = False
|
correctBtNr = False
|
||||||
@ -86,7 +97,7 @@ class Worker(QObject):
|
|||||||
|
|
||||||
|
|
||||||
def getDataOfArticleType(self, allArticles, articleType):
|
def getDataOfArticleType(self, allArticles, articleType):
|
||||||
''' die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück '''
|
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||||
for i in allArticles:
|
for i in allArticles:
|
||||||
if i[1] == articleType:
|
if i[1] == articleType:
|
||||||
return i
|
return i
|
||||||
@ -96,27 +107,26 @@ class Worker(QObject):
|
|||||||
def waageNichtEingeschwungenOutput(self):
|
def waageNichtEingeschwungenOutput(self):
|
||||||
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||||
|
|
||||||
def wahrscheinlichkeitsDichte(self, x,mue, var):
|
|
||||||
''' in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet '''
|
|
||||||
standardabweichung = var**0.5
|
|
||||||
|
|
||||||
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def readWaage(self):
|
def readWaage(self):
|
||||||
''' in folgender Funktion wird die Waage ausgelesen '''
|
# in folgender Funktion wird die Waage ausgelesen
|
||||||
|
|
||||||
|
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||||
|
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe
|
||||||
|
|
||||||
|
|
||||||
if ser.is_open == False:
|
if ser.is_open == False:
|
||||||
ser.open()
|
ser.open()
|
||||||
|
|
||||||
|
|
||||||
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||||||
ser.write(b'getWeight\n')
|
ser.write(b'getWeight\n')
|
||||||
|
#ser.write(b'tare\n')
|
||||||
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||||||
|
|
||||||
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||||||
lenString = len(serialString)-1
|
lenString = len(serialString)-1
|
||||||
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||||||
|
#print("ist eingeschwungen") #Debuggingausgabe
|
||||||
waageEingeschwungen = True
|
waageEingeschwungen = True
|
||||||
else:
|
else:
|
||||||
print("die Waage ist noch nicht eingeschwungen")
|
print("die Waage ist noch nicht eingeschwungen")
|
||||||
@ -128,13 +138,17 @@ class Worker(QObject):
|
|||||||
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||||||
intString = intString + i
|
intString = intString + i
|
||||||
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||||||
|
## Waage auslesen - ENDE
|
||||||
|
|
||||||
ser.close()
|
ser.close()
|
||||||
|
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||||
|
|
||||||
return waageEingeschwungen, intString
|
return waageEingeschwungen, intString
|
||||||
|
|
||||||
def objectTypeDetectionThread(self, auftragsnummer):
|
def objectTypeDetectionThread(self, auftragsnummer):
|
||||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||||
|
|
||||||
|
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
|
||||||
|
|
||||||
# Parameterdefinition
|
# Parameterdefinition
|
||||||
propDensVect = []
|
propDensVect = []
|
||||||
@ -154,9 +168,16 @@ class Worker(QObject):
|
|||||||
cursor.execute(sql_query)
|
cursor.execute(sql_query)
|
||||||
auftragEinzelteilDaten = cursor.fetchall()
|
auftragEinzelteilDaten = cursor.fetchall()
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Display data #Debugausgabe
|
||||||
|
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
||||||
for row in auftragEinzelteilDaten:
|
for row in auftragEinzelteilDaten:
|
||||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),float(row[6]), float(row[7])), row[1], row[5]])
|
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
|
# Jenen Eintrag des propDensVect raussuchen, welcher die größte Wahrscheinlichkeitsdichte beinhaltet
|
||||||
maxpropDens = 0
|
maxpropDens = 0
|
||||||
@ -174,6 +195,14 @@ class Worker(QObject):
|
|||||||
else:
|
else:
|
||||||
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
||||||
|
|
||||||
|
# Wahrscheinlichkeit berechnen, dass das angegebene Bauteil auch wirklich diesem entspricht
|
||||||
|
prop = 0
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
if row[1] == einzelteilID:
|
||||||
|
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6]), float(row[7]))
|
||||||
|
break
|
||||||
|
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||||
|
|
||||||
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
||||||
self.btTypeIsSet = True
|
self.btTypeIsSet = True
|
||||||
|
|
||||||
@ -184,7 +213,6 @@ class Worker(QObject):
|
|||||||
self.waageStoppedSignal.emit(einzelteilID)
|
self.waageStoppedSignal.emit(einzelteilID)
|
||||||
|
|
||||||
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
||||||
''' in dieser Funktion wird die Stückzahl der Bauteile, welche auf der Waage liegen, berechnet '''
|
|
||||||
|
|
||||||
self.correctBtNr = False
|
self.correctBtNr = False
|
||||||
prevAnzahl = 0
|
prevAnzahl = 0
|
||||||
@ -204,6 +232,14 @@ class Worker(QObject):
|
|||||||
cursor.execute(sql_query)
|
cursor.execute(sql_query)
|
||||||
auftragDaten = cursor.fetchall()
|
auftragDaten = cursor.fetchall()
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Display data - zum Debuggen
|
||||||
|
print("Ausgabe der Auftragsdetails:")
|
||||||
|
print("id|EinzelteilID|Auftragsnummer|Anzahl")
|
||||||
|
for row in auftragDaten:
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
||||||
anzBauteile_soll = 0
|
anzBauteile_soll = 0
|
||||||
idVorhanden = False
|
idVorhanden = False
|
||||||
@ -225,7 +261,7 @@ class Worker(QObject):
|
|||||||
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
||||||
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
||||||
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
||||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
propDensVect.append([wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
||||||
|
|
||||||
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
||||||
maxpropDens = 0
|
maxpropDens = 0
|
||||||
@ -238,6 +274,14 @@ class Worker(QObject):
|
|||||||
if prevAnzahl != anzahl:
|
if prevAnzahl != anzahl:
|
||||||
prevAnzahl = anzahl
|
prevAnzahl = anzahl
|
||||||
|
|
||||||
|
# Die Wahrscheinlichkeit berechnen, dass das obige Ergebnis auch dem Bauteil entspricht
|
||||||
|
if anzahl > 0:
|
||||||
|
for row in auftragDaten:
|
||||||
|
if row[1] == einzelteilID:
|
||||||
|
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6])*anzahl, float(row[7])*anzahl)
|
||||||
|
break
|
||||||
|
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||||
|
|
||||||
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
||||||
if (anzahl == anzBauteile_soll):
|
if (anzahl == anzBauteile_soll):
|
||||||
self.correctBtNr = True
|
self.correctBtNr = True
|
||||||
@ -257,7 +301,8 @@ class Worker(QObject):
|
|||||||
self.waageStoppedSignal.emit(einzelteilID)
|
self.waageStoppedSignal.emit(einzelteilID)
|
||||||
|
|
||||||
|
|
||||||
## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser
|
|
||||||
|
|
||||||
class Ui_MainWindow(object):
|
class Ui_MainWindow(object):
|
||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
self.auftragsnummer = ""
|
self.auftragsnummer = ""
|
||||||
@ -265,6 +310,7 @@ class Ui_MainWindow(object):
|
|||||||
self.correctBtNr = False
|
self.correctBtNr = False
|
||||||
self.btTypeIsSet = False
|
self.btTypeIsSet = False
|
||||||
|
|
||||||
|
|
||||||
MainWindow.setObjectName("MainWindow")
|
MainWindow.setObjectName("MainWindow")
|
||||||
MainWindow.resize(1400, 675)
|
MainWindow.resize(1400, 675)
|
||||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||||
@ -387,46 +433,15 @@ class Ui_MainWindow(object):
|
|||||||
self.checkBoxAutoTare.setGeometry(QtCore.QRect(1000, 520, 180, 23))
|
self.checkBoxAutoTare.setGeometry(QtCore.QRect(1000, 520, 180, 23))
|
||||||
self.checkBoxAutoTare.setObjectName("checkBoxAutoTare")
|
self.checkBoxAutoTare.setObjectName("checkBoxAutoTare")
|
||||||
|
|
||||||
# button and checkbox for camera workflow + graphicsview widget
|
#self.myTestLambda = lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer)
|
||||||
self.camWorkFlowcheckBox = QtWidgets.QCheckBox(self.centralwidget)
|
|
||||||
self.camWorkFlowcheckBox.setGeometry(QtCore.QRect(700, int(1080/2), 151, 23))
|
|
||||||
self.camWorkFlowcheckBox.setObjectName("camWorkFlowcheckBox")
|
|
||||||
self.modelComboBox = QtWidgets.QComboBox(self.centralwidget)
|
|
||||||
self.modelComboBox.setGeometry(QtCore.QRect(700, int(1080/2)+50, 161, 25))
|
|
||||||
self.modelComboBox.setObjectName("modelComboBox")
|
|
||||||
self.startCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.startCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
|
||||||
self.startCamBtn.setObjectName("startCamBtn")
|
|
||||||
self.stopCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.stopCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+150, 161, 25))
|
|
||||||
self.stopCamBtn.setObjectName("stopCamBtn")
|
|
||||||
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
|
|
||||||
self.graphicsView.setGeometry(QtCore.QRect(10, int(1080/2), 661, int(480*1.05))) # position and size of camera frame # int(640*1.05)
|
|
||||||
self.graphicsView.setObjectName("graphicsView")
|
|
||||||
|
|
||||||
# relay control buttons
|
|
||||||
self.startSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.startSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
|
||||||
self.startSpotlightBtn.setObjectName("startSpotlightBtn")
|
|
||||||
self.stopSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.stopSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+150, 161, 25))
|
|
||||||
self.stopSpotlightBtn.setObjectName("stopSpotlightBtn")
|
|
||||||
|
|
||||||
# led control buttons
|
|
||||||
self.redLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.redLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+100, 161, 25))
|
|
||||||
self.yellowLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.yellowLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+150, 161, 25))
|
|
||||||
self.greenLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.greenLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+200, 161, 25))
|
|
||||||
self.offLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.offLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+250, 161, 25))
|
|
||||||
self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.blinkLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+300, 161, 25))
|
|
||||||
|
|
||||||
# Maximize the window on startup
|
|
||||||
MainWindow.showMaximized()
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
item.setFont(font)
|
||||||
|
self.AuftragsdetailsTable.setVerticalHeaderItem(0,item)
|
||||||
|
'''
|
||||||
self.retranslateUi(MainWindow)
|
self.retranslateUi(MainWindow)
|
||||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
@ -458,6 +473,8 @@ class Ui_MainWindow(object):
|
|||||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
|
item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
|
||||||
item.setText(_translate("MainWindow", "ToDo:"))
|
item.setText(_translate("MainWindow", "ToDo:"))
|
||||||
|
|
||||||
|
# Befüllen der Arbeisschritttabelle mit Text
|
||||||
|
#item = self.ArbeitsschrittTable.
|
||||||
# Ein neues QTableWidgetItem erstellen und den Text setzen
|
# Ein neues QTableWidgetItem erstellen und den Text setzen
|
||||||
item = QtWidgets.QTableWidgetItem("Auftrag laden")
|
item = QtWidgets.QTableWidgetItem("Auftrag laden")
|
||||||
self.ArbeitsschrittTable.setItem(0, 0, item)
|
self.ArbeitsschrittTable.setItem(0, 0, item)
|
||||||
@ -475,10 +492,19 @@ class Ui_MainWindow(object):
|
|||||||
self.ArbeitsschrittTable.setItem(3, 0, item)
|
self.ArbeitsschrittTable.setItem(3, 0, item)
|
||||||
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||||
|
|
||||||
|
#self.ArbeitsschrittTable.item(0,0).setText("test")
|
||||||
|
|
||||||
|
#einzelteilID = int(self.AuftragsdetailsTable.item(i,0).text())
|
||||||
|
#self.PosNrTxtFeld.setText(str(self.AuftragsdetailsTable.item(i,0).text()))
|
||||||
|
#self.bauteiltypTextbox.setText(str(self.AuftragsdetailsTable.item(i,2).text()))
|
||||||
|
|
||||||
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
||||||
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
||||||
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
||||||
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
||||||
|
#self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||||
|
#item = self.AuftragsdetailsTable.verticalHeaderItem(0)
|
||||||
|
#item.setText(_translate("MainWindow", "test"))
|
||||||
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
||||||
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
||||||
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
||||||
@ -498,35 +524,21 @@ class Ui_MainWindow(object):
|
|||||||
self.checkBoxAutoTare.setCheckState(Qt.Checked)
|
self.checkBoxAutoTare.setCheckState(Qt.Checked)
|
||||||
self.checkBox.setCheckState(Qt.Unchecked)
|
self.checkBox.setCheckState(Qt.Unchecked)
|
||||||
|
|
||||||
# new camera workflow
|
|
||||||
self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
|
|
||||||
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
|
|
||||||
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
|
|
||||||
self.modelComboBox
|
|
||||||
|
|
||||||
# relay control buttons
|
|
||||||
self.startSpotlightBtn.setText(_translate("MainWindow", "Turn on light"))
|
|
||||||
self.stopSpotlightBtn.setText(_translate("MainWindow", "Turn off light"))
|
|
||||||
|
|
||||||
# led control buttons
|
|
||||||
self.redLightBtn.setText(_translate("MainWindow", "Turn on red LED"))
|
|
||||||
self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED"))
|
|
||||||
self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED"))
|
|
||||||
self.offLightBtn.setText(_translate("MainWindow", "Turn off all LEDs"))
|
|
||||||
self.blinkLightBtn.setText(_translate("MainWindow", "Blink Yellow LED"))
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
print("Das MainWindow wurde angeklickt.")
|
print("Das MainWindow wurde angeklickt.")
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
super().mousePressEvent(event)
|
super().mousePressEvent(event)
|
||||||
|
|
||||||
|
|
||||||
def onTareClick(self):
|
def onTareClick(self):
|
||||||
''' Tarieren der Waage '''
|
#Tarieren der Waage
|
||||||
if ser.is_open == False:
|
if ser.is_open == False:
|
||||||
ser.open()
|
ser.open()
|
||||||
ser.write(b'tare\n')
|
ser.write(b'tare\n')
|
||||||
ser.close()
|
ser.close()
|
||||||
|
|
||||||
|
|
||||||
def onCheckboxCheck(self):
|
def onCheckboxCheck(self):
|
||||||
if self.checkBox.isChecked() == True:
|
if self.checkBox.isChecked() == True:
|
||||||
print("static workflow activated")
|
print("static workflow activated")
|
||||||
@ -543,6 +555,9 @@ class Ui_MainWindow(object):
|
|||||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||||
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
||||||
return i
|
return i
|
||||||
|
# brauche ich hier vermutlich nicht mehr - ist in den Worker Thread kopiert worden
|
||||||
|
def waageNichtEingeschwungenOutput(self):
|
||||||
|
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||||
|
|
||||||
def onTableCellClick(self):
|
def onTableCellClick(self):
|
||||||
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
||||||
@ -567,21 +582,71 @@ class Ui_MainWindow(object):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# eventuell benötigt man die Funktion hier nicht mehr, da sie zu den Threads kopiert wurde
|
||||||
|
def getDataOfArticleType(self, allArticles, articleType):
|
||||||
|
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||||
|
for i in allArticles:
|
||||||
|
if i[1] == articleType:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
def updateGUI(self):
|
def updateGUI(self):
|
||||||
self.PosNrLabel.repaint() #GUI aktualisieren
|
self.PosNrLabel.repaint() #GUI aktualisieren
|
||||||
QApplication.processEvents() #GUI aktualisieren
|
QApplication.processEvents() #GUI aktualisieren
|
||||||
|
|
||||||
|
|
||||||
def setRowColor(self, tableObject, rowID,r,g,b):
|
def setRowColor(self, tableObject, rowID,r,g,b):
|
||||||
for col in range(tableObject.columnCount()-1):
|
for col in range(tableObject.columnCount()-1):
|
||||||
tableObject.item(rowID, col).setBackground(QtGui.QColor(r,g,b))
|
tableObject.item(rowID, col).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
'''
|
||||||
|
die alte Version der Programmierung
|
||||||
|
tableObject.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
tableObject.item(rowID, 1).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
tableObject.item(rowID, 2).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
tableObject.item(rowID, 3).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
tableObject.item(rowID, 4).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
tableObject.item(rowID, 5).setBackground(QtGui.QColor(r,g,b))
|
||||||
|
'''
|
||||||
|
|
||||||
# # call change led color
|
#wird hier vermutlich nicht mehr benötigt - wurde in die Workerklasse kopiert
|
||||||
# Check if the 'w' object already exists
|
def readWaage(self):
|
||||||
# hier könnte noch nachgearbeitet werden
|
# in folgender Funktion wird die Waage ausgelesen
|
||||||
if not hasattr(self, 'w'):
|
|
||||||
w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||||
w.connect()
|
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe
|
||||||
w.map_color_to_led([r,g,b])
|
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):
|
def auftragsBtnClicked(self):
|
||||||
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
||||||
@ -600,7 +665,16 @@ class Ui_MainWindow(object):
|
|||||||
print("Fehler in der Datenbankabfrage.")
|
print("Fehler in der Datenbankabfrage.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
||||||
|
'''
|
||||||
|
# Display data
|
||||||
|
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
if str(row[2]) == self.auftragsnummer:
|
||||||
|
print("passt")
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
### die Auftragsdaten in die Tabelle laden
|
### die Auftragsdaten in die Tabelle laden
|
||||||
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
||||||
@ -647,6 +721,7 @@ class Ui_MainWindow(object):
|
|||||||
self.bauteiltypTextbox.setText("")
|
self.bauteiltypTextbox.setText("")
|
||||||
self.PosNrTxtFeld.setText("")
|
self.PosNrTxtFeld.setText("")
|
||||||
|
|
||||||
|
|
||||||
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
|
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
|
||||||
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
||||||
|
|
||||||
@ -659,7 +734,7 @@ class Ui_MainWindow(object):
|
|||||||
self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
|
self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
|
||||||
|
|
||||||
def stopLoopClicked(self):
|
def stopLoopClicked(self):
|
||||||
''' damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert '''
|
# damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert
|
||||||
if hasattr(self, 'objectDetectionWorker'):
|
if hasattr(self, 'objectDetectionWorker'):
|
||||||
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
||||||
|
|
||||||
@ -667,15 +742,20 @@ class Ui_MainWindow(object):
|
|||||||
self.checkWaageWorker.stopLoopSignal.emit(True)
|
self.checkWaageWorker.stopLoopSignal.emit(True)
|
||||||
|
|
||||||
def checkFinished(self):
|
def checkFinished(self):
|
||||||
''' die Funktion geht alle Zeilen der Auftragsliste durch und schaut, ob die richtige Anzahl an Teilen vorhanden sind '''
|
#die Funktion geht alle Zeilen der Auftragsliste durch und schaut, ob die richtige Anzahl an Teilen vorhanden sind
|
||||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||||
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
|
if self.AuftragsdetailsTable.item(i,3).text() != self.AuftragsdetailsTable.item(i,4).text():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def checkWaage(self):
|
def checkWaage(self):
|
||||||
|
#print("Running in thread:", threading.current_thread().name) # Debuggingausgabe
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
|
||||||
|
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||||
|
#self.checkWaageWorker.stopLoopSignal.emit(False)
|
||||||
|
|
||||||
# überprüfen, ob der Auftrag geladen wurde
|
# überprüfen, ob der Auftrag geladen wurde
|
||||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||||
print("Der Auftrag muss zuerst geladen werden.")
|
print("Der Auftrag muss zuerst geladen werden.")
|
||||||
@ -764,13 +844,22 @@ class Ui_MainWindow(object):
|
|||||||
#self.updateGUI()
|
#self.updateGUI()
|
||||||
|
|
||||||
def objectTypeDetection(self):
|
def objectTypeDetection(self):
|
||||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||||
|
|
||||||
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
||||||
if self.checkBox.isChecked() == True:
|
if self.checkBox.isChecked() == True:
|
||||||
self.checkWaage()
|
self.checkWaage()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
'''
|
||||||
|
if(self.checkPosNrEmpty()==True):
|
||||||
|
print("Das Pos.-Nr.-Feld ist leer.")
|
||||||
|
return
|
||||||
|
'''
|
||||||
|
|
||||||
|
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||||
|
#self.objectDetectionWorker.stopLoopSignal.emit(False)
|
||||||
|
|
||||||
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
||||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||||
print("Der Auftrag muss zuerst geladen werden.")
|
print("Der Auftrag muss zuerst geladen werden.")
|
||||||
@ -794,7 +883,7 @@ class Ui_MainWindow(object):
|
|||||||
self.objectDetectionThread.start()
|
self.objectDetectionThread.start()
|
||||||
|
|
||||||
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
||||||
''' wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden '''
|
# wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden
|
||||||
|
|
||||||
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
||||||
self.PosNrTxtFeld.setText(str(rowData[1]))
|
self.PosNrTxtFeld.setText(str(rowData[1]))
|
||||||
@ -810,12 +899,20 @@ class Ui_MainWindow(object):
|
|||||||
self.objectDetectionThread.quit()
|
self.objectDetectionThread.quit()
|
||||||
self.objectDetectionThread.wait()
|
self.objectDetectionThread.wait()
|
||||||
|
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
self.objectDetectionThread.started.disconnect() # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
|
||||||
|
except:
|
||||||
|
print(f"Error while disconnecting: {e}")
|
||||||
|
print("Disconnecting the thread did not work.")
|
||||||
|
'''
|
||||||
|
|
||||||
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
||||||
self.updateGUI()
|
self.updateGUI()
|
||||||
self.checkWaage()
|
self.checkWaage()
|
||||||
|
|
||||||
def threadStopped(self, einzelteilID):
|
def threadStopped(self, einzelteilID):
|
||||||
''' wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0 '''
|
# wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0
|
||||||
if self.checkFinished() == False:
|
if self.checkFinished() == False:
|
||||||
if(einzelteilID > 0):
|
if(einzelteilID > 0):
|
||||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
||||||
@ -833,147 +930,10 @@ class Ui_MainWindow(object):
|
|||||||
self.checkWaageThread.wait()
|
self.checkWaageThread.wait()
|
||||||
print("Der CheckWaage-Thread wurde beendet.")
|
print("Der CheckWaage-Thread wurde beendet.")
|
||||||
|
|
||||||
# new class for Camera Object detection with YOLOv8
|
|
||||||
class CameraStreamApp(QtWidgets.QMainWindow):
|
|
||||||
def __init__(self, ui):
|
|
||||||
super().__init__()
|
|
||||||
self.ui = ui
|
|
||||||
self.yolo_stream = None # Initialize YOLOv8CameraStream as None
|
|
||||||
self.timer = QtCore.QTimer(self)
|
|
||||||
self.timer.timeout.connect(self.update_frame)
|
|
||||||
|
|
||||||
# Populate the model dropdown menu
|
|
||||||
self.populate_model_dropdown()
|
|
||||||
|
|
||||||
self.ui.startCamBtn.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
|
|
||||||
self.ui.stopCamBtn.clicked.connect(self.stop_camera) # start camera if button LoadAuftrag is clicked
|
|
||||||
self.scene = QtWidgets.QGraphicsScene(self)
|
|
||||||
self.ui.graphicsView.setScene(self.scene)
|
|
||||||
|
|
||||||
def populate_model_dropdown(self):
|
|
||||||
"""Populate the dropdown menu with model files from the models directory."""
|
|
||||||
models_dir = "models"
|
|
||||||
model_files = [f for f in os.listdir(models_dir) if f.endswith(".pt")]
|
|
||||||
self.ui.modelComboBox.clear()
|
|
||||||
self.ui.modelComboBox.addItems(model_files)
|
|
||||||
|
|
||||||
def start_camera(self):
|
|
||||||
# Start the YOLOv8 camera stream (only if not already started)
|
|
||||||
if self.yolo_stream is None:
|
|
||||||
self.yolo_stream = YOLOv8CameraStream(model_path="models/yolov8m_seg_e300.pt", logging_level="high")
|
|
||||||
# self.yolo_stream.start() # Start the YOLOv8 stream
|
|
||||||
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
|
|
||||||
|
|
||||||
def stop_camera(self):
|
|
||||||
# Stop the camera stream and processing
|
|
||||||
if self.yolo_stream is not None:
|
|
||||||
self.timer.stop() # Stop the timer
|
|
||||||
self.yolo_stream.cap.release() # Release the camera resource
|
|
||||||
self.yolo_stream = None # Reset the YOLOv8 stream object
|
|
||||||
self.scene.clear() # Clear the displayed frame from the graphicsView
|
|
||||||
print("Camera stream stopped and resources released.")
|
|
||||||
|
|
||||||
def update_frame(self):
|
|
||||||
# Update the frame from YOLOv8 stream
|
|
||||||
if self.yolo_stream:
|
|
||||||
ret, frame = self.yolo_stream.cap.read() # Capture frame from YOLOv8 stream
|
|
||||||
|
|
||||||
if ret:
|
|
||||||
# new part including processing via yolo model
|
|
||||||
processed_frame = self.yolo_stream.process_frame(frame)
|
|
||||||
|
|
||||||
# Convert the frame from BGR (OpenCV format) to RGB
|
|
||||||
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
||||||
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
|
||||||
|
|
||||||
# Convert the frame to QImage
|
|
||||||
h, w, ch = frame.shape
|
|
||||||
bytes_per_line = ch * w
|
|
||||||
qt_image = QtGui.QImage(frame.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
|
|
||||||
|
|
||||||
# Add the QImage to a QPixmap
|
|
||||||
pixmap = QtGui.QPixmap.fromImage(qt_image)
|
|
||||||
|
|
||||||
# Get the size of the graphicsView and scale the pixmap to fit
|
|
||||||
view_size = self.ui.graphicsView.size()
|
|
||||||
scaled_pixmap = pixmap.scaled(view_size, QtCore.Qt.KeepAspectRatio)
|
|
||||||
|
|
||||||
# Update the scene with the scaled pixmap
|
|
||||||
self.scene.clear()
|
|
||||||
self.scene.addPixmap(scaled_pixmap)
|
|
||||||
|
|
||||||
def closeEvent(self, event):
|
|
||||||
# Release the camera when the application is closed
|
|
||||||
if self.yolo_stream is not None:
|
|
||||||
self.yolo_stream.cap.release()
|
|
||||||
event.accept()
|
|
||||||
|
|
||||||
# new class for light control
|
|
||||||
class LightControl(QtWidgets.QMainWindow):
|
|
||||||
def __init__(self, ui):
|
|
||||||
super().__init__()
|
|
||||||
self.ui = ui
|
|
||||||
|
|
||||||
# init relay control
|
|
||||||
self.ui.startSpotlightBtn.clicked.connect(self.spot_on)
|
|
||||||
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
|
|
||||||
self.r = sainsmartrelay.SainsmartRelay()
|
|
||||||
|
|
||||||
# init led control
|
|
||||||
self.ui.redLightBtn.clicked.connect(self.red_on)
|
|
||||||
self.ui.yellowLightBtn.clicked.connect(self.yellow_on)
|
|
||||||
self.ui.greenLightBtn.clicked.connect(self.green_on)
|
|
||||||
self.ui.offLightBtn.clicked.connect(self.leds_off)
|
|
||||||
self.ui.blinkLightBtn.clicked.connect(self.blink_yellow)
|
|
||||||
self.w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
|
||||||
self.w.connect()
|
|
||||||
#self.w.switch_to_green() # at appstart the light is green
|
|
||||||
self.w.blink_green() # and switches to green blinking until the workflow gets started successfully#
|
|
||||||
|
|
||||||
# Connect app exit signal to the cleanup method
|
|
||||||
app.aboutToQuit.connect(self.cleanup)
|
|
||||||
|
|
||||||
def cleanup(self):
|
|
||||||
"""Clean up resources and switch off LEDs."""
|
|
||||||
print("Cleaning up resources and switching off LEDs")
|
|
||||||
self.leds_off() # Turn off LEDs
|
|
||||||
self.w.disconnect() # Disconnect WLED controller
|
|
||||||
|
|
||||||
def spot_on(self):
|
|
||||||
print("Turn on light clicked")
|
|
||||||
self.r.turn_on(1)
|
|
||||||
|
|
||||||
def spot_off(self):
|
|
||||||
print("Turn off light clicked")
|
|
||||||
self.r.turn_off(1)
|
|
||||||
|
|
||||||
def red_on(self):
|
|
||||||
print("Red light is on")
|
|
||||||
self.w.switch_to_red()
|
|
||||||
|
|
||||||
def yellow_on(self):
|
|
||||||
print("Yellow light is on")
|
|
||||||
self.w.switch_to_yellow()
|
|
||||||
|
|
||||||
def green_on(self):
|
|
||||||
print("Green light is on")
|
|
||||||
self.w.switch_to_green()
|
|
||||||
|
|
||||||
def leds_off(self):
|
|
||||||
print("LEDs are off")
|
|
||||||
self.w.turn_off_all()
|
|
||||||
|
|
||||||
def blink_yellow(self):
|
|
||||||
print("Yellow color is blinking")
|
|
||||||
self.w.blink_yellow()
|
|
||||||
|
|
||||||
def blink_red(self):
|
|
||||||
print("Red color is blinking")
|
|
||||||
self.w.blink_red()
|
|
||||||
|
|
||||||
def blink_green(self):
|
|
||||||
print("Green color is blinking")
|
|
||||||
self.w.blink_green()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
@ -981,11 +941,10 @@ if __name__ == "__main__":
|
|||||||
MainWindow = QtWidgets.QMainWindow()
|
MainWindow = QtWidgets.QMainWindow()
|
||||||
ui = Ui_MainWindow()
|
ui = Ui_MainWindow()
|
||||||
ui.setupUi(MainWindow)
|
ui.setupUi(MainWindow)
|
||||||
|
|
||||||
# Initialize the CameraStreamApp with the UI
|
|
||||||
camera_app = CameraStreamApp(ui)
|
|
||||||
# initialize light control app
|
|
||||||
light_app = LightControl(ui)
|
|
||||||
|
|
||||||
MainWindow.show()
|
MainWindow.show()
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
751
GUI_19_09_staticWorkflow_Multithreading.py
Normal 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_())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
823
GUI_26_09_staticWorkflow_Multithreading.py
Normal 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_())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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_())
|
@ -1,8 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'test.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.9
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
########## beim Static workflow funktionieren die Threads ab dem zweiten nicht mehr
|
||||||
|
|
||||||
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
#from PyQt5 import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
from PyQt5.QtWidgets import QApplication, QComboBox
|
from PyQt5.QtWidgets import QApplication, QComboBox
|
||||||
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject, Qt
|
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
import serial
|
import serial
|
||||||
@ -12,57 +23,55 @@ 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 lib.sainsmartrelay as sainsmartrelay
|
|
||||||
import lib.wledControl as wledControl
|
|
||||||
|
|
||||||
|
|
||||||
# ## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser -> Farben Drop Down
|
|
||||||
|
|
||||||
|
|
||||||
# ## Aufsetzen der Datenbank und Waagenverbindung
|
|
||||||
# # Definieren der Datenbankverbindung
|
|
||||||
db_config = {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
# # Establishing the connection
|
# Establishing the connection
|
||||||
# conn = mariadb.connect(**db_config)
|
conn = mariadb.connect(**db_config)
|
||||||
# # Create a cursor to execute queries
|
# Create a cursor to execute queries
|
||||||
# cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
try:
|
|
||||||
# Attempt to establish the connection
|
|
||||||
conn = mariadb.connect(**db_config)
|
|
||||||
print("Database connection established successfully.")
|
|
||||||
|
|
||||||
# Create a cursor to execute queries
|
|
||||||
cursor = conn.cursor()
|
|
||||||
except mariadb.Error as e:
|
|
||||||
# Handle connection errors
|
|
||||||
print(f"Error connecting to the database: {e}")
|
|
||||||
conn = None
|
|
||||||
cursor = None
|
|
||||||
|
|
||||||
|
# # Konfiguration der seriellen Schnittstelle
|
||||||
|
# ser = serial.Serial('/dev/ttyUSB0', 9600)
|
||||||
|
|
||||||
# Configuration of the serial port
|
# Configuration of the serial port
|
||||||
try:
|
try:
|
||||||
ser = serial.Serial('/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:3:1.0-port0', 9600)
|
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.")
|
print("Serial port connected successfully.")
|
||||||
except serial.SerialException:
|
except serial.SerialException:
|
||||||
ser = None
|
ser = None
|
||||||
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.")
|
print("Warning: Serial port not found. Continuing without serial connection. Only working for demo-purposes.")
|
||||||
|
|
||||||
|
waageEingeschwungen = False
|
||||||
|
|
||||||
# die Workerklasse ist dazu da die Schleifen - in welchen der Bauteiltyp erkannt wird und die Anzahl der Bauteile, welche auf der Waage liegen - in einem seperaten Thread auszuführen, um ein Blockieren des Mainthreads zu verhindern
|
|
||||||
|
def wahrscheinlichkeitsDichte(x,mue, var):
|
||||||
|
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet
|
||||||
|
standardabweichung = var**0.5
|
||||||
|
|
||||||
|
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def calcWahrscheinlichkeitFromDichte(x,mue, var):
|
||||||
|
# in der Funktion wird die Wahrscheinlichkeit via der Wahrscheinlichkeitsdichte berechnet, indem das Verhältnis aus der dem Bauteil zugehörigen Wahrscheinlichkeitsdichte zu der maximalen Wahrscheinlichkeitsdichte berechnet wird
|
||||||
|
p1 = wahrscheinlichkeitsDichte(x,mue, var)
|
||||||
|
p_max = wahrscheinlichkeitsDichte(mue,mue, var)
|
||||||
|
|
||||||
|
return p1/p_max
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#class Worker(QThread):
|
||||||
class Worker(QObject):
|
class Worker(QObject):
|
||||||
#progress = pyqtSignal(int)
|
#progress = pyqtSignal(int)
|
||||||
objectDetectionStartSignal = pyqtSignal(str)
|
objectDetectionStartSignal = pyqtSignal(str)
|
||||||
@ -75,7 +84,6 @@ class Worker(QObject):
|
|||||||
waageStoppedSignal = pyqtSignal(int)
|
waageStoppedSignal = pyqtSignal(int)
|
||||||
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
stopLoopSignal = pyqtSignal(bool) #das Signal wird verwendet um direkt den stopLoop-Wert zu ändern (also kein Funktionsaufruf)
|
||||||
|
|
||||||
waageEingeschwungen = False
|
|
||||||
stopLoop = False
|
stopLoop = False
|
||||||
btTypeIsSet = False
|
btTypeIsSet = False
|
||||||
correctBtNr = False
|
correctBtNr = False
|
||||||
@ -87,7 +95,7 @@ class Worker(QObject):
|
|||||||
|
|
||||||
|
|
||||||
def getDataOfArticleType(self, allArticles, articleType):
|
def getDataOfArticleType(self, allArticles, articleType):
|
||||||
''' die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück '''
|
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||||
for i in allArticles:
|
for i in allArticles:
|
||||||
if i[1] == articleType:
|
if i[1] == articleType:
|
||||||
return i
|
return i
|
||||||
@ -97,27 +105,26 @@ class Worker(QObject):
|
|||||||
def waageNichtEingeschwungenOutput(self):
|
def waageNichtEingeschwungenOutput(self):
|
||||||
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||||
|
|
||||||
def wahrscheinlichkeitsDichte(self, x,mue, var):
|
|
||||||
''' in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet '''
|
|
||||||
standardabweichung = var**0.5
|
|
||||||
|
|
||||||
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def readWaage(self):
|
def readWaage(self):
|
||||||
''' in folgender Funktion wird die Waage ausgelesen '''
|
# in folgender Funktion wird die Waage ausgelesen
|
||||||
|
|
||||||
|
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||||
|
#print("port to which it is connected: ", ser.portstr) #Debuggingausgabe
|
||||||
|
|
||||||
|
|
||||||
if ser.is_open == False:
|
if ser.is_open == False:
|
||||||
ser.open()
|
ser.open()
|
||||||
|
|
||||||
|
|
||||||
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||||||
ser.write(b'getWeight\n')
|
ser.write(b'getWeight\n')
|
||||||
|
#ser.write(b'tare\n')
|
||||||
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||||||
|
|
||||||
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||||||
lenString = len(serialString)-1
|
lenString = len(serialString)-1
|
||||||
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||||||
|
#print("ist eingeschwungen") #Debuggingausgabe
|
||||||
waageEingeschwungen = True
|
waageEingeschwungen = True
|
||||||
else:
|
else:
|
||||||
print("die Waage ist noch nicht eingeschwungen")
|
print("die Waage ist noch nicht eingeschwungen")
|
||||||
@ -129,13 +136,17 @@ class Worker(QObject):
|
|||||||
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||||||
intString = intString + i
|
intString = intString + i
|
||||||
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||||||
|
## Waage auslesen - ENDE
|
||||||
|
|
||||||
ser.close()
|
ser.close()
|
||||||
|
#print("connection is open: ", ser.is_open) #Debuggingausgabe
|
||||||
|
|
||||||
return waageEingeschwungen, intString
|
return waageEingeschwungen, intString
|
||||||
|
|
||||||
def objectTypeDetectionThread(self, auftragsnummer):
|
def objectTypeDetectionThread(self, auftragsnummer):
|
||||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||||
|
|
||||||
|
#print("objectTypeDetectionThread - Running in thread:", threading.current_thread().name) #Debuggausgabe
|
||||||
|
|
||||||
# Parameterdefinition
|
# Parameterdefinition
|
||||||
propDensVect = []
|
propDensVect = []
|
||||||
@ -155,9 +166,16 @@ class Worker(QObject):
|
|||||||
cursor.execute(sql_query)
|
cursor.execute(sql_query)
|
||||||
auftragEinzelteilDaten = cursor.fetchall()
|
auftragEinzelteilDaten = cursor.fetchall()
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Display data #Debugausgabe
|
||||||
|
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
# in der Folge werden alle Wahrscheinlichkeitsdichten der Auftragsbauteile berechnet und in dem Vektor gesammelt
|
||||||
for row in auftragEinzelteilDaten:
|
for row in auftragEinzelteilDaten:
|
||||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),float(row[6]), float(row[7])), row[1], row[5]])
|
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
|
# Jenen Eintrag des propDensVect raussuchen, welcher die größte Wahrscheinlichkeitsdichte beinhaltet
|
||||||
maxpropDens = 0
|
maxpropDens = 0
|
||||||
@ -175,6 +193,14 @@ class Worker(QObject):
|
|||||||
else:
|
else:
|
||||||
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
print("Bei dem Bauteil" , einzelteilID , "wurde die höchste Wahrscheinlichkeitsdichte berechnet.")
|
||||||
|
|
||||||
|
# Wahrscheinlichkeit berechnen, dass das angegebene Bauteil auch wirklich diesem entspricht
|
||||||
|
prop = 0
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
if row[1] == einzelteilID:
|
||||||
|
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6]), float(row[7]))
|
||||||
|
break
|
||||||
|
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||||
|
|
||||||
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
# den Bool auf true setzen, damit die Schleife beendet wird - dieser wird auf True gesetzt, wenn ein Bauteiltyp erkannt wird
|
||||||
self.btTypeIsSet = True
|
self.btTypeIsSet = True
|
||||||
|
|
||||||
@ -185,7 +211,6 @@ class Worker(QObject):
|
|||||||
self.waageStoppedSignal.emit(einzelteilID)
|
self.waageStoppedSignal.emit(einzelteilID)
|
||||||
|
|
||||||
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
def checkWaageThread(self, einzelteilID, teileZuViel, auftragsnummer):
|
||||||
''' in dieser Funktion wird die Stückzahl der Bauteile, welche auf der Waage liegen, berechnet '''
|
|
||||||
|
|
||||||
self.correctBtNr = False
|
self.correctBtNr = False
|
||||||
prevAnzahl = 0
|
prevAnzahl = 0
|
||||||
@ -205,6 +230,14 @@ class Worker(QObject):
|
|||||||
cursor.execute(sql_query)
|
cursor.execute(sql_query)
|
||||||
auftragDaten = cursor.fetchall()
|
auftragDaten = cursor.fetchall()
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Display data - zum Debuggen
|
||||||
|
print("Ausgabe der Auftragsdetails:")
|
||||||
|
print("id|EinzelteilID|Auftragsnummer|Anzahl")
|
||||||
|
for row in auftragDaten:
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
#auslesen, wie viele Bauteile des Types laut Auftrag vorhanden sein sollen
|
||||||
anzBauteile_soll = 0
|
anzBauteile_soll = 0
|
||||||
idVorhanden = False
|
idVorhanden = False
|
||||||
@ -226,7 +259,7 @@ class Worker(QObject):
|
|||||||
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
||||||
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
mueGes = float(articleData[6])*i # Berechnen des äquivalenten Mittelwert
|
||||||
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
varGes = float(articleData[7])*i # Berechnen der äquivalenten Varianz
|
||||||
propDensVect.append([self.wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
propDensVect.append([wahrscheinlichkeitsDichte(float(intString),mueGes, varGes), i])
|
||||||
|
|
||||||
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
# durch den propDensVect iterieren und jenen Eintrag mit der höchsten Wahrscheinlichkeitsdichte raussuchen
|
||||||
maxpropDens = 0
|
maxpropDens = 0
|
||||||
@ -239,6 +272,14 @@ class Worker(QObject):
|
|||||||
if prevAnzahl != anzahl:
|
if prevAnzahl != anzahl:
|
||||||
prevAnzahl = anzahl
|
prevAnzahl = anzahl
|
||||||
|
|
||||||
|
# Die Wahrscheinlichkeit berechnen, dass das obige Ergebnis auch dem Bauteil entspricht
|
||||||
|
if anzahl > 0:
|
||||||
|
for row in auftragDaten:
|
||||||
|
if row[1] == einzelteilID:
|
||||||
|
prop = calcWahrscheinlichkeitFromDichte(float(intString),float(row[6])*anzahl, float(row[7])*anzahl)
|
||||||
|
break
|
||||||
|
print("Die Wahrscheinlichkeit, dass es das Bauteil ist, beträgt: ", prop)
|
||||||
|
|
||||||
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
# wenn genug Bauteile vorhanden sind, dann soll die Schleife beendet werden
|
||||||
if (anzahl == anzBauteile_soll):
|
if (anzahl == anzBauteile_soll):
|
||||||
self.correctBtNr = True
|
self.correctBtNr = True
|
||||||
@ -258,24 +299,25 @@ class Worker(QObject):
|
|||||||
self.waageStoppedSignal.emit(einzelteilID)
|
self.waageStoppedSignal.emit(einzelteilID)
|
||||||
|
|
||||||
|
|
||||||
## in der Ui_MainWindow-Klasse wird die GUI erstellt - der MainThread läuft in dieser
|
|
||||||
|
|
||||||
class Ui_MainWindow(object):
|
class Ui_MainWindow(object):
|
||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
self.auftragsnummer = ""
|
self.auftragsnummer = ""
|
||||||
self.teileZuViel = 100 # Anzahl an Bauteilen, welche zu viel drinnen sein können - der Parameter kann selbst gesetzt werden #####
|
self.teileZuViel = 0 # Anzahl an Bauteilen, welche zu viel drinnen sein können - der Parameter kann selbst gesetzt werden #####
|
||||||
self.correctBtNr = False
|
self.correctBtNr = False
|
||||||
self.btTypeIsSet = False
|
self.btTypeIsSet = False
|
||||||
|
|
||||||
|
|
||||||
MainWindow.setObjectName("MainWindow")
|
MainWindow.setObjectName("MainWindow")
|
||||||
MainWindow.resize(1400, 675)
|
MainWindow.resize(1090, 675)
|
||||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||||
self.centralwidget.setObjectName("centralwidget")
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
|
self.btn1 = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.btn1.setGeometry(QtCore.QRect(700, 45, 111, 25))
|
self.btn1.setGeometry(QtCore.QRect(700, 45, 111, 25))
|
||||||
self.btn1.setObjectName("btn1")
|
self.btn1.setObjectName("btn1")
|
||||||
# Tabelle zur Darstellung der Auftragsdetails
|
|
||||||
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
|
self.AuftragsdetailsTable = QtWidgets.QTableWidget(self.centralwidget)
|
||||||
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 100, 661, 400))
|
self.AuftragsdetailsTable.setGeometry(QtCore.QRect(10, 300, 661, 192))
|
||||||
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
|
self.AuftragsdetailsTable.setObjectName("AuftragsdetailsTable")
|
||||||
self.AuftragsdetailsTable.setColumnCount(7)
|
self.AuftragsdetailsTable.setColumnCount(7)
|
||||||
self.AuftragsdetailsTable.setRowCount(0)
|
self.AuftragsdetailsTable.setRowCount(0)
|
||||||
@ -315,29 +357,6 @@ class Ui_MainWindow(object):
|
|||||||
item.setFont(font)
|
item.setFont(font)
|
||||||
self.AuftragsdetailsTable.setHorizontalHeaderItem(6, item)
|
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 = QtWidgets.QLabel(self.centralwidget)
|
||||||
self.label.setGeometry(QtCore.QRect(500, 20, 121, 17))
|
self.label.setGeometry(QtCore.QRect(500, 20, 121, 17))
|
||||||
self.label.setObjectName("label")
|
self.label.setObjectName("label")
|
||||||
@ -345,16 +364,16 @@ class Ui_MainWindow(object):
|
|||||||
self.textEdit.setGeometry(QtCore.QRect(450, 40, 221, 31))
|
self.textEdit.setGeometry(QtCore.QRect(450, 40, 221, 31))
|
||||||
self.textEdit.setObjectName("textEdit")
|
self.textEdit.setObjectName("textEdit")
|
||||||
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.bauteilTypBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.bauteilTypBtn.setGeometry(QtCore.QRect(700, 100, 161, 25))
|
self.bauteilTypBtn.setGeometry(QtCore.QRect(700, 150, 161, 25))
|
||||||
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
|
self.bauteilTypBtn.setObjectName("bauteilTypBtn")
|
||||||
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.checkWaageBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 150, 161, 25))
|
self.checkWaageBtn.setGeometry(QtCore.QRect(700, 460, 161, 25))
|
||||||
self.checkWaageBtn.setObjectName("checkWaageBtn")
|
self.checkWaageBtn.setObjectName("checkWaageBtn")
|
||||||
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.stopLoopBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 350, 161, 25))
|
self.stopLoopBtn.setGeometry(QtCore.QRect(700, 500, 161, 25))
|
||||||
self.stopLoopBtn.setObjectName("stopLoopBtn")
|
self.stopLoopBtn.setObjectName("stopLoopBtn")
|
||||||
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.waageTareBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.waageTareBtn.setGeometry(QtCore.QRect(700, 400, 161, 25))
|
self.waageTareBtn.setGeometry(QtCore.QRect(700, 100, 161, 25))
|
||||||
self.waageTareBtn.setObjectName("waageTareBtn")
|
self.waageTareBtn.setObjectName("waageTareBtn")
|
||||||
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
|
self.bauteiltypTextbox = QtWidgets.QTextEdit(self.centralwidget)
|
||||||
self.bauteiltypTextbox.setGeometry(QtCore.QRect(700, 290, 221, 31))
|
self.bauteiltypTextbox.setGeometry(QtCore.QRect(700, 290, 221, 31))
|
||||||
@ -367,12 +386,12 @@ class Ui_MainWindow(object):
|
|||||||
self.PosNrLabel.setObjectName("PosNrLabel")
|
self.PosNrLabel.setObjectName("PosNrLabel")
|
||||||
self.PosNrTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
self.PosNrTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
||||||
self.PosNrTxtFeld.setGeometry(QtCore.QRect(700, 220, 191, 31))
|
self.PosNrTxtFeld.setGeometry(QtCore.QRect(700, 220, 191, 31))
|
||||||
self.PosNrTxtFeld.setObjectName("PosNrTxtFeld")
|
self.BezeichnungLabel.setObjectName("BezeichnungLabel")
|
||||||
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
|
self.teileZuVielLabel = QtWidgets.QLabel(self.centralwidget)
|
||||||
self.teileZuVielLabel.setGeometry(QtCore.QRect(1000, 560, 350, 17))
|
self.teileZuVielLabel.setGeometry(QtCore.QRect(700, 350, 350, 17))
|
||||||
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
|
self.teileZuVielLabel.setObjectName("teileZuVielLabel")
|
||||||
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
self.teileZuVielTxtFeld = QtWidgets.QTextEdit(self.centralwidget)
|
||||||
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(1000, 580, 191, 31))
|
self.teileZuVielTxtFeld.setGeometry(QtCore.QRect(700, 370, 191, 31))
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1090, 22))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 1090, 22))
|
||||||
@ -382,52 +401,32 @@ class Ui_MainWindow(object):
|
|||||||
self.statusbar.setObjectName("statusbar")
|
self.statusbar.setObjectName("statusbar")
|
||||||
MainWindow.setStatusBar(self.statusbar)
|
MainWindow.setStatusBar(self.statusbar)
|
||||||
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
|
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
|
||||||
self.checkBox.setGeometry(QtCore.QRect(1000, 480, 151, 23))
|
self.checkBox.setGeometry(QtCore.QRect(700, 10, 151, 23))
|
||||||
self.checkBox.setObjectName("checkBox")
|
self.checkBox.setObjectName("checkBox")
|
||||||
self.checkBoxAutoTare = QtWidgets.QCheckBox(self.centralwidget)
|
|
||||||
self.checkBoxAutoTare.setGeometry(QtCore.QRect(1000, 520, 180, 23))
|
|
||||||
self.checkBoxAutoTare.setObjectName("checkBoxAutoTare")
|
|
||||||
|
|
||||||
# button and checkbox for camera workflow + graphicsview widget
|
# button and checkbox for camera workflow + graphicsview widget
|
||||||
self.camWorkFlowcheckBox = QtWidgets.QCheckBox(self.centralwidget)
|
|
||||||
self.camWorkFlowcheckBox.setGeometry(QtCore.QRect(700, int(1080/2), 151, 23))
|
|
||||||
self.camWorkFlowcheckBox.setObjectName("camWorkFlowcheckBox")
|
|
||||||
self.modelComboBox = QtWidgets.QComboBox(self.centralwidget)
|
|
||||||
self.modelComboBox.setGeometry(QtCore.QRect(700, int(1080/2)+50, 161, 25))
|
|
||||||
self.modelComboBox.setObjectName("modelComboBox")
|
|
||||||
self.startCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.startCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.startCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
self.startCamBtn.setGeometry(QtCore.QRect(900, 45, 161, 25))
|
||||||
self.startCamBtn.setObjectName("startCamBtn")
|
self.startCamBtn.setObjectName("startCamBtn")
|
||||||
self.stopCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
self.stopCamBtn = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.stopCamBtn.setGeometry(QtCore.QRect(700, int(1080/2)+150, 161, 25))
|
self.stopCamBtn.setGeometry(QtCore.QRect(900, 45+25, 161, 25))
|
||||||
self.stopCamBtn.setObjectName("stopCamBtn")
|
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 = QtWidgets.QGraphicsView(self.centralwidget)
|
||||||
self.graphicsView.setGeometry(QtCore.QRect(10, int(1080/2), 661, int(480*1.05))) # position and size of camera frame # int(640*1.05)
|
self.graphicsView.setGeometry(QtCore.QRect(1100, 20, int(640*1.2), int(480*1.2))) # position and size of camera frame
|
||||||
self.graphicsView.setObjectName("graphicsView")
|
self.graphicsView.setObjectName("graphicsView")
|
||||||
|
|
||||||
# relay control buttons
|
#self.myTestLambda = lambda: self.worker.checkWaageStartSignal.emit(einzelteilID, self.teileZuViel, self.auftragsnummer)
|
||||||
self.startSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.startSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+100, 161, 25)) #int(1080/2)+100
|
|
||||||
self.startSpotlightBtn.setObjectName("startSpotlightBtn")
|
|
||||||
self.stopSpotlightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.stopSpotlightBtn.setGeometry(QtCore.QRect(700+200, int(1080/2)+150, 161, 25))
|
|
||||||
self.stopSpotlightBtn.setObjectName("stopSpotlightBtn")
|
|
||||||
|
|
||||||
# led control buttons
|
|
||||||
self.redLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.redLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+100, 161, 25))
|
|
||||||
self.yellowLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.yellowLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+150, 161, 25))
|
|
||||||
self.greenLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.greenLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+200, 161, 25))
|
|
||||||
self.offLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.offLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+250, 161, 25))
|
|
||||||
self.blinkLightBtn = QtWidgets.QPushButton(self.centralwidget)
|
|
||||||
self.blinkLightBtn.setGeometry(QtCore.QRect(700+200+200, int(1080/2)+300, 161, 25))
|
|
||||||
|
|
||||||
# Maximize the window on startup
|
|
||||||
MainWindow.showMaximized()
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
item.setFont(font)
|
||||||
|
self.AuftragsdetailsTable.setVerticalHeaderItem(0,item)
|
||||||
|
'''
|
||||||
self.retranslateUi(MainWindow)
|
self.retranslateUi(MainWindow)
|
||||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
@ -436,8 +435,6 @@ class Ui_MainWindow(object):
|
|||||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||||
self.btn1.setText(_translate("MainWindow", "load Auftrag"))
|
self.btn1.setText(_translate("MainWindow", "load Auftrag"))
|
||||||
self.btn1.clicked.connect(self.auftragsBtnClicked)
|
self.btn1.clicked.connect(self.auftragsBtnClicked)
|
||||||
|
|
||||||
# Tabelle zur Darstellung der Auftragsdetails
|
|
||||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(0)
|
item = self.AuftragsdetailsTable.horizontalHeaderItem(0)
|
||||||
item.setText(_translate("MainWindow", "Pos.-Nr"))
|
item.setText(_translate("MainWindow", "Pos.-Nr"))
|
||||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(1)
|
item = self.AuftragsdetailsTable.horizontalHeaderItem(1)
|
||||||
@ -453,33 +450,13 @@ class Ui_MainWindow(object):
|
|||||||
item = self.AuftragsdetailsTable.horizontalHeaderItem(6)
|
item = self.AuftragsdetailsTable.horizontalHeaderItem(6)
|
||||||
item.setText(_translate("MainWindow", "set Farbe"))
|
item.setText(_translate("MainWindow", "set Farbe"))
|
||||||
|
|
||||||
# Tabelle zur Darstellung der Arbeitsschritte
|
|
||||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(0)
|
|
||||||
item.setText(_translate("MainWindow", "Arbeitsschritt"))
|
|
||||||
item = self.ArbeitsschrittTable.horizontalHeaderItem(1)
|
|
||||||
item.setText(_translate("MainWindow", "ToDo:"))
|
|
||||||
|
|
||||||
# Ein neues QTableWidgetItem erstellen und den Text setzen
|
|
||||||
item = QtWidgets.QTableWidgetItem("Auftrag laden")
|
|
||||||
self.ArbeitsschrittTable.setItem(0, 0, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("--> Auftragsnummer eingeben \n--> \"load Auftrag\" Buttonclick")
|
|
||||||
self.ArbeitsschrittTable.setItem(0, 1, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("Bauteiltyp erkennen")
|
|
||||||
self.ArbeitsschrittTable.setItem(1, 0, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("visuell: \n--> ein Bauteil in die Kamera halten\n\nWaage: \n--> ein Bauteil auf die Waage legen\n--> \"Bauteiltyp erkennen\" Buttonclick\n\nmanuell:\n--> Bauteiltypen auswählen\n-->\"ckeck Waage\" Button click")
|
|
||||||
self.ArbeitsschrittTable.setItem(1, 1, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("Bauteilanzahl erkennen")
|
|
||||||
self.ArbeitsschrittTable.setItem(2, 0, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("--> Bauteile auflegen")
|
|
||||||
self.ArbeitsschrittTable.setItem(2, 1, item)
|
|
||||||
item = QtWidgets.QTableWidgetItem("Prozess beendet")
|
|
||||||
self.ArbeitsschrittTable.setItem(3, 0, item)
|
|
||||||
self.ArbeitsschrittTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
|
||||||
|
|
||||||
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
self.label.setText(_translate("MainWindow", "Auftragsnummer:"))
|
||||||
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
self.bauteilTypBtn.setText(_translate("MainWindow", "Bauteiltyp erkennen"))
|
||||||
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
self.bauteilTypBtn.clicked.connect(self.objectTypeDetection)
|
||||||
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
self.AuftragsdetailsTable.cellClicked.connect(self.onTableCellClick)
|
||||||
|
#self.AuftragsdetailsTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||||
|
#item = self.AuftragsdetailsTable.verticalHeaderItem(0)
|
||||||
|
#item.setText(_translate("MainWindow", "test"))
|
||||||
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
self.BezeichnungLabel.setText(_translate("MainWindow", "Bezeichnung"))
|
||||||
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
self.PosNrLabel.setText(_translate("MainWindow", "Pos.-Nr:"))
|
||||||
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
self.teileZuVielLabel.setText(_translate("MainWindow", "Zu prüfende Teileanzahl über Auftragsanzahl:"))
|
||||||
@ -492,58 +469,35 @@ class Ui_MainWindow(object):
|
|||||||
self.waageTareBtn.clicked.connect(self.onTareClick)
|
self.waageTareBtn.clicked.connect(self.onTareClick)
|
||||||
self.checkBox.setText(_translate("MainWindow", "static workflow"))
|
self.checkBox.setText(_translate("MainWindow", "static workflow"))
|
||||||
self.checkBox.clicked.connect(self.onCheckboxCheck)
|
self.checkBox.clicked.connect(self.onCheckboxCheck)
|
||||||
self.checkBoxAutoTare.setText(_translate("MainWindow", "automatisches Tarieren"))
|
|
||||||
self.checkBoxAutoTare.clicked.connect(self.autoTareCheck)
|
|
||||||
|
|
||||||
self.setRowColor(self.ArbeitsschrittTable, 0,255,165,0) # zum setzen der ersten Spalte der Arbeitsschrittetabelle auf orange
|
|
||||||
self.checkBoxAutoTare.setCheckState(Qt.Checked)
|
|
||||||
self.checkBox.setCheckState(Qt.Unchecked)
|
|
||||||
|
|
||||||
# new camera workflow
|
# new camera workflow
|
||||||
self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
|
self.startCamBtn.setText(_translate("MainWindow", "Start Camera"))
|
||||||
|
# self.startCamBtn.clicked.connect(self.startCamBtnClicked)
|
||||||
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
|
self.stopCamBtn.setText(_translate("MainWindow", "Stop Camera"))
|
||||||
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
|
self.camWorkFlowcheckBox.setText(_translate("MainWindow", "Camera Workflow"))
|
||||||
self.modelComboBox
|
# self.camWorkFlowcheckBox.clicked.connect(self.onCheckboxCheck)
|
||||||
|
|
||||||
# relay control buttons
|
|
||||||
self.startSpotlightBtn.setText(_translate("MainWindow", "Turn on light"))
|
|
||||||
self.stopSpotlightBtn.setText(_translate("MainWindow", "Turn off light"))
|
|
||||||
|
|
||||||
# led control buttons
|
|
||||||
self.redLightBtn.setText(_translate("MainWindow", "Turn on red LED"))
|
|
||||||
self.yellowLightBtn.setText(_translate("MainWindow", "Turn on yellow LED"))
|
|
||||||
self.greenLightBtn.setText(_translate("MainWindow", "Turn on green LED"))
|
|
||||||
self.offLightBtn.setText(_translate("MainWindow", "Turn off all LEDs"))
|
|
||||||
self.blinkLightBtn.setText(_translate("MainWindow", "Blink Yellow LED"))
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
|
||||||
print("Das MainWindow wurde angeklickt.")
|
|
||||||
self.setFocus()
|
|
||||||
super().mousePressEvent(event)
|
|
||||||
|
|
||||||
def onTareClick(self):
|
def onTareClick(self):
|
||||||
''' Tarieren der Waage '''
|
#Tarieren der Waage
|
||||||
if ser.is_open == False:
|
if ser.is_open == False:
|
||||||
ser.open()
|
ser.open()
|
||||||
ser.write(b'tare\n')
|
ser.write(b'tare\n')
|
||||||
ser.close()
|
ser.close()
|
||||||
|
|
||||||
|
|
||||||
def onCheckboxCheck(self):
|
def onCheckboxCheck(self):
|
||||||
if self.checkBox.isChecked() == True:
|
if self.checkBox.isChecked() == True:
|
||||||
print("static workflow activated")
|
print("static workflow activated")
|
||||||
else:
|
else:
|
||||||
print("static workflow deactivated")
|
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):
|
def getRowNr(self, posNr):
|
||||||
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
for i in range(0,self.AuftragsdetailsTable.rowCount()):
|
||||||
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
if(self.AuftragsdetailsTable.item(i,0).text() == str(posNr)):
|
||||||
return i
|
return i
|
||||||
|
# brauche ich hier vermutlich nicht mehr - ist in den Worker Thread kopiert worden
|
||||||
|
def waageNichtEingeschwungenOutput(self):
|
||||||
|
print("Die Waage ist noch nicht eingeschwungen - Ergebnisse sind dadurch noch fehlerhaft.")
|
||||||
|
|
||||||
def onTableCellClick(self):
|
def onTableCellClick(self):
|
||||||
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
self.PosNrTxtFeld.setText(self.AuftragsdetailsTable.item(self.AuftragsdetailsTable.currentRow(),0).text())
|
||||||
@ -568,17 +522,65 @@ class Ui_MainWindow(object):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# eventuell benötigt man die Funktion hier nicht mehr, da sie zu den Threads kopiert wurde
|
||||||
|
def getDataOfArticleType(self, allArticles, articleType):
|
||||||
|
# die Funktion geht die Liste mit allen Artikeln durch und gibt jenen Eintrag, welcher mit dem "articleType" übereinstimmt zurück
|
||||||
|
for i in allArticles:
|
||||||
|
if i[1] == articleType:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
def updateGUI(self):
|
def updateGUI(self):
|
||||||
self.PosNrLabel.repaint() #GUI aktualisieren
|
self.PosNrLabel.repaint() #GUI aktualisieren
|
||||||
QApplication.processEvents() #GUI aktualisieren
|
QApplication.processEvents() #GUI aktualisieren
|
||||||
|
|
||||||
def setRowColor(self, tableObject, rowID,r,g,b):
|
def setRowColor(self, rowID,r,g,b):
|
||||||
for col in range(tableObject.columnCount()-1):
|
self.AuftragsdetailsTable.item(rowID, 0).setBackground(QtGui.QColor(r,g,b))
|
||||||
tableObject.item(rowID, col).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))
|
||||||
|
|
||||||
# # call change led color
|
#wird hier vermutlich nicht mehr benötigt - wurde in die Workerklasse kopiert
|
||||||
# later_instance = light_app_reference()
|
def readWaage(self):
|
||||||
# later_instance.map_color_to_led(r,g,b)
|
# 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):
|
def auftragsBtnClicked(self):
|
||||||
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
databaseQueryWorking = False #wird für die Überprüfung, ob die Datenbankabfrage fehlerhaft ist, verwendet
|
||||||
@ -597,7 +599,16 @@ class Ui_MainWindow(object):
|
|||||||
print("Fehler in der Datenbankabfrage.")
|
print("Fehler in der Datenbankabfrage.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
if databaseQueryWorking==True and len(auftragEinzelteilDaten)>0:
|
||||||
|
'''
|
||||||
|
# Display data
|
||||||
|
print("Ausgabe der Auftragsdetails des obigen Auftrags, inklusive Einzelteildetails:")
|
||||||
|
for row in auftragEinzelteilDaten:
|
||||||
|
if str(row[2]) == self.auftragsnummer:
|
||||||
|
print("passt")
|
||||||
|
print(row)
|
||||||
|
'''
|
||||||
|
|
||||||
### die Auftragsdaten in die Tabelle laden
|
### die Auftragsdaten in die Tabelle laden
|
||||||
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
self.AuftragsdetailsTable.setRowCount(len(auftragEinzelteilDaten))
|
||||||
@ -635,44 +646,35 @@ class Ui_MainWindow(object):
|
|||||||
self.AuftragsdetailsTable.setCellWidget(counter, 6, combo)
|
self.AuftragsdetailsTable.setCellWidget(counter, 6, combo)
|
||||||
counter = counter +1
|
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):
|
elif(databaseQueryWorking==True and len(auftragEinzelteilDaten)==0):
|
||||||
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
print("Es wurde in der Datenbank kein Auftrag mit dieser Auftragsnummer gefunden.")
|
||||||
|
|
||||||
def change_row_color(self, row, color_index):
|
def change_row_color(self, row, color_index):
|
||||||
if(color_index == 1):
|
if(color_index == 1):
|
||||||
self.setRowColor(self.AuftragsdetailsTable, row,255,255,255)
|
self.setRowColor(row,255,255,255)
|
||||||
if(color_index == 2):
|
if(color_index == 2):
|
||||||
self.setRowColor(self.AuftragsdetailsTable, row,255,165,0)
|
self.setRowColor(row,255,165,0)
|
||||||
if(color_index == 3):
|
if(color_index == 3):
|
||||||
self.setRowColor(self.AuftragsdetailsTable, row,0,255,0)
|
self.setRowColor(row,0,255,0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def stopLoopClicked(self):
|
def stopLoopClicked(self):
|
||||||
''' damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert '''
|
# damit wird beim Klick auf den Stopbutton der stopLoop-boolWert in der Workerklasse auf true gesetzt -> der Stop des Threads wird initiiert
|
||||||
if hasattr(self, 'objectDetectionWorker'):
|
if hasattr(self, 'objectDetectionWorker'):
|
||||||
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
self.objectDetectionWorker.stopLoopSignal.emit(True)
|
||||||
|
|
||||||
if hasattr(self, 'checkWaageWorker'):
|
if hasattr(self, 'checkWaageWorker'):
|
||||||
self.checkWaageWorker.stopLoopSignal.emit(True)
|
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):
|
def checkWaage(self):
|
||||||
|
#print("Running in thread:", threading.current_thread().name) # Debuggingausgabe
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
|
||||||
|
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||||
|
#self.checkWaageWorker.stopLoopSignal.emit(False)
|
||||||
|
|
||||||
# überprüfen, ob der Auftrag geladen wurde
|
# überprüfen, ob der Auftrag geladen wurde
|
||||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||||
print("Der Auftrag muss zuerst geladen werden.")
|
print("Der Auftrag muss zuerst geladen werden.")
|
||||||
@ -713,9 +715,7 @@ class Ui_MainWindow(object):
|
|||||||
|
|
||||||
|
|
||||||
#zum setzen den Farbe der gesamten Reihe auf Orange
|
#zum setzen den Farbe der gesamten Reihe auf Orange
|
||||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,165,0)
|
self.setRowColor(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
|
# den Thread starten, welcher die Bauteilanzahl überprüft
|
||||||
self.checkWaageWorker = Worker()
|
self.checkWaageWorker = Worker()
|
||||||
@ -737,16 +737,7 @@ class Ui_MainWindow(object):
|
|||||||
self.AuftragsdetailsTable.item(self.getRowNr(einzelteilID), 4).setText(str(anzahl)) # in die Tabelle die Anzahl an berechneten Bauteilen reinschreiben
|
self.AuftragsdetailsTable.item(self.getRowNr(einzelteilID), 4).setText(str(anzahl)) # in die Tabelle die Anzahl an berechneten Bauteilen reinschreiben
|
||||||
|
|
||||||
def checkWaageFinished(self, einzelteilID):
|
def checkWaageFinished(self, einzelteilID):
|
||||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),0,255,0) #zum setzen den Farbe der gesamten Reihe auf Grün
|
self.setRowColor(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
|
# den Thread beenden
|
||||||
self.checkWaageThread.quit()
|
self.checkWaageThread.quit()
|
||||||
@ -761,13 +752,22 @@ class Ui_MainWindow(object):
|
|||||||
#self.updateGUI()
|
#self.updateGUI()
|
||||||
|
|
||||||
def objectTypeDetection(self):
|
def objectTypeDetection(self):
|
||||||
''' in dieser Funktion wird der Typ des Bauteils automatisch erkannt '''
|
# in dieser Funktion wird der Typ des Bauteils automatisch erkannt
|
||||||
|
|
||||||
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
# wenn der statische Workflow ausgewählt wurde, dann soll die checkWaage Funktion aufgerufen werden, auch wenn die detectBauteiltyp-Funkion aufgerufen wurde
|
||||||
if self.checkBox.isChecked() == True:
|
if self.checkBox.isChecked() == True:
|
||||||
self.checkWaage()
|
self.checkWaage()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
'''
|
||||||
|
if(self.checkPosNrEmpty()==True):
|
||||||
|
print("Das Pos.-Nr.-Feld ist leer.")
|
||||||
|
return
|
||||||
|
'''
|
||||||
|
|
||||||
|
# die Loopvariable des Workers auf False setzten, damit die Schleife durchgelaufen wird (diese wird zum Abbruch der Schleife benötigt -> siehe stopLoop)
|
||||||
|
#self.objectDetectionWorker.stopLoopSignal.emit(False)
|
||||||
|
|
||||||
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
# überprüfen, ob der Auftrag in die Tabelle geladen wurde
|
||||||
if(self.AuftragsdetailsTable.item(0,0) == None):
|
if(self.AuftragsdetailsTable.item(0,0) == None):
|
||||||
print("Der Auftrag muss zuerst geladen werden.")
|
print("Der Auftrag muss zuerst geladen werden.")
|
||||||
@ -791,7 +791,7 @@ class Ui_MainWindow(object):
|
|||||||
self.objectDetectionThread.start()
|
self.objectDetectionThread.start()
|
||||||
|
|
||||||
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
def objectTypeDetectionFinished(self, einzelteilID, rowData):
|
||||||
''' wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden '''
|
# wenn der Typ des Objektes erkannt wurde, dann soll die Funktion aufgerufen werden
|
||||||
|
|
||||||
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
# Schreiben der Bauteiltype und Pos.-Nr in die jeweiligen Felder
|
||||||
self.PosNrTxtFeld.setText(str(rowData[1]))
|
self.PosNrTxtFeld.setText(str(rowData[1]))
|
||||||
@ -801,23 +801,28 @@ class Ui_MainWindow(object):
|
|||||||
self.btTypeIsSet = True
|
self.btTypeIsSet = True
|
||||||
|
|
||||||
#zum setzen den Farbe der gesamten Reihe auf Orange
|
#zum setzen den Farbe der gesamten Reihe auf Orange
|
||||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,165,0)
|
self.setRowColor(self.getRowNr(einzelteilID),255,165,0)
|
||||||
|
|
||||||
# den Thread beenden
|
# den Thread beenden
|
||||||
self.objectDetectionThread.quit()
|
self.objectDetectionThread.quit()
|
||||||
self.objectDetectionThread.wait()
|
self.objectDetectionThread.wait()
|
||||||
|
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
self.objectDetectionThread.started.disconnect() # Trenne das Signal, damit es beim nächsten Start keine Konflikte gibt
|
||||||
|
except:
|
||||||
|
print(f"Error while disconnecting: {e}")
|
||||||
|
print("Disconnecting the thread did not work.")
|
||||||
|
'''
|
||||||
|
|
||||||
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
# wenn der Bauteiltyp erkannt wurde, dann soll die GUI aktualisiert werden und anschließend die CheckWaage-Funktion aufgerufen werden
|
||||||
self.updateGUI()
|
self.updateGUI()
|
||||||
self.checkWaage()
|
self.checkWaage()
|
||||||
|
|
||||||
def threadStopped(self, einzelteilID):
|
def threadStopped(self, einzelteilID):
|
||||||
''' wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0 '''
|
# wenn kein Bauteil erkannt wurde, dann ist die EinzenteilID = 0
|
||||||
if self.checkFinished() == False:
|
if(einzelteilID > 0):
|
||||||
if(einzelteilID > 0):
|
self.setRowColor(self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
||||||
self.setRowColor(self.AuftragsdetailsTable, self.getRowNr(einzelteilID),255,255,255) #zum setzen den Farbe der gesamten Reihe auf Weiß
|
|
||||||
self.setRowColor(self.ArbeitsschrittTable, 2,255,255,255)
|
|
||||||
self.setRowColor(self.ArbeitsschrittTable, 1,255,165,0)
|
|
||||||
|
|
||||||
# den Thread beenden
|
# den Thread beenden
|
||||||
if hasattr(self, 'objectDetectionThread'):
|
if hasattr(self, 'objectDetectionThread'):
|
||||||
@ -838,22 +843,10 @@ class CameraStreamApp(QtWidgets.QMainWindow):
|
|||||||
self.yolo_stream = None # Initialize YOLOv8CameraStream as None
|
self.yolo_stream = None # Initialize YOLOv8CameraStream as None
|
||||||
self.timer = QtCore.QTimer(self)
|
self.timer = QtCore.QTimer(self)
|
||||||
self.timer.timeout.connect(self.update_frame)
|
self.timer.timeout.connect(self.update_frame)
|
||||||
|
|
||||||
# Populate the model dropdown menu
|
|
||||||
self.populate_model_dropdown()
|
|
||||||
|
|
||||||
self.ui.startCamBtn.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
|
self.ui.startCamBtn.clicked.connect(self.start_camera) # start camera if button LoadAuftrag is clicked
|
||||||
self.ui.stopCamBtn.clicked.connect(self.stop_camera) # start camera if button LoadAuftrag is clicked
|
|
||||||
self.scene = QtWidgets.QGraphicsScene(self)
|
self.scene = QtWidgets.QGraphicsScene(self)
|
||||||
self.ui.graphicsView.setScene(self.scene)
|
self.ui.graphicsView.setScene(self.scene)
|
||||||
|
|
||||||
def populate_model_dropdown(self):
|
|
||||||
"""Populate the dropdown menu with model files from the models directory."""
|
|
||||||
models_dir = "models"
|
|
||||||
model_files = [f for f in os.listdir(models_dir) if f.endswith(".pt")]
|
|
||||||
self.ui.modelComboBox.clear()
|
|
||||||
self.ui.modelComboBox.addItems(model_files)
|
|
||||||
|
|
||||||
def start_camera(self):
|
def start_camera(self):
|
||||||
# Start the YOLOv8 camera stream (only if not already started)
|
# Start the YOLOv8 camera stream (only if not already started)
|
||||||
if self.yolo_stream is None:
|
if self.yolo_stream is None:
|
||||||
@ -861,15 +854,6 @@ class CameraStreamApp(QtWidgets.QMainWindow):
|
|||||||
# self.yolo_stream.start() # Start the YOLOv8 stream
|
# self.yolo_stream.start() # Start the YOLOv8 stream
|
||||||
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
|
self.timer.start(30) # Start the timer to update the frame every 30ms (about 33 FPS)
|
||||||
|
|
||||||
def stop_camera(self):
|
|
||||||
# Stop the camera stream and processing
|
|
||||||
if self.yolo_stream is not None:
|
|
||||||
self.timer.stop() # Stop the timer
|
|
||||||
self.yolo_stream.cap.release() # Release the camera resource
|
|
||||||
self.yolo_stream = None # Reset the YOLOv8 stream object
|
|
||||||
self.scene.clear() # Clear the displayed frame from the graphicsView
|
|
||||||
print("Camera stream stopped and resources released.")
|
|
||||||
|
|
||||||
def update_frame(self):
|
def update_frame(self):
|
||||||
# Update the frame from YOLOv8 stream
|
# Update the frame from YOLOv8 stream
|
||||||
if self.yolo_stream:
|
if self.yolo_stream:
|
||||||
@ -881,7 +865,7 @@ class CameraStreamApp(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
# Convert the frame from BGR (OpenCV format) to RGB
|
# Convert the frame from BGR (OpenCV format) to RGB
|
||||||
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB) # might change nomenclature later?
|
||||||
|
|
||||||
# Convert the frame to QImage
|
# Convert the frame to QImage
|
||||||
h, w, ch = frame.shape
|
h, w, ch = frame.shape
|
||||||
@ -905,96 +889,7 @@ class CameraStreamApp(QtWidgets.QMainWindow):
|
|||||||
self.yolo_stream.cap.release()
|
self.yolo_stream.cap.release()
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
# new class for light control
|
|
||||||
class LightControl(QtWidgets.QMainWindow):
|
|
||||||
def __init__(self, ui):
|
|
||||||
super().__init__()
|
|
||||||
self.ui = ui
|
|
||||||
|
|
||||||
# init relay control
|
|
||||||
self.ui.startSpotlightBtn.clicked.connect(self.spot_on)
|
|
||||||
self.ui.stopSpotlightBtn.clicked.connect(self.spot_off)
|
|
||||||
self.r = sainsmartrelay.SainsmartRelay()
|
|
||||||
|
|
||||||
# init led control
|
|
||||||
self.ui.redLightBtn.clicked.connect(self.red_on)
|
|
||||||
self.ui.yellowLightBtn.clicked.connect(self.yellow_on)
|
|
||||||
self.ui.greenLightBtn.clicked.connect(self.green_on)
|
|
||||||
self.ui.offLightBtn.clicked.connect(self.leds_off)
|
|
||||||
self.ui.blinkLightBtn.clicked.connect(self.blink_yellow)
|
|
||||||
self.w = wledControl.WLEDController(port="/dev/serial/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-port0")
|
|
||||||
self.w.connect()
|
|
||||||
#self.w.switch_to_green() # at appstart the light is green
|
|
||||||
self.w.blink_green() # and switches to green blinking until the workflow gets started successfully#
|
|
||||||
|
|
||||||
# Connect app exit signal to the cleanup method
|
|
||||||
app.aboutToQuit.connect(self.cleanup)
|
|
||||||
|
|
||||||
def cleanup(self):
|
|
||||||
"""Clean up resources and switch off LEDs."""
|
|
||||||
print("Cleaning up resources and switching off LEDs")
|
|
||||||
self.leds_off() # Turn off LEDs
|
|
||||||
self.w.disconnect() # Disconnect WLED controller
|
|
||||||
|
|
||||||
def map_color(self, color):
|
|
||||||
"""
|
|
||||||
Map an RGB color to the corresponding WLED action based on predefined ranges.
|
|
||||||
|
|
||||||
:param color: A tuple of (R, G, B) values, where each component is an integer between 0 and 255.
|
|
||||||
"""
|
|
||||||
red, green, blue = color
|
|
||||||
|
|
||||||
# Check if the color is red (high R, low G and B)
|
|
||||||
if red > 200 and green < 100 and blue < 100:
|
|
||||||
self.switch_to_red()
|
|
||||||
|
|
||||||
# Check if the color is green (high G, low R and B)
|
|
||||||
elif red < 100 and green > 200 and blue < 100:
|
|
||||||
self.switch_to_green()
|
|
||||||
|
|
||||||
# Check if the color is yellow (high R and G, low B)
|
|
||||||
elif red > 200 and green > 200 and blue < 100:
|
|
||||||
self.switch_to_yellow()
|
|
||||||
|
|
||||||
# If none of the above, turn off the LEDs
|
|
||||||
else:
|
|
||||||
self.turn_off_all()
|
|
||||||
|
|
||||||
def spot_on(self):
|
|
||||||
print("Turn on light clicked")
|
|
||||||
self.r.turn_on(1)
|
|
||||||
|
|
||||||
def spot_off(self):
|
|
||||||
print("Turn off light clicked")
|
|
||||||
self.r.turn_off(1)
|
|
||||||
|
|
||||||
def red_on(self):
|
|
||||||
print("Red light is on")
|
|
||||||
self.w.switch_to_red()
|
|
||||||
|
|
||||||
def yellow_on(self):
|
|
||||||
print("Yellow light is on")
|
|
||||||
self.w.switch_to_yellow()
|
|
||||||
|
|
||||||
def green_on(self):
|
|
||||||
print("Green light is on")
|
|
||||||
self.w.switch_to_green()
|
|
||||||
|
|
||||||
def leds_off(self):
|
|
||||||
print("LEDs are off")
|
|
||||||
self.w.turn_off_all()
|
|
||||||
|
|
||||||
def blink_yellow(self):
|
|
||||||
print("Yellow color is blinking")
|
|
||||||
self.w.blink_yellow()
|
|
||||||
|
|
||||||
def blink_red(self):
|
|
||||||
print("Red color is blinking")
|
|
||||||
self.w.blink_red()
|
|
||||||
|
|
||||||
def blink_green(self):
|
|
||||||
print("Green color is blinking")
|
|
||||||
self.w.blink_green()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
@ -1005,8 +900,11 @@ 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
|
|
||||||
light_app = LightControl(ui)
|
|
||||||
|
|
||||||
MainWindow.show()
|
MainWindow.show()
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
47
mariadb-test.py
Normal 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()
|
BIN
pics/image-1.png
Before Width: | Height: | Size: 109 KiB |
301
readScale.py
Normal 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
@ -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
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
239
readme.md
@ -1,239 +0,0 @@
|
|||||||
# CPS Geislinger PackPal
|
|
||||||
|
|
||||||
Dieses Repository enthält die Software und Dokumentation für den **CPS Geislinger PackPal**, 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. [Funktionsumfang](#funktionsumfang)
|
|
||||||
4. [Installation](#installation)
|
|
||||||
5. [Anwendung](#anwendung)
|
|
||||||
- [Programmstart](#programmstart)
|
|
||||||
- [Arbeitsablauf](#arbeitsablauf)
|
|
||||||
6. [Fehlerbehebung](#fehlerbehebung)
|
|
||||||
7. [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**: Kubuntu 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**:
|
|
||||||
- Mitgelieferte Waage mit USB-/serieller Verbindung.
|
|
||||||
- Mitgelieferte Kamera für die Bauteilerkennung.
|
|
||||||
- Mitgelieferte 2x ESP32-Mikrocontroller als Hilfsgeräte.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Funktionsumfang
|
|
||||||
|
|
||||||
Der **CPS Geislinger PackPal** bietet eine Vielzahl an Funktionen, um den Verpackungsprozess effizient zu unterstützen.
|
|
||||||
|
|
||||||
### Lichtsteuerung
|
|
||||||
|
|
||||||
- **Flexible Steuerung**:
|
|
||||||
- LEDs und Scheinwerfer können unabhängig voneinander per Software gesteuert werden, um optimale Arbeitsbedingungen zu schaffen.
|
|
||||||
|
|
||||||
### Datenerfassung
|
|
||||||
|
|
||||||
- **Integrierte Geräteansteuerung**:
|
|
||||||
- Waage und Kamera werden über den mitgelieferten Mini-PC angesteuert und ausgelesen, sodass die Datenerfassung nahtlos in den Workflow integriert ist.
|
|
||||||
|
|
||||||
### Vortrainierte Modelle
|
|
||||||
|
|
||||||
- **Effiziente Bauteilerkennung**:
|
|
||||||
- Das System enthält vortrainierte Modelle, die mit knapp **5.000 annotierten Datenframes** erstellt wurden.
|
|
||||||
- **Modelloptionen**:
|
|
||||||
- Standardmäßig wird **YOLOv8n** (kleinste Modellvariante) verwendet, um die begrenzte Rechenleistung des Mini-PCs zu berücksichtigen.
|
|
||||||
- Zusätzlich werden vortrainierte **YOLOv8m**- und **YOLOv10n**-Modelle bereitgestellt, um erweiterte Tests durchzuführen oder zukünftige Hardware-Upgrades zu berücksichtigen.
|
|
||||||
|
|
||||||
### Vollständig vorinstallierter Mini-PC
|
|
||||||
|
|
||||||
- **Leistungsstarker Mini-PC**:
|
|
||||||
- **Prozessor**: 12th Gen Intel Prozessor, optimiert für Effizienz.
|
|
||||||
- **Betriebssystem**: Ubuntu 24.04 ist vorinstalliert und einsatzbereit.
|
|
||||||
- **Grafik**: Keine dedizierte Grafikkarte, um Energieverbrauch und Kosten zu minimieren, bei gleichzeitiger Eignung für die enthaltenen leichten Modelle.
|
|
||||||
|
|
||||||
### Softwareumgebung
|
|
||||||
|
|
||||||
- **Umsetzung in Python**:
|
|
||||||
Die gesamte Softwareumgebung wurde in **Python** entwickelt, um eine einfache Erweiterbarkeit, Wartung und Integration mit modernen Machine-Learning-Frameworks zu gewährleisten.
|
|
||||||
|
|
||||||
- **Quellcode verfügbar**:
|
|
||||||
Der komplette Quellcode ist in diesem Repository enthalten und modular aufgebaut, sodass spezifische Funktionen leicht angepasst oder erweitert werden können.
|
|
||||||
|
|
||||||
- **Vorteile der Python-Umgebung**:
|
|
||||||
- Breite Unterstützung durch Bibliotheken wie **OpenCV**, **PyTorch**, und **PyQt**.
|
|
||||||
- Leichte Integration von Machine-Learning-Modellen und Hardwaresteuerung.
|
|
||||||
- Hohe Lesbarkeit und einfache Anpassung durch gut dokumentierten Code.
|
|
||||||
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
![Workspace Overview](pics/image-1.png)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Arbeitsablauf
|
|
||||||
|
|
||||||
Der **CPS Geislinger PackPal** unterstützt den Verpackungsprozess mit einer intuitiven Benutzeroberfläche. Es stehen zwei Arbeitsmodi zur Verfügung: **statisch** und **dynamisch**, die über die Checkbox **"static workflow"** ausgewählt werden können.
|
|
||||||
|
|
||||||
- **Statischer Workflow**:
|
|
||||||
Der Benutzer wählt die Positionsnummer (Artikel) manuell aus, und die Waage addiert die Gewichte der eingelegten Bauteile, bis die gewünschte Stückzahl erreicht ist.
|
|
||||||
|
|
||||||
- **Dynamischer Workflow** (Standardmodus):
|
|
||||||
Die Kamera und die Waage arbeiten zusammen, um das eingelegte Bauteil automatisch zu erkennen und die korrekte Positionsnummer auszuwählen. Die Waage überwacht die eingelegten Teile, bis die erforderliche Stückzahl erreicht ist.
|
|
||||||
|
|
||||||
#### Schritt-für-Schritt-Anleitung
|
|
||||||
|
|
||||||
1. **Auftrag laden**
|
|
||||||
- Geben Sie die Auftragsnummer in das Feld **"Auftragsnummer"** ein.
|
|
||||||
- Klicken Sie auf **"load Auftrag"**, um die Auftragsdaten zu laden.
|
|
||||||
- Die Liste der Bauteile (mit Positionsnummer, Beschreibung, Soll-Menge, Ist-Menge und Lagerort) wird im linken Tabellenbereich angezeigt.
|
|
||||||
|
|
||||||
2. **Bauteilerkennung**
|
|
||||||
- **Manuelle Auswahl (statisch)**: Wählen Sie die gewünschte Positionsnummer direkt aus der Tabelle. Klicken Sie auf **"check Waage"**, um die Gewichtserfassung zu starten.
|
|
||||||
- **Automatische Erkennung (dynamisch)**:
|
|
||||||
- Legen Sie ein Bauteil auf die Waage und klicken Sie auf **"check Waage"**.
|
|
||||||
- Die automatisch erkannte Positionsnummer wird im Feld **"Pos.-Nr."** markiert.
|
|
||||||
|
|
||||||
3. **Bestücken**
|
|
||||||
- Legen Sie die Bauteile auf die Waage, bis die angezeigte **Ist-Menge** die **Soll-Menge** erreicht.
|
|
||||||
- Das System zeigt die aktuelle Stückzahl an.
|
|
||||||
- Falls die Waage nicht korrekt eingestellt ist, können Sie diese mit **"Waage tarieren"** neu kalibrieren.
|
|
||||||
|
|
||||||
4. **Weiterverpacken**
|
|
||||||
- Wiederholen Sie den Vorgang für alle Bauteile im Auftrag.
|
|
||||||
- Die Benutzeroberfläche führt Sie Schritt für Schritt durch die einzelnen Arbeitsvorgänge. Der aktuelle Arbeitsfortschritt wird in der **ToDo-Liste** rechts angezeigt.
|
|
||||||
|
|
||||||
5. **Auftragsabschluss**
|
|
||||||
- Sobald alle Bauteile verpackt sind, zeigt das System an, dass der Auftrag abgeschlossen ist.
|
|
||||||
- Überprüfen Sie die Daten und schließen Sie den Auftrag ab.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Zusätzliche Funktionen
|
|
||||||
|
|
||||||
- **Lichtsteuerung**:
|
|
||||||
Die LEDs und der Scheinwerfer können über die Schaltflächen gesteuert werden:
|
|
||||||
- **Turn on light / Turn off light**: Hauptbeleuchtung.
|
|
||||||
- **Turn on red/yellow/green LED**: Status-LEDs für visuelle Hinweise.
|
|
||||||
- **Blink Yellow LED**: Blinkt gelb zur Hervorhebung.
|
|
||||||
- **Turn off all LEDs**: Schaltet alle LEDs aus.
|
|
||||||
|
|
||||||
- **Kamera-Steuerung**:
|
|
||||||
- Aktivieren oder deaktivieren Sie den Kamera-Workflow über die Checkbox **"Camera Workflow"**.
|
|
||||||
- Starten und stoppen Sie die Kamera mit den Schaltflächen **"Start Camera"** und **"Stop Camera"**.
|
|
||||||
- Wählen Sie ein Modell für die automatische Bauteilerkennung aus der Dropdown-Liste aus (z. B. **"best_8n.pt"**).
|
|
||||||
|
|
||||||
- **Automatisches Tarieren**:
|
|
||||||
Aktivieren Sie die Checkbox **"automatisches Tarieren"**, um die Waage automatisch zu kalibrieren, sobald ein Arbeitsablauf gestartet wird.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Hinweise
|
|
||||||
|
|
||||||
- **ToDo-Liste**:
|
|
||||||
Die **ToDo-Liste** in der Benutzeroberfläche bietet eine klare Übersicht über die nächsten Schritte und den aktuellen Status. Befolgen Sie die Anweisungen, um den Workflow effizient abzuschließen.
|
|
||||||
|
|
||||||
- **Überwachung des Vorgangs**:
|
|
||||||
Verfolgen Sie die Statusanzeigen in der Benutzeroberfläche. Fehler oder Warnungen werden dort direkt angezeigt.
|
|
||||||
|
|
||||||
- **Stückzahlkontrolle**:
|
|
||||||
Die Waage erkennt automatisch Über- oder Unterfüllungen und zeigt entsprechende Hinweise an.
|
|
||||||
|
|
||||||
- **Korrektur**:
|
|
||||||
Sollten Fehler auftreten, können Sie jederzeit den aktuellen Artikel neu auswählen oder den Auftrag zurücksetzen.
|
|
||||||
|
|
||||||
## 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. Die Waage muss auf Kg eingestellt werden, damit die Daten korrekt übermittelt werden.
|
|
||||||
|
|
||||||
- Fehlerhafte Bauteilerkennung:
|
|
||||||
Stellen Sie sicher, dass die Kamera sauber ist und die Beleuchtung ausreichend ist. Prüfen Sie auch, ob das richtige Modell in models/ geladen wurde.
|
|
||||||
|
|
||||||
- Datenbankfehler:
|
|
||||||
Vergewissern Sie sich, dass die Datenbank MariaDB läuft und die Zugangsdaten korrekt in der Konfiguration hinterlegt sind.
|
|
||||||
|
|
||||||
- Konsolenausgaben kontrollieren:
|
|
||||||
Sollte es Probleme mit der Bauteilerkennung oder Waage geben, überprüfen Sie die Konsolenausgabe des Programms. Diese zeigt hilfreiche Diagnosen an.
|
|
||||||
|
|
||||||
## Kontakt
|
|
||||||
|
|
||||||
Für weitere Unterstützung oder Fragen wenden Sie sich bitte an:
|
|
||||||
|
|
||||||
- E-Mail: clemens.fritze@unileoben.ac.at
|
|
||||||
- Telefon: +43 3842 402 1904
|
|
||||||
- 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 PackPal!
|
|
BIN
readme.pdf
BIN
saved_frames/hand_20241025_105036.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
saved_frames/hand_20241025_105916.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
saved_frames/hand_20241025_105917.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_105918.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_105919.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_105920.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_105921.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_110016.jpg
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
saved_frames/hand_20241025_110017.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
saved_frames/hand_20241025_110018.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_110021.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
saved_frames/hand_20241025_110028.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_110031.jpg
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
saved_frames/hand_20241025_110032.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
saved_frames/hand_20241025_114821.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_114826.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_114827.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
saved_frames/hand_20241025_120810.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_120811.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_120813.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/hand_20241025_121052.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
saved_frames/hand_20241028_081631.jpg
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
saved_frames/hand_20241028_090057.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
saved_frames/hand_20241028_090058.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
saved_frames/hand_20241028_095023.jpg
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
saved_frames/hand_20241028_095024.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
saved_frames/hand_20241028_095025.jpg
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
saved_frames/hand_20241028_095026.jpg
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
saved_frames/hand_20241028_095027.jpg
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
saved_frames/hand_20241028_095028.jpg
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
saved_frames/hand_20241028_095029.jpg
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
saved_frames/hand_20241028_095030.jpg
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
saved_frames/hand_20241028_095031.jpg
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
saved_frames/oring_d300_b_20241028_095016.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
saved_frames/ring_58mm_20241025_114822.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
saved_frames/ring_58mm_20241025_114823.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
saved_frames/ring_58mm_20241025_114824.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
saved_frames/ring_58mm_20241025_114825.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
saved_frames/schraube_sk_m10x45_20241025_110317.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
230
test.ui
Normal 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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||||
|
<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></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||||
|
<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></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
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
hr { height: 1px; border-width: 0; }
|
||||||
|
li.unchecked::marker { content: "\2610"; }
|
||||||
|
li.checked::marker { content: "\2612"; }
|
||||||
|
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
|
<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></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
@ -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
@ -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
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
hr { height: 1px; border-width: 0; }
|
||||||
|
li.unchecked::marker { content: "\2610"; }
|
||||||
|
li.checked::marker { content: "\2612"; }
|
||||||
|
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
|
<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></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
hr { height: 1px; border-width: 0; }
|
||||||
|
li.unchecked::marker { content: "\2610"; }
|
||||||
|
li.checked::marker { content: "\2612"; }
|
||||||
|
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
|
<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></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
@ -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"))
|