Error flags byte 66: implementation RTC flags + escalade PDP reset → hardware reboot
- Constantes error_flags (byte 66) + methodes SensorPayload - Construction byte 66 avec flags RTC (disconnected/reset) - Escalade: si PDP reset echoue apres echec UDP → notification + hardware reboot + exit - Doc: ajout byte 68 device_status (specification) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -151,6 +151,16 @@ payload_json = {
|
|||||||
aircarto_profile_id = 0
|
aircarto_profile_id = 0
|
||||||
uSpot_profile_id = 1
|
uSpot_profile_id = 1
|
||||||
|
|
||||||
|
# Error flags constants (byte 66)
|
||||||
|
ERR_RTC_DISCONNECTED = 0x01
|
||||||
|
ERR_RTC_RESET = 0x02
|
||||||
|
ERR_BME280 = 0x04
|
||||||
|
ERR_NPM = 0x08
|
||||||
|
ERR_ENVEA = 0x10
|
||||||
|
ERR_NOISE = 0x20
|
||||||
|
ERR_MPPT = 0x40
|
||||||
|
ERR_WIND = 0x80
|
||||||
|
|
||||||
# database connection
|
# database connection
|
||||||
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
|
conn = sqlite3.connect("/var/www/nebuleair_pro_4g/sqlite/sensors.db")
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@@ -358,6 +368,18 @@ class SensorPayload:
|
|||||||
if direction is not None:
|
if direction is not None:
|
||||||
self.payload[64:66] = struct.pack('>H', int(direction))
|
self.payload[64:66] = struct.pack('>H', int(direction))
|
||||||
|
|
||||||
|
def set_error_flags(self, flags):
|
||||||
|
"""Set system error flags (byte 66)"""
|
||||||
|
self.payload[66] = flags & 0xFF
|
||||||
|
|
||||||
|
def set_npm_status(self, status):
|
||||||
|
"""Set NextPM status register (byte 67)"""
|
||||||
|
self.payload[67] = status & 0xFF
|
||||||
|
|
||||||
|
def set_device_status(self, status):
|
||||||
|
"""Set device status flags (byte 68)"""
|
||||||
|
self.payload[68] = status & 0xFF
|
||||||
|
|
||||||
def get_bytes(self):
|
def get_bytes(self):
|
||||||
"""Get the complete 100-byte payload"""
|
"""Get the complete 100-byte payload"""
|
||||||
return bytes(self.payload)
|
return bytes(self.payload)
|
||||||
@@ -1090,6 +1112,14 @@ try:
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# ---- Build error_flags (byte 66) ----
|
||||||
|
error_flags = 0x00
|
||||||
|
if rtc_status == "disconnected":
|
||||||
|
error_flags |= ERR_RTC_DISCONNECTED
|
||||||
|
if rtc_status == "reset":
|
||||||
|
error_flags |= ERR_RTC_RESET
|
||||||
|
payload.set_error_flags(error_flags)
|
||||||
|
|
||||||
if send_miotiq:
|
if send_miotiq:
|
||||||
print('<p class="fw-bold">➡️SEND TO MIOTIQ</p>', end="")
|
print('<p class="fw-bold">➡️SEND TO MIOTIQ</p>', end="")
|
||||||
|
|
||||||
@@ -1125,9 +1155,20 @@ try:
|
|||||||
print(response_SARA_1)
|
print(response_SARA_1)
|
||||||
else:
|
else:
|
||||||
print("⛔There were issues with the modem CSD PSD reinitialize process")
|
print("⛔There were issues with the modem CSD PSD reinitialize process")
|
||||||
|
print("🔄 PDP reset failed → escalating to hardware reboot")
|
||||||
# Clignotement LED rouge en cas d'erreur
|
# Clignotement LED rouge en cas d'erreur
|
||||||
led_thread = Thread(target=blink_led, args=(24, 5, 0.5))
|
led_thread = Thread(target=blink_led, args=(24, 5, 0.5))
|
||||||
led_thread.start()
|
led_thread.start()
|
||||||
|
#Send notification (WIFI)
|
||||||
|
send_error_notification(device_id, "UDP socket creation failed + PDP reset failed -> hardware reboot")
|
||||||
|
#Hardware Reboot
|
||||||
|
hardware_reboot_success = modem_hardware_reboot()
|
||||||
|
if hardware_reboot_success:
|
||||||
|
print("✅Modem successfully rebooted and reinitialized")
|
||||||
|
else:
|
||||||
|
print("⛔There were issues with the modem reboot/reinitialize process")
|
||||||
|
#end loop
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
#Retreive Socket ID
|
#Retreive Socket ID
|
||||||
socket_id = None
|
socket_id = None
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
# Error Flags — UDP Payload Miotiq (Bytes 66-67)
|
# Error Flags — UDP Payload Miotiq (Bytes 66-68)
|
||||||
|
|
||||||
## Principe
|
## Principe
|
||||||
|
|
||||||
Les bytes 66 et 67 de la payload UDP (100 bytes) sont utilises comme registres d'erreurs.
|
Les bytes 66, 67 et 68 de la payload UDP (100 bytes) sont utilises comme registres d'erreurs
|
||||||
Chaque bit represente un etat d'erreur independant. Plusieurs erreurs peuvent
|
et d'etat. Chaque bit represente un etat independant. Plusieurs flags peuvent
|
||||||
etre signalees simultanement.
|
etre actifs simultanement.
|
||||||
|
|
||||||
- **Byte 66** : erreurs systeme (RTC, capteurs)
|
- **Byte 66** : erreurs systeme (RTC, capteurs)
|
||||||
- **Byte 67** : status NextPM (registre interne du capteur)
|
- **Byte 67** : status NextPM (registre interne du capteur)
|
||||||
|
- **Byte 68** : status device (etat general du boitier)
|
||||||
|
|
||||||
## Position dans la payload
|
## Position dans la payload
|
||||||
|
|
||||||
@@ -15,7 +16,8 @@ etre signalees simultanement.
|
|||||||
Bytes 0-65 : donnees capteurs (existant)
|
Bytes 0-65 : donnees capteurs (existant)
|
||||||
Byte 66 : error_flags (erreurs systeme)
|
Byte 66 : error_flags (erreurs systeme)
|
||||||
Byte 67 : npm_status (status NextPM)
|
Byte 67 : npm_status (status NextPM)
|
||||||
Bytes 68-99 : reserved (initialises a 0xFF)
|
Byte 68 : device_status (etat general du boitier)
|
||||||
|
Bytes 69-99 : reserved (initialises a 0xFF)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -91,6 +93,35 @@ car les deux indiquent un capteur inactif.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Byte 68 — Device Status (etat general du boitier)
|
||||||
|
|
||||||
|
Flags d'etat du device, determines par le script d'envoi (`SARA_send_data_v2.py`).
|
||||||
|
Ces flags donnent du contexte sur l'etat general du boitier pour le diagnostic a distance.
|
||||||
|
|
||||||
|
| Bit | Masque | Nom | Description | Source |
|
||||||
|
|-----|--------|----------------------|----------------------------------------------------------------|-------------------------------------|
|
||||||
|
| 0 | 0x01 | SARA_REBOOTED | Le modem a ete reboot hardware au cycle precedent | flag fichier ou SQLite |
|
||||||
|
| 1 | 0x02 | WIFI_CONNECTED | Le device est connecte en WiFi (atelier/maintenance) | nmcli device status |
|
||||||
|
| 2 | 0x04 | HOTSPOT_ACTIVE | Le hotspot WiFi est actif (configuration en cours) | nmcli device status |
|
||||||
|
| 3 | 0x08 | GPS_NO_FIX | Pas de position GPS valide | config_table latitude/longitude |
|
||||||
|
| 4 | 0x10 | BATTERY_LOW | Tension batterie sous seuil critique | data_MPPT → battery_voltage |
|
||||||
|
| 5 | 0x20 | DISK_FULL | Espace disque critique sur la Pi (< 5%) | os.statvfs ou shutil.disk_usage |
|
||||||
|
| 6 | 0x40 | DB_ERROR | Erreur d'acces a la base SQLite | try/except sur connexion SQLite |
|
||||||
|
| 7 | 0x80 | BOOT_RECENT | Le device a redemarre recemment (uptime < 5 min) | /proc/uptime |
|
||||||
|
|
||||||
|
### Exemples de valeurs
|
||||||
|
|
||||||
|
| Valeur dec | Hex | Signification |
|
||||||
|
|------------|------|--------------------------------------------------|
|
||||||
|
| 0 | 0x00 | Tout est normal |
|
||||||
|
| 1 | 0x01 | Modem reboot au cycle precedent |
|
||||||
|
| 2 | 0x02 | WiFi connecte (probablement en atelier) |
|
||||||
|
| 6 | 0x06 | WiFi + hotspot actifs (configuration en cours) |
|
||||||
|
| 128 | 0x80 | Boot recent (uptime < 5 min) |
|
||||||
|
| 145 | 0x91 | Modem reboot + batterie faible + boot recent |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
|
|
||||||
### Etape 1 : Lire le status NPM depuis le capteur
|
### Etape 1 : Lire le status NPM depuis le capteur
|
||||||
@@ -112,6 +143,16 @@ ERR_NOISE = 0x20
|
|||||||
ERR_MPPT = 0x40
|
ERR_MPPT = 0x40
|
||||||
ERR_WIND = 0x80
|
ERR_WIND = 0x80
|
||||||
|
|
||||||
|
# Constantes device_status (byte 68)
|
||||||
|
DEV_SARA_REBOOTED = 0x01
|
||||||
|
DEV_WIFI_CONNECTED = 0x02
|
||||||
|
DEV_HOTSPOT_ACTIVE = 0x04
|
||||||
|
DEV_GPS_NO_FIX = 0x08
|
||||||
|
DEV_BATTERY_LOW = 0x10
|
||||||
|
DEV_DISK_FULL = 0x20
|
||||||
|
DEV_DB_ERROR = 0x40
|
||||||
|
DEV_BOOT_RECENT = 0x80
|
||||||
|
|
||||||
# Construction byte 66
|
# Construction byte 66
|
||||||
error_flags = 0x00
|
error_flags = 0x00
|
||||||
|
|
||||||
@@ -128,6 +169,27 @@ payload.set_error_flags(error_flags)
|
|||||||
# Construction byte 67 (lu depuis SQLite, ecrit par get_data_modbus_v3.py)
|
# Construction byte 67 (lu depuis SQLite, ecrit par get_data_modbus_v3.py)
|
||||||
npm_status = get_npm_status_from_db() # 0-255
|
npm_status = get_npm_status_from_db() # 0-255
|
||||||
payload.set_npm_status(npm_status)
|
payload.set_npm_status(npm_status)
|
||||||
|
|
||||||
|
# Construction byte 68
|
||||||
|
device_status = 0x00
|
||||||
|
|
||||||
|
if sara_was_rebooted(): # flag fichier persistant
|
||||||
|
device_status |= DEV_SARA_REBOOTED
|
||||||
|
if check_wifi_connected(): # nmcli device status
|
||||||
|
device_status |= DEV_WIFI_CONNECTED
|
||||||
|
if check_hotspot_active(): # nmcli device status
|
||||||
|
device_status |= DEV_HOTSPOT_ACTIVE
|
||||||
|
if latitude == 0.0 and longitude == 0.0: # config_table
|
||||||
|
device_status |= DEV_GPS_NO_FIX
|
||||||
|
if battery_voltage < 11.0: # data_MPPT seuil a ajuster
|
||||||
|
device_status |= DEV_BATTERY_LOW
|
||||||
|
if check_disk_usage() > 95: # shutil.disk_usage
|
||||||
|
device_status |= DEV_DISK_FULL
|
||||||
|
# DEV_DB_ERROR: set dans le try/except de la connexion SQLite
|
||||||
|
if get_uptime_seconds() < 300: # /proc/uptime
|
||||||
|
device_status |= DEV_BOOT_RECENT
|
||||||
|
|
||||||
|
payload.set_device_status(device_status)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Etape 3 : Ajouter les methodes dans SensorPayload
|
### Etape 3 : Ajouter les methodes dans SensorPayload
|
||||||
@@ -140,6 +202,10 @@ def set_error_flags(self, flags):
|
|||||||
def set_npm_status(self, status):
|
def set_npm_status(self, status):
|
||||||
"""Set NextPM status register (byte 67)"""
|
"""Set NextPM status register (byte 67)"""
|
||||||
self.payload[67] = status & 0xFF
|
self.payload[67] = status & 0xFF
|
||||||
|
|
||||||
|
def set_device_status(self, status):
|
||||||
|
"""Set device status flags (byte 68)"""
|
||||||
|
self.payload[68] = status & 0xFF
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -180,7 +246,8 @@ def set_npm_status(self, status):
|
|||||||
4|wind_direction|hex2dec|degrees||
|
4|wind_direction|hex2dec|degrees||
|
||||||
2|error_flags|hex2dec|||
|
2|error_flags|hex2dec|||
|
||||||
2|npm_status|hex2dec|||
|
2|npm_status|hex2dec|||
|
||||||
30|reserved|skip|||
|
2|device_status|hex2dec|||
|
||||||
|
28|reserved|skip|||
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -212,6 +279,18 @@ npm_fan_err = bool(npm_status & 0x20)
|
|||||||
npm_mem_err = bool(npm_status & 0x40)
|
npm_mem_err = bool(npm_status & 0x40)
|
||||||
npm_laser_err = bool(npm_status & 0x80)
|
npm_laser_err = bool(npm_status & 0x80)
|
||||||
|
|
||||||
|
# Byte 68 — status device
|
||||||
|
device_status = int(parsed_device_status)
|
||||||
|
|
||||||
|
sara_rebooted = bool(device_status & 0x01)
|
||||||
|
wifi_connected = bool(device_status & 0x02)
|
||||||
|
hotspot_active = bool(device_status & 0x04)
|
||||||
|
gps_no_fix = bool(device_status & 0x08)
|
||||||
|
battery_low = bool(device_status & 0x10)
|
||||||
|
disk_full = bool(device_status & 0x20)
|
||||||
|
db_error = bool(device_status & 0x40)
|
||||||
|
boot_recent = bool(device_status & 0x80)
|
||||||
|
|
||||||
# Alertes
|
# Alertes
|
||||||
if rtc_disconnected:
|
if rtc_disconnected:
|
||||||
alert("RTC module deconnecte — verifier pile/cables I2C")
|
alert("RTC module deconnecte — verifier pile/cables I2C")
|
||||||
@@ -219,6 +298,12 @@ if npm_fan_err:
|
|||||||
alert("NextPM: ventilateur hors plage — maintenance requise")
|
alert("NextPM: ventilateur hors plage — maintenance requise")
|
||||||
if npm_laser_err:
|
if npm_laser_err:
|
||||||
alert("NextPM: possible erreur laser — verifier le capteur")
|
alert("NextPM: possible erreur laser — verifier le capteur")
|
||||||
|
if battery_low:
|
||||||
|
alert("Batterie faible — verifier alimentation solaire")
|
||||||
|
if disk_full:
|
||||||
|
alert("Espace disque critique — verifier logs/DB")
|
||||||
|
if sara_rebooted:
|
||||||
|
alert("Modem reboot hardware au cycle precedent — instabilite reseau")
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user