Corrige une desynchronisation serie qui causait l'envoi de la commande AT+USOWR comme donnees UDP au lieu du payload capteurs. Ajout de flush buffer serie, verification du prompt @, et abort propre a chaque etape. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.3 KiB
Audit SARA_send_data_v2.py
Date: 2026-03-14
Correction deja appliquee
Bug AT+USOWR leak dans payload UDP Miotiq — Le device_id recu par Miotiq etait 41542b55534f5752 = AT+USOWR (la commande AT elle-meme).
Cause: desynchronisation serie entre le script et le modem. Le code envoyait les donnees binaires sans verifier que le modem avait bien envoye le prompt @.
Corrections appliquees dans la section UDP (send_miotiq):
ser_sara.reset_input_buffer()avant chaque commande AT critique- Verification que
"@" in responseavant d'envoyer les donnees binaires - Abort propre a chaque etape via
socket_id = Nonesi creation socket, connexion, ou prompt@echoue - Retry
AT+USOCR=17apres un PDP reset reussi
Bugs critiques restants
1. Double \r sur plusieurs commandes AT
Certaines commandes AT ont \r dans le f-string ET un + '\r' lors du write, ce qui envoie \r\r au modem.
Lignes concernees:
- Ligne 988:
command = f'AT+CSQ\r'puisser_sara.write((command + '\r')...) - Lignes 588, 628, 646, 656, 666, 674, 682, 690, 698: fonctions
reset_server_hostnameetreset_server_hostname_https - Lignes 1403, 1541, 1570, 1694, 1741: sections AirCarto et uSpot
Le modem tolere souvent le double \r, mais ca peut generer des reponses parasites dans le buffer serie et contribuer a des bugs de desynchronisation.
Correction: retirer le \r du f-string OU retirer le + '\r' dans le write. Choisir une convention unique.
2. Double guillemet dans AT+URDFILE (ligne 1402)
command = f'AT+URDFILE="aircarto_server_response.txt""\r'
# ^^ double "
Le " en trop peut causer une erreur AT ou une reponse inattendue.
Correction: command = f'AT+URDFILE="aircarto_server_response.txt"\r'
3. Crash si table SQLite vide (lignes 781-786, 820-826, 868-880)
rows = cursor.fetchall()
data_values = [row[2:] for row in rows]
averages = [round(sum(col) / len(col),1) for col in zip(*data_values)]
Si data_NPM, data_NPM_5channels ou data_envea est vide, data_values sera [] et le calcul d'average crashera (IndexError / division par zero).
Correction: ajouter un check if rows: avant le calcul, comme c'est deja fait pour BME280 (ligne 840), wind (ligne 912) et MPPT (ligne 936).
4. Overflow struct.pack sur valeurs negatives (class SensorPayload)
def set_npm_core(self, pm1, pm25, pm10):
self.payload[10:12] = struct.pack('>H', int(pm1 * 10)) # H = unsigned 16-bit
Si un capteur retourne une valeur negative (erreur capteur, -1, etc.), struct.pack('>H', -10) leve struct.error. Concerne: set_npm_core, set_noise, set_envea, set_npm_5channels, set_wind, set_mppt (sauf battery_current et temperatures qui utilisent '>h' signe).
Correction: clamper les valeurs avant pack: max(0, int(value * 10)) pour les champs unsigned, ou verifier value >= 0 avant le pack.
Problemes importants
5. Port serie et SQLite jamais fermes
ser_sara (ligne 248) et conn (ligne 155) sont ouverts mais jamais fermes, meme dans le bloc except final (ligne 1755). Si le script crash, le port serie peut rester verrouille pour le prochain cycle.
Correction: ajouter un bloc finally apres le except (ligne 1757):
finally:
ser_sara.close()
conn.close()
6. Code mort dans reset_server_hostname_https (lignes 717-722)
if profile_id == 1: # ligne 613
...
elif profile_id == 1: # ligne 718 — jamais atteint car meme condition
pass
Copie-colle de reset_server_hostname. Le elif est mort.
Correction: supprimer le bloc elif (lignes 717-722).
Resume
| # | Type | Description | Lignes |
|---|---|---|---|
| 1 | Bug | Double \r sur commandes AT | 988, 588+, ... |
| 2 | Bug | Double guillemet AT+URDFILE | 1402 |
| 3 | Crash | Table SQLite vide -> IndexError | 781, 820, 868 |
| 4 | Crash | struct.pack overflow valeur negative | SensorPayload |
| 5 | Cleanup | Serial/SQLite jamais fermes (finally) | 248, 155 |
| 6 | Cleanup | Code mort elif profile_id==1 | 717-722 |