Fix ping Miotiq: socket binde port 33333 + AT+USOST/USORF (mode non-connecte)
Le socket connecte (AT+USOCO) ne recevait pas le downlink Miotiq car celui-ci arrive sur un port different. Maintenant: - AT+USOCR=17,33333 : socket binde sur port local fixe - AT+USOST : envoi en mode non-connecte - AT+USORF : ecoute du downlink sur le port binde Le serveur doit envoyer le downlink avec dstPort=33333. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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('<small class="text-muted">La connexion PDP n\'est peut-être pas établie. Lancez "Vérifier connexion PDP" d\'abord.</small>')
|
||||
@@ -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'<br>⏳ <strong>Attente réponse descendante Miotiq ({LISTEN_TIMEOUT}s)...</strong>')
|
||||
# Step 3: Listen for downlink response on port LISTEN_PORT
|
||||
print(f'<br>⏳ <strong>Attente réponse descendante Miotiq sur port {LISTEN_PORT} ({LISTEN_TIMEOUT}s)...</strong>')
|
||||
|
||||
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: <socket_id>,<length>
|
||||
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)
|
||||
|
||||
# Extract data: +USORD: <socket_id>,<length>,"<data>"
|
||||
data_match = re.search(r'\+USORD:\s*\d+,\d+,"([^"]*)"', resp2)
|
||||
if data_match:
|
||||
received_data = data_match.group(1)
|
||||
# Parse response: +USORF: <socket_id>,"<ip>",<port>,<length>,"<data>"
|
||||
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'<br>✅ <strong class="text-success">Réponse reçue en {elapsed:.1f}s !</strong>')
|
||||
print(f'<small class="text-muted">Source: {src_ip}:{src_port} — {data_len} bytes</small><br>')
|
||||
print(f'<small class="text-muted">Data: {received_data}</small>')
|
||||
response_received = True
|
||||
break
|
||||
|
||||
time.sleep(2) # Poll every 2 seconds
|
||||
# Also check for no-data response: +USORF: <socket_id>,0
|
||||
# (means no data available yet, keep polling)
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
if not response_received:
|
||||
print(f'<br>⚠️ <strong class="text-warning">Aucune réponse reçue après {LISTEN_TIMEOUT}s</strong>')
|
||||
print('<small class="text-muted">Le payload a été envoyé mais le serveur n\'a pas renvoyé de réponse descendante.</small>')
|
||||
print(f'<small class="text-muted">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}.</small>')
|
||||
|
||||
# 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('<br><strong class="text-success">Test aller-retour OK — la communication bidirectionnelle Miotiq fonctionne.</strong>')
|
||||
else:
|
||||
print('<br><strong class="text-warning">L\'envoi UDP fonctionne mais la réponse descendante n\'a pas été reçue. Vérifiez la configuration serveur.</strong>')
|
||||
print('<br><strong class="text-warning">L\'envoi UDP fonctionne mais la réponse descendante n\'a pas été reçue.</strong>')
|
||||
|
||||
except serial.SerialException as e:
|
||||
print(f'❌ Erreur série: {e}')
|
||||
|
||||
Reference in New Issue
Block a user