diff --git a/app_v3_simplified.py b/app.py similarity index 74% rename from app_v3_simplified.py rename to app.py index 6ba2cfd..f066e87 100644 --- a/app_v3_simplified.py +++ b/app.py @@ -195,6 +195,32 @@ def post_backup_data(): except Exception as e: logging.error(f"Error posting backup data: {e}") +def load_config(): + """Launch configuration UI when config card is inserted (card ID: 12886709)""" + try: + config_path = "./config.py" + + if os.path.exists(config_path): + logging.info("🔧 Launching configuration interface...") + print("🔧 Launching configuration interface...") + + # Launch config.py as a subprocess + subprocess.Popen([sys.executable, config_path], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + + logging.info("✓ Configuration UI launched successfully") + print("✓ Configuration UI launched successfully") + return True + else: + logging.error("Config file not found at ./config.py") + print("✗ Config file not found at ./config.py") + return False + except Exception as e: + logging.error(f"Error launching configuration: {e}") + print(f"✗ Error launching configuration: {e}") + return False + # ============================================================================ # RFID READER - Background Thread # ============================================================================ @@ -256,10 +282,12 @@ class RFIDReader(rdm6300.BaseReader): """Detect card insertion - just set flag""" card_id = card.value - # Special card: device config card (ignore) + # Special card: device config card if card_id == 12886709: - logging.info(f"🔴 CONFIG CARD {card_id} detected (ignored)") - print(f"🔴 CONFIG CARD {card_id} detected (ignored)") + logging.info(f"🔴 CONFIG CARD {card_id} detected - Loading configuration") + print(f"🔴 CONFIG CARD {card_id} detected - Loading configuration") + # Call config loading function + load_config() return # IMMEDIATE LED feedback (BEFORE flag, for instant response) @@ -305,19 +333,23 @@ def process_card_events(hostname, device_ip): if card_id is not None: logging.info(f"[Main] Processing CARD INSERTED: {card_id}") - # Build API URL (1 = ON/inserted) - url = f"{HARTING_API_BASE}/{name}/{card_id}/1/{timestamp}" - - # Try to post - if post_to_harting(url): - logging.info(f"✓ Card event posted to API: {card_id}") + # Skip posting to Harting API if device is not configured + if name != "noconfig": + # Build API URL (1 = ON/inserted) + url = f"{HARTING_API_BASE}/{name}/{card_id}/1/{timestamp}" + + # Try to post + if post_to_harting(url): + logging.info(f"✓ Card event posted to API: {card_id}") + else: + logging.warning(f"✗ Offline: Saving card {card_id} to backup") + try: + with open(TAG_FILE, "a") as f: + f.write(url + "\n") + except Exception as e: + logging.error(f"Failed to save backup: {e}") else: - logging.warning(f"✗ Offline: Saving card {card_id} to backup") - try: - with open(TAG_FILE, "a") as f: - f.write(url + "\n") - except Exception as e: - logging.error(f"Failed to save backup: {e}") + logging.debug(f"Device not configured (noconfig). Skipping API post for card {card_id}") # ALWAYS send log to monitoring server (regardless of API post result) send_log_to_server(f"Card {card_id} inserted", hostname, device_ip, name) @@ -327,19 +359,23 @@ def process_card_events(hostname, device_ip): if card_id is not None: logging.info(f"[Main] Processing CARD REMOVED: {card_id}") - # Build API URL (0 = OFF/removed) - url = f"{HARTING_API_BASE}/{name}/{card_id}/0/{timestamp}" - - # Try to post - if post_to_harting(url): - logging.info(f"✓ Card event posted to API: {card_id}") + # Skip posting to Harting API if device is not configured + if name != "noconfig": + # Build API URL (0 = OFF/removed) + url = f"{HARTING_API_BASE}/{name}/{card_id}/0/{timestamp}" + + # Try to post + if post_to_harting(url): + logging.info(f"✓ Card event posted to API: {card_id}") + else: + logging.warning(f"✗ Offline: Saving card {card_id} to backup") + try: + with open(TAG_FILE, "a") as f: + f.write(url + "\n") + except Exception as e: + logging.error(f"Failed to save backup: {e}") else: - logging.warning(f"✗ Offline: Saving card {card_id} to backup") - try: - with open(TAG_FILE, "a") as f: - f.write(url + "\n") - except Exception as e: - logging.error(f"Failed to save backup: {e}") + logging.debug(f"Device not configured (noconfig). Skipping API post for card {card_id}") # ALWAYS send log to monitoring server (regardless of API post result) send_log_to_server(f"Card {card_id} removed", hostname, device_ip, name) @@ -495,6 +531,73 @@ def cleanup_old_logs(hostname, device_ip, name): except Exception as e: logging.error(f"Error cleaning up logs: {e}") +# ============================================================================ +# CHROMIUM LAUNCHER +# ============================================================================ + +def launch_chromium(name): + """ + Launch Chromium with either production URL or local fallback page + """ + try: + # Debug logging + print(f"DEBUG: launch_chromium called with name='{name}'") + print(f"DEBUG: name type={type(name)}, len={len(name)}") + print(f"DEBUG: name != 'noconfig' = {name != 'noconfig'}") + logging.debug(f"DEBUG: launch_chromium called with name='{name}' (type={type(name).__name__}, len={len(name)})") + + # Determine which URL to use based on device configuration + if name != "noconfig": + # Device is configured - use production URL + url = "http://10.76.140.17/iweb_v2/index.php/traceability/production" + print(f"Device configured as '{name}'. Launching production URL: {url}") + logging.info(f"Launching Chromium with production URL for device: {name}") + + # Launch Chromium with production URL + print("Starting Chromium with production URL...") + subprocess.Popen( + ["chromium", "--test-type", "--noerrors", "--kiosk", "--start-fullscreen", + "--unsafely-treat-insecure-origin-as-secure=http://10.76.140.17", url], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, + start_new_session=True + ) + else: + # Device not configured - use local HTML file + print(f"Device NOT configured (name='noconfig'). Using local HTML.") + local_html_dir = os.path.join(DATA_DIR, "html") + local_html_file = os.path.join(local_html_dir, "Screen.html") + + # Create directory if it doesn't exist + os.makedirs(local_html_dir, exist_ok=True) + + # Check if local HTML file exists + if not os.path.exists(local_html_file): + print(f"Warning: Local HTML file not found at {local_html_file}") + print(f"Please create the file or copy it from the data/html directory") + logging.warning(f"Local HTML file not found: {local_html_file}") + + # Convert to file:// URL for local file + abs_path = os.path.abspath(local_html_file) + url = f"file://{abs_path}" + print(f"Device not configured. Launching local fallback page: {url}") + logging.info(f"Loading Screen.html from: {abs_path}") + + # Launch Chromium with local file - different flags for file:// URLs + print("Starting Chromium with local HTML file...") + subprocess.Popen( + ["chromium", "--test-type", "--noerrors", "--kiosk", "--start-fullscreen", + "--no-first-run", "--no-default-browser-check", url], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, + start_new_session=True + ) + + print("✓ Chromium launched successfully") + logging.info("Chromium launched successfully") + + except Exception as e: + print(f"✗ Failed to launch Chromium: {e}") + logging.error(f"Failed to launch Chromium: {e}") + # ============================================================================ # MAIN APPLICATION # ============================================================================ @@ -550,7 +653,11 @@ def main(): wifi_thread.start() print("✓ WiFi monitor started") - # Application ready + # Launch Chromium browser + print("\nInitializing Chromium launcher...") + time.sleep(2) # Give system time to stabilize + launch_chromium(read_idmasa()) + print() logging.info("RFID Client operational") send_log_to_server("RFID Client operational", hostname, device_ip, read_idmasa()) print("✓ RFID Client operational - waiting for cards...") diff --git a/config.py b/config.py new file mode 100644 index 0000000..9f0c4a2 --- /dev/null +++ b/config.py @@ -0,0 +1,205 @@ +# config py este gandit pentru a verifica configurarile raspberiului +# verifica hostname-ul si il afiseaza +# verifica ce nume are masa si o afiseaza +# verifica daca masa este configurata cu sistem de prezenta operator +# verifica daca imprimanta este instalata corespunzator + +import os, time, socket, cups, subprocess +import FreeSimpleGUI as psg +import FreeSimpleGUI as sg +from multiprocessing import Process + + + +# import socket +host = socket.gethostname() # luam numele de host +def set_printer(): # importam codul python pentru printer + print("Cheking printer") + # acest segment acceseaza fisierul local idmas.txt si verifica ce informatii sunt acolo + # in mod normal acolo salvam numele mesei care trebuie sa corespunda cu numele imprimantei + f = open("./data/idmasa.txt","r") # deschid fisierul in care am salvat numele printerului + test = f.readlines() # citesc toate liniile + f.close() + # in cazul in care avem fisier corupt il resetam la original + try: + idmasa = test[0] + + except IndexError: + idmasa = "0" + print(idmasa) + # citim lista de printere disponibila + conn = cups.Connection () + printers = conn.getPrinters () + printer_stat=0 + for printer in printers: + print (printer, printers[printer]["device-uri"]) + if printer == idmasa: + printer_stat = 1 + + + if printer_stat == 1: + print("Printer is Ok") + else: + print("Printer is not ok") + p_Name = idmasa + print("Installing the new printer") + time.sleep(2) + cmd = "sudo /usr/sbin/lpadmin -p "+idmasa+" -E -v usb://CITIZEN/CT-S310II?serial=00000000 -m CTS310II.ppd" + os.popen(cmd) + time.sleep(2) + print("Printer Was Installed") + conn = cups.Connection() + printers = conn.getPrinters() + for printer in printers: + print(printer, printers[printer]["device-uri"]) + time.sleep(1) + print("Printerwas seted to "+idmasa+"") + print("Test printer App Closed") +# partea acesata se ocupa de verificarea existentei celor doua fisiere pentru a nu avea erori +# verificam daca exista fisierul care identifica masa +path = './data/idmasa.txt' +isFile = os.path.isfile(path) #verifica existenta fisierului prin bolean Tru/false + +if not isFile: +# print(path)# nu se face nimic pentru ca exista fisierul + + fp = open("./data/idmasa.txt", 'w') # cream fisier + fp.write('noconfig') # scriem in fisier prima line pentru a avea un punct de pornire + fp.close() # inchidem fisierul + +# verificam fisierul de prezenta pe baza acestuia stim daca locul de munca este configurat cu card de prezenta sau nu +path1 = './data/idmasa.txt' #verificare existenta al doilea fisier +isFile = os.path.isfile(path1)# verifica existenta fisierului + +#urmeaza sa citim fisierele pentru a crea cateva variabile +# prima variabila este idmasa +f = open("./data/idmasa.txt","r") # deschid fisierul +name = f.readlines() # citesc toate liniile +f.close() # inchid fisierul +try: + idmasa = name[0]# se verifica daca exista informatie in text + +except IndexError: + idmasa = "noconfig"# daca nu exista informatie in text setam variabila + + +n_config = 0 +#incepem sa definim primele functii din configurare +def notokfunction(): # este functie pentru butonul cancel din formular + global n_config + msg1 = "Id masa a fost actualizat la: "+ idmasa +"" ## pregatim mesajul pentru fereastra pop up + n_config = 1 + msg2 = "Slotul Pentru cartela este configurat by default" # pregatim mesajul pentru fereastra pop up + layout = [[sg.Text(msg1)], [sg.Text(msg2)], [sg.Button("Ok")]] + window = sg.Window("Configurari", layout) + while True: + event, values = window.read() + + if event == "Ok" or event == sg.WIN_CLOSED: + + break + + window.close() +#am inchis functia notok + +#functia pentru butonul ok din formular +def okfunction(): + global n_config + if idmasa == config1: # variabila config 1 este preluata din formular + msg1 = "Masa este setat corect: "+ idmasa +"" # se printeaza mesaj ca nu se actualizeaza id de masa + # print(msg1) + else: + f = open("./data/idmasa.txt","w") # deschidem fisierul config in mod scriere + L = config1 + f.write(L) # actualizam linia cu noua valuare din config + f.close() # inchidem fisierul + msg1 = "Id masa a fost actualizat la: "+ config1 +"" # pregatim mesajul pentru fereastra pop up + n_config = 0 +# + + # definim fereastra pentru ok asemena cu functia notok + layout = [[sg.Text(msg1)], [sg.Output(size=(40, 15))], [sg.Button("Ok")]] + + window = sg.Window("Configurari", layout) + while True: + event, values = window.read() + # End program if user closes window or + # presses the OK button + if event == "Ok" or event == sg.WIN_CLOSED: + + break + if nook == 1: + notokfunction() + n_config = 1 + time.sleep(2) + #asteptam 10 secunde si pornim functia de setare printer + set_printer() + #verificam daca hostul corespunde cu ce este in formular + time.sleep(2) + if host == host_conf: + print("Host name ok") + else: + print("Host name not ok") + time.sleep(2) + print("Update Hostname" ) + cmd = "sudo hostnamectl set-hostname "+host_conf+"" # comanda sa schimbam hostnameul + os.popen(cmd) + print("Os hostname updated") + time.sleep(2) + print("System will reboot in 5 seconds") + time.sleep(1) + print("System will reboot in 4 seconds") + time.sleep(1) + print("System will reboot in 3 seconds") + time.sleep(1) + print("System will reboot in 2 seconds") + time.sleep(1) + print("System will reboot in 1 seconds") + time.sleep(3) + + + + window.close() +# incepem initializarea feresteri ptrincipale gui + +sg.theme('dark grey 9') #alegem tema dark grey +psg.set_options(font=('Arial Bold', 16)) # setam fontul +#setarile de layout +layout = [ + [sg.Text('Host_Name', size=(20,1)),sg.InputText(default_text= ""+host+"" , enable_events=False)], + [sg.Text('Loc De Munca', size=(20,1)),sg.InputText(default_text=""+idmasa+"", enable_events=False)], + + [sg.Button('Ok'), sg.Button('Cancel')] +] +# setam window +window = psg.Window('Form', layout, size=(800,190),finalize=True) +# citim si configuram widgetul pentru butoanele 1 si 0 din randul + +while True: + + nook = 0 # cream o variabila care sa ne spuna daca a fost setao butonul ok sau nu + event, values = window.read() # citim valorile intr-o lista numita values + host_conf= values[0] # atribuim primul item din lista variabilei Host config + # aceasta variabila o vom folosi pentru a scrie sa nu noul hostname + print(host_conf) + if event == sg.WIN_CLOSED or event == 'Cancel': + nook = 1 # daca se da cancel setam variabila nook la 1 + n_config = 1 # setam variabila n_config la 1 + break + config1 = values[1] # atribuim lui config 1 valuarea din campul Loc de munca care a fost scris cu Id masa + + + # pornim functi care scrie valorile config in fisiere ok function + okfunction() +# si inchidem formularul + + # semnalam ca s-a terminat afisarea formularului + break + + +#inchidem formularul +window.close() +# daca variabila nook este 1 +time.sleep(2) +if n_config == 0: + os.system("sudo reboot now") diff --git a/data/device_info.txt b/data/device_info.txt index 41c707a..ccef6e2 100644 --- a/data/device_info.txt +++ b/data/device_info.txt @@ -1,2 +1,2 @@ -RPI-Device +RPI-testDevice 192.168.1.104 diff --git a/data/html/Screen.html b/data/html/Screen.html new file mode 100755 index 0000000..9e30af7 --- /dev/null +++ b/data/html/Screen.html @@ -0,0 +1,69 @@ + + + + + + Device Not Configured + + + +
+ Harting Module +
+

