""" QR Code Shopping Scanner Author: Leart Ramushi Version: 1.0 Bsc Artificial Intelligence in Software Engineering CDS-205 Hinweis: - Kommentare dieses Projekts wurden mit Unterstützung von ChatGPT erstellt. - Die Funktion `scan_qr_codes` wurde gemeinsam mit ChatGPT entwickelt. - Auch Error- bzw. Fehlermeldungen im Code stammen von ChatGPT. Coding Guidelines: - Klare, modulare Struktur (-> Funktionsorientiert) - Lesbare einfache Namen für Variablen und Funktionen - Namenskonvention: snake_case für Funktionen und Variablen - Konsistente Einrückung und Stil """ import cv2 import os import re import smtplib from email.mime.text import MIMEText from dotenv import load_dotenv from pyzbar.pyzbar import decode def load_email_settings(): """ Lädt die E-Mail-Zugangsdaten aus Umgebungsvariablen. Rückgabe: - Absender-E-Mail - Passwort - Dictionary mit auswählbaren Empfängern """ load_dotenv() sender = os.getenv("EMAIL_ADDRESS") password = os.getenv("APP_PASSWORD") recipients = { "0": ("Myself", sender), "1": ("Sister", os.getenv("EMAIL_SISTER")), "2": ("Mother", os.getenv("EMAIL_MOTHER")), "3": ("Father", os.getenv("EMAIL_FATHER")), } return sender, password, recipients def is_valid_qr_data(data): """ Prüft, ob der QR-Code-Inhalt dem erwarteten Format entspricht. Erlaubt sind: - alphabetische Begriffe - durch Kommas getrennte Einträge """ pattern = r"^[a-zA-ZäöüÄÖÜ]+(,\s*[a-zA-ZäöüÄÖÜ]+)*$" return re.fullmatch(pattern, data.strip()) is not None def send_email(sender, password, receiver, items): """ Sendet die gesammelten Artikel per E-Mail. """ body = "Shopping list scanned in this session:\n\n" body += "\n".join(items) msg = MIMEText(body) msg["From"] = sender msg["To"] = receiver msg["Subject"] = "Shopping List" try: with smtplib.SMTP_SSL("smtp.mail.me.com", 465) as server: server.login(sender, password) server.send_message(msg) except Exception as e: print("\nFailed to send email:", e) def scan_qr_codes(): """ Scannt QR-Codes in Echtzeit über die Webcam. Funktionale Beschreibung: - Zugriff auf die Standard-Webcam - Kontinuierliches Einlesen von Videoframes - Erkennung und Dekodierung von QR-Codes - Visuelle Markierung erkannter QR-Codes im Kamerabild - Validierung und Speicherung neuer, eindeutiger Einträge Benutzerinteraktion: - Live-Videostream mit Markierung erkannter QR-Codes - Beenden des Scan-Vorgangs durch Drücken der Taste 'q' Hinweis zur Erstellung: Diese Funktion wurde gemeinsam mit ChatGPT entwickelt, um OpenCV- und pyzbar-Integration korrekt umzusetzen und die Funktionsstruktur zu erstellen Rückgabewert: - scanned_items: Menge aller gültig gescannten QR-Code-Inhalte """ scanned_items = set() cap = cv2.VideoCapture(0) if not cap.isOpened(): print("Cannot open cam") return scanned_items print("Scan is running. Press 'Q' to finish current process\n") while True: ret, frame = cap.read() if not ret: break qrcodes = decode(frame) for qr in qrcodes: data = qr.data.decode("utf-8").strip() points = qr.polygon if len(points) > 3: for i in range(len(points)): pt1 = (points[i].x, points[i].y) pt2 = (points[(i + 1) % len(points)].x, points[(i + 1) % len(points)].y) cv2.line(frame, pt1, pt2, (255, 0, 255), 2) cv2.putText( frame, data, (points[0].x, points[0].y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2 ) if is_valid_qr_data(data) and data not in scanned_items: scanned_items.add(data) print("New item scanned:", data) print("Current items:") for item in scanned_items: print("-", item) print() cv2.imshow("QR Scanner", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows() return scanned_items def choose_recipient(recipients): """ Ermöglicht die Auswahl eines Empfängers über die Konsole. """ print("Choose recipient:") for key, (name, _) in recipients.items(): print(f"{key}: {name}") choice = input("\nEnter number: ").strip() return recipients.get(choice) def main(): """ Hauptfunktion zur Steuerung des Programmablaufs. """ sender, password, recipients = load_email_settings() items = scan_qr_codes() if not items: print("No valid QR codes scanned") return print("Items ready to send:") for item in items: print("-", item) selected = choose_recipient(recipients) if not selected: print("Invalid choice") return name, email = selected confirm = input(f"\nSend email to {name}? say 'yes' or 'no': ").strip().lower() if confirm == "yes": send_email(sender, password, email, items) print("\nEmail sent successfully") elif confirm == "no": print("\nEmail was not sent") if __name__ == "__main__": main()