From e0f7ec34f290fcd7eab0509817f94e60a17e039d Mon Sep 17 00:00:00 2001 From: RPI User Date: Fri, 19 Dec 2025 15:08:02 +0200 Subject: [PATCH] Implement dual logging workflow: noconfig vs configured mode NOCONFIG MODE (device not configured): - Sends 'App initialized' message on startup - Sends 'RFID initialized' message after RFID ready - Sends 'App working' message on startup - Sends periodic 'App working' health status every 5 minutes - Card inserted/removed events sent directly to monitoring server CONFIGURED MODE (table ID set): - Sends 'App initialized' and startup messages - Card events POST to Harting API first - Only sends to monitoring server on successful API post - Failed posts saved to tag.txt backup file - Backup data sent with summary when internet restored Changes: - Added send_health_status() function for periodic monitoring - Updated process_card_events() to handle both workflows - Updated main() to send startup messages and start health monitor - Improved monitoring server URL to use rpi-ansible hostname - Added retry logic for monitoring server requests --- app.py | 101 ++++++++++++++++++++++++++++++++------ data/log.txt | Bin 31620 -> 36977 bytes test_monitoring_server.py | 78 +++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 test_monitoring_server.py diff --git a/app.py b/app.py index e7df157..7bd76f4 100644 --- a/app.py +++ b/app.py @@ -24,7 +24,7 @@ import rdm6300 # ============================================================================ # Server URLs -MONITORING_SERVER = "http://192.168.1.103:80/logs" +MONITORING_SERVER = "http://rpi-ansible:80/logs" HARTING_API_BASE = "https://dataswsibiusb01.sibiusb.harting.intra/RO_Quality_PRD/api/record" WIFI_CHECK_HOST = "10.76.140.17" @@ -139,7 +139,7 @@ def read_idmasa(): return "noconfig" def send_log_to_server(message, hostname, device_ip, name): - """Send log message to monitoring server""" + """Send log message to monitoring server with retry logic""" try: log_data = { "hostname": hostname, @@ -147,11 +147,36 @@ def send_log_to_server(message, hostname, device_ip, name): "nume_masa": name, "log_message": message } - response = requests.post(MONITORING_SERVER, json=log_data, timeout=5) - response.raise_for_status() - return True + logging.debug(f"[LOG] Sending to {MONITORING_SERVER}: {log_data}") + print(f"[LOG] Sending: {log_data}") + + # Try up to 3 times with small delay + for attempt in range(3): + try: + response = requests.post(MONITORING_SERVER, json=log_data, timeout=5) + response.raise_for_status() + logging.info(f"✓ Log sent to server: {message}") + print(f"✓ Log sent successfully") + return True + except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e: + if attempt < 2: + time.sleep(1) # Wait 1 second before retry + continue + raise + + return False + + except requests.exceptions.Timeout: + logging.warning(f"✗ Log request timeout after retries: {message}") + print(f"✗ Timeout sending log") + return False + except requests.exceptions.ConnectionError as e: + logging.warning(f"✗ Connection error sending log: {e}") + print(f"✗ Connection error: {e}") + return False except Exception as e: - logging.warning(f"Failed to send log to server: {e}") + logging.warning(f"✗ Failed to send log to server: {e}") + print(f"✗ Failed to send log: {e}") return False def post_to_harting(url, verify=False, timeout=3): @@ -336,17 +361,24 @@ class RFIDReader(rdm6300.BaseReader): def process_card_events(hostname, device_ip): """Main thread checks card flags and processes them""" - name = read_idmasa() while True: try: + # Re-read name each time to catch configuration changes + name = read_idmasa() + # Check for inserted cards card_id, timestamp = card_state.get_inserted() if card_id is not None: logging.info(f"[Main] Processing CARD INSERTED: {card_id}") - # Skip posting to Harting API if device is not configured - if name != "noconfig": + if name == "noconfig": + # NOCONFIG MODE: Send card event directly to monitoring server + message = f"Card {card_id} inserted" + send_log_to_server(message, hostname, device_ip, name) + logging.info(f"✓ Card insert logged to monitoring: {message}") + else: + # CONFIGURED MODE: Try to post to Harting API first # Build API URL (1 = ON/inserted) url = f"{HARTING_API_BASE}/{name}/{card_id}/1/{timestamp}" @@ -362,16 +394,19 @@ def process_card_events(hostname, device_ip): f.write(url + "\n") except Exception as e: logging.error(f"Failed to save backup: {e}") - else: - logging.debug(f"Device not configured (noconfig). Skipping API post for card {card_id}") # Check for removed cards card_id, timestamp = card_state.get_removed() if card_id is not None: logging.info(f"[Main] Processing CARD REMOVED: {card_id}") - # Skip posting to Harting API if device is not configured - if name != "noconfig": + if name == "noconfig": + # NOCONFIG MODE: Send card event directly to monitoring server + message = f"Card {card_id} removed" + send_log_to_server(message, hostname, device_ip, name) + logging.info(f"✓ Card remove logged to monitoring: {message}") + else: + # CONFIGURED MODE: Try to post to Harting API first # Build API URL (0 = OFF/removed) url = f"{HARTING_API_BASE}/{name}/{card_id}/0/{timestamp}" @@ -387,8 +422,6 @@ def process_card_events(hostname, device_ip): f.write(url + "\n") except Exception as e: logging.error(f"Failed to save backup: {e}") - else: - logging.debug(f"Device not configured (noconfig). Skipping API post for card {card_id}") # Very small sleep for fast response (10ms = check 100x per second) time.sleep(0.01) @@ -608,6 +641,27 @@ def launch_chromium(name): print(f"✗ Failed to launch Chromium: {e}") logging.error(f"Failed to launch Chromium: {e}") +def send_health_status(hostname, device_ip): + """Send periodic health status messages when device is not configured""" + logging.info("Health status monitor started") + + while True: + try: + name = read_idmasa() + + # Only send health status when device is NOT configured + if name == "noconfig": + message = f"App working - RFID monitoring active" + send_log_to_server(message, hostname, device_ip, name) + logging.info(f"✓ Health check sent: {message}") + + # Send every 5 minutes + time.sleep(300) # 5 minutes + + except Exception as e: + logging.error(f"Error in health status monitor: {e}") + time.sleep(30) + # ============================================================================ # MAIN APPLICATION # ============================================================================ @@ -635,6 +689,10 @@ def main(): print(f"API: {HARTING_API_BASE}") print() + # Send startup message to monitoring server + name = read_idmasa() + send_log_to_server("App initialized", hostname, device_ip, name) + # Thread 1: Start RFID reader (background, listening for cards) rfid_reader = initialize_rfid_reader(hostname, device_ip) if not rfid_reader: @@ -642,6 +700,7 @@ def main(): logging.error("RFID reader initialization failed - exiting") sys.exit(1) print("✓ RFID reader started in background") + send_log_to_server("RFID initialized", hostname, device_ip, name) # Thread 2: Start card event processor (main thread checks flags and processes) card_processor_thread = threading.Thread( @@ -663,13 +722,23 @@ def main(): wifi_thread.start() print("✓ WiFi monitor started") + # Thread 4: Start health status monitor (sends periodic status when noconfig) + health_thread = threading.Thread( + target=send_health_status, + args=(hostname, device_ip), + daemon=False, + name="HealthMonitor" + ) + health_thread.start() + print("✓ Health status monitor started") + # 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()) + send_log_to_server("App working", hostname, device_ip, name) print("✓ RFID Client operational - waiting for cards...") print() diff --git a/data/log.txt b/data/log.txt index b1aa386bc199f3c7a2177a9051c80a732c7f4115..b259408e98567bd2ccc13e3b4e58af9a1e93a3a0 100644 GIT binary patch delta 1101 zcmY*XO-__S6buFuz8NC27)TUCSP?T{q<>!b>+VEHiQ;IYIAMV?8Y0ZZM2TjW%0?3| zVBQ7r1{^`o;05#mf)f{ReXqZd5qno%{i>_0>+sLS=;+e%;Q`GKFHb{E+LQ?NvG=G6 zse%EJR(7#CM}c1MJ|3e;U*{jr=zoVJy<59q4?`K8qLZ~Jjfxjc!>zKWJwr>Qz1^%P z$kVZM7g(fU>c$vH4>a2UHU$6!O%vv6EgMC4Zlm9D5WS7O3=NlC&B~Q=r7?8cy;JE3 zw2FRgb_z&NCBvp@WoIyBy>h5{Y3t}qyT#&6J5?gm^KR!Noal8}%;{wKYH#SIz1Os; zt(I{EGA+DGmc_jnz5t~?iZ_~TF9>Us^py*|I2BjahL;r6R(j7(|1saAH$ z`Z9v2x39MfS0kj~@7KpD(#e}ediG&8@5IttO|$!V1wkl{Qgqh6Ej}u&b0jrpUqOrO zDQ_%)(aph<%sJpBExqX8s?G_vhNE1e(+5kk=aYg`^Pkt+H4YMY#dE)+GUpmz`W6-Z zuc2*;-id~U&Sw}Sec#M>JttQNjl6kQs@w3Q-9 zEo~YU%6cKIzBHHxX)5~}Zue)L=2g+TsbZfS#M5-8#rCaHAWg)oiOhOwDql6XF_?_V XU(q?ZCU+vcDm`cQskcDKSEv61;)xrA delta 9 QcmeykfT`s>