Files

1568 lines
84 KiB
C

//**********************************************************************************************************************************************************************************
// Fichier BDD_FONCTIONS.C
//
// Contient les fonctions principales de gestion de la BDD
//
//**********************************************************************************************************************************************************************************
// #define __DEBUG_INIT //Décommenter cette ligne pour avoir les messages de debug concernant l'init
// #define __DEBUG_BDD_MESURES //Décommenter cette ligne pour avoir les messages de debug concernant l'init
// Include :
#include "main.h"
// Prototypes :
int8_t init_annuaire_nmea(void);
int8_t enregistrement_date_pgn_nmea(uint16_t rang);
int8_t creation_pgn_field_nmea(uint16_t rang, uint8_t field, char * code_unite, uint8_t precision_accueil, uint8_t precision_mesures, char * nom);
int8_t enregistrement_pgn_field_nmea(uint16_t rang, uint8_t field, float val);
int8_t suppression_pgn_nmea(uint16_t rang);
void maj_etat_cm3p(uint8_t etat);
int8_t enregistrement_annuaire_k_bus(void);
int8_t enregistrement_annuaire_ow(uint8_t nb_devices);
void enregistrement_eeprom(uint8_t adresse_module, uint16_t longueur);
void enregistrement_historique(uint8_t type_source, uint8_t type, uint16_t id_source, float valeur, char * complement);
void enregistrement_mesures(uint8_t mode);
void enregistrement_mesure(uint8_t type, uint16_t no, uint16_t no_variable, char str_date[MAX_LONGUEUR_DATE_COURANTE], uint8_t mode);
int32_t enregistrement_message_users(int32_t code, char * parametres, int8_t etat_demande);
int8_t maj_message_users(uint32_t id, char * parametres, int8_t etat_demande);
int8_t clear_scan_wifi_sta(void);
int8_t enregistrement_scan_wifi_sta(char * bssid, char * nom, uint8_t canal, uint8_t qualite);
int8_t nom_capteur_cle_primaire(uint16_t id, char * nom);
int8_t nom_circuit_cle_primaire(uint16_t id, char * nom);
// Variables globales :
//**********************************************************************************************************************************************************************************
// Fonction : 1. Supprime de la BDD les PGN n'ayant aucun Field Actif (dès qu'un PGN a au moins un Field Actif, tous les enregistrement de ce PGN sont conservés car, dans tous les cas,
// le Compagnon gère le PGN dans son ensemble...)
// 2. RAZ de l'annuaire stocké en RAM
// 3. Init de l'annuaire avec les PGN/Field restant en BDD
// Reçoit : Rien
// Renvoit : 0 si Ok, -1 si erreur
//**********************************************************************************************************************************************************************************
int8_t init_annuaire_nmea(void)
{
uint16_t i, j;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
// Suppression de tous les PGN qui n'ont aucun Field actif :
sprintf(requete, "DELETE FROM TB_Nmea2000 WHERE Pgn NOT IN (SELECT Pgn FROM TB_Nmea2000 WHERE Actif=1) ");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// RAZ dde l'annuaire :
for (i = 0; i < NMEA_MAX_NOMBRE_PGN; i ++) nmea.annuaire[i].flag_validite = false;
// Enregistrement dans l'annuaire des PGNs restant en BDD :
i = 0;
sprintf(requete, "SELECT Pgn FROM TB_Nmea2000 GROUP BY Pgn ");
// printf("Requete = [%s]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
nmea.annuaire[i].pgn = atoi(row[0]);
nmea.annuaire[i].flag_validite = true; // Marque cette position d'annuaire comme Utilisée
nmea.annuaire[i].flag_presence = false; // Permet de savoir qu'on n'a pas encore eu de retour du Compagnon et que la première fois que ça arrivera, il faudra configurer le PGN sur le Compagnon
nmea.annuaire[i].actif = 1; // Puisque seuls les PGN ayant au moins un Field Actif ont été conservés...
nmea.annuaire[i].priority = 0; // Par défaut
nmea.annuaire[i].source = 0; // Par défaut
nmea.annuaire[i].lg_data = 0; // Par défaut
// Recherche des infos du PGN dans le catalogue :
for (j = 0; ((j < NMEA_MAX_NOMBRE_PGN) && (catalogue_pgns[j].pgn != 0)); j ++)
{
if (catalogue_pgns[j].pgn == nmea.annuaire[i].pgn) // Le PGN a été trouvé dans le catalogue (ce qui doit toujours être le cas car pour que le PGN soit stocké en BDD, c'est qu'il a été détecté dans le catalogue)
{
nmea.annuaire[i].type = catalogue_pgns[j].type;
nmea.annuaire[i].periode_mini = catalogue_pgns[j].periode_mini;
break; // Sortie de la boucle du catalogue puisqu'on a trouvé l'entrée.
}
}
// c_bus_down_commande_config_pgn_nmea(nmea.nb_entrees_annuaire);
// NB : on n'émet pas de commande de config car rien ne dit que le Compagnon a déjà détecté ce PGN depuis son reset. Et si ce n'est pas le cas, il ne saura pas traiter cette commande
// (puisqu'il n'aura pas le PGN dans son annuaire). On attend donc de recevoir la première connexion de ce PGN de la part du Compagnon pour luyi envoyer la commande de config correspondante,
// dans 'nmea.c', fonction 'traitement_pgn_compagnon()'
i ++;
}
mysql_free_result(result); //Libération du jeu de résultat
return (0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Mise à jour de la dernière date de réception du PGN (concerne tous les Fields du PGN)
// Reçoit : Le rang du PGN
// Renvoit : 0 si Ok, -1 si erreur
//**********************************************************************************************************************************************************************************
int8_t enregistrement_date_pgn_nmea(uint16_t rang)
{
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
if (rang >= NMEA_MAX_NOMBRE_PGN) return (-1);
if (!nmea.annuaire[rang].flag_validite) return (-1);
sprintf(requete, "UPDATE TB_Nmea2000 SET Date_maj=CURRENT_TIMESTAMP() WHERE Pgn=%i", nmea.annuaire[rang].pgn);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
return (0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Création du field du PGN dans la BDD
// Reçoit : Le rang du PGN, le n° de field et son nom
// Renvoit : 0 si Ok, -1 si erreur
//**********************************************************************************************************************************************************************************
int8_t creation_pgn_field_nmea(uint16_t rang, uint8_t field, char * code_unite, uint8_t precision_accueil, uint8_t precision_mesures, char * nom)
{
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
uint16_t id_variable;
if (rang >= NMEA_MAX_NOMBRE_PGN) return (-1);
if (!nmea.annuaire[rang].flag_validite) return (-1);
// Recherche de la clé primaire de la variable à utiliser pour ce Field :
sprintf(requete, "SELECT Cle_primaire FROM TB_Variables WHERE Type=%i AND Code='%s' ", SOURCE_MESURE_CAPTEUR, code_unite);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
row = mysql_fetch_row(result);
id_variable = atoi(row[0]);
mysql_free_result(result); //Libération du jeu de résultat
// Création du Field dans la BDD :
sprintf(requete, "REPLACE INTO TB_Nmea2000 (Pgn, Field, Nom, Actif, Valeur, ID_Variable, Precision_affichage_accueil, Precision_affichage_mesures, Date_maj) VALUES (%i, %i, '%s', 0, 0, %i, %i, %i, CURRENT_TIMESTAMP()) ",
nmea.annuaire[rang].pgn, field, nom, id_variable, precision_accueil, precision_mesures);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
return (0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistrement de la valeur du field du PGN
// Reçoit : Le rang du PGN, le n° de Field et la Valeur
// Renvoit : 0 si Ok, -1 si erreur
//**********************************************************************************************************************************************************************************
int8_t enregistrement_pgn_field_nmea(uint16_t rang, uint8_t field, float val)
{
uint16_t i;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
if (rang >= NMEA_MAX_NOMBRE_PGN) return (-1);
if (!nmea.annuaire[rang].flag_validite) return (-1);
sprintf(requete, "UPDATE TB_Nmea2000 SET Valeur=%f, Date_maj=CURRENT_TIMESTAMP() WHERE Pgn=%i AND Field=%i ", val, nmea.annuaire[rang].pgn, field);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Mise à jour de la valeur dans la ou les entrées NMEA correspondante (s'il y en a) :
for (i=0; i < entrees.nmea.nb; i++)
{
if (!entrees.nmea.entrees[i].flag_validite) continue;
if (entrees.nmea.entrees[i].pgn != nmea.annuaire[rang].pgn) continue;
if (entrees.nmea.entrees[i].field != field) continue;
entrees.nmea.entrees[i].valeur = val;
}
return (0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Suppression de toutes les entrées du PGN (éventuellement, plusieurs fields) de TB_NMEA2000
// Reçoit : Le rang du PGN
// Renvoit : 0 si Ok, -1 si erreur
//**********************************************************************************************************************************************************************************
int8_t suppression_pgn_nmea(uint16_t rang)
{
return (0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Met à jour le flag d'état du CM3P et enregistre dans la BDD cet état
// Reçoit : l'état du CM3P : ON ou OFF
// Renvoit : Rien
//**********************************************************************************************************************************************************************************
void maj_etat_cm3p(uint8_t etat)
{
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
if (etat == OFF)
{
// Mise à jour du flag interne :
systeme.flag_cm3p_ready = FALSE;
// Mise à jour dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='0' WHERE Nom='Etat_cm3p' "); // Indication d'init en cours pour la partie web/écran
mysql_query(bdd.pointeur, requete);
// Coupure de la sortie correspondante vers CM3+/CM4 :
ecriture_sortie(TYPE_SORTIE_GPIO, 0, systeme.sortie_gpio_cm_do_to_uc, OFF); // Coupure de la sortie CM3P_READY vers le Compagnon. 0 est l'adresse de ShipBase
// Info de debug :
affichage_debug(__FILE__, __LINE__, "L'état de CM3P est passé à\t\t: OFF", TYPE_MESSAGE_DEBUG_WARNING);
}
else if (etat == ON)
{
// Mise à jour du flag interne :
systeme.flag_cm3p_ready = TRUE;
// Mise à jour dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='1' WHERE Nom='Etat_cm3p' ");
mysql_query(bdd.pointeur, requete);
// Activation de la sortie correspondante vers CM3+/CM4 :
ecriture_sortie(TYPE_SORTIE_GPIO, 0, systeme.sortie_gpio_cm_do_to_uc, ON); // Activation de la sortie CM3P_READY vers le Compagnon. 0 est l'adresse de ShipBase
// Info de debug :
affichage_debug(__FILE__, __LINE__, "L'état de CM3P est repassé à\t\t: ON", TYPE_MESSAGE_DEBUG_OK);
}
else
{
sprintf(tmp, "La valeur d'état demandée dans 'maj_etat_cm3p' n'est pas valide (%i). La demande est ignorée...", etat);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD les cartes présentes dans le système
// Reçoit : Rien
// Renvoit : 0 si le traitement n'a détecté aucun problème pour démarrer, -1 si au moins une erreur a été détectée.
//**********************************************************************************************************************************************************************************
int8_t enregistrement_annuaire_k_bus(void)
{
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
uint8_t defaut_config_k_bus;
uint8_t adresse_defaut_config_k_bus;
int8_t type_module_defaut_config_k_bus;
char chaine_adresse_mac[TAILLE_ADRESSE_MAC * 3]; // On a besoin de 3 caractères par octet (xx:) sauf pour le dernier (xx) + le NULL de fin
char chaine_unique_id[MAX_TAILLE_UNIQUE_ID * 3]; // On a besoin de 3 caractères par octet (xx ) sauf pour le dernier (xx) + le NULL de fin
uint16_t i;
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
affichage_debug(__FILE__, __LINE__, "------------------ANNUAIRE K BUS INIT", TYPE_MESSAGE_DEBUG_WARNING);
// Remarques sur Création/Suppression, validité et présence :
// Un circuit (ou une batterie ou un capteur ou un réservoir) est créé ou supprimé exclusivement par l'utilisateur. En particulier, il n'est JAMAIS supprimé automatiquement.
// Dans le cas d'une suppression (par l'utilisateur donc...), l'entrée du circuit dans TB_Circuits (ou de la batterie dans TB_Batteries ou du capteur dans TB_Capteurs, ...) est
// supprimée purement et simplement (DELETE).
// Plutôt que supprimer un circuit (ou une batterie ou un capteur ou un réservoir), l'utilisateur peut le positionner à 'non affecté'. En général, de façon temporaire mais pas forcément.
// Dans ce cas, le champ 'Adresse_module' du circuit (ou de la batterie ou du capteur ou un réservoir) est positionné à '-1'.
// Note : a priori, seuls les circuits utilisent actuellement cette option (par exemple, pour intervertir 2 circuits sur un module SP8DC plein)
// mais le principe est identique pour les capteurs, les batteries et les réservoirs et pourrait être utilisé si besoin.
// Le champ 'validite' a été supprimé des tables de circuits (batterie, capteur et réservoir) car il prétait à confusion avec le 'flag_validite' utilisé dans les structures 'circuits ('batteries',
// 'capteurs' et 'reservoirs). Ce dernier est juste une indication pour mettre de côté les entrées du tableau de structure qui ne sont pas utilisées (comme le tableau a une taille maxi fixe, il y a forcément
// de nombreuses entrées inutilisées). Les tables comme TB_Circuits (TB_Batteries, TB_Capteurs ou TB_Reservoirs) utilisaient le champ Validité pour une fonction de dévalidation manuelle (souvent temporaire).
// Les deux fonctions étaient donc très différentes et de nombreuses confusions ont eu lieu. Pour régler ce problème, les tables n'ont plus de champ Validité. Chaque entrée de la table est valide. On peut
// juste positionner le circuit (ou la batterie ou le capteur ou le réservoir) à 'non affecté' comme indiqué ci-dessus via 'Adresse_module'=-1 ou le supprimer purement et simplement.
// Enfin, l'Etat_systeme (cf commentaires ci-dessous) permet de savoir en temps réel si le ciruit est opérationnel (config Ok et module présent et du bon type) ou non.
// Enfin, dans le cas d'un circuit (ou une batterie ou un capteur ou un réservoir) existant (s'il est supprimé, on n'en parle pas...) et valide (donc affecté à un module d'adresse >=0),
// il est important de savoir si le circui est bien opérationnel. Cette condition est définie par 2 niveaux de tests :
// 1. sa configuration est valide : Cette vérification consiste à tester la validité de chacun de ses paramètres propres (par exemple, un
// réservoir ne peut pas avoir plus d'une entrée) mais aussi la compatibilité de ses paramètres avec le type de module auquel il est affecté (par exemple, un circuit ne peut pas avoir un
// no_circuit=5 sur un SP4AC qui ne comprend que 4 circuits). Ces tests de conformité vs le module prennent pour référence TB_Modules_config et sont donc indépendants de l'état physique
// du réseau K-Bus.
// 2. le module auquel il est affecté est bien présent : l'objet est alors de vérifier qu'un module physique est bien présent à l'adresse prévue en config ET du même type que celui indiqué
// dans TB_Modules_config.
// Une réponse positive à ces 2 tests permet d'affirmer que le circuit (ou la batterie ou le capteur ou le réservoir) est bien opérationnel. Dans ce cas, son champ 'Etat_systeme' est positionné à 0.
// Les test de configuration (1) est effectué dans 'bdd_init.c'. S'il échoue, Etat_systeme est positionné à -1.
// La vérification de la présence du module (2) est fait ci-dessous, après avoir reçu l'annuaire K-Bus du compagnon. S'il échoue, Etat_systeme est positionné à -2.
// Par principe, le niveau 2 est "prioritaire" sur le niveau 1 (si les deux tests sont négatifs, Etat_systeme = -2).
// Lorsque Etat_systeme != 0, le circuit (ou la batterie ou le capteur ou le réservoir) est dévalidé dans l'Appli (flag_validite=FALSE). Dans la BDD, seul le champ Etat_systeme < 0 le distingue d'un
//-----------------------------------------------------------------------------------------
// TRAITEMENT DES MODULES PHYSIQUES
// Tous les flags Presence de TB_Modules_physiques ont été mis à 0 dans 'bdd_init()'.
// Tous les flag_presence de 'systeme.modules_physique' ont été mis à FALSE dans 'bdd_init()' puis à FALSE / TRUE dans 'c_bus_down_reponse_annuaire_k_bus()'.
// On parcours ici tous les modules trouvés par le Compagnon pour :
// - vérifier si le module est nouveau (adresse MAC pas encore dans TB_Modules_physiques, peu importe l'adresse K-bus) : si nouveau, enregistrement dans l'historique
// - mettre à jour les données fraichement récupérées par le Compagnon dans TB_Modules_physiques si le module était connu. Sinon, idem mais en création.
// NB : cette maj se fait à l'adresse K-Bus actuelle (le module a donc pu bouger).
// - vérifier les modules qui ont "disparus" et enregistrement dans l'historique.
// - suppression de TB_Modules_physiques des modules diparus
// - afficher les infos de debug correspondantes (notamment la liste des modules présents et leurs caractéristiques)
// A la fin de cette phase, TB_Modules_physiques est à jour avec seulement les lignes de modules physiquement présents.
// Dit autrement, le champ Présence de TB_Modules_physiques est toujours = 1 un fois l'init terminée.
// NB : même si cela ne serait pas normal (et probablement 'impossible' au niveau du Compagnon), il peut techniquement y avoir des "trous" dans les adresses K-Bus.
//-----------------------------------------------------------------------------------------
#ifdef __DEBUG_INIT
affichage_debug(__FILE__, __LINE__, "\t\tSynthèse des cartes après traitement de l'annuaire :", TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (!systeme.modules_physiques[i].flag_presence) continue; // On ne traite que les cartes qui sont présentes physiquement.
conversion_adresse_mac_chaine(systeme.modules_physiques[i].adresse_mac, chaine_adresse_mac, ':');
conversion_unique_id_chaine(systeme.modules_physiques[i].hardware_unique_id, chaine_unique_id);
// Vérification si le module est nouveau à bord :
sprintf(requete, "SELECT COUNT(*) AS Nb FROM TB_Modules_physiques WHERE Adresse_mac='%s' ", chaine_adresse_mac);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (atoi(row[0]) == 0)
{
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODULES_NOUVEAU_MODULE, i, systeme.modules_physiques[i].type, chaine_adresse_mac);
}
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à jour de la BDD avec les valeurs lues dans le module physique :
sprintf(requete, "REPLACE INTO TB_Modules_physiques \
(Adresse_k_bus, Adresse_mac, Presence, Type, Flag_r_term, Hardware_version, Cpu_unique_id, Cpu_flash_size, Cpu_package, Software_type, Software_version, Software_crc) VALUES \
(%i, '%s', %i, %i, %i, %i, '%s', %i, %i, '%s', '%s', '%08X')",
i, chaine_adresse_mac, 1, systeme.modules_physiques[i].type, systeme.modules_physiques[i].resistance_terminaison, systeme.modules_physiques[i].hardware_version,
chaine_unique_id, systeme.modules_physiques[i].hardware_flash_size, systeme.modules_physiques[i].hardware_package, systeme.modules_physiques[i].soft_type,
systeme.modules_physiques[i].soft_version, systeme.modules_physiques[i].soft_crc);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
#ifdef __DEBUG_INIT
// Affichage des infos de la carte :
sprintf(tmp, "Carte n° %2i : ", i);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
printf("\t%-40s: %s\n", "Adresse MAC", conversion_adresse_mac_chaine(systeme.modules_physiques[i].adresse_mac, chaine_adresse_mac, ':'));
printf("\t%-40s: %s\n", "Type de carte", nom_type_carte(systeme.modules_physiques[i].type));
printf("\t%-40s: %s\n", "ID unique CPU", conversion_unique_id_chaine(systeme.modules_physiques[i].hardware_unique_id, chaine_unique_id));
printf("\t%-40s: %i\n", "Taille de la flash", systeme.modules_physiques[i].hardware_flash_size);
printf("\t%-40s: %i\n", "Type de package de la CPU", systeme.modules_physiques[i].hardware_package);
printf("\t%-40s: %i\n", "Version materielle", systeme.modules_physiques[i].hardware_version);
printf("\t%-40s: %s\n", "Type de logiciel", systeme.modules_physiques[i].soft_type);
printf("\t%-40s: %s\n", "Version de logiciel", systeme.modules_physiques[i].soft_version);
printf("\t%-40s: %08Xh\n","CRC du logiciel", systeme.modules_physiques[i].soft_crc);
printf("\n");
#endif
}
// Enregistrement dans l'historique des modules ayant "disparus" :
sprintf(requete, "SELECT Adresse_k_bus, Adresse_mac, Type FROM TB_Modules_physiques WHERE Presence=0 ");
// printf("Requete = [%s]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_MODULES_SUPPRESSION_MODULE, atoi(row[0]), atoi(row[2]), row[1]);
}
mysql_free_result(result); //Libération du jeu de résultat
// Suppression des entrées de TB_Modules_physiques qui ne sont pas présents sur le bus :
sprintf(requete, "DELETE FROM TB_Modules_physiques WHERE Presence=0; ");
mysql_query(bdd.pointeur, requete);
//-----------------------------------------------------------------------------------------
// TRAITEMENT DES MODULES EN CONFIGURATION
// Tous les flags Presence de TB_Modules_config ont été mis à 0 dans 'bdd_init()'.
// Tous les flag_presence de 'systeme.modules' sont mis à FALSE dans 'bdd_init()'.
// La comparaison, pour une adresse k_bus donnée, entre l'entrée dans 'modules_config' et 'modules_physiques' permet de
// positionner le flag_presence de 'modules_config'. Après ce traitement, chaque entrée de 'modules_config' a donc :
// - flag_validite = FALSE si absente de TB_Modules_config,
// TRUE si présente dans TB_Modules_config
// - flag_presence = TRUE si un module du même type qu'attendu est physiquement présent à cette adresse.
// FALSE sinon (dans ce cas, un defaut_k_bus est positionné SI le module est Affecté - Si le module n'est Affecté à aucun circuit (ou batterie ou capteur), on ne considère pas cette différence comme une erreur)
//-----------------------------------------------------------------------------------------
// Valeurs par défaut :
defaut_config_k_bus = DEFAUT_K_BUS_AUCUN; // Par défaut
adresse_defaut_config_k_bus = MAX_NOMBRE_MODULES; // On cherche une erreur AVANT ce maxi
type_module_defaut_config_k_bus = TYPE_CARTE_INCONNU; // Par défaut
// Mise à jour du flag Presence dans TB_Modules_config et dans la structure 'modules_config' :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
if (!systeme.modules_config[i].flag_validite) continue;
//============================================================================================================================
// Cas normal : un module physique est présent à l'adresse du module en config ET il est du même type
if ((systeme.modules_physiques[i].flag_presence) && // Si un module est physiquepment présent à cette adresse...
(systeme.modules_physiques[i].type == systeme.modules_config[i].type) ) // ... et du même type que celui attendu en config :
{
systeme.modules_config[i].flag_presence = TRUE; // on positionne le module de config à PRESENT
// Mise à jour du flag PRESENCE dans la BDD :
sprintf(requete, "UPDATE TB_Modules_config SET Presence=1 WHERE Adresse_k_bus=%i ", i);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
}
//============================================================================================================================
// Cas d'erreur : aucun module physique n'est présent à cette adresse OU un module physique est présent mais pas du bon type :
else
{
//-------------------------------------------------------------------------------------------------------------------------
// Cas d'une erreur majeure : le module en config est affecté à un ou plusieurs éléments ; ils ne seront donc pas accessibles...
if (systeme.modules_config[i].flag_affecte)
{
defaut_config_k_bus = DEFAUT_K_BUS_MAJEUR;
// Enregistrement de la position de l'erreur si elle est AVANT la précédente :
if (i < adresse_defaut_config_k_bus)
{
adresse_defaut_config_k_bus = i;
type_module_defaut_config_k_bus = systeme.modules_config[i].type;
}
}
//-------------------------------------------------------------------------------------------------------------------------
// Cas d'une erreur mineure : aucun élément n'est affecté au module en erreur donc cette incohérence n'aura pas d'effet...
else
{
if (defaut_config_k_bus == DEFAUT_K_BUS_AUCUN) defaut_config_k_bus = DEFAUT_K_BUS_MINEUR;
// Enregistrement de la position de l'erreur si elle est AVANT la précédente :
if (i < adresse_defaut_config_k_bus)
{
adresse_defaut_config_k_bus = i;
type_module_defaut_config_k_bus = systeme.modules_config[i].type;
}
}
}
}
//------------------------
// Message de défaut K-bus :
//------------------------
// Suppression des messages précédents de ce type :
sprintf(requete, "DELETE FROM TB_Messages_users WHERE Code=%i ", MESSAGE_USERS_CODE_DEFAUT_CONFIG_K_BUS);
mysql_query(bdd.pointeur, requete);
// Création du nouveau si un défaut est présent :
if (adresse_defaut_config_k_bus < MAX_NOMBRE_MODULES)
{
sprintf(tmp, "%i;%i;%i", adresse_defaut_config_k_bus, systeme.modules_physiques[adresse_defaut_config_k_bus].type, type_module_defaut_config_k_bus); // Paramètres = 'adresse_k_bus du premier module Nok';'Type_module_physique à cette adresse (yc -1 pour type inconnu)';'Type module configuré'.
enregistrement_message_users(MESSAGE_USERS_CODE_DEFAUT_CONFIG_K_BUS, tmp, MESSAGE_USERS_ETAT_URGENT);
}
// Mise à jour du flag de défaut dans TB_Systeme :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%i' WHERE Nom='Defaut_config_k_bus' ", ((adresse_defaut_config_k_bus < MAX_NOMBRE_MODULES) ? 1 : 0));
mysql_query(bdd.pointeur, requete);
//-----------------------------------------------------------------------------------------
// VERIFICATION DE LA CONFIGURATION EN COURS DES CIRCUITS (ou BATTERIES/CAPTEURS/RESERVOIRS)
//-----------------------------------------------------------------------------------------
// Tous les flag Presence de TB_Circuits ont été mis à 0 dans 'bdd_init()'.
// Tous les flag_presence de 'circuits.circuits[]' sont mis à FALSE dans 'bdd_init()'
// Les traitements suivants sont faits selon le même modèle :
// - parcours de tous les circuits valides
// - recherche du module sur lequel le circuit est affecté
// - Vérification que :
// - il y a bien un module présent à cette adresse,
// - le module physiquement présent correspond au type de module attendu par le circuit
// - le module comprend biens les entrées/sorties sur lesquelles le circuit est configuré
// Si le résultat est positif, le champ 'TB_Circuits.Presence' et le flag 'circuits.circuits[].flag_presence' sont passés à TRUE.
// Sinon, le champ 'TB_Circuits.Presence' et le flag 'circuits.circuits[].flag_presence' sont laissés à FALSE.
// Dans ce cas (pas présent), le flag 'circuits.circuits[].flag_validite' est aussi passé à FALSE ain de simplifier le traitement mais
// 'TB_Circuits.Presence' est laissé à TRUE ! Il s'agit juste de simplifier le traitement ultérieur par l'appli.
//------------------------
// Circuits :
//------------------------
// Recherche des circuits affectés à un module absent (ou un module du mauvais type) :
sprintf(requete, "SELECT Cle_primaire FROM TB_Circuits WHERE Adresse_module NOT IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE Presence=1)");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
circuits.circuits[circuit_cle_primaire(atoi(row[0]))].etat_systeme = ERREUR_SYSTEME_RESEAU; // Si une erreur systeme de type config est déjà détectée sur ce circuit, elle est "écrasée" par l'Erreur_système_réseau qui est considérée comme plus grave...
}
mysql_free_result(result); //Libération du jeu de résultat
// Traitement des circuits en en erreur systeme (config ou reseau) :
for (i = 0; i < circuits.nb; i ++) // Parcours de tous les circuits
{
if (!circuits.circuits[i].flag_validite) continue; // On ne traite que ceux qui ont une configuration dans la BDD (éventuellement non valide si Etat_systeme = Erreur_systeme_config)
if (circuits.circuits[i].etat_systeme != ERREUR_SYSTEME_AUCUNE)
{
// Désactivation du circuit pour l'exécution en cours :
circuits.circuits[i].flag_validite = FALSE;
// Mise à jour de Etat_systeme dans la BDD :
sprintf(requete, "UPDATE TB_Circuits SET Etat_systeme=%i WHERE Cle_primaire=%i", circuits.circuits[i].etat_systeme, circuits.circuits[i].cle_primaire);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Message de debug :
if (circuits.circuits[i].etat_systeme == ERREUR_SYSTEME_RESEAU)
{
sprintf(tmp, "Le module auquel est affecté le circuit # %i (cle_primaire = %i) n'est pas disponible à l'adresse %i. Le circuit est dévalidé...", i, circuits.circuits[i].cle_primaire, circuits.circuits[i].adresse_module);
}
else
{
sprintf(tmp, "La configuration du circuit # %i (cle_primaire = %i) présente des incohérences rendant son exploitation impossible. Le circuit est dévalidé...", i, circuits.circuits[i].cle_primaire);
}
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//------------------------
// Batteries :
//------------------------
// Recherche des batteries affectées à un module absent (ou un module du mauvais type) :
sprintf(requete, "SELECT Cle_primaire FROM TB_Batteries WHERE Adresse_module NOT IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE Presence=1)");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
batteries.batteries[batterie_cle_primaire(atoi(row[0]))].etat_systeme = ERREUR_SYSTEME_RESEAU; // Si une erreur systeme de type config est déjà détectée sur cette batterie, elle est "écrasée" par l'Erreur_système_réseau qui est considérée comme plus grave...
}
mysql_free_result(result); //Libération du jeu de résultat
// Traitement des batteries en erreur systeme (config ou reseau) :
for (i = 0; i < batteries.nb; i ++) // Parcours de toutes les batteries
{
if (!batteries.batteries[i].flag_validite) continue; // On ne traite que celles qui ont une configuration dans la BDD (éventuellement non valide si Etat_systeme = Erreur_systeme_config)
if (batteries.batteries[i].etat_systeme != ERREUR_SYSTEME_AUCUNE)
{
// Désactivation de la batterie pour l'exécution en cours :
batteries.batteries[i].flag_validite = FALSE;
// Mise à jour de Etat_systeme dans la BDD :
sprintf(requete, "UPDATE TB_Batteries SET Etat_systeme=%i WHERE Cle_primaire=%i", batteries.batteries[i].etat_systeme, batteries.batteries[i].cle_primaire);
printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Message de debug :
if (batteries.batteries[i].etat_systeme == ERREUR_SYSTEME_RESEAU)
{
sprintf(tmp, "Le module auquel est affectée la batterie # %i (cle_primaire = %i) n'est pas disponible à l'adresse %i. La batterie est dévalidée...", i, batteries.batteries[i].cle_primaire, batteries.batteries[i].adresse_module);
}
else
{
sprintf(tmp, "La configuration de la batterie # %i (cle_primaire = %i) présente des incohérences rendant son exploitation impossible. La batterie est dévalidée...", i, batteries.batteries[i].cle_primaire);
}
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//------------------------
// Capteurs :
//------------------------
// Recherche des capteurs affectés à un module absent (ou un module du mauvais type) :
sprintf(requete, "SELECT Cle_primaire FROM TB_Capteurs WHERE Adresse_module NOT IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE Presence=1)");
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
capteurs.capteurs[capteur_cle_primaire(atoi(row[0]))].etat_systeme = ERREUR_SYSTEME_RESEAU; // Si une erreur systeme de type config est déjà détectée sur ce capteur, elle est "écrasée" par l'Erreur_système_réseau qui est considérée comme plus grave...
}
mysql_free_result(result); //Libération du jeu de résultat
// Traitement des capteurs en erreur systeme (config ou reseau) :
for (i = 0; i < capteurs.nb; i ++) // Parcours de tous les capteurs
{
if (!capteurs.capteurs[i].flag_validite) continue; // On ne traite que ceux qui ont une configuration dans la BDD (éventuellement non valide si Etat_systeme = Erreur_systeme_config)
if (capteurs.capteurs[i].etat_systeme != ERREUR_SYSTEME_AUCUNE)
{
// Désactivation du capteurs pour l'exécution en cours :
capteurs.capteurs[i].flag_validite = FALSE;
// Mise à jour de Etat_systeme dans la BDD :
sprintf(requete, "UPDATE TB_Capteurs SET Etat_systeme=%i WHERE Cle_primaire=%i", capteurs.capteurs[i].etat_systeme, capteurs.capteurs[i].cle_primaire);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Message de debug :
if (capteurs.capteurs[i].etat_systeme == ERREUR_SYSTEME_RESEAU)
{
sprintf(tmp, "Le module auquel est affecté le capteurs # %i (cle_primaire = %i) n'est pas disponible à l'adresse %i. Le capteurs est dévalidé...", i, capteurs.capteurs[i].cle_primaire, capteurs.capteurs[i].adresse_module);
}
else
{
sprintf(tmp, "La configuration du capteurs # %i (cle_primaire = %i) présente des incohérences rendant son exploitation impossible. Le capteurs est dévalidé...", i, capteurs.capteurs[i].cle_primaire);
}
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
//------------------------
// Réservoirs :
//------------------------
// Recherche des réservoirs affectés à un module absent (ou un module du mauvais type) :
sprintf(requete, "SELECT Cle_primaire FROM TB_Reservoirs WHERE Adresse_module NOT IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE Presence=1)");
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
reservoirs.reservoirs[reservoir_cle_primaire(atoi(row[0]))].etat_systeme = ERREUR_SYSTEME_RESEAU; // Si une erreur systeme de type config est déjà détectée sur ce réservoir, elle est "écrasée" par l'Erreur_système_réseau qui est considérée comme plus grave...
}
mysql_free_result(result); //Libération du jeu de résultat
// Traitement des réservoirs en erreur systeme (config ou reseau) :
for (i = 0; i < reservoirs.nb; i ++) // Parcours de tous les réservoirs
{
if (!reservoirs.reservoirs[i].flag_validite) continue; // On ne traite que ceux qui ont une configuration dans la BDD (éventuellement non valide si Etat_systeme = Erreur_systeme_config)
if (reservoirs.reservoirs[i].etat_systeme != ERREUR_SYSTEME_AUCUNE)
{
// Désactivation du réservoir pour l'exécution en cours :
reservoirs.reservoirs[i].flag_validite = FALSE;
// Mise à jour de Etat_systeme dans la BDD :
sprintf(requete, "UPDATE TB_Reservoirs SET Etat_systeme=%i WHERE Cle_primaire=%i", reservoirs.reservoirs[i].etat_systeme, reservoirs.reservoirs[i].cle_primaire);
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Message de debug :
if (reservoirs.reservoirs[i].etat_systeme == ERREUR_SYSTEME_RESEAU)
{
sprintf(tmp, "Le module auquel est affecté le réservoirs # %i (cle_primaire = %i) n'est pas disponible à l'adresse %i. Le réservoirs est dévalidé...", i, reservoirs.reservoirs[i].cle_primaire, reservoirs.reservoirs[i].adresse_module);
}
else
{
sprintf(tmp, "La configuration du réservoirs # %i (cle_primaire = %i) présente des incohérences rendant son exploitation impossible. Le réservoirs est dévalidé...", i, reservoirs.reservoirs[i].cle_primaire);
}
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
}
return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD les devices OW présents dans le système
// Lors de 'bdd_init()', toutes les entrées de TB_One_wire sont positionnées à Validite=0 SAUF celles utilisées par un Capteur. Dans ce cas, Validite=1.
// L'appel de 'enregistrement_annuaire_ow()' a été fait depuis la fonction 'c_bus_down_reponse_annuaire_ow()' dans 'c_commande.c'. Celle-ci a, avant l'appel, positionné
// les 'flag_présence' et les 'rom_code[]' avec les infos reçues du Compagnon.
// Reçoit : Le nombre de devices renvoyés par le Compagnon. En pratique, on ne se sert que du cas particulier où 'nb_devices=FFh' qui indique une erreur matérielle du bus.
// Renvoit : 0 si le traitement n'a détecté aucun problème pour démarrer, -1 si au moins une erreur a été détectée.
//**********************************************************************************************************************************************************************************
int8_t enregistrement_annuaire_ow(uint8_t nb_devices)
{
uint16_t i, j;
uint16_t nb;
float valeur_initiale;
int8_t etat_initial;
uint8_t no_entree;
int8_t etat_systeme;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
// Mise à jour de TB_One_wire pour dévalider le flag de présence et d'affectation de toutes les entrées dans la BDD, par défaut :
sprintf(requete, "UPDATE TB_One_wire SET Presence=0, Affecte=0 "); // SDIR 330
mysql_query(bdd.pointeur, requete);
//========================================================================================
// Cas où le Compagnon a rencontré une erreur matérielle lors de la découverte réseau OW :
if (nb_devices == 0xFF)
{
sprintf(tmp, "Le bus OW est détecté en erreur matérielle (%i). Aucun device n'a pu être identifié sur le bus.", entrees.ow.defaut_bus);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
sprintf(requete, "UPDATE TB_One_wire SET Etat=%i", OW_ETAT_BUS_NOK);
mysql_query(bdd.pointeur, requete);
nb_devices = 0; // Permet de mettre à jour en conséquence les différentes structures en aval. Notamment en cas de réception d'un annuaire SANS synchro de la BDD (périodique)
// return(0);
}
else // S'il n'y a pas d'erreur matérielle, on remet à jour les éventuelles erreurs de bus :
{
sprintf(requete, "UPDATE TB_One_wire SET Etat=%i WHERE Etat=%i ", OW_ETAT_DEVICE_OK, OW_ETAT_BUS_NOK);
mysql_query(bdd.pointeur, requete);
}
//========================================================================================
// Mise à jour de TB_One_wire et complément du tableau 'entrees.ow.devices[]' pour les devices qui étaient déjà existants :
entrees.ow.nb_devices = nb_devices;
for (i = 0; i < nb_devices; i ++)
{
// Recherche des devices déjà enregistrés dans la BDD avec ce ROM-Code :
nb = 0;
valeur_initiale = 0;
etat_initial = OW_ETAT_DEVICE_OK;
sprintf(requete, "SELECT Valeur, Etat FROM TB_One_wire WHERE Rom_code='%s' ", entrees.ow.devices[i].rom_code);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (nb == 0)
{
valeur_initiale = atof(row[0]); // On ne conserve que la valeur de la première entrée trouvée (dans le cas où il y en a > 1, les entrées > 1 sont ensuite dévalidées...)
etat_initial = atoi(row[1]); // Idem pour l'état.
}
nb ++;
}
mysql_free_result(result);
// printf("Requête de comptage des ROM-Codes = [ %s; ] et le résultat est : [%i]\n", requete, nb);
switch(nb)
{
//----------------------------------------------------------------------------------------------------
// Cas d'un nouveau device :
case 0 :
{
// Création de la requête d'insertion :
sprintf(requete, "INSERT INTO TB_One_wire (Affecte, Presence, Rom_code) VALUES (0, 1, '%s')", entrees.ow.devices[i].rom_code); // S'il est nouveau, c'est qu'il n'est affecté à aucun capteur. Par contre, il est présent...
mysql_query(bdd.pointeur, requete);
// printf("Requête d'insertion du ROM-Code = [ %s; ]\n", requete);
// Info débug :
sprintf(tmp, "Le device OW [%s] vient d'être détecté pour la première fois sur le bus. Il vient d'être ajouté à la table TB_One_wire et il est stocké localement dans les devices sous le n° %i.", entrees.ow.devices[i].rom_code, i);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
break;
}
//----------------------------------------------------------------------------------------------------
// Cas d'un device existant :
case 1 :
{
// Mise à jour du flag de présence :
sprintf(requete, "UPDATE TB_One_wire SET Presence=1 WHERE Rom_code='%s' ", entrees.ow.devices[i].rom_code);
mysql_query(bdd.pointeur, requete);
// printf("Requête de réactivation du ROM-Code = [ %s; ]\n", requete);
// Info debug :
#ifdef __DEBUG_INIT
sprintf(tmp, "Le device OW [%s] est détecté présent sur le bus et est stocké localement sous le n° %i. Sa valeur initiale est %.2f °C", entrees.ow.devices[i].rom_code, i, valeur_initiale);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
#endif
break;
}
//----------------------------------------------------------------------------------------------------
// Cas d'un device apparaissant plusieurs fois dans la table : Ce cas n'est techniqueemnt pas possible puisque le Rom-Code est une clé primaire.
}
// Mise à jour de la valeur en cours :
entrees.ow.devices[i].valeur = valeur_initiale;
entrees.ow.devices[i].etat = etat_initial;
entrees.ow.devices[i].no_entree = -1; // Par défaut, on considère qu'aucune entrée n'est attrinuée à ce device.
}
//========================================================================================
// Vérification des capteurs utilisant les entrées OW :
for (i = 0; i < capteurs.nb; i ++) // Parcours de tous les capteurs
{
if (!capteurs.capteurs[i].flag_validite) continue; // On ne traite que ceux qui ont une configuration valide (donc Etat_systeme = 0 => config:Ok et module:Ok)
if (capteurs.capteurs[i].type_entrees != TYPE_ENTREES_OW) continue; // Affectés à des entrées OW
//printf("Capteur # %i : type_entrees=%i, id_entrees=%i, cle primaire=%i\n", i, capteurs.capteurs[i].type_entrees, capteurs.capteurs[i].no_entrees[0], capteurs.capteurs[i].cle_primaire);
no_entree = capteurs.capteurs[i].no_entrees[0]; // Simplifie le traitement et la lecture. No_entree est maintenant le n° d'entrée OW affectée à ce capteur.
etat_systeme = ERREUR_SYSTEME_RESEAU; // Valeur par défaut
entrees.ow.entrees[no_entree].flag_validite = FALSE; // Mise à FALSE temporaire de la validité de l'entrée OW (pour le cas où on ne trouve pas de match ensuite)
for (j = 0; j < nb_devices; j ++)
{
if (strstr(entrees.ow.entrees[no_entree].rom_code, entrees.ow.devices[j].rom_code) != NULL)
{
etat_systeme = ERREUR_SYSTEME_AUCUNE;
entrees.ow.entrees[no_entree].flag_validite = TRUE; // Remise à TRUE de la validité de l'entrée OW
entrees.ow.devices[j].no_entree = no_entree; // Créé le lien entre 'entrees.ow.devices[]' et 'entrees.ow.entrees[]'
// Mise à jour du flag Affecté du Device dans la BDD :
sprintf(requete, "UPDATE TB_One_wire SET Affecte=1 WHERE Rom_code='%s' ", entrees.ow.entrees[no_entree].rom_code);
mysql_query(bdd.pointeur, requete);
// printf("Requête de réactivation du ROM-Code = [ %s; ]\n", requete);
break;
}
}
// Mise à jour de l'état du Capteur dans la BDD :
if (capteurs.capteurs[i].etat_systeme != etat_systeme)
{
capteurs.capteurs[i].etat_systeme = etat_systeme;
capteurs.capteurs[i].flag_dde_maj_bdd = true;
}
// Note : on ne modifie pas le caractère "Affecté" du device dans TB_One_wire si le device a disparu.
// En effet, s'il était affecté à la précédente synchro c'est que c'était le cas...
// On est ici probablement dans le cas où le device a "disparu" en cours de fonctionnement.
// Conclusion : on sort ici SOIT avec Capteur ET Entrée_ow validés, SOIT Capteur ET Entrée_ow dévalidés (toujours les deux).
}
//========================================================================================
// Supression de tous les devices enregistrés dans TB_One_wire qui sont pas présents et auquel aucun capteur n'est lié :
sprintf(requete, "DELETE FROM TB_One_wire WHERE Affecte=0 AND Presence=0 ");
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
//========================================================================================
if (nb_devices == 0)
{
sprintf(tmp, "Aucun device OW n'est présent actuellement");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT);
}
entrees.ow.flag_maj_annuaire_en_cours = FALSE; // utilisé par Système.c pour s'ssurer que la mise à jour de l'annuaire est terminé
return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD le contenu de l'EEPROM de la carte
// Reçoit : Le numéro de carte et le nombre d'octets d'EEPROM à stocker dans la BDD
// Renvoit : Rien
//**********************************************************************************************************************************************************************************
void enregistrement_eeprom(uint8_t adresse_module, uint16_t longueur)
{
uint16_t i;
char chaine_eeprom[(MAX_TAILLE_EEPROM * 2) + 1] = ""; // Chaque octet est codé sur 2 caractères hexa + null de fin
char chaine_octet[3];
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
if (systeme.modules_config[adresse_module].flag_presence == FALSE) return; // On ne taite que les cartes présentes
if (longueur > MAX_TAILLE_EEPROM)
{
sprintf(tmp, "La taille d'EEPROM à stocker dans la BDD (TB_Modules_physiques) est supérieure au maxi autorisé (%i octets demandés pour une taille maxi de %i octets)", longueur, MAX_TAILLE_EEPROM);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return;
}
// Codage de chaque octet en 2 caractères hexa :
for (i = 0; i < longueur; i ++)
{
sprintf(chaine_octet, "%02X", systeme.modules_physiques[adresse_module].eeprom[i]); // Codage d'un octet
strcat(chaine_eeprom, chaine_octet); // Ajout à la chaine
}
// Enregistrement des nouvelles valeurs dans la BDD :
sprintf(requete, "UPDATE TB_Modules_physiques SET Eeprom='%s' WHERE Adresse_k_bus='%i'", chaine_eeprom, adresse_module);
mysql_query(bdd.pointeur, requete);
// Debug :
// sprintf(tmp, "La requête de mise à jour de l'EEPROM est [%.3000s]", requete); // NB : le '.3000' permet de limiter le nombre de caractère transférés et évite un warning pour cause de taille de buffers...
// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
// Fin de debug
}
//**********************************************************************************************************************************************************************************
// Fonction ENREGISTREMENT_HISTORIQUE
//
// Enregistre un évènement dans la table historique
//**********************************************************************************************************************************************************************************
void enregistrement_historique(uint8_t type_source, uint8_t type, uint16_t id_source, float valeur, char * complement)
{
bool flag_enregistrement;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
// Valeurs par défaut :
flag_enregistrement = TRUE;
if (complement == NULL) complement = ""; // Sinon le printf suivant va coller une valeur '(null)' qui sera stockée comme une chaine...
// Calcul des paramètres des requêtes selon le type_source d'objet concerné :
switch(type_source)
{
//------------------------------------
case TYPE_SOURCE_HISTORIQUE_BATTERIES :
{
if (batteries.batteries[batterie_cle_primaire(id_source)].mode_enregistrement_historique == MODE_ENREGISTREMENT_HISTORIQUE_AUCUN) flag_enregistrement = FALSE;
break;
}
//------------------------------------
case TYPE_SOURCE_HISTORIQUE_CAPTEURS :
{
if (capteurs.capteurs[capteur_cle_primaire(id_source)].mode_enregistrement_historique == MODE_ENREGISTREMENT_HISTORIQUE_AUCUN) flag_enregistrement = FALSE;
break;
}
//------------------------------------
case TYPE_SOURCE_HISTORIQUE_CIRCUITS :
{
if (circuits.circuits[circuit_cle_primaire(id_source)].mode_enregistrement_historique == MODE_ENREGISTREMENT_HISTORIQUE_AUCUN) flag_enregistrement = FALSE;
break;
}
//------------------------------------
case TYPE_SOURCE_HISTORIQUE_RESERVOIRS :
{
if (reservoirs.reservoirs[reservoir_cle_primaire(id_source)].mode_enregistrement_historique == MODE_ENREGISTREMENT_HISTORIQUE_AUCUN) flag_enregistrement = FALSE;
break;
}
//------------------------------------
case TYPE_SOURCE_HISTORIQUE_SYSTEME :
case TYPE_SOURCE_HISTORIQUE_USB :
{
break;
}
//------------------------------------
default :
{
flag_enregistrement = FALSE;
break;
}
}
// Enregistrement si cela est autorisé :
if (flag_enregistrement)
{
sprintf(requete, "INSERT INTO TB_Historique (Type_source, ID_Source, Type, Valeur, Complement, No_paquet) VALUES (%i, %i, %i, %.4f, '%s', %i)", type_source, id_source, type, valeur, complement, systeme.no_paquet);
// printf("Requete d'enregistrement dans l'historique = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
}
}
//**********************************************************************************************************************************************************************************
// Fonction : A intervalle régulier, enregistre la valeur moyenne depuis le dernier enregistrement de chaque batterie, capteur, circuit et réservoir valide (et dont le flag
// de mesure est VRAI) dans la table TB_Mesures_xxx correspondante. L'enregistrement d'une nouvelle valeur n'a lieu que si la nouvelle valeur est suffisement eloignée
// de la précédente valeur enregistrée (utilisation de la valeur de Marge).
// Cette fonction est également appelée en moe Init. Dans ce cas, il s'agit de crééer une mesure à valeur NULL pour chaque variable de chaque batterie, capteur,
// circuit et réservoir datée de la dernière valeur connue de Heart_beat. Cela permet d'enregistrer sur chaque variable la date à partir de laquelle on a perdu les mesures.
// Reçu : Le mode (BDD_ENREGISTREMENT_MESURE_INIT=0 ou BDD_ENREGISTREMENT_MESURE_NORMAL=1)
// Retour : Rien
//**********************************************************************************************************************************************************************************
void enregistrement_mesures(uint8_t mode)
{
int i;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char str_date[MAX_LONGUEUR_DATE_COURANTE];
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
if ((bdd.compteur_enregistrement_mesures == 0) || (mode == BDD_ENREGISTREMENT_MESURE_INIT))
{
// Rechargement du timer :
bdd.compteur_enregistrement_mesures = PERIODE_ENREGISTREMENT_MESURES;
//---------------------------------------------
//Calcul de la date et de l'heure des mesures :
//---------------------------------------------
// On ne fait le calcul qu'une fois et, surtout, tous les enregistrements de cette boucle auront le même horodatage :
if (mode == BDD_ENREGISTREMENT_MESURE_NORMAL) date_courante(str_date, DATE_COURANTE_SANS_MS, FORMAT_DATE_COURANTE_MYSQL);
else
{
// Dans le cas d'une init, on va chercher la date du dernier Heart-Beat qui sera utilisée pour générer une mesure NULL à cette date sur tous les canaux de mesure.
sprintf(requete, "SELECT Date_maj FROM TB_Systeme WHERE Nom='Heart_beat' ");
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
strcpy(str_date, row[0]); // Copie de la dernière date de MAJ du Heart-Beat comme date des mesures à créer
}
mysql_free_result(result); //Libération du jeu de résultat
}
//------------------------------------
// Boucle sur toutes les batteries :
//------------------------------------
for (i=0; i<batteries.nb; i++)
{
if ((!batteries.batteries[i].flag_validite) || // On n'enregistre la mesure que des batteries VALIDES...
(batteries.batteries[i].mode_enregistrement_mesures != MODE_ENREGISTREMENT_MESURES_PERIODIQUE)) continue; // ... et dont le MODE_ENREGISTREMENT_MESURES_PERIODIQUE est validé
if ((batteries.batteries[i].cumuls_nb_val != 0) || // S'il n'y a eu aucun cumul depuis la dernière mesure, il est inutile de traiter...
(mode == BDD_ENREGISTREMENT_MESURE_INIT)) // Par contre, si on est en phase d'init, on fait le traitement quoi qu'il arrive (la valeur sera de toute façon NULL).
{
//-----------------------
// Tension :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_TENSION, str_date, mode);
//-----------------------
// SOC :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_SOC, str_date, mode);
//-----------------------
// Courant de décharge :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_COURANT_DECHARGE, str_date, mode);
//-----------------------
// Puissance :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_PUISSANCE, str_date, mode);
// Paramètres spécifiques aux batteries supervisées par IBS :
if (batteries.batteries[i].type_entrees == TYPE_ENTREES_IBS)
{
//-----------------------
// Température :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_TEMPERATURE, str_date, mode);
//-----------------------
// Courant différentiel :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_COURANT_DIFFERENTIEL, str_date, mode);
//-----------------------
// Courant de charge :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_COURANT_CHARGE, str_date, mode);
//-----------------------
// SOH :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_SOH, str_date, mode);
//-----------------------
// Autonomie :
enregistrement_mesure(SOURCE_MESURE_BATTERIE, i, BATTERIE_VARIABLE_AUTONOMIE, str_date, mode);
}
// Fin des traitements pour cette batterie :
batteries.batteries[i].cumuls_nb_val = 0; // RAZ du nb d'échantillons
}
else ; // S'il n'y a pas eu de mise à jour dans l'intervalle ET ce n'est pas une INIT, on ne stocke aucune valeur (la dernière mesure continuera à courir)
}
//------------------------------------
// Boucle sur tous les capteurs :
//------------------------------------
for (i=0; i<capteurs.nb; i++)
{
if ((!capteurs.capteurs[i].flag_validite) || // On n'enregistre la mesure que des capteurs VALIDES...
(capteurs.capteurs[i].mode_enregistrement_mesures != MODE_ENREGISTREMENT_MESURES_PERIODIQUE)) continue; // ... et dont le MODE_ENREGISTREMENT_MESURES_PERIODIQUE est validé
if ((capteurs.capteurs[i].cumuls_nb_val != 0) || // S'il n'y a eu aucun cumul depuis la dernière mesure, il est inutile de traiter...
(mode == BDD_ENREGISTREMENT_MESURE_INIT)) // Par contre, si on est en phase d'init, on fait le traitement quoi qu'il arrive (la valeur sera de toute façon NULL).
{
//-----------------------------------------------------
// Variable correspondant à 'id_variable' du capteur :
enregistrement_mesure(SOURCE_MESURE_CAPTEUR, i, capteurs.capteurs[i].no_variable, str_date, mode);
// Fin des traitements pour ce capteur :
capteurs.capteurs[i].cumuls_nb_val = 0; // RAZ du nb d'échantillons
}
else ; // S'il n'y a pas eu de mise à jour dans l'intervalle ET ce n'est pas une INIT, on ne stocke aucune valeur (la dernière mesure continuera à courir)
}
//------------------------------------
// Boucle sur tous les circuits :
//------------------------------------
for (i=0; i<circuits.nb; i++)
{
if ((!circuits.circuits[i].flag_validite) || // On n'enregistre la mesure que des circuits VALIDES...
(circuits.circuits[i].id_circuit_esclave < 0) || // ... des circuits qui ne sont pas esclaves...
(circuits.circuits[i].mode_enregistrement_mesures != MODE_ENREGISTREMENT_MESURES_PERIODIQUE)) continue; // ... et dont le MODE_ENREGISTREMENT_MESURES_PERIODIQUE est validé
if ((circuits.circuits[i].cumuls_nb_val != 0) || // S'il n'y a eu aucun cumul depuis la dernière mesure, il est inutile de traiter...
(mode == BDD_ENREGISTREMENT_MESURE_INIT)) // Par contre, si on est en phase d'init, on fait le traitement quoi qu'il arrive (la valeur sera de toute façon NULL).
{
// Variables spécifiques aux circuits de certaines cartes :
switch(systeme.modules_config[circuits.circuits[i].adresse_module].type)
{
//-----------------------
case TYPE_CARTE_SHIPBASE:
{
switch(circuits.circuits[i].no_circuit)
{
//-----------------------------------------------------------------------------------------------
case 0 : // Circuit correspondant à ShipBase sans les ports USB (appelé 'ShipHeart' dans la BDD)
case 1 : // Circuit correspondant aux ports USB seulement (appelé 'ShipHeart - USB' dans la BDD)
{
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_TENSION, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_COURANT, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_PUISSANCE, str_date, mode);
break;
}
//-----------------------------------------------------------------------------------------------
case 2 : // Circuit correspondant aux ports USB seulement (appelé 'ShipHeart - USB arrière' dans la BDD)
{
break;
}
default : break;
}
break;
}
//-----------------------
case TYPE_CARTE_SP812:
case TYPE_CARTE_SP8DC:
{
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_TENSION, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_COURANT, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_PUISSANCE, str_date, mode);
break;
}
//-----------------------
case TYPE_CARTE_SP4AC:
{
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_TENSION_SECTEUR, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_COURANT, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_PUISSANCE, str_date, mode);
enregistrement_mesure(SOURCE_MESURE_CIRCUIT, i, CIRCUIT_VARIABLE_FREQUENCE, str_date, mode);
break;
}
default: break;
}
// Fin des traitements pour ce circuit :
circuits.circuits[i].cumuls_nb_val = 0; // RAZ du nb d'échantillons
}
else ; // S'il n'y a pas eu de mise à jour dans l'intervalle ET ce n'est pas une INIT, on ne stocke aucune valeur (la dernière mesure continuera à courir)
}
//------------------------------------
// Boucle sur tous les réservoirs :
//------------------------------------
for (i=0; i<reservoirs.nb; i++)
{
if ((!reservoirs.reservoirs[i].flag_validite) || // On n'enregistre la mesure que des réservoirs VALIDES...
(reservoirs.reservoirs[i].mode_enregistrement_mesures != MODE_ENREGISTREMENT_MESURES_PERIODIQUE)) continue; // ... et dont le MODE_ENREGISTREMENT_MESURES_PERIODIQUE est validé
if ((reservoirs.reservoirs[i].cumuls_nb_val != 0) || // S'il n'y a eu aucun cumul depuis la dernière mesure, il est inutile de traiter...
(mode == BDD_ENREGISTREMENT_MESURE_INIT)) // Par contre, si on est en phase d'init, on fait le traitement quoi qu'il arrive (la valeur sera de toute façon NULL).
{
//-----------------------
// Niveau :
enregistrement_mesure(SOURCE_MESURE_RESERVOIR, i, RESERVOIR_VARIABLE_NIVEAU, str_date, mode);
// Fin des traitements pour ce réservoir :
reservoirs.reservoirs[i].cumuls_nb_val = 0; // RAZ du nb d'échantillons
}
else ; // S'il n'y a pas eu de mise à jour dans l'intervalle ET ce n'est pas une INIT, on ne stocke aucune valeur (la dernière mesure continuera à courir)
}
// Message spcécifique à l'init :
if (mode == BDD_ENREGISTREMENT_MESURE_INIT)
{
sprintf(tmp, "Les mesures de fin d'enregistrement ont été créées au %s", str_date);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
}
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD une nouvelle mesure si la valeur de la variable est suffisemment éloignée de la dernière mesure stockée.
// Traite aussi le cas de l'initialisation (selon la valeur de 'mode') pour générer un enregistrement avec la valeur NULL. Dans ce cas, la valeur de 'str_date' contient
// la date d'arrêt de ShipHeart.
// Reçoit : 'type' pour savoir quel objet est traité, 'no' de l'objet dans sa série, 'no_variable' pour savoir quelle est la variable concernée sur cet objet, 'str_date' la chaine
// de caractère à utiliser comme date d'enregistrement s'il est généré et 'mode' pour séparer le cas de l'init du cas normal.
// Retour : Rien
//**********************************************************************************************************************************************************************************
void enregistrement_mesure(uint8_t type, uint16_t no, uint16_t no_variable, char str_date[MAX_LONGUEUR_DATE_COURANTE], uint8_t mode)
{
char nom_table[MAX_LONGUEUR_NOM_TABLE];
uint16_t cle_primaire;
float valeur;
uint16_t cumuls_nb_val;
struct Struct_variable * variable; // Contient l'ID (dans TB_Variables) et la marge de la variable
struct Struct_variables * variables; // Contient les valeurs courante, bdd, last_mesure et cumul de la variable
char str_date_ponctuelle[MAX_LONGUEUR_DATE_COURANTE];
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
#ifdef __DEBUG_BDD_MESURES
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
#endif
//====================================================================
// Préparation des éléments selon le type d'objet concerné :
//====================================================================
switch(type)
{
//-------------------------------------
case SOURCE_MESURE_BATTERIE :
{
strcpy(nom_table, "TB_Mesures_batteries");
cle_primaire = batteries.batteries[no].cle_primaire;
cumuls_nb_val = batteries.batteries[no].cumuls_nb_val;
variable = &batteries.variables[no_variable];
variables = &batteries.batteries[no].variables[no_variable];
break;
}
//-------------------------------------
case SOURCE_MESURE_CAPTEUR :
{
strcpy(nom_table, "TB_Mesures_capteurs");
cle_primaire = capteurs.capteurs[no].cle_primaire;
cumuls_nb_val = capteurs.capteurs[no].cumuls_nb_val;
variable = &capteurs.variables[no_variable];
variables = &capteurs.capteurs[no].variables[CAPTEUR_VARIABLE_VALEUR]; // Attention : pour les capteurs, le n° de variable est utilisé pour définir quelle valeur utiliser dans 'capteur.variables[]' et
// PAS pour définir quelle variabke est en cours dans 'capteurs.capteurs[].variables[]' qui n'en a uniquement qu'une !!
break;
}
//-------------------------------------
case SOURCE_MESURE_CIRCUIT :
{
strcpy(nom_table, "TB_Mesures_circuits");
cle_primaire = circuits.circuits[no].cle_primaire;
cumuls_nb_val = circuits.circuits[no].cumuls_nb_val;
variable = &circuits.variables[no_variable];
variables = &circuits.circuits[no].variables[no_variable];
break;
}
//-------------------------------------
case SOURCE_MESURE_RESERVOIR :
{
strcpy(nom_table, "TB_Mesures_reservoirs");
cle_primaire = reservoirs.reservoirs[no].cle_primaire;
cumuls_nb_val = reservoirs.reservoirs[no].cumuls_nb_val;
variable = &reservoirs.variables[no_variable];
variables = &reservoirs.reservoirs[no].variables[no_variable];
break;
}
//-------------------------------------
default: return;
}
//====================================================================
// Traitement :
//====================================================================
switch(mode)
{
//---------------------------------------------------------------------------
case BDD_ENREGISTREMENT_MESURE_INIT : // Traitement spécifique lors de l'initialisation :
//---------------------------------------------------------------------------
{
#ifdef __DEBUG_BDD_MESURES
sprintf(tmp, "Enregistrement d'une nouvelle valeur de mesure dans %s, pour la clé_primaire %i, sur variable %i, avec valeur = NULL en date du %s pour indiquer la fin des enregistrements de mesure", nom_table, cle_primaire, variable->cle_primaire, str_date);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
variables->last_mesure = FLT_MAX; // Initialisation à la valeur maximale d'un float pour être sûr que le prochain appel générera un enregistrement...
sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', NULL, '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, str_date, systeme.no_paquet);
// printf("Requete d'enregistement mesure = %s\n", requete);
mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD
break;
}
//---------------------------------------------------------------------------
case BDD_ENREGISTREMENT_MESURE_NORMAL :
//---------------------------------------------------------------------------
{
valeur = (variables->cumul / cumuls_nb_val); // Calcul de la valeur moyenne
variables->cumul = 0; // RAZ du cumul
if (fabs(variables->last_mesure - valeur) >= variable->marge) // On n'enregistre une nouvelle valeur que si la moyenne calculée depuis le dernier enregistrement a dévié de plus que [marge]
{
#ifdef __DEBUG_BDD_MESURES
sprintf(tmp, "Enregistrement d'une nouvelle valeur de mesure dans %s, pour la clé_primaire %i, sur variable %i, avec ancienne valeur = %.3f et nouvelle valeur = %.3f (delta = %.3f pour marge = %.3f)", nom_table, cle_primaire, variable->cle_primaire, variables->last_mesure, valeur, fabs(variables->last_mesure - valeur), variable->marge);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
variables->last_mesure = valeur; // Mémorisation de la dernière valeur enregistrée dans mesures pour usage ultérieur.
sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', '%f', '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date, systeme.no_paquet);
// printf("Requete d'enregistement mesure = %s\n", requete);
mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD
}
else
{
#ifdef __DEBUG_BDD_MESURES
sprintf(tmp, "Annulation de l'enregistrement d'une nouvelle valeur de mesure dans %s, pour la clé_primaire %i, sur variable %i, avec ancienne valeur = %.3f et nouvelle valeur = %.3f (delta = %.3f pour marge = %.3f)", nom_table, cle_primaire, variable->cle_primaire, variables->last_mesure, valeur, fabs(variables->last_mesure - valeur), variable->marge);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
}
break;
}
//---------------------------------------------------------------------------
case BDD_ENREGISTREMENT_MESURE_PONCTUEL :
//---------------------------------------------------------------------------
{
valeur = variables->valeur_courante;
if (fabs(variables->last_mesure - valeur) >= variable->marge) // On n'enregistre une nouvelle valeur que si la nouvelle valeur a dévié de plus que [marge] depuis le dernier enregistrement de mesure
{
date_courante(str_date_ponctuelle, DATE_COURANTE_SANS_MS, FORMAT_DATE_COURANTE_MYSQL);
#ifdef __DEBUG_BDD_MESURES
sprintf(tmp, "Enregistrement d'une nouvelle valeur de mesure ponctuelle dans %s, pour la clé_primaire %i, sur variable %i, avec ancienne valeur = %.3f et nouvelle valeur = %.3f (delta = %.3f pour marge = %.3f)", nom_table, cle_primaire, variable->cle_primaire, variables->last_mesure, valeur, fabs(variables->last_mesure - valeur), variable->marge);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
#endif
variables->last_mesure = valeur; // Mémorisation de la dernière valeur enregistrée dans mesures pour usage ultérieur.
sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', '%f', '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date_ponctuelle, systeme.no_paquet);
// printf("Requete d'enregistement mesure = %s\n", requete);
mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD
}
break;
}
}
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD un nouveau message utilisateur
// Reçoit : le code du message, les paramètres du message s'il y en a et son niveau d'affichage
// Retour : -1 si erreur, l'ID du message créé sinon.
//**********************************************************************************************************************************************************************************
int32_t enregistrement_message_users(int32_t code, char * parametres, int8_t niveau)
{
int32_t id = -1;
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
if ((niveau != MESSAGE_USERS_ETAT_INFO) &&
(niveau != MESSAGE_USERS_ETAT_ALERTE) &&
(niveau != MESSAGE_USERS_ETAT_URGENT)) return(-1);
// Préparation de la requête de création du message :
sprintf(requete, "INSERT INTO TB_Messages_users (Code, Parametres, Niveau) VALUES ('%i', '%s', '%i')", code, parametres, niveau);
// printf("Requete d'enregistement nouveau message users = %s\n", requete);
mysql_query(bdd.pointeur, requete);
// Récupération de la clé_primaire du message créé :
sprintf(requete, "SELECT Cle_primaire FROM TB_Messages_users ORDER BY Cle_primaire DESC LIMIT 1");
// printf("Requete d'enregistement d'un message user = %s\n", requete);
mysql_query(bdd.pointeur, requete);
result = mysql_store_result(bdd.pointeur);
row = mysql_fetch_row(result);
id = atoi(row[0]);
mysql_free_result(result);
return(id);
}
//**********************************************************************************************************************************************************************************
// Fonction : Mise à jour dans la BDD d'un message utilisateur existant
// Reçoit : l'ID du message, les paramètres du message s'il y en a et l'état demandé.
// Si le champ 'parametres' est une chaine vide, le champ n'est pas mis à jour (utiliser un espace pour l'effacer...)
// Si 'niveau' a la valeur de suppression (-1) la requête consiste juste à mettre son champ Validité à 0 (paramètres est ignoré)
// Nb : le Code du message ne peut pas être modifié une fois créé
// Retour : -1 si erreur, 0 sinon
//**********************************************************************************************************************************************************************************
int8_t maj_message_users(uint32_t id, char * parametres, int8_t niveau)
{
#define MAX_LG_PARAMETRES 1000
uint32_t l;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
char update_parametres[MAX_LG_PARAMETRES+20] = ""; // Le '20' correspond au texte fixe dans ", Parametres='%s' "
char update_niveau[25] = ""; // '25' correspond à la taille maxi de ", Niveau=%i "
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
l = strlen(parametres);
if (l > MAX_LG_PARAMETRES)
{
sprintf(tmp, "Les [parametres] reçus ont une longueur trop importante (%i pour maxi = %i)", l, MAX_LG_PARAMETRES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
if (l > 0) sprintf(update_parametres, ", Parametres='%s' ", parametres);
if ((niveau == MESSAGE_USERS_ETAT_INFO) ||
(niveau == MESSAGE_USERS_ETAT_ALERTE) ||
(niveau == MESSAGE_USERS_ETAT_URGENT)) // Mise à jour d'un message :
{
sprintf(update_niveau, ", Niveau=%i ", niveau);
// Requête de mise à jour :
sprintf(requete, "UPDATE TB_Messages_users SET Cle_primaire=%i %s %s WHERE Cle_primaire=%i", id, update_parametres, update_niveau, id); // NB : l'update de Cle_primaire ne sert à rien mais permet de gérer simplement les virgules...
// printf("Requete de mise à jour de message users = %s\n", requete);
mysql_query(bdd.pointeur, requete);
}
else // Suppression d'un message :
{
// Requête de mise à jour :
sprintf(requete, "DELETE FROM TB_Messages_users WHERE Cle_primaire=%i", id); // Changement de Dévalidation à Suppression au passage à V1.4 pour éviter le remplissage infi de TB_Messages_users.
// printf("Requete de mise à jour de message users = %s\n", requete);
mysql_query(bdd.pointeur, requete);
}
return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Efface dans la BDD les entrées de TB_Wifi_sta qui n'ont jamais été connectées (les autres sont conservées jusqu'à un effacement manuel)
// Reçoit : Rien
// Retour : -1 si erreur, 0 sinon
//**********************************************************************************************************************************************************************************
int8_t clear_scan_wifi_sta(void)
{
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
// Suppression de tous les réseaux non connus :
sprintf(requete, "DELETE FROM TB_Wifi_sta WHERE Connu!=1");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Raz du flag de présence de tous les réseaux :
sprintf(requete, "UPDATE TB_Wifi_sta SET Presence=0");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Enregistre dans la BDD un enregistrement du scan des réseaux Wifi en mode STA
// Reçoit : Rien
// Retour : -1 si erreur, 0 sinon
//**********************************************************************************************************************************************************************************
int8_t enregistrement_scan_wifi_sta(char * bssid, char * nom, uint8_t canal, uint8_t qualite)
{
bool flag_existe = FALSE;
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
// Recherche si le Bssid existe déjà dans la BDD :
// NB : on est obligé de passer par cette phase intermédiaire cer le REPLACE envisagé au départ (UPDATE ou INSERT) efface le Psk lorsque le réseau existe déjà.
sprintf(requete, "SELECT COUNT(*) FROM TB_Wifi_sta WHERE Bssid='%s' ", bssid);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
if (atoi(row[0]) > 0) flag_existe = TRUE;
}
mysql_free_result(result); //Libération du jeu de résultat
if (flag_existe)
{
sprintf(requete, "UPDATE TB_Wifi_sta SET Nom='%s', Canal=%i, Qualite=%i, Presence=1 WHERE Bssid='%s' ", nom, canal, qualite, bssid);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
}
else
{
sprintf(requete, "INSERT INTO TB_Wifi_sta (Bssid, Nom, Canal, Qualite, Presence) VALUES ('%s', '%s', %i, %i, 1)", bssid, nom, canal, qualite);
// printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
}
return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Recherche le nom d'un capteur dans la BDD (a priori, utilisé en debug ou pour certaines fonctions de mise à jour)
// Reçoit : La clé primaire du capteur et le pointeur de la chaine où déposer le nom
// Retour : -1 si erreur, 0 sinon
//**********************************************************************************************************************************************************************************
int8_t nom_capteur_cle_primaire(uint16_t id, char * nom)
{
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
nom[0] = 0; // Valeur "" par défaut
sprintf(requete, "SELECT Nom FROM TB_Capteurs WHERE Cle_primaire=%i ", id);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
strcpy(nom, row[0]);
}
mysql_free_result(result); //Libération du jeu de résultat
if (nom[0] == 0) return(-1);
else return(0);
}
//**********************************************************************************************************************************************************************************
// Fonction : Recherche le nom d'un circuit dans la BDD (a priori, utilisé en debug ou pour certaines fonctions de mise à jour)
// Reçoit : La clé primaire du circuit et le pointeur de la chaine où déposer le nom
// Retour : -1 si erreur, 0 sinon
//**********************************************************************************************************************************************************************************
int8_t nom_circuit_cle_primaire(uint16_t id, char * nom)
{
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
nom[0] = 0; // Valeur "" par défaut
sprintf(requete, "SELECT Nom FROM TB_Circuits WHERE Cle_primaire=%i ", id);
mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL
result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête
while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête
{
strcpy(nom, row[0]);
}
mysql_free_result(result); //Libération du jeu de résultat
if (nom[0] == 0) return(-1);
else return(0);
}