v1.4.2 — Fix bug AT+USOWR leak dans payload UDP Miotiq
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>
This commit is contained in:
107
loop/AUDIT_SARA_send_data_v2.md
Normal file
107
loop/AUDIT_SARA_send_data_v2.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# 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 response` avant d'envoyer les donnees binaires
|
||||
- Abort propre a chaque etape via `socket_id = None` si creation socket, connexion, ou prompt `@` echoue
|
||||
- Retry `AT+USOCR=17` apres 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'` puis `ser_sara.write((command + '\r')...)`
|
||||
- **Lignes 588, 628, 646, 656, 666, 674, 682, 690, 698**: fonctions `reset_server_hostname` et `reset_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)
|
||||
|
||||
```python
|
||||
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)
|
||||
|
||||
```python
|
||||
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)
|
||||
|
||||
```python
|
||||
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):
|
||||
```python
|
||||
finally:
|
||||
ser_sara.close()
|
||||
conn.close()
|
||||
```
|
||||
|
||||
### 6. Code mort dans reset_server_hostname_https (lignes 717-722)
|
||||
|
||||
```python
|
||||
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 |
|
||||
Reference in New Issue
Block a user