Je voudrais publier sur mqtt via le topic alarme/memory, quand il reste moins de 20% de mémoire disponible pour le fichier alarme.log, 2 informations : la mémoire restante et un flag d'alerte. Ce pourait être : freeMemory = xxxxx et flagMemory = 1
Pour publier une alerte sur MQTT lorsque l’espace restant pour le fichier alarme.log
est inférieur à 20 %, tu peux mettre en place un code pour surveiller régulièrement l’espace disponible sur le système de fichiers SPIFFS et envoyer un message MQTT avec la mémoire restante et un flag d'alerte si la condition est remplie.
Voici un exemple de code pour accomplir cela :
Code Arduino pour ESP32 avec MQTT
Assurez-vous que les bibliothèques PubSubClient
(pour MQTT) et SPIFFS
sont installées et configurées.
#include <WiFi.h>
#include <PubSubClient.h>
#include <SPIFFS.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const char* mqttServer = "YOUR_MQTT_SERVER";
const int mqttPort = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
const char* topic = "alarme/memory"; // Topic MQTT pour les alertes mémoire
const int memoryThreshold = 20; // Seuil de 20% pour déclencher l'alerte
void setup() {
Serial.begin(115200);
// Connexion Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connecté");
// Configuration MQTT
client.setServer(mqttServer, mqttPort);
// Initialisation de SPIFFS
if (!SPIFFS.begin(true)) {
Serial.println("Erreur de montage de SPIFFS");
return;
}
}
void loop() {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
// Vérification de la mémoire disponible pour alarme.log
checkMemoryAndPublish();
delay(60000); // Vérifie la mémoire toutes les 60 secondes
}
void checkMemoryAndPublish() {
// Taille totale et espace disponible
size_t totalBytes = SPIFFS.totalBytes();
size_t usedBytes = SPIFFS.usedBytes();
size_t freeBytes = totalBytes - usedBytes;
// Calcul du pourcentage de mémoire libre
int freeMemoryPercentage = (freeBytes * 100) / totalBytes;
// Vérifie si le seuil de 20% est atteint
if (freeMemoryPercentage < memoryThreshold) {
String payload = "freeMemory=" + String(freeBytes) + " ; flagMemory=1";
client.publish(topic, payload.c_str());
Serial.println("Alerte mémoire publiée sur MQTT: " + payload);
} else {
Serial.println("Mémoire suffisante: " + String(freeMemoryPercentage) + "% restant.");
}
}
void reconnectMQTT() {
// Connexion au serveur MQTT
while (!client.connected()) {
Serial.print("Connexion à MQTT...");
if (client.connect("ESP32Client")) {
Serial.println("connecté");
} else {
Serial.print("Erreur de connexion, rc=");
Serial.print(client.state());
Serial.println(" nouvelle tentative dans 5 secondes");
delay(5000);
}
}
}
Explication du Code
- Connexion Wi-Fi et MQTT : Configure le Wi-Fi et se connecte au serveur MQTT.
- Contrôle de la Mémoire : La fonction
checkMemoryAndPublish()
utiliseSPIFFS.totalBytes()
etSPIFFS.usedBytes()
pour calculer l’espace libre en pourcentage. Si le pourcentage est inférieur au seuil (20 %), elle publie un message MQTT sur le topicalarme/memory
avec les informations de mémoire libre et un flag d'alerte. - Reconnexion MQTT : La fonction
reconnectMQTT()
s’assure que la connexion MQTT reste active.
Points à Vérifier
- Configuration du Serveur MQTT : Assurez-vous que les informations (
mqttServer
,mqttPort
, etc.) correspondent à celles de votre serveur MQTT. - Fréquence de Vérification : La vérification est configurée toutes les 60 secondes (60000 ms). Ajustez selon vos besoins.
Ce code enverra donc un message MQTT au format suivant lorsque la mémoire est critique :
freeMemory=XXXXX ; flagMemory=1
Cela devrait te permettre de suivre l'état de la mémoire et de recevoir une alerte lorsque l'espace disponible tombe en dessous de 20 %.
Est-ce que l'on peut transformer checkMemoryAndPublish() en tache rtos pour qu'elle ne s'éxécute qu'à une fréquence définie dans le config.json (par défaut, 1 fois par joir à minuit)
Oui, il est possible de transformer la fonction checkMemoryAndPublish()
en une tâche RTOS pour qu’elle s'exécute à une fréquence définie, comme une fois par jour à minuit. L'ESP32 utilise FreeRTOS, ce qui permet de créer des tâches périodiques, et le timing peut être configuré pour exécuter la tâche à une fréquence personnalisée en utilisant un paramètre dans le fichier config.json
.
Voici les étapes pour transformer checkMemoryAndPublish()
en tâche RTOS :
1. Lire la fréquence depuis config.json
Commence par récupérer la fréquence souhaitée depuis le fichier config.json
. Par exemple, si la fréquence est définie en secondes ou en heures, elle peut être convertie en millisecondes pour l'utiliser avec FreeRTOS. Une fois par jour peut être configurée comme 86 400 000 millisecondes.
2. Créer une tâche RTOS pour checkMemoryAndPublish()
Tu peux créer une tâche RTOS qui s'exécute selon l'intervalle défini, comme suit :
#include <ArduinoJson.h>
#include "SPIFFS.h"
// Variables globales
unsigned long intervalMillis = 86400000; // Par défaut, 1 jour en millisecondes
void checkMemoryAndPublish() {
// Implémentation de ta fonction existante
}
void checkMemoryTask(void *parameter) {
for (;;) {
// Exécute la fonction principale
checkMemoryAndPublish();
// Met en pause la tâche pour l'intervalle configuré
vTaskDelay(intervalMillis / portTICK_PERIOD_MS);
}
}
void setup() {
// Initialisation de SPIFFS pour lire config.json
if (!SPIFFS.begin(true)) {
Serial.println("Erreur de montage SPIFFS");
return;
}
// Lire la configuration
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
StaticJsonDocument<512> doc;
DeserializationError error = deserializeJson(doc, configFile);
if (!error) {
// Lire l'intervalle depuis config.json (en millisecondes, par exemple)
intervalMillis = doc["checkMemoryInterval"].as<unsigned long>();
}
configFile.close();
}
// Créer la tâche RTOS
xTaskCreate(
checkMemoryTask, // Fonction de tâche
"CheckMemoryTask", // Nom de la tâche
4096, // Taille de la pile
NULL, // Paramètres de tâche
1, // Priorité
NULL // Gestion de la tâche
);
}
void loop() {
// Vide, car la tâche RTOS s'exécute indépendamment
}
Explication du code
-
Initialisation de SPIFFS : On monte SPIFFS pour accéder au fichier
config.json
, puis on récupère l'intervalle depuis la clécheckMemoryInterval
. -
Fonction
checkMemoryTask
: Cette tâche RTOS appellecheckMemoryAndPublish()
pour vérifier la mémoire et publier sur MQTT, puis elle est mise en pause pourintervalMillis
avant de se relancer. -
Définir un intervalle en millisecondes :
intervalMillis
est initialisé à une valeur par défaut de 86 400 000 ms (24 heures). Ce délai peut être configuré dansconfig.json
et mis à jour au démarrage.
Exemple de config.json
{
"checkMemoryInterval": 86400000 // Intervalle en millisecondes (1 jour)
}
Ajustements pour exécution quotidienne à minuit
Si tu veux que l'exécution se fasse précisément à minuit, tu peux :
- Utiliser un module RTC pour vérifier l'heure actuelle.
- Calculer le délai jusqu'à minuit et le mettre en pause pour cette durée initialement, puis utiliser
vTaskDelay()
pour 24 heures ensuite.
Ce processus assure que checkMemoryAndPublish()
s'exécute de façon optimisée sans bloquer les autres processus de l’ESP32, tout en respectant l’intervalle configuré.
Étape 2 : Supprimer les anciens logs si l’espace SPIFFS est saturé
-
Fonction pour vérifier l’espace disponible et nettoyer :
void cleanLogIfLowSpace() { // Taille et espace disponibles sur SPIFFS size_t totalBytes = SPIFFS.totalBytes(); size_t usedBytes = SPIFFS.usedBytes(); // Si l’espace utilisé est supérieur à 80 % de l’espace total if (usedBytes > (totalBytes * 0.8)) { SPIFFS.remove("/alarme.log"); // Supprimer l'ancien log File logFile = SPIFFS.open("/alarme.log", FILE_WRITE); // Recréer un fichier vide if (logFile) { logFile.println("Nouveau journal démarré après nettoyage"); logFile.close(); } } }
- Créer une tâche journalière dans
loop
pour exécutercleanLogIfLowSpace()
:
unsigned long lastCleanTime = 0;
const unsigned long cleanInterval = 24 * 60 * 60 * 1000; // Intervalle de 24 heures
void loop() {
handleMqtt(config);
unsigned long currentMillis = millis();
if (currentMillis - lastCleanTime >= cleanInterval) {
cleanLogIfLowSpace();
lastCleanTime = currentMillis;
}
}