Files

3606 lines
174 KiB
C

//**********************************************************************************************************************************************************************************
// Fichier BDD_INIT.C
//
// Contient la fonction d'initialisation de la BDD depuis l'appl
//
//**********************************************************************************************************************************************************************************
// #define __DEBUG_PATCH_1_4_10 // Si décommenté, les infos de traitement du patch V1.4.10 seront affichées
#define __DEBUG_PATCH_3_0_13 // Si décommenté, les infos de traitement du patch V3.0.13 seront affichées
// Include :
#include "main.h"
// Prototypes :
int8_t init_bdd(uint8_t mode_init);
// Variables globales :
struct Struct_bdd bdd;
//**********************************************************************************************************************************************************************************
// Fonction INIT_BDD
//
// Fonction initialisant l'accès à la base de données...
//**********************************************************************************************************************************************************************************
int8_t init_bdd(uint8_t mode_init)
{
uint8_t val_u8;
int8_t val_8;
int16_t val_16;
uint32_t val_u32;
uint16_t i, j, k, m; // On évite la lettre 'l' qu'on confond avec le chiffre '1'...
bool flag_erreur;
char *ptr[MAX_NOMBRE_CHAMPS_INTERNES];
char *ptr_val;
char *ptr_niv;
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
char requete[MAX_LONGUEUR_REQUETE_MYSQL];
affichage_debug(__FILE__, __LINE__, "------------------BDD_INIT", TYPE_MESSAGE_DEBUG_WARNING);
// ********************************************************************************************************************************************************
// INIT DE L'ACCES A LA BDD
// ********************************************************************************************************************************************************
if (mode_init == BDD_MODE_INIT_RESET)
{
//initialise l'objet MYSQL pour connections ultérieures:
bdd.pointeur = mysql_init(NULL);
if(bdd.pointeur == NULL) // Cas où l'initialisation n'a pas été possible :
{
sprintf(tmp,"Initialisation de la Base de Données impossible....!");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1); // Arrêt de l'initialisation...
}
// Définition du Charset en UTF-8 :
if (mysql_options(bdd.pointeur, MYSQL_SET_CHARSET_NAME, "utf8") != 0)
{
sprintf(tmp,"Changement du charset de la base de données en UTF-8 IMPOSSIBLE....!");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
//Connection à la BDD :
for (i=0; i < MAX_TENTATIVES_CONNEXION_BDD; i++)
{
if(mysql_real_connect(bdd.pointeur, BDD_SERVER, BDD_USER, BDD_PASSWORD, BDD_DATABASE, 0, NULL, 0) != NULL) break;
delai_dixieme_sec(10); // 1s environ
}
if (i == MAX_TENTATIVES_CONNEXION_BDD)
{
sprintf(tmp,"ERREUR de connexion à la Base de Données ....!");
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
return(-1);
}
else // Cas normal :
{
sprintf(tmp, "Connexion à la base de données [après %i tentative(s)]\t\t\t: OK", (i+1));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);
}
}
// ********************************************************************************************************************************************************
// SYSTEME
// ********************************************************************************************************************************************************
maj_etat_cm3p(OFF); // C'est ici que la mise à jour est "au plus tôt"... => Maj du flag, de la BDD et de la sortie physique
if (mode_init == BDD_MODE_INIT_RESET)
{
// Vidage de la table TB_Messages_users (SDIR #140) :
// sprintf(requete, "TRUNCATE TB_Messages_users "); // SDIR #156 (mise en commentaires)
sprintf(requete, "DELETE FROM TB_Messages_users WHERE Code!=%i ", MESSAGE_USERS_CODE_NOUVELLE_VERSION_DETECTEE); // SDIR #156 (nouvelle ligne)
mysql_query(bdd.pointeur, requete);
// Mise à jour de la version de Compute Module :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Version_cm' ", systeme.cm.chaine_version);
mysql_query(bdd.pointeur, requete);
// Mise à jour de la version de package :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Version_soft_package' ", systeme.package_version);
mysql_query(bdd.pointeur, requete);
// Mise à jour du numéro de la version de package :
// Lecture du numéro de version AVANT mise à jour (SDIR #156) :
sprintf(requete, "SELECT Valeur FROM TB_Systeme WHERE Nom='Version_soft_no_package' ");
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 (strcmp(row[0], systeme.package_no_version) != 0) // Si le n° de version actuel n'est pas celui stocké en base de données :
{
sprintf(tmp, "%s;%s", row[0], systeme.package_no_version); // Paramètres = 'ancienne version';'nouvelle version'
enregistrement_message_users(MESSAGE_USERS_CODE_NOUVELLE_VERSION_DETECTEE, tmp, MESSAGE_USERS_ETAT_INFO);
sprintf(tmp, "Une nouvelle version de package a été installée [Ancienne version = %s et Nouvelle version = %s] ",row[0], systeme.package_no_version);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à jour de la nouvelle version dans la BDD :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Version_soft_no_package' ", systeme.package_no_version);
mysql_query(bdd.pointeur, requete);
// Mise à jour de la version de l'application :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Version_soft_application_cm3p' ", systeme.cm3p_soft_version);
mysql_query(bdd.pointeur, requete);
}
// Mise à jour du flag de veille :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='0' WHERE Nom='Veille' ");
mysql_query(bdd.pointeur, requete);
// Lecture de tous les paramètres système :
sprintf(requete, "SELECT Nom, Valeur FROM TB_Systeme ");
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 (strcmp(row[0], "Etat_modem") == 0) modem.etat = atoi(row[1]);
else if (strcmp(row[0], "Presence_jack") == 0) audio.etat_presence_jack = atoi(row[1]);
else if (strcmp(row[0], "Presence_sim") == 0) modem.etat_presence_sim = atoi(row[1]);
else if (strcmp(row[0], "No_paquet") == 0) systeme.no_paquet = atoi(row[1]);
// Les adresses IP sont systématiquement réinitialisées à ADRESSE_IP_INCONNUE dans l'init de 'systeme.c' :
// else if (strcmp(row[0], "Adresse_ip_ethernet") == 0) strcpy(systeme.adresse_ip_ethernet, row[1]);
// else if (strcmp(row[0], "Adresse_ip_wifi_sta") == 0) strcpy(systeme.adresse_ip_wifi_sta, row[1]);
// else if (strcmp(row[0], "Adresse_ip_wifi_ap") == 0) strcpy(systeme.adresse_ip_wifi_ao, row[1]);
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Lecture de tous les paramètres de configuration :
sprintf(requete, "SELECT Nom, Valeur FROM TB_Configuration ");
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 (strcmp(row[0], "Nom_du_bateau") == 0) strcpy(systeme.nom_bateau, row[1]);
else if (strcmp(row[0], "Mode_validation_maj") == 0) systeme.mode_validation_maj = atoi(row[1]);
else if (strcmp(row[0], "Mode_maj_firmwares") == 0) systeme.mode_maj_firmwares = atoi(row[1]);
else if (strcmp(row[0], "Fuseau_horaire") == 0) systeme.fuseau_horaire = atoi(row[1]);
else if (strcmp(row[0], "Heure_ete") == 0) systeme.heure_ete = atoi(row[1]);
else if (strcmp(row[0], "Consigne_leds") == 0) ecran.consigne_leds = atof(row[1]);
else if (strcmp(row[0], "Validation_leds") == 0) ecran.validation_leds = atoi(row[1]);
else if (strcmp(row[0], "Consigne_backlight") == 0) ecran.consigne_backlight = atof(row[1]);
else if (strcmp(row[0], "Consigne_volume") == 0) audio.consigne_volume = atof(row[1]);
else if (strcmp(row[0], "Fonction_jack") == 0) audio.fonction_jack = atoi(row[1]);
else if (strcmp(row[0], "Periode_sauvegarde_bdd") == 0) systeme.periode_sauvegarde_bdd = atoi(row[1]);
else if (strcmp(row[0], "Periode_connexion_ship2net") == 0) reseaux.periode_connexion_ship2net = atoi(row[1]);
else if (strcmp(row[0], "Wifi_sta_cde") == 0) reseaux.wifi.sta.cde = atoi(row[1]);
else if (strcmp(row[0], "Wifi_ap_cde") == 0) reseaux.wifi.ap.cde = atoi(row[1]);
else if (strcmp(row[0], "Wifi_sta_ssid") == 0)
{
if (strlen(row[1]) < MAX_RESEAUX_WIFI_STA_TAILLE_SSID) strcpy(reseaux.wifi.sta.ssid, row[1]);
}
else if (strcmp(row[0], "Wifi_sta_psk") == 0)
{
if (strlen(row[1]) < MAX_RESEAUX_WIFI_STA_TAILLE_PSK) strcpy(reseaux.wifi.sta.psk, row[1]);
}
else if (strcmp(row[0], "Wifi_ap_ssid") == 0)
{
if (strlen(row[1]) < MAX_RESEAUX_WIFI_AP_TAILLE_SSID) strcpy(reseaux.wifi.ap.ssid, row[1]);
}
else if (strcmp(row[0], "Wifi_ap_pwd") == 0)
{
if (strlen(row[1]) < MAX_RESEAUX_WIFI_AP_TAILLE_PWD) strcpy(reseaux.wifi.ap.pwd, row[1]);
}
else if (strcmp(row[0], "Wifi_ap_canal") == 0) reseaux.wifi.ap.canal = atoi(row[1]);
else if (strcmp(row[0], "Periode_check_adresses_ip") == 0) reseaux.periode_check_adresses_ip = atoi(row[1]);
else if (strcmp(row[0], "Periode_scan_wifi_sta") == 0) reseaux.periode_scan_sta = atoi(row[1]);
else if (strcmp(row[0], "Acces_webgl_1_validation") == 0) reseaux.webgl_new[0].validite = atoi(row[1]);
else if (strcmp(row[0], "Acces_webgl_1_parametres") == 0)
{
if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[0].parametres, row[1]);
}
else if (strcmp(row[0], "Acces_webgl_2_validation") == 0) reseaux.webgl_new[1].validite = atoi(row[1]);
else if (strcmp(row[0], "Acces_webgl_2_parametres") == 0)
{
if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[1].parametres, row[1]);
}
else if (strcmp(row[0], "Acces_webgl_3_validation") == 0) reseaux.webgl_new[2].validite = atoi(row[1]);
else if (strcmp(row[0], "Acces_webgl_3_parametres") == 0)
{
if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[2].parametres, row[1]);
}
else if (strcmp(row[0], "Courant_masses_maxi_sp8dc") == 0) // SDIR #318
{
systeme.courant_masses_maxi_sp8dc = atof(row[1]);
if (systeme.courant_masses_maxi_sp8dc > MAX_COURANT_MASSES_SP8DC) systeme.courant_masses_maxi_sp8dc = MAX_COURANT_MASSES_SP8DC;
}
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Dévalidation par défaut de l'adresse IP du port Ethernet :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Adresse_ip_ethernet' ", ADRESSE_IP_INCONNUE);
mysql_query(bdd.pointeur, requete);
// Dévalidation par défaut de l'adresse IP du port Wifi_sta :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Adresse_ip_wifi_sta' ", ADRESSE_IP_INCONNUE);
mysql_query(bdd.pointeur, requete);
// Dévalidation par défaut de l'adresse IP du port Wifi_ap :
sprintf(requete, "UPDATE TB_Systeme SET Valeur='%s' WHERE Nom='Adresse_ip_wifi_ap' ", ADRESSE_IP_INCONNUE);
mysql_query(bdd.pointeur, requete);
// RAZ de la liste existante des entrées AUX (utile lors d'une reconfiguration) :
entrees.aux.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_AUXILIAIRES; i ++) entrees.aux.entrees[i].flag_validite = FALSE;
// RAZ de la liste existante des entrées LEVEL SENSORS (utile lors d'une reconfiguration) :
entrees.level_sensor.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_LEVEL_SENSOR; i ++) entrees.level_sensor.entrees[i].flag_validite = FALSE;
// RAZ de la liste existante des entrées VOLTAGE (utile lors d'une reconfiguration) :
entrees.volt.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_VOLTAGE; i ++) entrees.volt.entrees[i].flag_validite = FALSE;
// RAZ de la liste existante des entrées OW (utile lors d'une reconfiguration) :
entrees.ow.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_OW; i ++) entrees.ow.entrees[i].flag_validite = FALSE;
// RAZ de la liste existante des entrées NMEA (utile lors d'une reconfiguration) :
entrees.nmea.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_NMEA; i ++) entrees.nmea.entrees[i].flag_validite = FALSE;
// RAZ de la liste existante des entrées PREDEFINIES (utile lors d'une reconfiguration) :
entrees.predefinies.nb = 0;
for (i = 0; i < MAX_NOMBRE_ENTREES_PREDEFINIES; i ++) entrees.predefinies.entrees[i].flag_validite = FALSE;
// Les entrées prédéfinies suivantes sont créées automatiquement car elles sont utilisées par des fonctions de base.
// Il faut noter qu'il est par ailleurs possible que ces entrées soient utilisées par d'autres équipements (capteurs et/ou batteries)
// comme n'importe quelle entrée prédéfinie. Dans ce cas, la même entrée physique sera routée vers plusieurs entrées prédéfinies par
// la 'commande c_bus_up_commande_etat_carte()' sans que cela ne pose de problème.
// Création de l'entrée prédéfinie IN_V (qui est utilisée quoi qu'il arrive) :
entrees.predefinies.entrees[entrees.predefinies.nb].flag_validite = TRUE;
entrees.predefinies.entrees[entrees.predefinies.nb].module = 0;
entrees.predefinies.entrees[entrees.predefinies.nb].no = ENTREE_PREDEFINIE_IN_V;
entrees.predefinies.nb ++;
// Création de l'entrée prédéfinie IN_I (qui est utilisée quoi qu'il arrive) :
entrees.predefinies.entrees[entrees.predefinies.nb].flag_validite = TRUE;
entrees.predefinies.entrees[entrees.predefinies.nb].module = 0;
entrees.predefinies.entrees[entrees.predefinies.nb].no = ENTREE_PREDEFINIE_IN_I;
entrees.predefinies.nb ++;
// Création de l'entrée prédéfinie USB_V (qui est utilisée quoi qu'il arrive) :
entrees.predefinies.entrees[entrees.predefinies.nb].flag_validite = TRUE;
entrees.predefinies.entrees[entrees.predefinies.nb].module = 0;
entrees.predefinies.entrees[entrees.predefinies.nb].no = ENTREE_PREDEFINIE_USB_I;
entrees.predefinies.nb ++;
// ********************************************************************************************************************************************************
// MODULES
//
// NB : Une partie importante de la configuration des modules se fait dans la fonction 'enregistrement_annuaire_k_bus()' appelée
// après avoir récupéré la commande ANNUAIRE auprès du Compagnon. Cf Commentaire dans 'enregistrement_annuaire_k_bus()' pour plus d'explications.
// ********************************************************************************************************************************************************
// SDIR #300 :
// Mise à jour depuis la BDD de l'adresse MAC de ShipBase en attendant qu'elle soit remise à jour via le retour de 'annuaire_k_bus' :
for (i=0; i<TAILLE_ADRESSE_MAC; i++) systeme.modules_physiques[0].adresse_mac[i] = 0; // Valeur par défaut qui permet d'avoir une valeur connue même quand on démarre après un Factory Reset (TB_Modules_physiques est vide !)
sprintf(requete, "SELECT Adresse_mac FROM TB_Modules_physiques WHERE Adresse_k_bus=0 ");
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
{
conversion_chaine_adresse_mac(row[0], systeme.modules_physiques[0].adresse_mac);
}
mysql_free_result(result); //Libération du jeu de résultat
// Fin de SDIR #300
//----------------------------------------------
// Modules physiques :
// Mise à 0 des flags de la structure 'modules_physiques' (utile pour les reconfig à chaud !) :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
systeme.modules_physiques[i].type = -1; // Marqueur utilisé pour vérifier que la config de la carte a bien été téléchargée.
systeme.modules_physiques[i].flag_presence = FALSE;
}
// Mise à 0 des flags de présence dans la BDD :
sprintf(requete, "UPDATE TB_Modules_physiques SET Presence=0 ");
mysql_query(bdd.pointeur, requete);
//----------------------------------------------
// Modules config :
// Mise à 0 des flags de la structure 'modules' (utile pour les reconfig à chaud !) :
for (i = 0; i < MAX_NOMBRE_MODULES; i ++)
{
systeme.modules_config[i].type = -1;
systeme.modules_config[i].flag_validite = FALSE; // Mise à jour ci-dessous dès que le module apparait dans TB_Modules_config (permet juste de ne pas traiter dans le tableau les modules non référencés en BDD)
systeme.modules_config[i].flag_presence = FALSE; // Sera mis à jour après réception de l'annuaire K-Bus (présence d'un module physique du même type à cette adresse)
systeme.modules_config[i].flag_affecte = FALSE; // Mis à jour ci-dessous via une requête sur les Circuits, Batteries, Réservoirs et Capteurs.
}
// Mise à 0 des flags de présence dans la BDD :
sprintf(requete, "UPDATE TB_Modules_config SET Presence=0 ");
mysql_query(bdd.pointeur, requete);
// Mise à jour du champ Affecté de toutes les entrées de TB_Modules_config :
// On commence par les mettre tous à 0 :
sprintf(requete, "UPDATE TB_Modules_config SET Affecte=0; ");
mysql_query(bdd.pointeur, requete);
// Avant de positionner à 1 tous les modules qui ont au moins un élément affecté dessus :
sprintf(requete, "UPDATE TB_Modules_config SET Affecte=1 WHERE Adresse_k_bus IN ");
strcat(requete, " ( ");
strcat(requete, " SELECT DISTINCT Adresse_module AS Adresse_k_bus FROM TB_Circuits "); // Attention : l'ajout de () autour de la ligne génère une erreur sur le UNION...
strcat(requete, " UNION ");
strcat(requete, " SELECT DISTINCT Adresse_module AS Adresse_k_bus FROM TB_Batteries ");
strcat(requete, " UNION ");
strcat(requete, " SELECT DISTINCT Adresse_module AS Adresse_k_bus FROM TB_Capteurs ");
strcat(requete, " UNION ");
strcat(requete, " SELECT DISTINCT Adresse_module AS Adresse_k_bus FROM TB_Reservoirs ");
strcat(requete, " ) ");
//printf("Requete = [ %s; ]\n", requete);
mysql_query(bdd.pointeur, requete);
// Remplissage de la structure 'modules_config' à partir de TB_Modules_config :
sprintf(requete, "SELECT Adresse_k_bus, Type, ID_Batterie, Affecte FROM TB_Modules_config ORDER BY Adresse_k_bus");
//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
{
i = atoi(row[0]); // Adresse k_bus
if (i < MAX_NOMBRE_MODULES)
{
systeme.modules_config[i].flag_validite = TRUE;
systeme.modules_config[i].type = atoi(row[1]);
systeme.modules_config[i].id_batterie = atoi(row[2]);
systeme.modules_config[i].flag_affecte = atoi(row[3]);
// Le fait que le module soit Présent ou pas, doit attendre la réception de la commande Annuaire du Compagnon...
}
}
mysql_free_result(result); //Libération du jeu de résultat
// ********************************************************************************************************************************************************
// CIRCUITS
// ********************************************************************************************************************************************************
//-------------------------------------------------------------
// Patch pour passage à version >= 3.0.13 :
// Supprimé en 06/2026, au passage à la V4.0.0.
// Fin du patch
//-------------------------------------------------------------
// Init par défaut de toutes les variables de circuits de l'appli :
for (i = 0; i < MAX_NOMBRE_CIRCUITS; i ++)
{
circuits.circuits[i].flag_validite = FALSE; // Valeur par défaut
circuits.circuits[i].etat_systeme = ERREUR_SYSTEME_AUCUNE; // Valeur par défaut
}
// Mise à jour des IDs de variables utilisées par les circuits :
sprintf(requete, "SELECT Code, Cle_primaire, Marge FROM TB_Variables WHERE Code LIKE 'Circ_%%' ");
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 (strcmp(row[0], "Circ_consigne") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_CONSIGNE].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_CONSIGNE].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_tension") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_TENSION].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_TENSION].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_courant") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_COURANT].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_COURANT].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_frequence") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_FREQUENCE].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_FREQUENCE].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_puissance") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_PUISSANCE].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_PUISSANCE].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_energie") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_ENERGIE].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_ENERGIE].marge = atof(row[2]);
}
else if (strcmp(row[0], "Circ_tension_secteur") == 0)
{
circuits.variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].cle_primaire = atoi(row[1]);
circuits.variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].marge = atof(row[2]);
}
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à 0 de Etat_systeme de toutes les batteries par défaut.
// La remise à une autre valeur sera éventuellement faite :
// - en fin de cette fonction si la configuration n'est pas cohérente et ne peut être exploitée
// - dans 'bdd_fonctions.c', dans 'enregistrement_annuaire_k_bus()', si le module auquel est affecté cette batterie n'est pas pas présent (module physique absent ou pas du bon type)
sprintf(requete, "UPDATE TB_Circuits SET Etat_systeme=0");
mysql_query(bdd.pointeur, requete);
// Récupération de la configuration des circuits :
i = 0;
sprintf(requete, "SELECT Cle_primaire, Adresse_module, No_circuit, ID_Circuit_esclave, Mode_commande, Etat, Mode_test, Consigne, \
Tension, Intensite, Frequence, Tension_coeff_filtrage, Intensite_coeff_filtrage, Frequence_coeff_filtrage, \
Intensite_seuil_haut, Intensite_seuil_haut_tempo, Step_time, T_on, T_off, Time_out, Validation_cdes_events, \
Mode_enregistrement_mesures, Mode_enregistrement_historique \
FROM TB_Circuits ORDER BY Adresse_module, No_circuit"); // On ne récupère PAS les circuits NON AFFECTES (non valides)
// 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
{
// Vérification que le nombre de circuits n'est pas trop important :
if (i >= MAX_NOMBRE_CIRCUITS)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de circuits valides dans la Base de Données (TB_Circuits) est trop important (MAX = %i)...!", MAX_NOMBRE_CIRCUITS);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// Traiter ce cas avec un message d'alerte user ????
break; // On arrête l'init des circuits mais on continue l'initialisation...
}
// Stokage des valeurs lues :
circuits.circuits[i].flag_validite = TRUE; // Valeur par défaut
j = 0; // Permet l'insertion plus facile d'un champs par la suite..! Ne pas oublier de l'incrémenter correctement à chaque étape !!
//---------------------------------------
// Clé primaire :
//---------------------------------------
circuits.circuits[i].cle_primaire = atoi(row[j ++]); // ATTENTION : dans les lignes suivantes, on alterne entre 'atoi()' et 'atof()' en fonction du type de variable. Prendre garde lors des copier/coller !!
//---------------------------------------
// Adresse de module :
//---------------------------------------
val_16 = atoi(row[j ++]); // On prend en compte les circuits 'non affectés' qui arrivent avec un numéro de module = -1
if ((val_16 < 0) || (val_16 >= MAX_NOMBRE_MODULES))
{
// Message d'erreur :
if (val_16 < 0)
{
sprintf(tmp, "Le circuit n° %i (Cle_primaire = %i) dans TB_Circuits est Non Affecté (Adresse_module = %i). Le circuit est dévalidé.", i, circuits.circuits[i].cle_primaire, val_16);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le numéro de module du circuit n° %i (Cle_primaire = %i) dans TB_Circuits est trop élevé (%i, MAX = %i). Le circuit est dévalidé.", i, circuits.circuits[i].cle_primaire, val_16, MAX_NOMBRE_MODULES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
circuits.circuits[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
else circuits.circuits[i].adresse_module = val_16;
//---------------------------------------
// N° de circuit sur le module :
//---------------------------------------
circuits.circuits[i].no_circuit = atoi(row[j ++]);
//---------------------------------------
// ID Circuit esclave :
//---------------------------------------
circuits.circuits[i].id_circuit_esclave = atoi(row[j ++]); // NB : on ne peut pas calculer ici le 'no_circuit_esclave' car toutes les clés primaires n'ont pas été enregistrées...
//---------------------------------------
// Mode de commande :
//---------------------------------------
circuits.circuits[i].mode_cde = atoi(row[j ++]);
//---------------------------------------
// Etat :
//---------------------------------------
circuits.circuits[i].etat = atoi(row[j ++]);
//---------------------------------------
// Mode test :
//---------------------------------------
circuits.circuits[i].mode_test = atoi(row[j ++]);
//---------------------------------------
// Consigne :
//---------------------------------------
circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].valeur_bdd = atoi(row[j ++]);
//---------------------------------------
// Tension :
//---------------------------------------
if (systeme.modules_config[circuits.circuits[i].adresse_module].type != TYPE_CARTE_SP4AC) circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_bdd = atof(row[j ++]);
else circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Intensité :
//---------------------------------------
circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Fréquence :
//---------------------------------------
circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Tension coeff filtrage :
//---------------------------------------
circuits.circuits[i].tension_coeff_filtrage = atoi(row[j ++]);
//---------------------------------------
// Intensité coeff filtrage :
//---------------------------------------
circuits.circuits[i].intensite_coeff_filtrage = atoi(row[j ++]);
//---------------------------------------
// Fréquence coeff filtrage :
//---------------------------------------
circuits.circuits[i].frequence_coeff_filtrage = atoi(row[j ++]);
//---------------------------------------
// Intensité seuil haut :
//---------------------------------------
circuits.circuits[i].intensite_seuil_haut = atof(row[j ++]);
//---------------------------------------
// Intensité seuil haut tempo :
//---------------------------------------
circuits.circuits[i].intensite_seuil_haut_tempo = atoi(row[j ++]);
//---------------------------------------
// Step Time :
//---------------------------------------
circuits.circuits[i].step_time = atoi(row[j ++]);
//---------------------------------------
// Ton :
//---------------------------------------
circuits.circuits[i].t_on = atoi(row[j ++]);
//---------------------------------------
// Toff :
//---------------------------------------
circuits.circuits[i].t_off = atoi(row[j ++]);
//---------------------------------------
// Time-out :
//---------------------------------------
circuits.circuits[i].time_out = atoi(row[j ++]);
//---------------------------------------
// Validation Commandes Events :
//---------------------------------------
val_8 = atoi(row[j ++]);
if ((val_8 != CIRCUIT_VALIDATION_COMMANDES_EVENTS_OFF) && (val_8 != CIRCUIT_VALIDATION_COMMANDES_EVENTS_ON))
{
sprintf(tmp, "La validation des commandes par évènements du circuit n° %i (Cle_primaire = %i) dans la Base de Données (TB_Circuits) est hors limite (%i pour 0 ou 1). Le circuit est laissé valide MAIS son Validation_cdes_event est arbitrairement fixé à %i.", i, circuits.circuits[i].cle_primaire, val_8, CIRCUIT_VALIDATION_COMMANDES_EVENTS_ON);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
val_8 = CIRCUIT_VALIDATION_COMMANDES_EVENTS_ON;
}
circuits.circuits[i].validation_cdes_events = val_8;
//---------------------------------------
// Enregistrement mesures :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT)
{
sprintf(tmp, "Le mode d'enregistrement des mesures du circuit n° %i (Cle_primaire = %i) dans la Base de Données (TB_Circuits) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement des mesures est arbitrairement fixé à %i.", i, circuits.circuits[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT, MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
val_u8 = MODE_ENREGISTREMENT_MESURES_PERIODIQUE; // Valeur arbitraire correspondant à aucun enregistrement des mesures. NB : on considère que ce n'est pas une raison pour dévalider le capteur mais on pourrait tout aussi bien le faire ici...
}
circuits.circuits[i].mode_enregistrement_mesures = val_u8;
//---------------------------------------
// Enregistrement historique :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_HISTORIQUE_NORMAL)
{
sprintf(tmp, "Le mode d'enregistrement de l'historique du circuit n° %i (Cle_primaire = %i) dans la Base de Données (TB_Circuits) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement d'historique est arbitrairement fixé à %i.", i, circuits.circuits[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_HISTORIQUE_NORMAL, MODE_ENREGISTREMENT_HISTORIQUE_NORMAL);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
val_u8 = MODE_ENREGISTREMENT_HISTORIQUE_NORMAL;
}
circuits.circuits[i].mode_enregistrement_historique = val_u8;
//===================================================================================================
// Vérification de la cohérence de la configuration du circuit avec le module auquel il est affecté :
//===================================================================================================
flag_erreur = false;
switch (systeme.modules_config[circuits.circuits[i].adresse_module].type)
{
//-----------------------
case TYPE_CARTE_SHIPBASE:
{
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
{
// Cas particulier du port USB arrière absent des V1 et présent dans la config usine commune aux 2 versions :
if (circuits.circuits[i].no_circuit == SB_CIRCUIT_NO_USB_ARRIERE)
{
sprintf(requete, "DELETE FROM TB_Circuits WHERE Cle_primaire='%i' ", circuits.circuits[i].cle_primaire); // Dans le cas d'une V1 avec le port USB arrière configuré (exemple de Factiry reset), on supprime purement et simplement l'entrée pour les fois suivantes
mysql_query(bdd.pointeur, requete);
sprintf(tmp, "La configuration contenait un port USB Arrière alors que l'on est sur une V1. Le circuit est supprimé de TB_Circuits (clé primaire = %i) et dévalidé pour l'exécution en cours.", circuits.circuits[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
// circuits.circuits[i].flag_validite = FALSE; // Le circuit est dévalidé pour cette exécution là (plus simple)
circuits.circuits[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
}
// Test du n° de circuit :
if (circuits.circuits[i].no_circuit >= MAX_CIRCUITS_PAR_MODULE_SHIPBASE_V2)
{
printf("N° de circuit = %i alors que MAX ShipBase = 2\n", circuits.circuits[i].no_circuit);
flag_erreur = true;
break;
}
// Cas particulier des ports USB sur ShipBase :
if (circuits.circuits[i].no_circuit == SB_CIRCUIT_NO_USB_AVANT) usb.no_circuit_usb_avant = i;
else if (circuits.circuits[i].no_circuit == SB_CIRCUIT_NO_USB_ARRIERE) usb.no_circuit_usb_arriere = i;
// Forçage des paramètres qui n'ont qu'une valeur admissible (plus rapide...) :
circuits.circuits[i].id_circuit_esclave = 0;
circuits.circuits[i].mode_cde = CIRCUITS_MODE_COMMANDE_ON_OFF;
break;
}
//-----------------------
case TYPE_CARTE_SP812:
case TYPE_CARTE_SP8DC:
{
if (circuits.circuits[i].no_circuit >= MAX_CIRCUITS_PAR_MODULE_SP8XX)
{
printf("N° de circuit = %i alors que MAX SP8XXX = 7\n", circuits.circuits[i].no_circuit);
flag_erreur = true;
break;
}
break;
}
//-----------------------
case TYPE_CARTE_SP4AC:
{
if (circuits.circuits[i].no_circuit >= MAX_CIRCUITS_PAR_MODULE_SP4AC)
{
printf("N° de circuit = %i alors que MAX ShipBase = 3\n", circuits.circuits[i].no_circuit);
flag_erreur = true;
break;
}
// Forçage des paramètres qui n'ont qu'une valeur admissible (plus rapide...) :
circuits.circuits[i].id_circuit_esclave = 0;
break;
}
//-----------------------
case TYPE_CARTE_SBS:
case TYPE_CARTE_INCONNU:
default:
{
printf("Ciruit affecté à un module de type %i \n", systeme.modules_config[circuits.circuits[i].adresse_module].type);
flag_erreur = true;
break;
}
}
if (flag_erreur)
{
sprintf(tmp, "Le circuit n° %i (Cle_primaire = %i) dans TB_Circuits contient des paramètres non compatibles avec le module auquel il est affecté. Le circuit est dévalidé.", i, circuits.circuits[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// circuits.circuits[i].flag_validite = FALSE; // Le circuit est dévalidé pour cette exécution là (plus simple)
circuits.circuits[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
//================================================================
// Traitements non directement liés au retour de la requête en BDD :
//================================================================
// ID Batterie :
circuits.circuits[i].id_batterie = systeme.modules_config[circuits.circuits[i].adresse_module].id_batterie;
//================================================================
// Mise à jour des valeurs courantes (SDIR #188) :
//================================================================
// Initialisation des valeurs courantes à partir des valeurs de BDD (évite de repartir à 0 mais plutôt de la dernière valeur connue) :
circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].valeur_bdd;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_bdd;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_bdd;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].valeur_bdd;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_PUISSANCE].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_bdd * circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_bdd;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].valeur_courante = circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].valeur_bdd;
// SDIR #174 :
// circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].valeur_courante;
// circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].cumul = 0;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_courante;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].cumul = 0;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_courante;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].cumul = 0;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].valeur_courante;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].cumul = 0;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_PUISSANCE].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_PUISSANCE].valeur_courante;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_PUISSANCE].cumul = 0;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].last_mesure = circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].valeur_courante;
circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION_SECTEUR].cumul = 0;
circuits.circuits[i].cumuls_nb_val = 0;
/*printf("Circuit %i : ----------------------------------------------------------\n", i);
printf("Clé=%i, adresse_module=%i, No_circuit=%i, ID_Circuit_esclave=%i, Mode_cde=%i, Etat=%i, Mode_test=%i, Consigne=%.2f, \
Tension=%.3f, Intensité=%.3f, Fréq=%.3f, Tension_filtrage=%i, Intensite_filtrage=%i, Freq_filtrage=%i, \
Intensité_seuil_haut=%.3f, Intensité_seuil_hau_tempo=%i, Step_time=%i, T_on=%i, Toff=%i, Time_out=%i, Mode_mesures=%i, Mode_historique=%i \n",
circuits.circuits[i].cle_primaire, circuits.circuits[i].adresse_module, circuits.circuits[i].no_circuit,
circuits.circuits[i].id_circuit_esclave, circuits.circuits[i].mode_cde, circuits.circuits[i].etat, circuits.circuits[i].mode_test,
circuits.circuits[i].variables[CIRCUIT_VARIABLE_CONSIGNE].valeur_bdd, circuits.circuits[i].variables[CIRCUIT_VARIABLE_TENSION].valeur_bdd,
circuits.circuits[i].variables[CIRCUIT_VARIABLE_COURANT].valeur_bdd, circuits.circuits[i].variables[CIRCUIT_VARIABLE_FREQUENCE].valeur_bdd,
circuits.circuits[i].tension_coeff_filtrage, circuits.circuits[i].intensite_coeff_filtrage, circuits.circuits[i].frequence_coeff_filtrage,
circuits.circuits[i].intensite_seuil_haut, circuits.circuits[i].intensite_seuil_haut_tempo, circuits.circuits[i].step_time, circuits.circuits[i].t_on,
circuits.circuits[i].t_off, circuits.circuits[i].time_out, circuits.circuits[i].mode_enregistrement_mesures, circuits.circuits[i].mode_enregistrement_historique);
*/
i++; // Circuit suivant
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à jour des paramètres nécessitant d'avoir tous les circuits configurés :
circuits.nb = i;
for (i = 0; i < circuits.nb; i ++)
{
if (! circuits.circuits[i].flag_validite) continue;
circuits.circuits[i].no_circuit_esclave = circuit_cle_primaire(circuits.circuits[i].id_circuit_esclave);
}
// ********************************************************************************************************************************************************
// CAPTEURS
// ********************************************************************************************************************************************************
// Init par défaut de toutes les variables de capteurs de l'appli :
for (i = 0; i < MAX_NOMBRE_CAPTEURS; i ++)
{
capteurs.capteurs[i].flag_validite = FALSE; // Valeur par défaut
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_AUCUNE; // Valeur par défaut
capteurs.capteurs[i].nb_entrees = 0;
for (j = 0; j < MAX_NOMBRE_CONDITIONS_PAR_CAPTEUR; j ++) capteurs.capteurs[i].conditions.conditions[j].flag_validite = FALSE;
}
// Mise à jour des IDs de variables utilisées par les capteurs :
sprintf(requete, "SELECT Code, Cle_primaire, Marge FROM TB_Variables WHERE Code LIKE 'Capt_%%' ");
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 (strcmp(row[0], "Capt_sans_unite") == 0) { capteurs.variables[CAPTEUR_VARIABLE_SANS_UNITE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_SANS_UNITE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_tension_v") == 0) { capteurs.variables[CAPTEUR_VARIABLE_TENSION_V].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_TENSION_V].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_tension_mv") == 0) { capteurs.variables[CAPTEUR_VARIABLE_TENSION_MV].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_TENSION_MV].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_courant_a") == 0) { capteurs.variables[CAPTEUR_VARIABLE_COURANT_A].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_COURANT_A].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_courant_ma") == 0) { capteurs.variables[CAPTEUR_VARIABLE_COURANT_MA].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_COURANT_MA].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_puissance_w") == 0) { capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_W].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_W].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_puissance_va") == 0) { capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_VA].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_VA].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_puissance_db") == 0) { capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_DB].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_PUISSANCE_DB].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_frequence") == 0) { capteurs.variables[CAPTEUR_VARIABLE_FREQUENCE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_FREQUENCE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_resistance") == 0) { capteurs.variables[CAPTEUR_VARIABLE_RESISTANCE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_RESISTANCE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_temperature") == 0) { capteurs.variables[CAPTEUR_VARIABLE_TEMPERATURE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_TEMPERATURE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_pression_atm") == 0) { capteurs.variables[CAPTEUR_VARIABLE_PRESSION_ATM].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_PRESSION_ATM].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_humidite") == 0) { capteurs.variables[CAPTEUR_VARIABLE_HUMIDITE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_HUMIDITE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_acceleration") == 0) { capteurs.variables[CAPTEUR_VARIABLE_ACCELERATION].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_ACCELERATION].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_position") == 0) { capteurs.variables[CAPTEUR_VARIABLE_POSITION].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_POSITION].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_pourcentage") == 0) { capteurs.variables[CAPTEUR_VARIABLE_POURCENTAGE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_POURCENTAGE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_distance_m") == 0) { capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_M].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_M].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_distance_km") == 0) { capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_KM].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_KM].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_distance_nq") == 0) { capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_NQ].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_DISTANCE_NQ].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_vitesse_kts") == 0) { capteurs.variables[CAPTEUR_VARIABLE_VITESSE_KTS].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_VITESSE_KTS].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_vitesse_kmh") == 0) { capteurs.variables[CAPTEUR_VARIABLE_VITESSE_KMH].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_VITESSE_KMH].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_angle_degres") == 0) { capteurs.variables[CAPTEUR_VARIABLE_ANGLE_DEGRES].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_ANGLE_DEGRES].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_latitude") == 0) { capteurs.variables[CAPTEUR_VARIABLE_LATITUDE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_LATITUDE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_longitude") == 0) { capteurs.variables[CAPTEUR_VARIABLE_LONGITUDE].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_LONGITUDE].marge = atof(row[2]); }
else if (strcmp(row[0], "Capt_volume") == 0) { capteurs.variables[CAPTEUR_VARIABLE_VOLUME].cle_primaire = atoi(row[1]); capteurs.variables[CAPTEUR_VARIABLE_VOLUME].marge = atof(row[2]); }
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à 0 de Etat_systeme de tous les capteurs par défaut.
// La remise à une autre valeur sera éventuellement faite :
// - en fin de cette fonction si la configuration n'est pas cohérente et ne peut être exploitée
// - dans 'bdd_fonctions.c', dans 'enregistrement_annuaire_k_bus()', si le module auquel est affecté ce capteur n'est pas pas présent (module physique absent ou pas du bon type)
sprintf(requete, "UPDATE TB_Capteurs SET Etat_systeme=0");
mysql_query(bdd.pointeur, requete);
// Récupération de la configuration des capteurs :
i = 0;
sprintf(requete, "SELECT Cle_primaire, Adresse_module, Type_entrees, Entrees, Mode_entrees, ID_Variable, Etat, Decalage, Gain, Valeur, \
Valeur_coeff_filtrage, Mode_enregistrement_mesures, Mode_enregistrement_historique \
FROM TB_Capteurs ORDER BY Type_entrees, Cle_primaire");
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
{
// Vérification que le nombre de capteur n'est pas trop important :
if (i == MAX_NOMBRE_CAPTEURS)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de capteurs valides dans la Base de Données (TB_Capteurs) est trop important (MAX = %i)...!", MAX_NOMBRE_CAPTEURS);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// return(-1);
// Traiter ce cas avec un message d'alerte user ????
break; // On arrête l'init des capteurs là mais on continue l'initialisation...
}
// Stockage des valeurs lues :
j = 0; // Permet l'insertion plus facile d'un champs par la suite..! Ne pas oublier de l'incrémenter correctement à chaque étape !!
capteurs.capteurs[i].flag_validite = TRUE; // On en est sûr puisque le filtre SQL est basé là-dessus...
//---------------------------------------
// Clé primaire :
//---------------------------------------
capteurs.capteurs[i].cle_primaire = atoi(row[j ++]); // ATTENTION : dans les lignes suivantes, on alterne entre 'atoi()' et 'atof()' en fonction du type de variable. Prendre garde lors des copier/coller !!
//---------------------------------------
// Adresse de module :
//---------------------------------------
val_16 = atoi(row[j ++]); // On prend en compte les capteur 'non affectés' qui arrivent avec un numéro de module = -1 (pas encore utilisé en 06/2026)
if ((val_16 < 0) || (val_16 >= MAX_NOMBRE_MODULES))
{
// Message d'erreur :
if (val_16 < 0)
{
sprintf(tmp, "Le capteur n° %i (Cle_primaire = %i) dans TB_Capteurs est Non Affecté (Adresse_module = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, val_16);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le numéro de module du capteur n° %i (Cle_primaire = %i) dans TB_Capteurs est trop élevé (%i, MAX = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, val_16, MAX_NOMBRE_MODULES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
else capteurs.capteurs[i].adresse_module = val_16;
//---------------------------------------
// Type d'entrées :
//---------------------------------------
val_u8 = atoi(row[j ++]);
switch(val_u8)
{
case TYPE_ENTREES_AUXILIAIRES :
case TYPE_ENTREES_LEVEL_SENSOR :
case TYPE_ENTREES_VOLTAGE :
case TYPE_ENTREES_OW :
case TYPE_ENTREES_PREDEFINIES :
// case TYPE_ENTREES_IBS :
case TYPE_ENTREES_NMEA :
// case TYPE_ENTREES_CAN :
case TYPE_ENTREES_CALCULEE_BOOLEEN :
// case TYPE_ENTREES_CALCULEE_NUMERIQUE :
{
capteurs.capteurs[i].type_entrees = val_u8;
break;
}
default :
{
sprintf(tmp, "Le capteur n° %i (clé primaire = %i) dans la Base de Données (TB_Capteurs) a une configuration de 'Type_entrees' invalide (valeur = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
}
//---------------------------------------
// Entrées :
//---------------------------------------
if (row[j][0] != 0) // Si le champ "Entrees" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';' ATTENTION : si aucun délimiteur trouvé, la fonction renvoit la chaine entière (et pas NULL...)
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
// Calcul du nombre maxi d'entrées, selon le type de capteur :
uint16_t max_entrees = MAX_NOMBRE_ENTREES_PAR_CAPTEUR;
if (capteurs.capteurs[i].type_entrees == TYPE_ENTREES_CALCULEE_BOOLEEN) max_entrees = MAX_NOMBRE_CONDITIONS_PAR_CAPTEUR;
// Check du nombre d'entrées trouvées :
if (k > max_entrees)
{
// Message d'erreur :
sprintf(tmp, "Le nombre d'entrées du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est trop important (MAX = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, max_entrees);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
// Traitement des entrées trouvées selon la valeur de 'type_entrees' :
switch(capteurs.capteurs[i].type_entrees)
{
//....................................................................................................................
case TYPE_ENTREES_AUXILIAIRES :
{
for (m = 0; m < k; m ++) // Nb : on a déjà vérifié que k < MAX_NOMBRE_ENTREES_PAR_CAPTEUR
{
val_u8 = atoi(ptr[m]);
// Mise à jour des variables d'entrées :
if (entrees.aux.nb < MAX_NOMBRE_ENTREES_AUXILIAIRES)
{
// Mise à jour de l'entrée correspondante :
entrees.aux.entrees[entrees.aux.nb].flag_validite = TRUE;
entrees.aux.entrees[entrees.aux.nb].module = capteurs.capteurs[i].adresse_module;
entrees.aux.entrees[entrees.aux.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[m] = entrees.aux.nb;
entrees.aux.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées AUX est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_AUXILIAIRES, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
break; // Sort de la boucle FOR
}
}
if (m < k) // Une erreur a été détectée dans la boucle des numéros d'entrées (le message d'erreur a été émis ci-dessus)
{
i ++;
continue;
}
capteurs.capteurs[i].nb_entrees = m;
break;
}
//....................................................................................................................
case TYPE_ENTREES_LEVEL_SENSOR :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (%i pour 1 autorisé). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée
// Mise à jour des variables d'entrées :
if (entrees.level_sensor.nb < MAX_NOMBRE_ENTREES_LEVEL_SENSOR)
{
// Mise à jour de l'entrée correspondante :
entrees.level_sensor.entrees[entrees.level_sensor.nb].flag_validite = TRUE;
entrees.level_sensor.entrees[entrees.level_sensor.nb].module = capteurs.capteurs[i].adresse_module;
entrees.level_sensor.entrees[entrees.level_sensor.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[0] = entrees.level_sensor.nb;
capteurs.capteurs[i].nb_entrees = 1;
entrees.level_sensor.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées LEVEL SENSOR est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_LEVEL_SENSOR, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_VOLTAGE :
{
if (k != 1)
{
sprintf(tmp, "Le nombre de paramètres 'Entrees' du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (%i pour 1 autorisé). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée
// Mise à jour des variables d'entrées :
if (entrees.volt.nb < MAX_NOMBRE_ENTREES_VOLTAGE)
{
// Mise à jour de l'entrée correspondante :
entrees.volt.entrees[entrees.volt.nb].flag_validite = TRUE;
entrees.volt.entrees[entrees.volt.nb].module = capteurs.capteurs[i].adresse_module;
entrees.volt.entrees[entrees.volt.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[0] = entrees.volt.nb;
capteurs.capteurs[i].nb_entrees = 1;
entrees.volt.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées VOLTAGE est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_VOLTAGE, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_OW :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (%i pour 1 autorisé). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
// val_u8 = atoi(ptr[0]); // On ne peut pas calculer ici le n° d'entre OW car elle n'est pas encore connue... On stocke la clé_primaire de TB_One_wire et on fera le lien avec le n° d'entrée à la volée.
// Mise à jour des variables d'entrées :
if (entrees.ow.nb < MAX_NOMBRE_ENTREES_OW)
{
if (strlen(ptr[0]) < (TAILLE_ROM_CODE_OW * 3))
{
// Mise à jour de l'entrée correspondante :
entrees.ow.entrees[entrees.ow.nb].flag_validite = TRUE;
strcpy(entrees.ow.entrees[entrees.ow.nb].rom_code, ptr[0]);
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[0] = entrees.ow.nb;
capteurs.capteurs[i].nb_entrees = 1;
entrees.ow.nb ++;
}
else
{
sprintf(tmp, "Le champ Entrees du capteur n° %i (Cle_primaire = %i) est trop important (max = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, (TAILLE_ROM_CODE_OW * 3));
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
}
else
{
sprintf(tmp, "Le nombre d'entrées OW est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_OW, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_PREDEFINIES :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (%i pour 1 autorisé). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée prédéfinie (cf liste dans .id_entrees.h'))
// Mise à jour des variables d'entrées :
if (entrees.predefinies.nb < MAX_NOMBRE_ENTREES_PREDEFINIES)
{
// Mise à jour de l'entrée correspondante :
entrees.predefinies.entrees[entrees.predefinies.nb].flag_validite = TRUE;
entrees.predefinies.entrees[entrees.predefinies.nb].module = capteurs.capteurs[i].adresse_module;
entrees.predefinies.entrees[entrees.predefinies.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[0] = entrees.predefinies.nb;
capteurs.capteurs[i].nb_entrees = 1;
entrees.predefinies.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées PREDEFINIES est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_PREDEFINIES, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
// case TYPE_ENTREES_IBS :
//....................................................................................................................
case TYPE_ENTREES_NMEA :
{
if (k != 1)
{
sprintf(tmp, "Le nombre de paramètres 'Entrees' du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (%i pour 1 autorisé). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
//-------------------
// PGN :
ptr_val = strtok (ptr[0],":"); // Extraction du premier segment avant le ':'
if (ptr_val == NULL) break;
val_u32 = atoi(ptr_val);
//-------------------
// Field :
ptr_val = strtok (NULL, ":"); // Extraction du deuxieme segment après le ':'
if (ptr_val == NULL) break;
val_u8 = atoi(ptr_val);
// Mise à jour des variables d'entrées :
if (entrees.nmea.nb < MAX_NOMBRE_ENTREES_NMEA)
{
// Mise à jour de l'entrée correspondante :
entrees.nmea.entrees[entrees.nmea.nb].flag_validite = TRUE;
entrees.nmea.entrees[entrees.nmea.nb].module = capteurs.capteurs[i].adresse_module;
entrees.nmea.entrees[entrees.nmea.nb].pgn = val_u32;
entrees.nmea.entrees[entrees.nmea.nb].field = val_u8;
// Mise à jour du n° d'entrée du capteur :
capteurs.capteurs[i].no_entrees[0] = entrees.nmea.nb;
capteurs.capteurs[i].nb_entrees = 1;
entrees.nmea.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées NMEA est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_NMEA, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_CAN :
{
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
break;
}
//....................................................................................................................
case TYPE_ENTREES_CALCULEE_BOOLEEN :
{
// liste de conditions [validite/type_condition/type_source:id_source/id_variable/test/seuil], séparées par des [;] si plusieurs conditions.
// A noter que le séparateur entre [type_source] et [id_source] n'est pas un '/' mais un ':'. Cela permet avec une simple requête de retrouver ces deux champs (ou un seul des deux)
// Avec :
// [type_condition] : 0=condition normale, >0=début de groupe de conditions avec l\'opérateur suivant : 1=Ou, 2=Et, 3=Ou Exclusif, 10=Plus, 11=Moins, 12=Multiplié, 13=Divisé, <0=fin de groupe de conditions (même valeurs que début mais en négatif) ;
// [type_source] : 0=Non défini, 1=circuit, 2=capteur, 3=réservoir, 4=batterie ;
// [id_source] : Clé primaire dans TB_[Source] ;
// [id_variable] : Clé primaire dans TB_Variables indiquant la variable concernée dans ID_Source ;
// [test] : 0=Non défini, 1=strictement inférieure au seuil, 2=inférieure ou égale au seuil, 3=égale au seuil, 4=supérieure ou égale au seuil, 5= strictement supérieure au seuil ;
// [seuil] : valeur, exprimée en unités de l\'ID_Variable.
capteurs.capteurs[i].nb_entrees = 0;
for (m = 0; m < k; m ++) // Nb : on a déjà vérifié que k <= MAX_NOMBRE_CONDITIONS_PAR_CAPTEUR
{
//-------------------
// Validite :
ptr_val = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].flag_validite = atoi(ptr_val);
//-------------------
// Type condition :
ptr_val = strtok (NULL, "/"); // Extraction du deuxieme segment après le premier '/'
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].type_condition = atoi(ptr_val);
//-------------------
// Type source :
ptr_val = strtok (NULL, ":"); // Extraction du 3ème segment après le 2ème '/' et avant le ':'. ATTENTION : séparateur = ':' !!
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].type_source = atoi(ptr_val);
//-------------------
// ID Source :
ptr_val = strtok (NULL, "/"); // Extraction du 4ème segment après le ':' et avant le '/' suivant
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].id_source = atoi(ptr_val);
//-------------------
// ID Variable :
ptr_val = strtok (NULL, "/"); // Extraction du 5ème segment après le '/' et avant le '/' suivant
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].id_variable = atoi(ptr_val);
//-------------------
// Test :
ptr_val = strtok (NULL, "/"); // Extraction du 6ème segment après le '/' et avant le '/' suivant
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].test = atoi(ptr_val);
//-------------------
// Seuil :
ptr_val = strtok (NULL, "/"); // Extraction du 7ème segment après le dernier '/'
if (ptr_val == NULL) break;
capteurs.capteurs[i].conditions.conditions[capteurs.capteurs[i].nb_entrees].seuil = atof(ptr_val);
// Mise à jour du nombre de conditions et test de dépassement :
capteurs.capteurs[i].nb_entrees ++;
if (capteurs.capteurs[i].nb_entrees >= MAX_NOMBRE_CONDITIONS_PAR_CAPTEUR)
{
sprintf(tmp, "Le nombre de conditions est trop important (max = %i). Le capteur n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_CONDITIONS_PAR_CAPTEUR, i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].flag_validite = FALSE; // Le capteur est dévalidé car sa configuration ne sera pas exploitable...
break; // Sort de la boucle FOR
}
}
if (m < k) // Une erreur a été détectée dans la boucle des numéros d'entrées (le message d'erreur a été émis ci-dessus)
{
sprintf(tmp, "Le capteur n° %i (clé primaire = %i) dans la Base de Données (TB_Capteurs) a un champ 'Entrees' dont la structure est incorrecte. Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break; // Le champs 'Entrees' est systématiquement égal à "0"
}
//....................................................................................................................
case TYPE_ENTREES_CALCULEE_NUMERIQUE :
{
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
break;
}
//....................................................................................................................
default : ; // Ne devrait pas arriver car testé au § 'Type_entrees'....
}
}
else // Si le champ "Entrees" est vide :
{
sprintf(tmp, "Le capteur n° %i (clé primaire = %i) dans la Base de Données (TB_Capteurs) a un champ 'Entrees' vide. Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
j ++;
//---------------------------------------
// Mode entrées :
//---------------------------------------
val_u8 = atoi(row[j ++]);
switch(capteurs.capteurs[i].type_entrees)
{
//....................................................................................................................
case TYPE_ENTREES_AUXILIAIRES :
{
if ((val_u8 != 0) && (val_u8 != 1))
{
// Message d'erreur :
sprintf(tmp, "Le mode de fonctionnement des entrées AUX du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (valeur = %i). Le mode NORMAL (entrées Non inversées) est défini par défaut et la configuration se poursuit.", i, capteurs.capteurs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
val_u8 = 0;
}
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++)
{
entrees.aux.entrees[capteurs.capteurs[i].no_entrees[k]].logique = val_u8; // On met à jour la logique dans les entrées AUX (inutile de disposer de l'info dans le capteur)
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_LEVEL_SENSOR :
{
if ((val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_0_10V) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_500R) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_4_20MA) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_AUTO_TEST) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_DEFAUT_ISOLEMENT_MASSE) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_DEFAUT_ISOLEMENT_PLUS) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_DEFAUT_ISOLEMENT_FULL))
{
// Message d'erreur :
sprintf(tmp, "Le mode de fonctionnement de l'entrée Level Sensor du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est incorrect (valeur = %i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
entrees.level_sensor.entrees[capteurs.capteurs[i].no_entrees[0]].flag_validite = FALSE; // L'entrée est dévalidée car non utilisable
i ++;
continue;
}
entrees.level_sensor.entrees[capteurs.capteurs[i].no_entrees[0]].mode = val_u8; // On met à jour le mode dans l'entre LEVEL SENSOR (inutile de disposer de l'info dans le capteur)
break;
}
//....................................................................................................................
case TYPE_ENTREES_VOLTAGE :
case TYPE_ENTREES_OW :
case TYPE_ENTREES_PREDEFINIES :
// case TYPE_ENTREES_IBS :
case TYPE_ENTREES_NMEA :
case TYPE_ENTREES_CAN :
case TYPE_ENTREES_CALCULEE_BOOLEEN :
case TYPE_ENTREES_CALCULEE_NUMERIQUE :
default : // Ne devrait pas arriver car testé au § 'Type_entrees'....
{
break;
}
}
//---------------------------------------
// ID variable :
//---------------------------------------
capteurs.capteurs[i].id_variable = atoi(row[j ++]);
// Recherche du n° de variable correspondant :
val_16 = variable_capteur_cle_primaire(capteurs.capteurs[i].id_variable);
if (val_16 >= 0) capteurs.capteurs[i].no_variable = val_16;
else
{
capteurs.capteurs[i].flag_validite = FALSE;
sprintf(tmp, "L'ID de variable du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) ne correspond à aucune variable connue (ID_Variable=%i). Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire, capteurs.capteurs[i].id_variable);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
//---------------------------------------
// Etat :
//---------------------------------------
capteurs.capteurs[i].etat = atoi(row[j ++]);
//---------------------------------------
// Offset :
//---------------------------------------
capteurs.capteurs[i].offset = atof(row[j ++]);
//---------------------------------------
// Gain :
//---------------------------------------
capteurs.capteurs[i].gain = atof(row[j ++]);
if (capteurs.capteurs[i].gain == 0)
{
capteurs.capteurs[i].gain = 1;
sprintf(tmp, "Le gain du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est égal à 0, ce qui n'est pas autorisé. Le capteur est laissé valide MAIS son gain est arbitrairement fixé à %.3f.", i, capteurs.capteurs[i].cle_primaire, capteurs.capteurs[i].gain);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
//---------------------------------------
// Valeur :
//---------------------------------------
capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Coeff filtrage :
//---------------------------------------
val_u8 = atoi(row[j ++]); // Coeff filtrage
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider le capteur mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est hors limite (0<n). Le capteur est laissé valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, capteurs.capteurs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
capteurs.capteurs[i].valeur_coeff_filtrage = val_u8;
//---------------------------------------
// Enregistrement mesures :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT)
{
val_u8 = MODE_ENREGISTREMENT_MESURES_PERIODIQUE; // Valeur arbitraire correspondant à aucun enregistrement des mesures. NB : on considère que ce n'est pas une raison pour dévalider le capteur mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le mode d'enregistrement des mesures du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est hors limite (%i pour 0<= n <= %i). Le capteur est laissé valide MAIS son mode d'enregistrement des mesures est arbitrairement fixé à %i.", i, capteurs.capteurs[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
capteurs.capteurs[i].mode_enregistrement_mesures = val_u8;
//---------------------------------------
// Enregistrement historique :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_HISTORIQUE_NORMAL)
{
val_u8 = MODE_ENREGISTREMENT_HISTORIQUE_NORMAL;
sprintf(tmp, "Le mode d'enregistrement de l'historique du capteur n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est hors limite (%i pour 0<= n <= %i). Le capteur est laissé valide MAIS son mode d'enregistrement d'historique est arbitrairement fixé à %i.", i, capteurs.capteurs[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_HISTORIQUE_NORMAL, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
capteurs.capteurs[i].mode_enregistrement_historique = val_u8;
//===================================================================================================
// Vérification de la cohérence de la configuration du capteur :
//===================================================================================================
flag_erreur = false;
switch (systeme.modules_config[capteurs.capteurs[i].adresse_module].type)
{
//-----------------------------------------------------------------------------------------------
case TYPE_CARTE_SHIPBASE:
{
switch(capteurs.capteurs[i].type_entrees)
{
//.............................
case TYPE_ENTREES_AUXILIAIRES :
{
// Vérification que les n° d'entrées AUX sont compatibles avec un ShipBase :
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if ((entrees.aux.entrees[capteurs.capteurs[i].no_entrees[j]].no < 1) ||
(entrees.aux.entrees[capteurs.capteurs[i].no_entrees[j]].no > 32))
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.aux.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//.............................
case TYPE_ENTREES_LEVEL_SENSOR :
{
// Vérification que le ou les n° d'entrées LEVEL SENSOR sont compatibles avec un ShipBase :
// NB : a priori, une seule entrée par capteur mais permet de garder la même structure que pour les entrées AUX...
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if ((entrees.level_sensor.entrees[capteurs.capteurs[i].no_entrees[j]].no < 1) ||
(entrees.level_sensor.entrees[capteurs.capteurs[i].no_entrees[j]].no > 8))
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.level_sensor.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//.............................
case TYPE_ENTREES_VOLTAGE :
{
// Vérification que le ou les n° d'entrées VOLT sont compatibles avec un ShipBase :
// NB : a priori, une seule entrée par capteur mais permet de garder la même structure que pour les entrées AUX...
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if ((entrees.volt.entrees[capteurs.capteurs[i].no_entrees[j]].no < 1) ||
(entrees.volt.entrees[capteurs.capteurs[i].no_entrees[j]].no > 4))
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.volt.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//.............................
case TYPE_ENTREES_OW :
{
break; // Sera traité ultérieurement par 'enregistrement_annuaire_ow()'
}
//.............................
case TYPE_ENTREES_PREDEFINIES :
{
// Vérification que le n° d'entrée prédéfinie est compatible avec un ShipBase :
// NB : a priori, une seule entrée par capteur mais permet de garder la même structure que pour les entrées AUX...
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if ((entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_PAT) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_HUM) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_TEMP) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_LAT) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_LON) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_IN_V) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_IN_I) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_USB_I) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_ACC_XYZ) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_ACC_X) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_ACC_Y) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_ACC_Z) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_ALT) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_SOG) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_COG) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_SIV) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_HPA) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_VPA) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_RSRP) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_RSSI) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_SINR) )
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.volt.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//.............................
case TYPE_ENTREES_IBS :
{
flag_erreur = true;
break;
}
//.............................
case TYPE_ENTREES_NMEA :
{
break;
}
//.............................
case TYPE_ENTREES_CAN :
{
flag_erreur = true;
break;
}
//.............................
case TYPE_ENTREES_CALCULEE_BOOLEEN :
{
break;
}
//.............................
case TYPE_ENTREES_CALCULEE_NUMERIQUE :
{
flag_erreur = true;
break;
}
//.............................
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------------------------------------------------------------------------------
case TYPE_CARTE_SP812:
case TYPE_CARTE_SP8DC:
case TYPE_CARTE_SBS :
{
switch(capteurs.capteurs[i].type_entrees)
{
//.............................
case TYPE_ENTREES_PREDEFINIES :
{
// Vérification que le n° d'entrée prédéfinie est compatible avec ce type de modules :
// NB : a priori, une seule entrée par capteur mais permet de garder la même structure que pour les entrées AUX...
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if ((entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_TEMP) &&
(entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_IN_V) )
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.volt.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//..........................
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------------------------------------------------------------------------------
case TYPE_CARTE_SP4AC:
{
switch(capteurs.capteurs[i].type_entrees)
{
//.............................
case TYPE_ENTREES_PREDEFINIES :
{
// Vérification que le n° d'entrée prédéfinie est compatible avec ce type de modules :
// NB : a priori, une seule entrée par capteur mais permet de garder la même structure que pour les entrées AUX...
for (j = 0; j < capteurs.capteurs[i].nb_entrees; j ++)
{
if (entrees.predefinies.entrees[capteurs.capteurs[i].no_entrees[j]].no != ENTREE_PREDEFINIE_TEMP)
{
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++) entrees.volt.entrees[capteurs.capteurs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//..........................
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------------------------------------------------------------------------------
case TYPE_CARTE_INCONNU:
default:
{
flag_erreur = true;
break;
}
}
if (flag_erreur)
{
sprintf(tmp, "Le circuit n° %i (Cle_primaire = %i) dans TB_Capteurs contient des paramètres non compatibles avec le module auquel il est affecté. Le capteur est dévalidé.", i, capteurs.capteurs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
capteurs.capteurs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
//================================================================
// Traitements non directement liés au retour de la requête en BDD :
//================================================================
//------------------------------------------------
// Mise à jour des valeurs courantes (SDIR #188) :
//------------------------------------------------
// Initilisation des valeurs courantes à partir des valeurs de BDD (évite de repartir à 0 mais plutôt de la dernière valeur connue) :
capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].valeur_courante = capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].valeur_bdd;
// SDIR #174 :
capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].last_mesure = capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].valeur_courante;
capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].cumul = 0;
capteurs.capteurs[i].cumuls_nb_val = 0;
/*
// DEBUG :
printf("Capteur %i : ----------------------------------------------------------\n", i);
printf("Clé=%i, Module entrées=%i, Type d'entrées=%i, No_entrée=%i, ID_Variable=%i, No variable=%i, Offset=%.3f, Gain=%.3f, \
Valeur=%.3f, Coeff_filtrage=%i, mesures=%i, historique=%i \n",
capteurs.capteurs[i].cle_primaire, capteurs.capteurs[i].adresse_module, capteurs.capteurs[i].type_entrees, capteurs.capteurs[i].no_entrees[0],
capteurs.capteurs[i].id_variable, capteurs.capteurs[i].no_variable, capteurs.capteurs[i].offset,
capteurs.capteurs[i].gain, capteurs.capteurs[i].variables[CAPTEUR_VARIABLE_VALEUR].valeur_courante, capteurs.capteurs[i].valeur_coeff_filtrage,
capteurs.capteurs[i].mode_enregistrement_mesures, capteurs.capteurs[i].mode_enregistrement_historique );
*/
/*if (capteurs.capteurs[i].type_entrees == TYPE_ENTREES_CALCULEE_BOOLEEN)
{
printf("Conditions du capteur calculé :\n");
for (k = 0; k < capteurs.capteurs[i].nb_entrees; k ++)
{
printf("%i : validite=%i, type_condition=%i, type_source=%i, id_source=%i, id_variable=%i, test=%i et seuil=%.2f\n", k,
capteurs.capteurs[i].conditions.conditions[k].flag_validite, capteurs.capteurs[i].conditions.conditions[k].type_condition,
capteurs.capteurs[i].conditions.conditions[k].type_source, capteurs.capteurs[i].conditions.conditions[k].id_source,
capteurs.capteurs[i].conditions.conditions[k].id_variable, capteurs.capteurs[i].conditions.conditions[k].test,
capteurs.capteurs[i].conditions.conditions[k].seuil );
}
}*/
i++;
}
mysql_free_result(result); //Libération du jeu de résultat
capteurs.nb = i;
// SDIR #198 :
if (mode_init == BDD_MODE_INIT_RELOAD) capteurs.sequenceur.etat = ETAT_SEQUENCEUR_CAPTEURS_INIT; // Permet de s'assurer qu'on remet toutes les variables d'aplomb. Notamment si ajout/suppression de capteur car les n° sont alors reattribués et il faut que toutes les variables globales soient également reintialisées.
// ********************************************************************************************************************************************************
// BATTERIES
// ********************************************************************************************************************************************************
// RAZ de la liste existante (utile lors d'une reconfiguration) :
for (i = 0; i < MAX_NOMBRE_BATTERIES; i ++)
{
batteries.batteries[i].flag_validite = FALSE; // Valeur par défaut
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_AUCUNE; // Valeur par défaut
}
// Mise à jour des IDs de variables utilisées par les batteries :
sprintf(requete, "SELECT Code, Cle_primaire, Marge FROM TB_Variables WHERE Code LIKE 'Batt_%%' ");
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 (strcmp(row[0], "Batt_temperature") == 0) { batteries.variables[BATTERIE_VARIABLE_TEMPERATURE].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_TEMPERATURE].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_tension") == 0) { batteries.variables[BATTERIE_VARIABLE_TENSION].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_TENSION].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_courant_differentiel") == 0) { batteries.variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_courant_charge") == 0) { batteries.variables[BATTERIE_VARIABLE_COURANT_CHARGE].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_COURANT_CHARGE].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_courant_decharge") == 0) { batteries.variables[BATTERIE_VARIABLE_COURANT_DECHARGE].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_COURANT_DECHARGE].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_soh") == 0) { batteries.variables[BATTERIE_VARIABLE_SOH].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_SOH].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_soc") == 0) { batteries.variables[BATTERIE_VARIABLE_SOC].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_SOC].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_autonomie") == 0) { batteries.variables[BATTERIE_VARIABLE_AUTONOMIE].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_AUTONOMIE].marge = atof(row[2]); }
else if (strcmp(row[0], "Batt_puissance") == 0) { batteries.variables[BATTERIE_VARIABLE_PUISSANCE].cle_primaire = atoi(row[1]); batteries.variables[BATTERIE_VARIABLE_PUISSANCE].marge = atof(row[2]); }
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à 0 de Etat_systeme de toutes les batteries par défaut.
// La remise à une autre valeur sera éventuellement faite :
// - en fin de cette fonction si la configuration n'est pas cohérente et ne peut être exploitée
// - dans 'bdd_fonctions.c', dans 'enregistrement_annuaire_k_bus()', si le module auquel est affecté cette batterie n'est pas pas présent (module physique absent ou pas du bon type)
sprintf(requete, "UPDATE TB_Batteries SET Etat_systeme=0");
mysql_query(bdd.pointeur, requete);
// Récupération de la configuration des batteries :
i = 0;
sprintf(requete, "SELECT Cle_primaire, Adresse_module, Type_entrees, Entrees, Type, Tension_nominale, Capacite_1, Coeff_peukert, \
Tension_pleine_charge, Courant_pleine_charge, Temporisation_pleine_charge, \
Tension_charge_nulle, Temporisation_charge_nulle, Resistance_interne, Efficacite_charge, \
Efficacite_decharge, Courant_repos, Nombre_cycles, Flag_increment_cycles, \
Nombre_decharges_completes, Flag_increment_decharges_completes, \
Temperature, Temperature_coeff_filtrage, \
Tension, Tension_coeff_filtrage, Tension_gain, \
Courant_differentiel, Courant_differentiel_coeff_filtrage, Courant_charge, Courant_decharge, \
Soh, Soc, Soc_coeff_filtrage, Eod, Autonomie, \
Liste_tension_soc, Liste_temperature_resistance_interne, Mode_enregistrement_mesures, Mode_enregistrement_historique \
FROM TB_Batteries ORDER BY Type_entrees, Cle_primaire");
//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
{
// Vérification que le nombre de batteries n'est pas trop important :
if (i == MAX_NOMBRE_BATTERIES)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de batteries valides dans la Base de Données (TB_Batteries) est trop important (MAX = %i)...!", MAX_NOMBRE_BATTERIES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// return(-1);
// Traiter ce cas avec un message d'alerte user ????
break; // On arrête l'init des batteries mais on continue l'initialisation...
}
// Stockage des valeurs lues :
batteries.batteries[i].flag_validite = TRUE; // Valeur par défaut
j = 0; // Permet l'insertion plus facile d'un champs par la suite..! Ne pas oublier de l'incrémenter correctement à chaque étape !!
//---------------------------------------
// Clé primaire :
//---------------------------------------
batteries.batteries[i].cle_primaire = atoi(row[j ++]); // ATTENTION : dans les lignes suivantes, on alterne entre 'atoi()' et 'atof()' en fonction du type de variable. Prendre garde lors des copier/coller !!
//---------------------------------------
// Adresse de module :
//---------------------------------------
val_16 = atoi(row[j ++]); // On prend en compte les batteries 'non affectées' qui arrivent avec un numéro de module = -1 (pas encore utilisé en 06/2026)
if ((val_16 < 0) || (val_16 >= MAX_NOMBRE_MODULES))
{
// Message d'erreur :
if (val_16 < 0)
{
sprintf(tmp, "La batterie n° %i (Cle_primaire = %i) dans TB_Batteries est Non Affectée (Adresse_module = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, val_16);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le numéro de module de la batterie n° %i (Cle_primaire = %i) dans TB_Batteries est trop élevé (%i, MAX = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, val_16, MAX_NOMBRE_MODULES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
else batteries.batteries[i].adresse_module = val_16;
//---------------------------------------
// Type d'entrées :
//---------------------------------------
val_u8 = atoi(row[j ++]);
switch(val_u8)
{
case TYPE_ENTREES_VOLTAGE :
case TYPE_ENTREES_PREDEFINIES :
case TYPE_ENTREES_IBS :
{
batteries.batteries[i].type_entrees = val_u8;
break;
}
default :
{
sprintf(tmp, "La batterie n° %i (clé primaire = %i) dans TB_Batteries a une configuration de 'Type_entrees' invalide (valeur = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
}
//---------------------------------------
// Entrées :
//---------------------------------------
if (row[j][0] != 0) // Si le champ "Entrees" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
// Check du nombre d'entrées trouvées :
if (k > MAX_NOMBRE_ENTREES_PAR_BATTERIE)
{
// Message d'erreur :
sprintf(tmp, "Le nombre d'entrées de la batterie n° %i (Cle_primaire = %i) dans TB_Batteries est trop important (MAX = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, MAX_NOMBRE_ENTREES_PAR_BATTERIE);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
// Traitement des entrées trouvées selon la valeur de 'type_entrees' :
switch(batteries.batteries[i].type_entrees)
{
//....................................................................................................................
case TYPE_ENTREES_VOLTAGE :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' de la batterie n° %i (Cle_primaire = %i) dans TB_Batteries est incorrect (%i pour 1 autorisé). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée
// Mise à jour des variables d'entrées :
if (entrees.volt.nb < MAX_NOMBRE_ENTREES_VOLTAGE) // Si le nombre d'entrées Voltage n'est pas déjà au maxi...
{
// Mise à jour de l'entrée correspondante :
entrees.volt.entrees[entrees.volt.nb].flag_validite = TRUE;
entrees.volt.entrees[entrees.volt.nb].module = batteries.batteries[i].adresse_module;
entrees.volt.entrees[entrees.volt.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
batteries.batteries[i].no_entrees = entrees.volt.nb;
entrees.volt.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées VOLTAGE est trop important (max = %i). La batterie n° %i (Cle_primaire = %i) est dévalidée.", MAX_NOMBRE_ENTREES_VOLTAGE, i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_PREDEFINIES :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' de la batterie n° %i (Cle_primaire = %i) dans TB_Batteries est incorrect (%i pour 1 autorisé). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée
// Mise à jour des variables d'entrées :
if (entrees.predefinies.nb < MAX_NOMBRE_ENTREES_PREDEFINIES)
{
// Mise à jour de l'entrée correspondante :
entrees.predefinies.entrees[entrees.predefinies.nb].flag_validite = TRUE;
entrees.predefinies.entrees[entrees.predefinies.nb].module = batteries.batteries[i].adresse_module;
entrees.predefinies.entrees[entrees.predefinies.nb].no = val_u8;
// Mise à jour du n° d'entrée du capteur :
batteries.batteries[i].no_entrees = entrees.predefinies.nb;
entrees.predefinies.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées PREDEFINIES est trop important (max = %i). La batterie n° %i (Cle_primaire = %i) est dévalidée.", MAX_NOMBRE_ENTREES_PREDEFINIES, i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_IBS :
{
break; // Le champ Entrees n'est pas utilisé avec ce type_entrees (on n'utilise que 'adresse_module')
}
//....................................................................................................................
default : ; // Ne devrait pas arriver car testé au § 'Type_entrees'....
}
}
else // Si le champ "Entrees" est vide :
{
sprintf(tmp, "La batterie n° %i (clé primaire = %i) dans la Base de Données (TB_Batteries) a un champ 'Entrees' vide. La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
j ++;
//---------------------------------------
// Type :
//---------------------------------------
batteries.batteries[i].type = atoi(row[j ++]);
//---------------------------------------
// Tension nominale :
//---------------------------------------
batteries.batteries[i].tension_nominale = atoi(row[j ++]);
//---------------------------------------
// Capacité_1 :
//---------------------------------------
flag_erreur = false;
if (row[j][0] != 0) // Si le champ "Capacité_1" n'est pas vide :
{
// Récupération de la liste :
k = 0;
ptr[k] = strtok (row[j],"/"); // Extraction du premier segment avant le premier '/'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, "/"); // Extraction du segment suivant le prochain '/'
}
if (k == 2) // Format valide :
{
batteries.batteries[i].capacite = atof(ptr[0]);
batteries.batteries[i].heures_capacite = atof(ptr[1]);
if ((batteries.batteries[i].capacite <= 0) || (batteries.batteries[i].heures_capacite <= 0)) flag_erreur = true;
}
else flag_erreur = true; // Si le format est invalide
}
else flag_erreur = true;
j ++;
if (flag_erreur)
{
batteries.batteries[i].capacite = 0;
batteries.batteries[i].heures_capacite = 0;
}
if (batteries.batteries[i].capacite == 0) //On ne peut pas fonctionner avec une capacité nulle...
{
batteries.batteries[i].capacite = 100;
sprintf(tmp, "La capacité de la batterie n° %i (clé primaire = %i) dans la Base de Données (TB_Batteries) a une valeur nulle, ce qui n'est pas acceptable pour fonctionner. La valeur est arbitrairement fixée à %.2fAh.", i, batteries.batteries[i].cle_primaire, batteries.batteries[i].capacite);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
if (batteries.batteries[i].heures_capacite == 0) //On ne peut pas fonctionner avec une durée de capacité nulle...
{
batteries.batteries[i].heures_capacite = 20;
sprintf(tmp, "La durée de capacité de la batterie n° %i (clé primaire = %i) dans la Base de Données (TB_Batteries) a une valeur nulle, ce qui n'est pas acceptable pour fonctionner. La valeur est arbitrairement fixée à %.2fh.", i, batteries.batteries[i].cle_primaire, batteries.batteries[i].heures_capacite);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
//---------------------------------------
// Coeff de Peukert :
//---------------------------------------
batteries.batteries[i].coeff_peukert = atof(row[j ++]);
//---------------------------------------
// Tension pleine charge :
//---------------------------------------
batteries.batteries[i].tension_pleine_charge = atof(row[j ++]);
//---------------------------------------
// Courant_pleine_charge :
//---------------------------------------
batteries.batteries[i].courant_pleine_charge = atof(row[j ++]);
//---------------------------------------
// Tempo pleine charge :
//---------------------------------------
batteries.batteries[i].temporisation_pleine_charge = atoi(row[j ++]);
//---------------------------------------
// Tension charge nulle :
//---------------------------------------
batteries.batteries[i].tension_charge_nulle = atof(row[j ++]);
//---------------------------------------
// Tempo charge nulle :
//---------------------------------------
batteries.batteries[i].temporisation_charge_nulle = atoi(row[j ++]);
//---------------------------------------
// Résistance interne :
//---------------------------------------
batteries.batteries[i].resistance_interne = atof(row[j ++]);
//---------------------------------------
// Efficacité charge :
//---------------------------------------
batteries.batteries[i].efficacite_charge = atof(row[j ++]);
if (batteries.batteries[i].efficacite_charge == 0) //On ne peut pas fonctionner avec une efficacité nulle...
{
batteries.batteries[i].efficacite_charge = 1;
sprintf(tmp, "L'éfficacité de charge de la batterie n° %i (clé primaire = %i) dans la Base de Données (TB_Batteries) a une valeur nulle, ce qui n'est pas acceptable pour fonctionner. La valeur est arbitrairement fixée à %.2f Ah.", i, batteries.batteries[i].cle_primaire, batteries.batteries[i].efficacite_charge);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
//---------------------------------------
// Efficacité décharge :
//---------------------------------------
batteries.batteries[i].efficacite_decharge = atof(row[j ++]);
if (batteries.batteries[i].efficacite_decharge == 0) //On ne peut pas fonctionner avec une efficacité nulle...
{
batteries.batteries[i].efficacite_decharge = 1;
sprintf(tmp, "L'éfficacité de charge de la batterie n° %i (clé primaire = %i) dans la Base de Données (TB_Batteries) a une valeur nulle, ce qui n'est pas acceptable pour fonctionner. La valeur est arbitrairement fixée à %.2f Ah.", i, batteries.batteries[i].cle_primaire, batteries.batteries[i].efficacite_decharge);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
//---------------------------------------
// Courant de repos :
//---------------------------------------
batteries.batteries[i].courant_repos = atof(row[j ++]);
//---------------------------------------
// Nombre de cycles :
//---------------------------------------
batteries.batteries[i].nombre_cycles = atoi(row[j ++]);
//---------------------------------------
// Flag incrément cycles :
//---------------------------------------
batteries.batteries[i].flag_increment_cycles = atoi(row[j ++]);
//---------------------------------------
// Nombre décharges complètes :
//---------------------------------------
batteries.batteries[i].nombre_decharges_completes = atoi(row[j ++]);
//---------------------------------------
// Flag incrément décharges complètes :
//---------------------------------------
batteries.batteries[i].flag_increment_decharges_completes = atoi(row[j ++]);
//---------------------------------------
// Température :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].valeur_bdd = atof(row[j ++]);
val_u8 = atoi(row[j ++]); // Coeff filtrage de température
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider le réservoir mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage de la température de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (0<n). La batterie est laissée valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].temperature_coeff_filtrage = val_u8;
//---------------------------------------
// Tension :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Tension coeff filtrage :
//---------------------------------------
val_u8 = atoi(row[j ++]); // Coeff filtrage de température
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider le réservoir mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage de la tension de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (0<n). La batterie est laissée valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].tension_coeff_filtrage = val_u8;
//---------------------------------------
// Tension gain :
//---------------------------------------
batteries.batteries[i].tension_gain = atof(row[j ++]);
//---------------------------------------
// Courant différentiel :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Courant différentiel coeff filtrage :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider le réservoir mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage du courant différentiel de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (0<n). La batterie est laissée valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].courant_differentiel_coeff_filtrage = val_u8;
//---------------------------------------
// Courant charge :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Courant décharge :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// SOH :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// SOC :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// SOC coeff filtrage :
//---------------------------------------
val_u8 = atoi(row[j ++]); // Coeff filtrage de SOC
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider la batterie mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage du SOC de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (0<n). La batterie est laissée valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].soc_coeff_filtrage = val_u8;
//---------------------------------------
// EOD :
//---------------------------------------
batteries.batteries[i].eod = atof(row[j ++]);
//---------------------------------------
// Autonomie :
//---------------------------------------
batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Points Tension/Soc :
//---------------------------------------
// RAZ de la liste existante (utile lors d'une reconfiguration) :
for (m = 0; m < MAX_NOMBRE_POINTS_TENSION_SOC_BATTERIE; m ++) batteries.batteries[i].points_tension_soc[m].flag_validite = FALSE;
if (row[j][0] != 0) // Si le champ "Liste_tension_soc" n'est pas vide :
{
// Récupération de la nouvelle liste :
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
if (k > MAX_NOMBRE_POINTS_TENSION_SOC_BATTERIE)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de points dans la liste Tension/SOC de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est trop important (MAX = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, MAX_NOMBRE_POINTS_TENSION_SOC_BATTERIE);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
for (m = 0; m < k; m ++)
{
ptr_val = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
ptr_niv = strtok (NULL, "/"); // Extraction du second segment après le '/'
if ((ptr_val != NULL) && (ptr_niv != NULL))
{
batteries.batteries[i].points_tension_soc[m].valeur = atof(ptr_val);
batteries.batteries[i].points_tension_soc[m].niveau = atof(ptr_niv);
if (batteries.batteries[i].points_tension_soc[m].niveau <= 100) batteries.batteries[i].points_tension_soc[m].flag_validite = TRUE;
}
}
if (tri_liste_valeurs_niveaux(batteries.batteries[i].points_tension_soc, MAX_NOMBRE_POINTS_TENSION_SOC_BATTERIE) == -1)
{
sprintf(tmp, "Le tri de la liste Valeurs/Niveaux de la batterie n° %i (Cle_primaire = %i) ne s'est pas effectué normalement. Le démarrage se fait avec la liste en l'état mais peu provoquer des dysfonctionnements.", i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
j ++;
//---------------------------------------
// Points Température/Résistance_interne :
//---------------------------------------
// RAZ de la liste existante (utile lors d'une reconfiguration) :
for (m = 0; m < MAX_NOMBRE_POINTS_TEMPERATURE_RESISTANCE_INTERNE_BATTERIE; m ++) batteries.batteries[i].points_temperature_resistance_interne[m].flag_validite = FALSE;
if (row[j][0] != 0) // Si le champ "Liste_temperature_resistance_interne" n'est pas vide :
{
// Récupération de la nouvelle liste :
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
if (k > MAX_NOMBRE_POINTS_TEMPERATURE_RESISTANCE_INTERNE_BATTERIE)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de points dans la liste Température/Résistance_interne de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est trop important (MAX = %i). La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire, MAX_NOMBRE_POINTS_TEMPERATURE_RESISTANCE_INTERNE_BATTERIE);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
for (m = 0; m < k; m ++)
{
ptr_val = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
ptr_niv = strtok (NULL, "/"); // Extraction du second segment après le '/'
if ((ptr_val != NULL) && (ptr_niv != NULL))
{
batteries.batteries[i].points_temperature_resistance_interne[m].valeur = atof(ptr_val);
batteries.batteries[i].points_temperature_resistance_interne[m].niveau = atof(ptr_niv);
batteries.batteries[i].points_temperature_resistance_interne[m].flag_validite = TRUE;
}
}
if (tri_liste_valeurs_niveaux(batteries.batteries[i].points_temperature_resistance_interne, MAX_NOMBRE_POINTS_TEMPERATURE_RESISTANCE_INTERNE_BATTERIE) == -1)
{
sprintf(tmp, "Le tri de la liste Température/Résistance_interne de la batterie n° %i (Cle_primaire = %i) ne s'est pas effectué normalement. Le démarrage se fait avec la liste en l'état mais peu provoquer des dysfonctionnements.", i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
j ++;
//---------------------------------------
// Enregistrement mesures :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT)
{
val_u8 = MODE_ENREGISTREMENT_MESURES_PERIODIQUE; // Valeur arbitraire correspondant à aucun enregistrement des mesures. NB : on considère que ce n'est pas une raison pour dévalider le capteur mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le mode d'enregistrement des mesures de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement des mesures est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].mode_enregistrement_mesures = val_u8;
//---------------------------------------
// Enregistrement historique :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_HISTORIQUE_NORMAL)
{
val_u8 = MODE_ENREGISTREMENT_HISTORIQUE_NORMAL;
sprintf(tmp, "Le mode d'enregistrement de l'historique de la batterie n° %i (Cle_primaire = %i) dans la Base de Données (TB_Batteries) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement d'historique est arbitrairement fixé à %i.", i, batteries.batteries[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_HISTORIQUE_NORMAL, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
batteries.batteries[i].mode_enregistrement_historique = val_u8;
//===================================================================================================
// Vérification de la cohérence de la configuration de la batterie :
//===================================================================================================
flag_erreur = false;
switch (systeme.modules_config[batteries.batteries[i].adresse_module].type)
{
//-----------------------
case TYPE_CARTE_SHIPBASE:
{
switch(batteries.batteries[i].type_entrees)
{
case TYPE_ENTREES_VOLTAGE :
{
// Vérification que le n° d'entrée VOLT est compatible avec un ShipBase :
if ((entrees.volt.entrees[batteries.batteries[i].no_entrees].no < 1) ||
(entrees.volt.entrees[batteries.batteries[i].no_entrees].no > 4)) flag_erreur = true;
break;
}
case TYPE_ENTREES_PREDEFINIES :
{
// Vérification que le n° d'entrée prédéfinie est compatible avec un ShipBase :
if (entrees.predefinies.entrees[batteries.batteries[i].no_entrees].no != ENTREE_PREDEFINIE_IN_V) flag_erreur = true;
break;
}
case TYPE_ENTREES_IBS :
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------
case TYPE_CARTE_SP812:
case TYPE_CARTE_SP8DC:
{
switch(batteries.batteries[i].type_entrees)
{
case TYPE_ENTREES_PREDEFINIES :
{
// Vérification que le n° d'entrée prédéfinie est compatible avec un ShipPowerxDC :
if (entrees.predefinies.entrees[batteries.batteries[i].no_entrees].no != ENTREE_PREDEFINIE_IN_V) flag_erreur = true;
break;
}
case TYPE_ENTREES_VOLTAGE :
case TYPE_ENTREES_IBS :
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------
case TYPE_CARTE_SBS:
{
switch(batteries.batteries[i].type_entrees)
{
case TYPE_ENTREES_IBS : break;
case TYPE_ENTREES_PREDEFINIES :
case TYPE_ENTREES_VOLTAGE :
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------
case TYPE_CARTE_SP4AC:
case TYPE_CARTE_INCONNU:
default:
{
flag_erreur = true;
break;
}
}
if (flag_erreur)
{
sprintf(tmp, "La batterie n° %i (Cle_primaire = %i) dans TB_Batteries contient des paramètres non compatibles avec le module auquel elle est affectée. La batterie est dévalidée.", i, batteries.batteries[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
batteries.batteries[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
//================================================================
// Traitements non directement liés au retour de la requête en BDD :
//================================================================
// Puissance :
batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].valeur_courante = 0; // Valeur par défaut
//------------------------------------------------
// Mise à jour des valeurs courantes (SDIR #188) :
//------------------------------------------------
// Initilisation des valeurs courantes à partir des valeurs de BDD (évite de repartir à 0 mais plutôt de la dernière valeur connue) :
batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].valeur_bdd;
batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].valeur_courante = batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].valeur_bdd;
// SDIR #174 :
batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_TEMPERATURE].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_TENSION].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DIFFERENTIEL].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_CHARGE].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_COURANT_DECHARGE].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOC].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_AUTONOMIE].cumul = 0;
batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].last_mesure = batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].valeur_courante;
batteries.batteries[i].variables[BATTERIE_VARIABLE_PUISSANCE].cumul = 0;
batteries.batteries[i].cumuls_nb_val = 0;
// DEBUG :
/* printf("Batterie %i : ----------------------------------------------------------\n", i);
printf("Clé=%i, Adresse_module=%i, Type d'entrées=%i, No_Entrée=%i, Capacite=%.2fAh, Tension_gain=%.3f, Soh=%.2f %%, mesures=%i, historique=%i \n",
batteries.batteries[i].cle_primaire, batteries.batteries[i].adresse_module, batteries.batteries[i].type_entrees, batteries.batteries[i].no_entrees,
batteries.batteries[i].capacite, batteries.batteries[i].tension_gain,
batteries.batteries[i].variables[BATTERIE_VARIABLE_SOH].valeur_bdd,
batteries.batteries[i].mode_enregistrement_mesures, batteries.batteries[i].mode_enregistrement_historique );
*/
/*printf("Valeurs/Niveaux :");
for (j=0; j<MAX_NOMBRE_POINTS_TENSION_SOC_BATTERIE; j++)
{
if (batteries.batteries[i].points_tension_soc[j].flag_validite == TRUE) printf(" %.3f/%.2f", batteries.batteries[i].points_tension_soc[j].valeur, batteries.batteries[i].points_tension_soc[j].niveau);
}
printf("\n");*/
i++;
}
mysql_free_result(result); //Libération du jeu de résultat
batteries.nb = i;
// SDIR #198 :
if (mode_init == BDD_MODE_INIT_RELOAD) batteries.sequenceur.etat = ETAT_SEQUENCEUR_BATTERIES_INIT; // Permet de s'assurer qu'on remet toutes les variables d'aplomb. Notamment si ajout/suppression de batterie car les n° sont alors reattribués et il faut que toutes les variables globales soient également reintialisées.
// ********************************************************************************************************************************************************
// RESERVOIRS
// ********************************************************************************************************************************************************
// RAZ de la liste existante (utile lors d'une reconfiguration) :
for (i = 0; i < MAX_NOMBRE_RESERVOIRS; i ++)
{
reservoirs.reservoirs[i].flag_validite = FALSE; // Valeur par défaut
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_AUCUNE; // Valeur par défaut
}
// Mise à jour des IDs de variables utilisées par les réservoirs :
sprintf(requete, "SELECT Code, Cle_primaire, Marge FROM TB_Variables WHERE Code LIKE 'Res_%%' ");
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 (strcmp(row[0], "Res_niveau") == 0) { reservoirs.variables[RESERVOIR_VARIABLE_NIVEAU].cle_primaire = atoi(row[1]); reservoirs.variables[RESERVOIR_VARIABLE_NIVEAU].marge = atof(row[2]); }
else ;
}
mysql_free_result(result); //Libération du jeu de résultat
// Mise à 0 de Etat_systeme de toutes les batteries par défaut.
// La remise à une autre valeur sera éventuellement faite :
// - en fin de cette fonction si la configuration n'est pas cohérente et ne peut être exploitée
// - dans 'bdd_fonctions.c', dans 'enregistrement_annuaire_k_bus()', si le module auquel est affecté ce réservoir n'est pas pas présent (module physique absent ou pas du bon type)
sprintf(requete, "UPDATE TB_Reservoirs SET Etat_systeme=0");
mysql_query(bdd.pointeur, requete);
// Récupération de la configuration des réservoirs :
i = 0;
sprintf(requete, "SELECT Cle_primaire, Adresse_module, Type_entrees, Entrees, Mode_entrees, Etat_entrees, Liste_valeurs_niveaux, Niveau, Niveau_coeff_filtrage, \
Logique, Mode_enregistrement_mesures, Mode_enregistrement_historique \
FROM TB_Reservoirs ORDER BY Type_entrees, Cle_primaire");
// 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
{
// Vérification que le nombre de réservoir n'est pas trop important :
if (i == MAX_NOMBRE_RESERVOIRS)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de réservoirs valides dans la Base de Données (TB_Reservoirs) est trop important (MAX = %i)...!", MAX_NOMBRE_RESERVOIRS);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// return(-1);
// Traiter ce cas avec un message d'alerte user ????
break; // On arrête l'init des réservoirs mais on continue l'initialisation...
}
// Stokage des valeurs lues :
j = 0; // Permet l'insertion plus facile d'un champs par la suite..! Ne pas oublier de l'incrémenter correctement à chaque étape !!
reservoirs.reservoirs[i].flag_validite = TRUE; // On en est sûr puisque le filtre SQL est basé là-dessus...
//---------------------------------------
// Clé primaire :
//---------------------------------------
reservoirs.reservoirs[i].cle_primaire = atoi(row[j ++]);
//---------------------------------------
// Adresse de module :
//---------------------------------------
val_16 = atoi(row[j ++]); // On prend en compte les réservoirs 'non affectés' qui arrivent avec un numéro de module = -1 (pas encore utilisé en 06/2026)
if ((val_16 < 0) || (val_16 >= MAX_NOMBRE_MODULES))
{
// Message d'erreur :
if (val_16 < 0)
{
sprintf(tmp, "Le réservoir n° %i (Cle_primaire = %i) dans TB_Reservoirs est Non Affecté (Adresse_module = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, val_16);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
else
{
sprintf(tmp, "Le numéro de module du réservoir n° %i (Cle_primaire = %i) dans TB_Circuits est trop élevé (%i, MAX = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, val_16, MAX_NOMBRE_MODULES);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
}
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
else reservoirs.reservoirs[i].adresse_module = val_16;
//---------------------------------------
// Type d'entrées :
//---------------------------------------
val_u8 = atoi(row[j ++]);
switch(val_u8)
{
case TYPE_ENTREES_AUXILIAIRES :
case TYPE_ENTREES_LEVEL_SENSOR :
{
reservoirs.reservoirs[i].type_entrees = val_u8;
break;
}
default :
{
sprintf(tmp, "Le réservoir n° %i (clé primaire = %i) dans la Base de Données (TB_Reservoirs) a une configuration de 'Type_entrees' invalide (valeur = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
}
//---------------------------------------
// Entrées :
//---------------------------------------
if (row[j][0] != 0) // Si le champ "Entrees" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
// Check du nombre d'entrées trouvées :
if (k > MAX_NOMBRE_ENTREES_PAR_RESERVOIR)
{
// Message d'erreur :
sprintf(tmp, "Le nombre d'entrées du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est trop important (MAX = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, MAX_NOMBRE_ENTREES_PAR_RESERVOIR);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
// Traitement des entrées trouvées selon la valeur de 'type_entrees' :
switch(reservoirs.reservoirs[i].type_entrees)
{
//....................................................................................................................
case TYPE_ENTREES_AUXILIAIRES :
{
for (m = 0; m < k; m ++) // Nb : on a déjà vérifié que k < MAX_NOMBRE_ENTREES_PAR_CAPTEUR
{
val_u8 = atoi(ptr[m]);
// Mise à jour des variables d'entrées :
if (entrees.aux.nb < MAX_NOMBRE_ENTREES_AUXILIAIRES)
{
// Mise à jour de l'entrée correspondante :
entrees.aux.entrees[entrees.aux.nb].flag_validite = TRUE;
entrees.aux.entrees[entrees.aux.nb].module = reservoirs.reservoirs[i].adresse_module;
entrees.aux.entrees[entrees.aux.nb].no = val_u8;
// Mise à jour du n° d'entrée du réservoir :
reservoirs.reservoirs[i].no_entrees[m] = entrees.aux.nb;
entrees.aux.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées AUX est trop important (max = %i). Le réservoir n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_AUXILIAIRES, i, reservoirs.reservoirs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
break; // Sort de la boucle FOR
}
}
if (m < k) // Une erreur a été détectée dans la boucle des numéros d'entrées (le message d'erreur a été émis ci-dessus)
{
i ++;
continue;
}
reservoirs.reservoirs[i].nb_entrees = m;
break;
}
//....................................................................................................................
case TYPE_ENTREES_LEVEL_SENSOR :
{
if (k != 1)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de paramètres 'Entrees' du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est incorrect (%i pour 1 autorisé). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, k);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
val_u8 = atoi(ptr[0]); // N° de l'entrée
// Mise à jour des variables d'entrées :
if (entrees.level_sensor.nb < MAX_NOMBRE_ENTREES_LEVEL_SENSOR)
{
// Mise à jour de l'entrée correspondante :
entrees.level_sensor.entrees[entrees.level_sensor.nb].flag_validite = TRUE;
entrees.level_sensor.entrees[entrees.level_sensor.nb].module = reservoirs.reservoirs[i].adresse_module;
entrees.level_sensor.entrees[entrees.level_sensor.nb].no = val_u8;
// Mise à jour du n° d'entrée du réservoir :
reservoirs.reservoirs[i].no_entrees[0] = entrees.level_sensor.nb;
reservoirs.reservoirs[i].nb_entrees = 1;
entrees.level_sensor.nb ++;
}
else
{
sprintf(tmp, "Le nombre d'entrées LEVEL SENSOR est trop important (max = %i). Le réservoir n° %i (Cle_primaire = %i) est dévalidé.", MAX_NOMBRE_ENTREES_LEVEL_SENSOR, i, reservoirs.reservoirs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
break;
}
//....................................................................................................................
default : ; // Ne devrait pas arriver car testé au § 'Type_entrees'....
}
}
else // Si le champ "Entrees" est vide :
{
sprintf(tmp, "Le réservoir n° %i (clé primaire = %i) dans la Base de Données (TB_Reservoirs) a un champ 'Entrees' vide. Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
j ++;
//---------------------------------------
// Mode entrées :
//---------------------------------------
val_u8 = atoi(row[j ++]);
switch(reservoirs.reservoirs[i].type_entrees)
{
//....................................................................................................................
case TYPE_ENTREES_AUXILIAIRES :
{
if ((val_u8 != 0) && (val_u8 != 1))
{
// Message d'erreur :
sprintf(tmp, "Le mode de fonctionnement des entrées AUX du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est incorrect (valeur = %i). Le mode NORMAL (entrées Non inversées) est défini par défaut et la configuration se poursuit.", i, reservoirs.reservoirs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
val_u8 = 0;
}
for (k = 0; k < reservoirs.reservoirs[i].nb_entrees; k ++)
{
entrees.aux.entrees[reservoirs.reservoirs[i].no_entrees[k]].logique = val_u8; // On met à jour la logique dans les entrées AUX (inutile de disposer de l'info dans le réservoir)
}
break;
}
//....................................................................................................................
case TYPE_ENTREES_LEVEL_SENSOR :
{
if ((val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_0_10V) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_500R) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_4_20MA) &&
(val_u8 != ENTREE_LEVEL_SENSOR_MODE_FONCTIONNEMENT_AUTO_TEST) ) // SDIR #319
{
// Message d'erreur :
sprintf(tmp, "Le mode de fonctionnement de l'entrée Level Sensor du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est incorrect (valeur = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
entrees.level_sensor.entrees[reservoirs.reservoirs[i].no_entrees[0]].flag_validite = FALSE; // L'entrée est dévalidée car non utilisable
i ++;
continue;
}
entrees.level_sensor.entrees[reservoirs.reservoirs[i].no_entrees[0]].mode = val_u8; // On met à jour le mode dans l'entre LEVEL SENSOR (inutile de disposer de l'info dans le capteur)
break;
}
//....................................................................................................................
default : // Pour les autres Type_entrees, le champ Mode_entrees n'est pas utilisé...
{
break;
}
}
//---------------------------------------
// Etat_entrees :
//---------------------------------------
reservoirs.reservoirs[i].etat_entrees = atoi(row[j ++]);
//---------------------------------------
// Liste Valeurs/Niveaux :
//---------------------------------------
// RAZ de la liste existante (utile lors d'une reconfiguration) :
for (m = 0; m < MAX_NOMBRE_VALEURS_NIVEAUX_RESERVOIRS; m ++) reservoirs.reservoirs[i].liste_valeurs_niveaux[m].flag_validite = FALSE;
if (row[j][0] != 0) // Si le champ "Liste_valeurs_niveaux" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
if (k > MAX_NOMBRE_VALEURS_NIVEAUX_RESERVOIRS)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de points dans la liste Valeurs/Niveaux du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est trop important (MAX = %i). Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire, MAX_NOMBRE_VALEURS_NIVEAUX_RESERVOIRS);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
continue;
}
for (m = 0; m < k; m ++)
{
ptr_val = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
ptr_niv = strtok (NULL, "/"); // Extraction du second segment après le '/'
if ((ptr_val != NULL) && (ptr_niv != NULL))
{
reservoirs.reservoirs[i].liste_valeurs_niveaux[m].valeur = atof(ptr_val);
reservoirs.reservoirs[i].liste_valeurs_niveaux[m].niveau = atof(ptr_niv);
if (reservoirs.reservoirs[i].liste_valeurs_niveaux[m].niveau <= 100000) reservoirs.reservoirs[i].liste_valeurs_niveaux[m].flag_validite = TRUE;
}
}
if (tri_liste_valeurs_niveaux(reservoirs.reservoirs[i].liste_valeurs_niveaux, MAX_NOMBRE_VALEURS_NIVEAUX_RESERVOIRS) == -1)
{
sprintf(tmp, "Le tri de la liste Valeurs/Niveaux du réservoir n° %i (Cle_primaire = %i) ne s'est pas effectué normalement. Le démarrage se fait avec la liste en l'état mais peu provoquer des dysfonctionnements.", i, reservoirs.reservoirs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
j ++;
//---------------------------------------
// Niveau :
//---------------------------------------
reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].valeur_bdd = atof(row[j ++]);
//---------------------------------------
// Niveau Coeff filtrage :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 < 1)
{
val_u8 = 1; // Valeur arbitraire correspondant à aucun filtrage. NB : on considère que ce n'est pas une raison pour dévalider le réservoir mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le coefficent de filtrage du réservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Capteurs) est hors limite (0<n). Le réservoir est laissé valide MAIS son coefficient de filtrage est arbitrairement fixé à %i.", i, reservoirs.reservoirs[i].cle_primaire, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
reservoirs.reservoirs[i].niveau_coeff_filtrage = val_u8;
//---------------------------------------
// Logique :
//---------------------------------------
reservoirs.reservoirs[i].logique = atoi(row[j ++]);
//---------------------------------------
// Enregistrement mesures :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT)
{
val_u8 = MODE_ENREGISTREMENT_MESURES_PERIODIQUE; // Valeur arbitraire correspondant à aucun enregistrement des mesures. NB : on considère que ce n'est pas une raison pour dévalider le capteur mais on pourrait tout aussi bien le faire ici...
sprintf(tmp, "Le mode d'enregistrement des mesures du reservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Reservoirs) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement des mesures est arbitrairement fixé à %i.", i, reservoirs.reservoirs[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_MESURES_CHANGEMENT_ETAT, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
reservoirs.reservoirs[i].mode_enregistrement_mesures = val_u8;
//---------------------------------------
// Enregistrement historique :
//---------------------------------------
val_u8 = atoi(row[j ++]);
if (val_u8 > MODE_ENREGISTREMENT_HISTORIQUE_NORMAL)
{
val_u8 = MODE_ENREGISTREMENT_HISTORIQUE_NORMAL;
sprintf(tmp, "Le mode d'enregistrement de l'historique du reservoir n° %i (Cle_primaire = %i) dans la Base de Données (TB_Circuits) est hors limite (%i pour 0<= n <= %i). Le circuit est laissé valide MAIS son mode d'enregistrement d'historique est arbitrairement fixé à %i.", i, reservoirs.reservoirs[i].cle_primaire, val_u8, MODE_ENREGISTREMENT_HISTORIQUE_NORMAL, val_u8);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
reservoirs.reservoirs[i].mode_enregistrement_historique = val_u8;
//===================================================================================================
// Vérification de la cohérence de la configuration de la batterie :
//===================================================================================================
flag_erreur = false;
switch (systeme.modules_config[reservoirs.reservoirs[i].adresse_module].type)
{
//-----------------------
case TYPE_CARTE_SHIPBASE:
{
switch(reservoirs.reservoirs[i].type_entrees)
{
//-----------------------------
case TYPE_ENTREES_AUXILIAIRES :
{
// Vérification que les n° d'entrées AUX sont compatibles avec un ShipBase :
for (j = 0; j < reservoirs.reservoirs[i].nb_entrees; j ++)
{
if ((entrees.aux.entrees[reservoirs.reservoirs[i].no_entrees[j]].no < 1) ||
(entrees.aux.entrees[reservoirs.reservoirs[i].no_entrees[j]].no > 32))
{
for (k = 0; k < reservoirs.reservoirs[i].nb_entrees; k ++) entrees.aux.entrees[reservoirs.reservoirs[i].no_entrees[k]].flag_validite = false; // Dévalidation des entrées qui ne seront plus utiles....
flag_erreur = true;
break;
}
}
break;
}
//------------------------------
case TYPE_ENTREES_LEVEL_SENSOR :
{
j = reservoirs.reservoirs[i].no_entrees[0]; // Simplifie le traitement et la lecture
if ((entrees.level_sensor.entrees[j].no < 1) ||
(entrees.level_sensor.entrees[j].no > 8))
{
entrees.level_sensor.entrees[j].flag_validite = false; // Si le réservoir n'est pas opérationnel, inutile de traiter l'entrée correspondante.
flag_erreur = true;
}
break;
}
//------------------------------
default :
{
flag_erreur = true;
break;
}
}
break;
}
//-----------------------
case TYPE_CARTE_SP812:
case TYPE_CARTE_SP8DC:
case TYPE_CARTE_SBS:
case TYPE_CARTE_SP4AC:
case TYPE_CARTE_INCONNU:
default:
{
flag_erreur = true;
break;
}
}
if (flag_erreur)
{
sprintf(tmp, "Le réservoir n° %i (Cle_primaire = %i) dans TB_Reservoirs contient des paramètres non compatibles avec le module auquel il est affecté. Le réservoir est dévalidé.", i, reservoirs.reservoirs[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
reservoirs.reservoirs[i].etat_systeme = ERREUR_SYSTEME_CONFIG;
i ++;
continue;
}
//================================================================
// Traitements non directement liés au retour de la requête en BDD :
//================================================================
//------------------------------------------------
// Mise à jour des valeurs courantes (SDIR #188) :
//------------------------------------------------
// Initilisation des valeurs courantes à partir des valeurs de BDD (évite de repartir à 0 mais plutôt de la dernière valeur connue) :
reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].valeur_courante = reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].valeur_bdd;
// SDIR #174 :
reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].last_mesure = reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].valeur_courante;
reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].cumul = 0;
reservoirs.reservoirs[i].cumuls_nb_val = 0;
/*printf("Réservoir %i : ----------------------------------------------------------\n", i);
printf("Clé=%i, Type d'entrées=%i, No d'entrée 1=%i, No d'entrée 2=%i, No d'entrée 3=%i, No d'entrée 4=%i, Niveau=%.2f, Niveau_coeff_filtrage=%i, Niveau_seuil_Haut=%.3f, Niveau_seuil_Bas=%.3f, \
Logique=%i, mesures=%i, historique=%i \n",
reservoirs.reservoirs[i].cle_primaire, reservoirs.reservoirs[i].type_entrees, reservoirs.reservoirs[i].no_entrees[0], reservoirs.reservoirs[i].no_entrees[1], reservoirs.reservoirs[i].no_entrees[2],
reservoirs.reservoirs[i].no_entrees[3], reservoirs.reservoirs[i].variables[RESERVOIR_VARIABLE_NIVEAU].valeur_courante,
reservoirs.reservoirs[i].niveau_coeff_filtrage, reservoirs.reservoirs[i].niveau_seuil_haut, reservoirs.reservoirs[i].niveau_seuil_bas,
reservoirs.reservoirs[i].logique, reservoirs.reservoirs[i].mode_enregistrement_mesures, reservoirs.reservoirs[i].mode_enregistrement_historique );
printf("Valeurs/Niveaux :");
for (j=0; j<MAX_NOMBRE_VALEURS_NIVEAUX_RESERVOIRS; j++)
{
if (reservoirs.reservoirs[i].liste_valeurs_niveaux[j].flag_validite == TRUE) printf(" %.2f/%.2f", reservoirs.reservoirs[i].liste_valeurs_niveaux[j].valeur, reservoirs.reservoirs[i].liste_valeurs_niveaux[j].niveau);
}
printf("\n");
*/
i++;
}
mysql_free_result(result); //Libération du jeu de résultat
reservoirs.nb = i;
// SDIR #198 :
if (mode_init == BDD_MODE_INIT_RELOAD) reservoirs.sequenceur.etat = ETAT_SEQUENCEUR_RESERVOIRS_INIT; // Permet de s'assurer qu'on remet toutes les variables d'aplomb. Notamment si ajout/suppression de réservoir car les n° sont alors reattribués et il faut que toutes les variables globales soient également reintialisées.
// ********************************************************************************************************************************************************
// EVENEMENTS
// ********************************************************************************************************************************************************
// RAZ des variables globales (utile en cas de reconfiguration) :
// NB : cette init ne peut PAS être faite dans la boucle principale de retour de requête car ici on traite TOUTES la structure alors que la requête ne traite que le nombre présent dans la table...
events.nb = 0;
for (i = 0; i < MAX_NOMBRE_EVENTS; i ++)
{
// events.events[i].sequenceur.etat = ETAT_SEQUENCEUR_EVENT_REPOS; // SDIR #68
events.events[i].sequenceur.etat = ETAT_SEQUENCEUR_EVENT_INIT; // SDIR #68
events.events[i].flag_validite = false;
events.events[i].condition_test.flag_validite = false;
events.events[i].conditions_horaires.nb = 0;
events.events[i].action_circuits.nb = 0;
for (j = 0; j < MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT; j ++) events.events[i].conditions_horaires.conditions[j].flag_validite= false;
for (j = 0; j < MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT; j ++) events.events[i].action_circuits.action[j].flag_validite= false;
}
// Récupération de la configuration des events :
i = 0;
sprintf(requete, "SELECT Cle_primaire, Type_source, ID_Source, ID_Variable, Test, Seuil, Tempo, Conditions_horaires, \
Alarme_son, Alarme_led, Alarme_soutien, Alarme_source, Alarme_message, Alarme_sms, Alarme_email, Action_circuits \
FROM TB_Events WHERE Validite=1 ORDER BY Type_source, ID_Source, ID_Variable ");
//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
{
// Vérification que le nombre d'events n'est pas trop important :
if (i == MAX_NOMBRE_EVENTS)
{
// Message d'erreur :
sprintf(tmp, "Le nombre d'évènements valides dans la Base de Données (TB_Events) est trop important (MAX = %i)...!", MAX_NOMBRE_EVENTS);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
// return(-1);
// Traiter ce cas avec un message d'alerte user ????
break; // On arrête l'init des events mais on continue l'initialisation...
}
// Stokage des valeurs lues :
j = 0; // Permet l'insertion plus facile d'un champs par la suite..! Ne pas oublier de l'incrémenter correctement à chaque étape !!
events.events[i].flag_validite = TRUE; // On en est sûr puisque le filtre SQL est basé là-dessus...
events.events[i].condition_test.flag_validite = TRUE; // Valeur "par défaut" qui est ensuite mise à FALSE si une condition le nécessite.
//---------------------------------------
// Clé primaire :
//---------------------------------------
events.events[i].cle_primaire = atoi(row[j ++]);
//---------------------------------------
// Type_source :
//---------------------------------------
events.events[i].condition_test.type_source = atoi(row[j ++]);
if (events.events[i].condition_test.type_source == 0) events.events[i].condition_test.flag_validite = FALSE; // 0 correspond à "condition horaire seulement"
//---------------------------------------
// ID_Source :
//---------------------------------------
val_16 = atoi(row[j ++]);
switch(events.events[i].condition_test.type_source)
{
case SOURCE_MESURE_CIRCUIT:
{
val_16 = circuit_cle_primaire(val_16);
break;
}
case SOURCE_MESURE_CAPTEUR:
{
val_16 = capteur_cle_primaire(val_16);
break;
}
case SOURCE_MESURE_RESERVOIR:
{
val_16 = reservoir_cle_primaire(val_16);
break;
}
case SOURCE_MESURE_BATTERIE:
{
val_16 = batterie_cle_primaire(val_16);
break;
}
default: // Cas notamment de Type_source=0 : conditions horaires seules
{
events.events[i].condition_test.flag_validite = FALSE;
val_16 = 0;
break;
}
}
if (val_16 < 0) // Si on n'a pas trouvé d'équipement valide correspondant à l'ID reçu
{
events.events[i].condition_test.flag_validite = FALSE;
val_16 = 0;
}
events.events[i].condition_test.no_source = val_16;
//---------------------------------------
// ID variable :
//---------------------------------------
val_16 = atoi(row[j ++]);
switch(events.events[i].condition_test.type_source)
{
//--------------------------------------
case SOURCE_MESURE_CIRCUIT:
{
val_16 = variable_circuit_cle_primaire(val_16);
// Calcul du diviseur en fonction du type de variable concernée :
switch(val_16)
{
case CIRCUIT_VARIABLE_CONSIGNE:
case CIRCUIT_VARIABLE_ENERGIE:
{ events.events[i].diviseur_gestion = 5; break; }
case CIRCUIT_VARIABLE_TENSION:
case CIRCUIT_VARIABLE_COURANT:
case CIRCUIT_VARIABLE_FREQUENCE:
case CIRCUIT_VARIABLE_PUISSANCE:
case CIRCUIT_VARIABLE_TENSION_SECTEUR:
default: { events.events[i].diviseur_gestion = 0; break; } // En x 100ms
}
break;
}
//--------------------------------------
case SOURCE_MESURE_CAPTEUR:
{
// Calcul du diviseur en fonction du type de variable concernée :
val_16 = variable_capteur_cle_primaire(val_16);
switch(val_16)
{
case CAPTEUR_VARIABLE_TEMPERATURE:
case CAPTEUR_VARIABLE_PRESSION_ATM:
case CAPTEUR_VARIABLE_HUMIDITE:
case CAPTEUR_VARIABLE_POSITION:
case CAPTEUR_VARIABLE_DISTANCE_M:
case CAPTEUR_VARIABLE_DISTANCE_KM:
case CAPTEUR_VARIABLE_DISTANCE_NQ:
case CAPTEUR_VARIABLE_VITESSE_KTS:
case CAPTEUR_VARIABLE_VITESSE_KMH:
case CAPTEUR_VARIABLE_ANGLE_DEGRES:
{ events.events[i].diviseur_gestion = 10; break; }
case CAPTEUR_VARIABLE_SANS_UNITE:
case CAPTEUR_VARIABLE_TENSION_MV:
case CAPTEUR_VARIABLE_COURANT_A:
case CAPTEUR_VARIABLE_COURANT_MA:
case CAPTEUR_VARIABLE_PUISSANCE_W:
case CAPTEUR_VARIABLE_TENSION_V:
case CAPTEUR_VARIABLE_PUISSANCE_VA:
case CAPTEUR_VARIABLE_PUISSANCE_DB:
case CAPTEUR_VARIABLE_FREQUENCE:
case CAPTEUR_VARIABLE_RESISTANCE:
case CAPTEUR_VARIABLE_ACCELERATION:
case CAPTEUR_VARIABLE_POURCENTAGE:
default: { events.events[i].diviseur_gestion = 0; break; } // En x 100ms
}
val_16 = 0; // Un capteur n'a qu'un n° de variable...
break;
}
//--------------------------------------
case SOURCE_MESURE_RESERVOIR:
{
val_16 = variable_reservoir_cle_primaire(val_16);
// Calcul du diviseur en fonction du type de variable concernée :
switch(val_16)
{
case RESERVOIR_VARIABLE_NIVEAU:
default: { events.events[i].diviseur_gestion = 10; break; } // En x 100ms
}
break;
}
//--------------------------------------
case SOURCE_MESURE_BATTERIE:
{
val_16 = variable_batterie_cle_primaire(val_16);
// Calcul du diviseur en fonction du type de variable concernée :
switch(val_16)
{
case BATTERIE_VARIABLE_TEMPERATURE:
case BATTERIE_VARIABLE_SOH:
case BATTERIE_VARIABLE_SOC:
case BATTERIE_VARIABLE_AUTONOMIE:
case BATTERIE_VARIABLE_ENERGIE:
{ events.events[i].diviseur_gestion = 10; break; }
case BATTERIE_VARIABLE_TENSION:
case BATTERIE_VARIABLE_COURANT_DIFFERENTIEL:
case BATTERIE_VARIABLE_COURANT_CHARGE:
case BATTERIE_VARIABLE_COURANT_DECHARGE:
case BATTERIE_VARIABLE_PUISSANCE:
default: { events.events[i].diviseur_gestion = 0; break; } // En x 100ms
}
break;
}
//--------------------------------------
default: val_16 = 0; // Cas notament de Type_source=0 : conditions horaires seules
}
if (val_16 < 0) // Si on n'a pas trouvé de variable valide correspondant à l'ID reçu
{
events.events[i].condition_test.flag_validite = FALSE;
val_16 = 0;
}
events.events[i].condition_test.no_variable = val_16;
//---------------------------------------
// Test :
//---------------------------------------
events.events[i].condition_test.test = atoi(row[j ++]);
if ((events.events[i].condition_test.test < EVENTS_TYPE_TEST_STRICT_INFERIEUR) ||
(events.events[i].condition_test.test > EVENTS_TYPE_TEST_STRICT_SUPERIEUR)) events.events[i].condition_test.flag_validite = FALSE;
//---------------------------------------
// Seuil :
//---------------------------------------
events.events[i].condition_test.seuil = atof(row[j ++]);
//---------------------------------------
// Tempo :
//---------------------------------------
events.events[i].tempo = atoi(row[j ++]);
//---------------------------------------
// Conditions horaires :
//---------------------------------------
if (row[j][0] != 0) // Si le champ "Conditions_horaires" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
// Check du nombre de conditions trouvées :
if (k > MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT)
{
// Message d'erreur :
sprintf(tmp, "Le nombre de conditions horaires de l'évènement n° %i (Cle_primaire = %i) dans la Base de Données (TB_Events) est trop important (MAX = %i). Les conditions supérieures à %i sont ignorées.", i, events.events[i].cle_primaire, MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT, MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
k = MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT; // Limite du nombre de conditions au maxi autorisé
}
// Traitement des conditions :
char * ptr_jour, *ptr_heure, *ptr_minute;
for (m = 0; m < k; m ++) // Nb : on a déjà vérifié que k <= MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT
{
ptr_jour = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
ptr_heure = strtok (NULL, "/"); // Extraction du deuxieme segment après le premier '/'
ptr_minute = strtok (NULL, "/"); // Extraction du troisème segment après le second '/'
// Extraction des données de la condition et vérification de leurs validité :
if ((ptr_jour != NULL) && (ptr_heure != NULL) && (ptr_minute != NULL))
{
events.events[i].conditions_horaires.conditions[m].jour = atoi(ptr_jour);
events.events[i].conditions_horaires.conditions[m].heure = atoi(ptr_heure);
events.events[i].conditions_horaires.conditions[m].minute = atoi(ptr_minute);
if ((events.events[i].conditions_horaires.conditions[m].jour >= JOUR_SEMAINE_LUNDI) &&
(events.events[i].conditions_horaires.conditions[m].jour <= JOUR_SEMAINE_TOUS_LES_JOURS) &&
(events.events[i].conditions_horaires.conditions[m].heure <= (24 + HEURE_SPECIALE_DEBUT_NUIT)) &&
(events.events[i].conditions_horaires.conditions[m].minute <= 59) )
{
events.events[i].conditions_horaires.conditions[m].flag_validite = TRUE;
events.events[i].conditions_horaires.nb ++;
}
}
// Message d'info si la condition n'est pas valide :
if (!events.events[i].conditions_horaires.conditions[m].flag_validite)
{
sprintf(tmp, "La condition horaire #%i de l'évènement n° %i (Cle_primaire = %i) dans la Base de Données (TB_Events) a une structure invalide, elle est dévalidé.", m, i, events.events[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
}
else ; // Si le champ "Conditions_horaires" est vide : le champ 'events.events[i].nb_conditions_horaires' a été mis à 0 par défaut à l'init.
j ++;
//---------------------------------------
// Alarme_son :
//---------------------------------------
events.events[i].alarme_son = atoi(row[j ++]);
//---------------------------------------
// Alarme_led :
//---------------------------------------
events.events[i].alarme_led = atoi(row[j ++]);
//---------------------------------------
// Alarme_soutien :
//---------------------------------------
events.events[i].alarme_soutien = atoi(row[j ++]);
//---------------------------------------
// Alarme_source :
//---------------------------------------
events.events[i].alarme_source = atoi(row[j ++]);
//---------------------------------------
// Alarme_message :
//---------------------------------------
events.events[i].alarme_message = atoi(row[j ++]);
//---------------------------------------
// Alarme_sms :
//---------------------------------------
events.events[i].alarme_sms = atoi(row[j ++]);
//---------------------------------------
// Alarme_email :
//---------------------------------------
events.events[i].alarme_email = atoi(row[j ++]);
//---------------------------------------
// Action circuits :
//---------------------------------------
if (row[j][0] != 0) // Si le champ "Action_circuits" n'est pas vide :
{
k = 0;
ptr[k] = strtok (row[j],";"); // Extraction du premier segment avant le premier ';'
while ((ptr[k] != NULL) && (k < MAX_NOMBRE_CHAMPS_INTERNES))
{
k ++;
ptr[k] = strtok (NULL, ";"); // Extraction du segment suivant le prochain ';'
}
// Check du nombre d'actions trouvées :
if (k > MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT)
{
// Message d'erreur :
sprintf(tmp, "Le nombre d'action sur circuits de l'évènement n° %i (Cle_primaire = %i) dans la Base de Données (TB_Events) est trop important (MAX = %i). Les actions supérieures à %i sont ignorées.", i, events.events[i].cle_primaire, MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT, MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
k = MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT; // Limite du nombre d'actions au maxi autorisé
}
// Traitement des actions :
char * ptr_circuit, *ptr_action;
for (m = 0; m < k; m ++) // Nb : on a déjà vérifié que k <= MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT
{
ptr_circuit = strtok (ptr[m],"/"); // Extraction du premier segment avant le '/'
ptr_action = strtok (NULL, "/"); // Extraction du deuxieme segment, après le '/'
// Extraction des données de l'action et vérification de leurs validité :
if ((ptr_circuit != NULL) && (ptr_action != NULL))
{
val_16 = circuit_cle_primaire(atoi(ptr_circuit));
val_8 = atoi(ptr_action);
if ((val_16 >= 0) &&
(val_8 >= EVENTS_TYPE_ACTION_CIRCUIT_TOGGLE) &&
(val_8 <= MAX_CONSIGNE_CIRCUIT))
{
events.events[i].action_circuits.action[m].no_circuit = val_16; // Mémorisation du n° de circuit
events.events[i].action_circuits.action[m].action = val_8; // Mémorisation de l'action
events.events[i].action_circuits.action[m].flag_validite = TRUE;
events.events[i].action_circuits.nb ++;
}
}
// Message d'info si l'action n'est pas valide :
if (!events.events[i].action_circuits.action[m].flag_validite)
{
sprintf(tmp, "L'action #%i de l'évènement n° %i (Cle_primaire = %i) dans la Base de Données (TB_Events) a une structure invalide ; elle est dévalidé.", m, i, events.events[i].cle_primaire);
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
}
}
}
else ; // Si le champ "Conditions_horaires" est vide : le champ 'events.events[i].nb_conditions_horaires' a été mis à 0 par défaut à l'init.
j ++;
/*
// Debug :
printf("Evènement %i : ----------------------------------------------------------\n", i);
printf("Clé=%i, Condition_test_flag_validite=%i, Type source=%i, No source=%i, No_variable=%i, Test=%i, Seuil=%f, Tempo=%i, Alarme_son=%i, Alarme_led=%i, Alarme_soutien=%i, \
Alarme_source=%i, Alarme_SMS=%i, Alarme_email=%i, Alarme_message=%i \n",
events.events[i].cle_primaire, events.events[i].condition_test.flag_validite, events.events[i].condition_test.type_source, events.events[i].condition_test.no_source,
events.events[i].condition_test.no_variable, events.events[i].condition_test.test, events.events[i].condition_test.seuil, events.events[i].tempo, events.events[i].alarme_son,
events.events[i].alarme_led, events.events[i].alarme_soutien, events.events[i].alarme_source, events.events[i].alarme_sms, events.events[i].alarme_email,
events.events[i].alarme_message );
printf("Conditions horaires :");
for (j=0; j<MAX_NOMBRE_CONDITIONS_HORAIRES_PAR_EVENT; j++)
{
if (events.events[i].conditions_horaires.conditions[j].flag_validite) printf(" %i/%i/%i",
events.events[i].conditions_horaires.conditions[j].jour,
events.events[i].conditions_horaires.conditions[j].heure,
events.events[i].conditions_horaires.conditions[j].minute);
}
printf("\n");
printf("Actions circuits :");
for (j=0; j<MAX_NOMBRE_ACTION_CIRCUITS_PAR_EVENT; j++)
{
if (events.events[i].action_circuits.action[j].flag_validite) printf(" %i/%i",
events.events[i].action_circuits.action[j].no_circuit,
events.events[i].action_circuits.action[j].action);
}
printf("\n");
printf("-------------------------------------------------------------------------\n");
*/
i++;
}
mysql_free_result(result); //Libération du jeu de résultat
events.nb = i;
if (mode_init == BDD_MODE_INIT_RELOAD) events.sequenceur.etat = ETAT_SEQUENCEUR_EVENTS_INIT; // Principe de précaution, si un jour des init de données sont faites dans la phase d'init du séquenceur.
// ********************************************************************************************************************************************************
// MESURES
// ********************************************************************************************************************************************************
if (mode_init == BDD_MODE_INIT_RESET) // Important de ne le faire qu'au reset (et pas à chaque mise à jour de la config...!)
{
enregistrement_mesures(BDD_ENREGISTREMENT_MESURE_INIT);
}
// ********************************************************************************************************************************************************
// ARCHIVAGE
// ********************************************************************************************************************************************************
if (mode_init == BDD_MODE_INIT_RESET) // Important de ne le faire qu'au reset (et pas à chaque mise à jour de la config...!)
{
char str_date[MAX_LONGUEUR_DATE_COURANTE];
date_courante(str_date, DATE_COURANTE_SANS_MS, FORMAT_DATE_COURANTE_MYSQL);
archivage_bdd(str_date, BDD_TYPE_ARCHIVAGE_PURGE_SEULE); // On ne teste pas le retour car même s'il y a une erreur d'archivage, on démarre...
}
// ********************************************************************************************************************************************************
// INIT DES VARIABLES GLOBALES
// ********************************************************************************************************************************************************
if (mode_init == BDD_MODE_INIT_RESET)
{
bdd.compteur_synchro = PERIODE_CHECK_SYNCHRO_WEB;
bdd.compteur = PERIODE_MAJ_BDD;
bdd.compteur_enregistrement_mesures = PERIODE_ENREGISTREMENT_MESURES;
}
return(0);
}