{
  "versions": [
    {
      "version": "1.7.7",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [],
        "fixes": [
          "Page database (Informations sur la base): la colonne 'Plus récente' affichait 'not connected' a cause d'un tri lexicographique mixant des chaines 'not connected' et des dates ISO. Les requetes MIN/MAX excluent maintenant 'not connected'."
        ],
        "compatibility": [
          "Aucun impact sur les donnees: les lignes 'not connected' restent en base, elles sont juste ignorees pour le calcul des bornes temporelles affichees"
        ]
      },
      "notes": "Effet de bord du bug RTC corrige en v1.7.4: les capteurs deployes avec un rtc_save_to_db.service inactif ont accumule des lignes avec timestamp='not connected'. En tri ASCII, 'n' > '2' donc MAX(timestamp) renvoyait 'not connected' au lieu de la vraie date la plus recente."
    },
    {
      "version": "1.7.6",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [
          "Page admin (tableau SystemD Services): ajout de 3 services manquants — rtc_save_to_db, nebuleair-wifi-powersave.timer, nebuleair-cpu-power.service",
          "Page admin: support d'un display_name explicite par service (sinon auto-cleanup) — affichage propre pour les services .service en plus des .timer",
          "Page admin: nebuleair-noise-data.timer ajoute aux listes allowed pour restart/toggle (etait dans get_systemd_services mais pas dans les 2 autres)"
        ],
        "fixes": [],
        "compatibility": []
      },
      "notes": "Le tableau SystemD Services affiche maintenant la liste complete des 11 services NebuleAir. Cohérence des 3 listes hardcodees (display, restart, toggle)."
    },
    {
      "version": "1.7.5",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [],
        "fixes": [
          "update_firmware.sh: chmod +x avant d'executer setup_services.sh (le bit executable est strippé par git config core.fileMode=false, donc le check -x echouait systematiquement et Step 3c logguait 'not found or not executable, skipping')"
        ],
        "compatibility": []
      },
      "notes": "Suite v1.7.4: le self-heal Step 3c n'etait pas reellement actif a cause d'un check -x trop strict. Cette version corrige le probleme en chmod +x avant l'execution, comme le fait deja installation_part2.sh."
    },
    {
      "version": "1.7.4",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [
          "Services systemd: source de verite unique dans services/setup_services.sh (le service rtc_save_to_db etait auparavant cree inline dans installation_part2.sh)",
          "update_firmware.sh: appelle maintenant setup_services.sh apres git pull (self-healing des services manquants/masques sur les capteurs deja deployes)",
          "setup_services.sh: systemctl unmask defensif sur rtc_save_to_db avant creation du fichier (evite l'ecriture dans /dev/null si le service avait ete masque)"
        ],
        "fixes": [
          "Bug observe sur capteur deployé: rtc_save_to_db.service masque -> timestamp_table reste a 'not connected' -> RTC affiche comme non connecte dans les logs SARA alors que le materiel fonctionne. L'update firmware ne reparait pas cette situation. Avec v1.7.4, un simple update firmware repare automatiquement."
        ],
        "compatibility": [
          "Aucun risque sur les capteurs sains: les fichiers .service sont reecrits avec le meme contenu, comportement inchange",
          "Capteurs avec services manquants/masques: seront repares automatiquement au prochain update firmware",
          "Aucune migration manuelle requise"
        ]
      },
      "notes": "Reorganisation interne du provisionnement des services systemd. installation_part2.sh ne contient plus la definition inline du service RTC (deduplique). save_to_db.py ne contient plus les instructions systemd en commentaire (deduplique). update_firmware.sh devient self-healing pour les services."
    },
    {
      "version": "1.7.3",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [],
        "fixes": [
          "Revert v1.7.2: retrait du check SIM sur la branche CSQ=99 (overhead inutile a chaque coupure signal temporaire, le check sur la branche USOCR/PDP suffit avec un delai de 1-2 cycles maximum)"
        ],
        "compatibility": []
      },
      "notes": "Apres tests: la SIM est detectee tres vite via la branche PDP meme sans le check sur CSQ=99 (le modem alterne CSQ=99 et CSQ>0 sans SIM). Le check sur CSQ=99 ajoutait du cout AT a chaque coupure reseau temporaire pour un gain marginal. On garde uniquement le check v1.7.1 dans la branche USOCR/PDP."
    },
    {
      "version": "1.7.2",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [
          "Loop SARA: detection SIM injoignable etendue au cas 'signal CSQ=99' (sans SIM, le modem ne peut pas s'enregistrer donc CSQ=99 systematique)",
          "Distinction claire entre 'SIM absente' (alerte rouge + notification) et 'coupure reseau temporaire' (message vert, retry au prochain cycle)"
        ],
        "fixes": [
          "v1.7.1 ne detectait pas la SIM absente quand CSQ=99 (le script sortait avant d'atteindre le check SIM dans la branche USOCR)"
        ],
        "compatibility": []
      },
      "notes": "Complement v1.7.1: le check SIM est maintenant appele dans les deux branches d'echec (CSQ=99 et USOCR ERROR). Couvre tous les cas de SIM injoignable."
    },
    {
      "version": "1.7.1",
      "date": "2026-05-12",
      "changes": {
        "features": [],
        "improvements": [
          "Loop SARA: detection SIM injoignable avant escalade hardware reboot (evite les reboots inutiles en boucle quand la SIM est absente/mal inseree)",
          "Logs HTML: bloc rouge tres visible quand la SIM n'est pas detectee (bordure, fond rose, message d'action clair)",
          "Notification WiFi dediee: 'SIM NOT DETECTED -> physical check required' au lieu du generique 'UDP socket creation failed'"
        ],
        "fixes": [
          "Plus de hardware reboots repetes a chaque cycle de 60s quand la SIM est physiquement injoignable (economie courant + usure transistor GPIO 16)"
        ],
        "compatibility": []
      },
      "notes": "Quand la sequence PDP echoue, le script verifie maintenant AT+CPIN? et AT+CCID pour diagnostiquer si le probleme vient de la SIM ou du reseau. Si SIM absente: notification claire + arret propre, pas de reboot. Si SIM presente: comportement actuel (reboot hardware). Le check ne s'execute qu'en cas d'erreur, zero impact sur le happy path."
    },
    {
      "version": "1.7.0",
      "date": "2026-04-27",
      "changes": {
        "features": [
          "Page modem: section Tests Miotiq (UDP) visible uniquement avec carte SIM Miotiq",
          "Test 1 — Verification connexion PDP: detecte si PDP deja actif, active automatiquement si besoin",
          "Test 2 — Test socket UDP: cree/connecte/envoie/ferme un socket vers 192.168.0.20:4242",
          "Test 3 — Ping aller-retour Miotiq: envoie payload ping (command=0x02), ecoute reponse descendante via API Miotiq sendToDevice"
        ],
        "improvements": [
          "Sections Test HTTP et Send message masquees automatiquement en mode Miotiq (pas d'acces internet)",
          "Script check PDP user-friendly: affiche IP si deja actif, pas d'erreurs inutiles",
          "Logs AT bruts accessibles via bouton collapse sur tous les tests Miotiq",
          "Payload UDP: byte 9 recycle de protocol_version (redondant avec bytes 69-71) en champ command",
          "Ping Miotiq: socket binde sur port fixe 33333 + mode non-connecte (AT+USOST/USORF) pour recevoir le downlink"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite mise a jour du parser Miotiq: renommer version en command (byte 9)",
          "Byte 9: 0x00=data (nouveaux capteurs), 0x01=data (anciens capteurs, retrocompat), 0x02=ping test",
          "Necessite configuration serveur: reponse descendante Miotiq sur dstPort=33333"
        ]
      },
      "notes": "La page modem s'adapte au type de carte SIM. En mode Miotiq, les tests HTTP sont remplaces par des tests UDP dedies avec 3 niveaux: connexion PDP, socket UDP, et ping aller-retour bidirectionnel via l'API descendante Miotiq (valide en ~2s)."
    },
    {
      "version": "1.6.4",
      "date": "2026-04-02",
      "changes": {
        "features": [
          "Page modem: boutons Activer/Desactiver LED status connexion PCB (AT+UGPIOC=16,2 / AT+UGPIOC=16,255)"
        ],
        "improvements": [
          "Page modem: messages de progression en 3 etapes pendant le reset hardware (coupure, redemarrage, test connexion)",
          "Page modem: bouton reset hardware desactive pendant l'operation pour eviter les doubles clics"
        ],
        "fixes": [],
        "compatibility": []
      },
      "notes": "Le reset hardware affiche maintenant les etapes en temps reel (~20s). Deux nouveaux boutons permettent de controler la LED bleue du PCB qui indique l'etat de la connexion reseau du modem."
    },
    {
      "version": "1.6.3",
      "date": "2026-04-01",
      "changes": {
        "features": [
          "Page logs: bouton Auto-refresh pour suivre les logs SARA en temps reel (polling 3s)"
        ],
        "improvements": [
          "Service SARA: ajout flag python3 -u (unbuffered) pour ecriture immediate des logs dans le fichier"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite re-execution de setup_services.sh pour activer le mode unbuffered (optionnel, pas d'impact si non fait)"
        ]
      },
      "notes": "Les logs SARA sont maintenant visibles en temps reel sur la page logs grace au mode unbuffered Python et au rafraichissement automatique. Aucun impact sur les anciennes installations qui ne relancent pas setup_services.sh."
    },
    {
      "version": "1.6.2",
      "date": "2026-03-27",
      "changes": {
        "features": [],
        "improvements": [
          "Simplification du script de boot SARA (start.py): suppression config AirCarto, uSpot/SSL, PDP et geolocalisation",
          "La configuration modem est desormais entierement geree par le script principal (SARA_send_data_v2.py)"
        ],
        "fixes": [],
        "compatibility": []
      },
      "notes": "Le script de boot ne fait plus que 3 choses: reset modem_config_mode, alimentation modem GPIO 16, detection modele R4/R5. Toute la configuration (URLs, certificats, PDP, geolocalisation) est deja geree par le script principal qui tourne chaque minute avec gestion d'erreur et retry."
    },
    {
      "version": "1.6.1",
      "date": "2026-03-19",
      "changes": {
        "features": [
          "Sonometre NSRT MK4: detection deconnexion avec message explicite (page capteurs + self-test)",
          "Colonne noise_status dans data_NOISE (0x00=OK, 0xFF=deconnecte)",
          "ERR_NOISE (bit 5, byte 66) dans error_flags UDP quand sonometre deconnecte"
        ],
        "improvements": [
          "Script NSRT_mk4_get_data.py ecrit en base meme si capteur deconnecte (valeurs a 0, noise_status=0xFF)",
          "Script read.py: message d'erreur clair au lieu de l'exception Python brute",
          "Self-test: affiche 'Capteur deconnecte — verifiez le cablage USB' au lieu de l'erreur technique"
        ],
        "fixes": [],
        "compatibility": [
          "Migration automatique: colonne noise_status ajoutee via set_config.py lors du firmware update"
        ]
      },
      "notes": "Gestion de la deconnexion du sonometre NSRT MK4 alignee sur le modele NPM: ecriture en base avec status d'erreur, flag ERR_NOISE dans la payload UDP, et messages utilisateur explicites sur l'interface web."
    },
    {
      "version": "1.6.0",
      "date": "2026-03-18",
      "changes": {
        "features": [
          "Payload UDP Miotiq: envoi npm_status (byte 67) — registre status NextPM en temps reel"
        ],
        "improvements": [
          "npm_status lu depuis la derniere mesure en base (rowid DESC, pas de moyenne ni de timestamp)"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite mise a jour du parser Miotiq pour decoder le byte 67 (npm_status)"
        ]
      },
      "notes": "Le capteur envoie maintenant le registre status du NextPM dans chaque trame UDP (byte 67). La valeur est prise de la derniere mesure sans moyenne (un code erreur ne se moyenne pas). Utilise rowid pour eviter toute dependance au RTC."
    },
    {
      "version": "1.5.2",
      "date": "2026-03-18",
      "changes": {
        "features": [
          "Page capteurs: lecture NPM via get_data_modbus_v3.py --dry-run (meme script que le timer)",
          "Page capteurs: affichage temperature et humidite interne du NPM",
          "Page capteurs: decodage npm_status avec flags d'erreur individuels"
        ],
        "improvements": [
          "NPM get_data_modbus_v3.py: mode --dry-run (print JSON sans ecriture en base)",
          "Page capteurs: status NPM affiche en vert (OK) ou orange/rouge (erreurs decodees)"
        ],
        "fixes": [
          "Page capteurs: suppression unite ug/m3 sur le champ message/status"
        ],
        "compatibility": []
      },
      "notes": "La page capteurs utilise maintenant le meme script Modbus que le timer systemd, en mode dry-run pour eviter les conflits d'ecriture SQLite. Le status NPM est decode bit par bit."
    },
    {
      "version": "1.5.1",
      "date": "2026-03-18",
      "changes": {
        "features": [
          "Payload UDP Miotiq: bytes 69-71 firmware version (major.minor.patch)",
          "README: documentation complete de la structure des 100 bytes UDP"
        ],
        "improvements": [],
        "fixes": [],
        "compatibility": [
          "Necessite mise a jour du parser Miotiq pour decoder les bytes 69-71 (firmware version)"
        ]
      },
      "notes": "Le capteur envoie maintenant sa version firmware dans chaque trame UDP. Cote serveur, bytes 69/70/71 = major/minor/patch. Documentation payload complete ajoutee au README."
    },
    {
      "version": "1.5.0",
      "date": "2026-03-18",
      "changes": {
        "features": [
          "Payload UDP Miotiq: byte 66 error_flags (erreurs systeme RTC/capteurs)",
          "Payload UDP Miotiq: byte 67 npm_status (registre status NextPM)",
          "Payload UDP Miotiq: byte 68 device_status (etat general du boitier, specification)",
          "Methodes SensorPayload: set_error_flags(), set_npm_status(), set_device_status()"
        ],
        "improvements": [
          "Initialisation bytes 66-68 a 0x00 au lieu de 0xFF pour eviter faux positifs cote serveur",
          "Escalade erreur UDP: si PDP reset echoue, notification WiFi + hardware reboot + exit"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite mise a jour du parser Miotiq pour decoder les bytes 66-68 (error_flags, npm_status, device_status)"
        ]
      },
      "notes": "Ajout de registres d'erreur et d'etat dans la payload UDP (bytes 66-68). Les bytes de status sont initialises a 0x00 (aucune erreur) au lieu de 0xFF. Le flag RTC est implemente, les autres flags seront actives progressivement."
    },
    {
      "version": "1.4.6",
      "date": "2026-03-17",
      "changes": {
        "features": [
          "Page Admin: comparaison RTC vs heure du navigateur (au lieu de system time)",
          "Page Admin: ajout champ Browser time (UTC) dans l'onglet Clock",
          "Page Admin: bloquer update firmware en mode hotspot avec message explicatif",
          "Page Admin: liens Gitea pour mise a jour hors-ligne (releases + main.zip)"
        ],
        "improvements": [
          "Page Admin: RTC time mis en evidence (label bold, input large, bordure bleue)",
          "Page Admin: System time replie dans un details/summary (non utilise par le capteur)",
          "Page Admin: descriptions ajoutees pour System time, RTC time et Synchroniser le RTC"
        ],
        "fixes": [
          "Fix forget_wifi scan: delai 5s + rescan explicite pour remplir wifi_list.csv",
          "Fix blocage navigateur: revert optimisations fetch qui saturaient la limite 6 connexions/domaine"
        ],
        "compatibility": []
      },
      "notes": "L'onglet Clock compare maintenant le RTC a l'heure du navigateur, plus fiable que le system time Linux (non utilise par le capteur). L'update firmware est bloque en mode hotspot avec un message explicatif. La mise a jour hors-ligne via upload .zip reste disponible."
    },
    {
      "version": "1.4.5",
      "date": "2026-03-17",
      "changes": {
        "features": [
          "Page WiFi: bouton Oublier le reseau pour passer en mode hotspot sans reboot",
          "Page WiFi: badge Mode Hotspot visible dans la sidebar (lien vers page WiFi)",
          "Page WiFi: scan des reseaux WiFi en mode hotspot via cache CSV (scan au demarrage)"
        ],
        "improvements": [
          "Page WiFi: refonte UI avec cards contextuelles (infos connexion detaillees si connecte, scan si hotspot)",
          "Page WiFi: affichage SSID, signal, IP, passerelle, hostname, frequence, securite",
          "Page WiFi: scan WiFi masque quand deja connecte, scan avec colonnes signal et securite",
          "Page WiFi: migration de config.json vers get_config_sqlite",
          "Endpoint internet enrichi: SSID, signal, frequence, securite, passerelle, hostname",
          "Scan WiFi en mode hotspot: lecture du fichier wifi_list.csv avec notice explicative",
          "forget_wifi.sh: scan WiFi avec rescan explicite et delai avant lancement hotspot"
        ],
        "fixes": [
          "Correction VERSION 1.4.3 -> 1.4.4",
          "Fix IP hotspot: 192.168.43.1 -> 10.42.0.1 (defaut NetworkManager)",
          "Fix forget_wifi.sh: appel bash explicite + disconnect wlan0 avant delete"
        ],
        "compatibility": []
      },
      "notes": "Le bouton Oublier le reseau supprime la connexion WiFi sauvegardee, scanne les reseaux disponibles, puis demarre le hotspot (pas de reboot necessaire). En mode hotspot, la page WiFi affiche les reseaux scannes au demarrage via un cache CSV. Adresse hotspot: http://10.42.0.1/html/"
    },
    {
      "version": "1.4.4",
      "date": "2026-03-16",
      "changes": {
        "features": [
          "Bouton Self Test disponible sur les pages Accueil, Capteurs et Admin (en plus de Modem 4G)",
          "Test du module RTC DS3231 integre dans le self-test (connexion + synchronisation horloge)"
        ],
        "improvements": [
          "Refactoring self-test : code JS et HTML des modals extraits dans des fichiers partages (selftest.js, selftest-modal.html)",
          "Le modal self-test est charge dynamiquement via fetch, plus besoin de dupliquer le HTML"
        ],
        "fixes": [],
        "compatibility": []
      },
      "notes": "Le self-test est maintenant accessible depuis toutes les pages principales. Le test RTC verifie la connexion du module et l'ecart avec l'heure systeme."
    },
    {
      "version": "1.4.3",
      "date": "2026-03-16",
      "changes": {
        "features": [
          "Page database: bouton telecharger toute la table (bypass filtre dates)",
          "Page database: validation obligatoire des dates avant telechargement par periode"
        ],
        "improvements": [
          "Payload UDP bruit: bytes 22-23 = noise_cur_leq, 24-25 = noise_cur_level, 26-27 = max_noise (reserve)",
          "Envoi des deux valeurs bruit (cur_LEQ + DB_A_value) en UDP Miotiq au lieu d'une seule"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite mise a jour du parser Miotiq pour decoder les nouveaux champs noise_cur_leq et noise_cur_level"
        ]
      },
      "notes": "Mise a jour structure UDP bruit pour alignement avec parser Miotiq et ameliorations page database."
    },
    {
      "version": "1.4.2",
      "date": "2026-03-14",
      "changes": {
        "features": [],
        "improvements": [],
        "fixes": [
          "Fix envoi UDP Miotiq: desynchronisation serie causant l'envoi de la commande AT+USOWR comme payload au lieu des donnees capteurs",
          "Ajout flush buffer serie (reset_input_buffer) avant chaque etape UDP critique",
          "Verification du prompt @ du modem avant envoi des donnees binaires",
          "Abort propre de l'envoi UDP si creation socket, connexion ou prompt @ echoue",
          "Retry creation socket apres reset PDP reussi"
        ],
        "compatibility": []
      },
      "notes": "Corrige un bug ou le modem SARA envoyait la commande AT+USOWR comme donnees UDP, causant des erreurs UNKNOWN_DEVICE sur le parser Miotiq."
    },
    {
      "version": "1.4.1",
      "date": "2026-03-12",
      "changes": {
        "features": [],
        "improvements": [
          "Migration capteur bruit de l'ancien systeme I2C vers le sonometre NSRT MK4 en USB",
          "Nouveau script sound_meter/read.py pour lecture a la demande (retour JSON)",
          "Page capteurs: carte USB avec affichage LEQ et dB(A) au lieu de l'ancien format texte",
          "Self-test modem: parsing JSON du NSRT MK4 au lieu de texte brut"
        ],
        "fixes": [
          "Correction du self-test bruit qui affichait 'Unexpected value' avec le nouveau capteur"
        ],
        "compatibility": []
      },
      "notes": "Mise a jour necessaire si le sonometre NSRT MK4 est connecte en USB. L'ancien capteur I2C n'est plus supporte sur la page capteurs."
    },
    {
      "version": "1.4.0",
      "date": "2026-03-10",
      "changes": {
        "features": [
          "Mise a jour firmware hors-ligne par upload de fichier ZIP via l'interface web admin",
          "Barre de progression pour suivre l'upload du fichier",
          "Fichier .update-exclude versionne pour gerer les exclusions rsync de maniere evolutive"
        ],
        "improvements": [
          "Vidage du buffer serie avant chaque commande AT dans sara.py (evite les URCs residuelles au demarrage)"
        ],
        "fixes": [],
        "compatibility": [
          "Necessite l'ajout de update_firmware_from_file.sh dans les permissions sudo de www-data",
          "Necessite Apache mod_rewrite pour html/.htaccess (upload 50MB)"
        ]
      },
      "notes": "Permet la mise a jour du firmware sans connexion internet : telecharger le .zip depuis Gitea, se connecter au hotspot du capteur, et uploader via admin.html."
    },
    {
      "version": "1.3.0",
      "date": "2026-02-17",
      "changes": {
        "features": [
          "Onglet 'Ecran' pour le controle de l'affichage HDMI (ModuleAir Pro uniquement)",
          "Demarrage et arret du script d'affichage via l'interface web",
          "Verification automatique du type d'appareil pour afficher l'onglet"
        ],
        "improvements": [
          "Ajout de logs console pour le debougage des commandes web",
          "Traduction de l'element de menu 'Ecran'"
        ],
        "fixes": [
          "Correction des permissions d'execution des scripts python via web (sudo)",
          "Correction de la visibilite des onglets du menu lateral (doublons ID)"
        ],
        "compatibility": [
          "Necessite python3-kivy installe",
          "Necessite l'ajout de permissions sudo pour www-data (voir documentation)"
        ]
      },
      "notes": "Ajout de la fonctionnalite de controle d'ecran pour les demonstrations."
    },
    {
      "version": "1.2.0",
      "date": "2026-02-17",
      "changes": {
        "features": [
          "Integration capteur CO2 MH-Z19 (scripts, base de donnees, service systemd, interface web)",
          "Carte test CO2 sur la page capteurs",
          "Checkbox activation CO2 sur la page admin",
          "Consultation et telechargement des mesures CO2 sur la page base de donnees"
        ],
        "improvements": [],
        "fixes": [
          "Logo ModuleAir Pro ne s'affichait pas (script dans innerHTML non execute)"
        ],
        "compatibility": [
          "Necessite re-execution de create_db.py, set_config.py et setup_services.sh apres mise a jour"
        ]
      },
      "notes": "Ajout du support capteur CO2 MH-Z19 pour le ModuleAir Pro. La transmission SARA sera integree dans une version ulterieure."
    },
    {
      "version": "1.1.0",
      "date": "2026-02-16",
      "changes": {
        "features": [
          "Card informations base de donnees (taille, nombre d'entrees, dates min/max par table)",
          "Telechargement CSV complet par table depuis la page base de donnees",
          "Bouton version firmware NextPM sur la page capteurs",
          "Tests capteurs integres dans l'auto-test modem",
          "Logo dynamique selon le type d'appareil (NebuleAir/ModuleAir)"
        ],
        "improvements": [
          "Reordonnancement de l'auto-test : capteurs avant communication"
        ],
        "fixes": [],
        "compatibility": []
      },
      "notes": "Ameliorations de l'interface web : meilleure visibilite sur l'etat de la base de donnees et des capteurs."
    },
    {
      "version": "1.0.0",
      "date": "2026-02-11",
      "changes": {
        "features": [
          "Support multi-device : NebuleAir Pro / ModuleAir Pro",
          "Systeme de versioning firmware",
          "Changelog viewer dans l'interface web"
        ],
        "improvements": [],
        "fixes": [],
        "compatibility": [
          "Les capteurs existants sont automatiquement configures en 'nebuleair_pro'"
        ]
      },
      "notes": "Premiere version tracee. Les capteurs anterieurs recevront device_type=nebuleair_pro par defaut lors de la mise a jour."
    }
  ]
}