diff --git a/SARA/sara_ping_miotiq.py b/SARA/sara_ping_miotiq.py index d5f7605..4415bc1 100644 --- a/SARA/sara_ping_miotiq.py +++ b/SARA/sara_ping_miotiq.py @@ -6,10 +6,13 @@ r''' |____/_/ \_\_| \_\/_/ \_\ Test aller-retour Miotiq: -1. Construit un payload 100 bytes avec device_id + command=1 (ping) -2. Envoie via UDP vers 192.168.0.20:4242 -3. Ecoute sur le socket pour une reponse descendante (~15s) -4. Affiche le resultat +1. Construit un payload 100 bytes avec device_id + command=0x02 (ping) +2. Cree un socket UDP binde sur un port local fixe (LISTEN_PORT) +3. Envoie via AT+USOST vers 192.168.0.20:4242 (mode non-connecte) +4. Ecoute avec AT+USORF pour la reponse descendante Miotiq (~15s) + +Le serveur doit envoyer le downlink via l'API Miotiq sendToDevice +avec dstPort = LISTEN_PORT (33333). /usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_ping_miotiq.py ''' @@ -23,6 +26,7 @@ import sqlite3 # --- Config --- MIOTIQ_IP = "192.168.0.20" MIOTIQ_PORT = 4242 +LISTEN_PORT = 33333 # Port local sur lequel le capteur ecoute le downlink PAYLOAD_SIZE = 100 COMMAND_PING = 0x02 LISTEN_TIMEOUT = 15 # seconds to wait for downlink response @@ -44,14 +48,12 @@ def load_device_id(): # --- Build ping payload --- def build_ping_payload(device_id): payload = bytearray(PAYLOAD_SIZE) - # Init all to 0xFF (no data) for i in range(PAYLOAD_SIZE): payload[i] = 0xFF # Bytes 0-7: device_id (ASCII, padded with 0x00) device_id_bytes = device_id.encode('ascii')[:8].ljust(8, b'\x00') payload[0:8] = device_id_bytes - # Byte 8: signal quality (0xFF = not set, fine for ping) - # Byte 9: command = 0x01 (ping test) + # Byte 9: command = 0x02 (ping test) payload[9] = COMMAND_PING return bytes(payload) @@ -121,9 +123,9 @@ try: ping_payload = build_ping_payload(device_id) print(f'Payload: {PAYLOAD_SIZE} bytes, command=0x{COMMAND_PING:02X} (ping)') - # Step 1: Create UDP socket - resp, ok = send_at('AT+USOCR=17') - log_raw('AT+USOCR=17', resp) + # Step 1: Create UDP socket bound to local port (for receiving downlink) + resp, ok = send_at(f'AT+USOCR=17,{LISTEN_PORT}') + log_raw(f'AT+USOCR=17,{LISTEN_PORT}', resp) if not ok: print('❌ Création socket UDP — erreur') print('La connexion PDP n\'est peut-être pas établie. Lancez "Vérifier connexion PDP" d\'abord.') @@ -134,19 +136,14 @@ try: print('❌ Impossible d\'extraire le socket ID') sys.exit(1) socket_id = match.group(1) - print(f'✅ Socket UDP créé (ID: {socket_id})') + print(f'✅ Socket UDP créé (ID: {socket_id}, port local: {LISTEN_PORT})') - # Step 2: Connect to Miotiq - resp, ok = send_at(f'AT+USOCO={socket_id},"{MIOTIQ_IP}",{MIOTIQ_PORT}', timeout=5) - log_raw(f'AT+USOCO={socket_id}', resp) - if not ok: - print(f'❌ Connexion à {MIOTIQ_IP}:{MIOTIQ_PORT} — erreur') - sys.exit(1) - print(f'✅ Connecté à {MIOTIQ_IP}:{MIOTIQ_PORT}') - - # Step 3: Write ping payload - resp, ok = send_at(f'AT+USOWR={socket_id},{len(ping_payload)}', wait_for=["@", "OK", "+CME ERROR", "ERROR"]) - log_raw(f'AT+USOWR={socket_id},{len(ping_payload)}', resp) + # Step 2: Send ping payload via AT+USOST (unconnected mode) + resp, ok = send_at( + f'AT+USOST={socket_id},"{MIOTIQ_IP}",{MIOTIQ_PORT},{len(ping_payload)}', + wait_for=["@", "OK", "+CME ERROR", "ERROR"] + ) + log_raw(f'AT+USOST={socket_id}', resp) if "@" not in resp: print('❌ Le modem n\'a pas envoyé le prompt @ — envoi annulé') sys.exit(1) @@ -157,56 +154,54 @@ try: if "+CME ERROR" in resp or ("ERROR" in resp and "OK" not in resp): print('❌ Erreur envoi du payload ping') sys.exit(1) - print(f'✅ Payload ping envoyé ({PAYLOAD_SIZE} bytes)') + print(f'✅ Payload ping envoyé vers {MIOTIQ_IP}:{MIOTIQ_PORT} ({PAYLOAD_SIZE} bytes)') - # Step 4: Listen for downlink response - print(f'
Attente réponse descendante Miotiq ({LISTEN_TIMEOUT}s)...') + # Step 3: Listen for downlink response on port LISTEN_PORT + print(f'
Attente réponse descendante Miotiq sur port {LISTEN_PORT} ({LISTEN_TIMEOUT}s)...') response_received = False start_listen = time.time() while time.time() - start_listen < LISTEN_TIMEOUT: - # Poll for available data on socket + # Check for URC +UUSORF or poll with AT+USORF ser_sara.reset_input_buffer() - resp, ok = send_at(f'AT+USORD={socket_id},0', timeout=2) - log_raw(f'AT+USORD={socket_id},0', resp) + resp, ok = send_at(f'AT+USORF={socket_id},512', timeout=2) + log_raw(f'AT+USORF={socket_id},512', resp) - # Parse response: +USORD: , - usord_match = re.search(r'\+USORD:\s*\d+,(\d+)', resp) - if usord_match: - available_bytes = int(usord_match.group(1)) - if available_bytes > 0: - # Read the data - resp2, ok2 = send_at(f'AT+USORD={socket_id},{available_bytes}', timeout=2) - log_raw(f'AT+USORD={socket_id},{available_bytes}', resp2) + # Parse response: +USORF: ,"",,,"" + usorf_match = re.search(r'\+USORF:\s*\d+,"([^"]*)",(\d+),(\d+),"([^"]*)"', resp) + if usorf_match: + src_ip = usorf_match.group(1) + src_port = usorf_match.group(2) + data_len = usorf_match.group(3) + received_data = usorf_match.group(4) + elapsed = time.time() - start_listen + print(f'
Réponse reçue en {elapsed:.1f}s !') + print(f'Source: {src_ip}:{src_port} — {data_len} bytes
') + print(f'Data: {received_data}') + response_received = True + break - # Extract data: +USORD: ,,"" - data_match = re.search(r'\+USORD:\s*\d+,\d+,"([^"]*)"', resp2) - if data_match: - received_data = data_match.group(1) - elapsed = time.time() - start_listen - print(f'
Réponse reçue en {elapsed:.1f}s !') - print(f'Data: {received_data}') - response_received = True - break + # Also check for no-data response: +USORF: ,0 + # (means no data available yet, keep polling) - time.sleep(2) # Poll every 2 seconds + time.sleep(2) if not response_received: print(f'
⚠️ Aucune réponse reçue après {LISTEN_TIMEOUT}s') - print('Le payload a été envoyé mais le serveur n\'a pas renvoyé de réponse descendante.') + print(f'Le payload a été envoyé mais aucune donnée reçue sur le port {LISTEN_PORT}. Vérifiez que le serveur envoie le downlink sur dstPort={LISTEN_PORT}.') - # Step 5: Close socket + # Step 4: Close socket resp, ok = send_at(f'AT+USOCL={socket_id}') log_raw(f'AT+USOCL={socket_id}', resp) - socket_id = None # Prevent double close in finally + socket_id = None print('✅ Socket fermé') # Summary if response_received: print('
Test aller-retour OK — la communication bidirectionnelle Miotiq fonctionne.') else: - print('
L\'envoi UDP fonctionne mais la réponse descendante n\'a pas été reçue. Vérifiez la configuration serveur.') + print('
L\'envoi UDP fonctionne mais la réponse descendante n\'a pas été reçue.') except serial.SerialException as e: print(f'❌ Erreur série: {e}')