Device Not Configured

+

Please scan the configuration RFID card

+
+
+ + + + diff --git a/data/html/harting_background.jpg b/data/html/harting_background.jpg new file mode 100644 index 0000000..32eb409 Binary files /dev/null and b/data/html/harting_background.jpg differ diff --git a/data/html/index.html b/data/html/index.html new file mode 100644 index 0000000..b61f66c --- /dev/null +++ b/data/html/index.html @@ -0,0 +1,125 @@ + + + + + + Device Configuration Required + + + +
+
+ Harting Module +
+
+
+ Device Not Configured +
+
+ Please scan the configuration RFID card to initialize this device +
+
+
+
+ + + + diff --git a/data/html/myimage.jpg b/data/html/myimage.jpg new file mode 100755 index 0000000..cf64bf7 Binary files /dev/null and b/data/html/myimage.jpg differ diff --git a/data/html/myimage.png b/data/html/myimage.png new file mode 100755 index 0000000..edbf8a0 Binary files /dev/null and b/data/html/myimage.png differ diff --git a/data/idmasa.txt b/data/idmasa.txt index 4513642..3b0ab66 100644 --- a/data/idmasa.txt +++ b/data/idmasa.txt @@ -1 +1 @@ -2_15051100_10 \ No newline at end of file +noconfig diff --git a/data/log.txt b/data/log.txt index 1252c9c..b1aa386 100644 Binary files a/data/log.txt and b/data/log.txt differ diff --git a/data/tag.txt b/data/tag.txt index e69de29..03ce1cd 100644 --- a/data/tag.txt +++ b/data/tag.txt @@ -0,0 +1,2 @@ +https://dataswsibiusb01.sibiusb.harting.intra/RO_Quality_PRD/api/record/2_15051100_10/7758885/1/2025-12-19&09:35:25 +https://dataswsibiusb01.sibiusb.harting.intra/RO_Quality_PRD/api/record/2_15051100_10/7758885/0/2025-12-19&09:35:27 diff --git a/oldcode/app_old.py b/oldcode/app_old.py index 2a4c4ad..a467803 100644 --- a/oldcode/app_old.py +++ b/oldcode/app_old.py @@ -652,6 +652,11 @@ def read_name_from_file(): # Function to send logs to a remote server for the Server_monitorizare APP def send_log_to_server(log_message, n_masa, hostname, device_ip): + # Skip sending logs if device is not configured + if n_masa == "noconfig": + logging.debug(f"Skipping server log (device not configured): {log_message}") + return + host = hostname device = device_ip try: @@ -1125,12 +1130,60 @@ def check_internet_connection(): log_info_with_server(f"An error occurred during internet check: {e}") time.sleep(60) # Retry after 1 minute in case of an error +# Function to launch Chromium +def launch_chromium(): + """ + Launch Chromium with either production URL or local fallback page + """ + try: + # Determine which URL to use based on device configuration + if name != "noconfig": + # Device is configured - use production URL + url = "http://10.76.140.17/iweb_v2/index.php/traceability/production" + print(f"Device configured as '{name}'. Launching production URL: {url}") + log_info_with_server(f"Launching Chromium with production URL for device: {name}") + else: + # Device not configured - use local HTML file + local_html_dir = "./data/html" + local_html_file = os.path.join(local_html_dir, "Screen.html") + + # Create directory if it doesn't exist + os.makedirs(local_html_dir, exist_ok=True) + + # Check if local HTML file exists + if not os.path.exists(local_html_file): + print(f"Warning: Local HTML file not found at {local_html_file}") + print(f"Please create the file or copy it from the data/html directory") + logging.warning(f"Local HTML file not found: {local_html_file}") + + # Convert to file:// URL for local file + url = f"file://{os.path.abspath(local_html_file)}" + print(f"Device not configured. Launching local fallback page: {url}") + log_info_with_server("Device not configured. Launching local fallback page") + + # Launch Chromium with the determined URL - using same parameters as v3 + print("Starting Chromium...") + subprocess.Popen( + ["chromium", "--test-type", "--noerrors", "--kiosk", "--start-fullscreen", + "--unsafely-treat-insecure-origin-as-secure=http://10.76.140.17", url], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, + start_new_session=True + ) + print("✓ Chromium launched successfully") + log_info_with_server("Chromium launched successfully") + + except Exception as e: + print(f"✗ Failed to launch Chromium: {e}") + log_info_with_server(f"Failed to launch Chromium: {e}") + # Start the internet connection check in a separate process internet_check_process = Process(target=check_internet_connection) internet_check_process.start() -url = "10.76.140.17/iweb_v2/index.php/traceability/production" # pentru cazul in care raspberiul nu are sistem de prezenta -# Launch Chromium with the specified URLs -subprocess.Popen(["chromium", "--test-type", "--noerrors", "--kiosk", "--start-fullscreen", "--unsafely-treat-insecure-origin-as-secure=http://10.76.140.17", url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, start_new_session=True) + +# Launch Chromium in any situation +print("Initializing Chromium launcher...") +time.sleep(2) # Give system time to stabilize +launch_chromium() info = "0" #function to post info