// ********************************************************************************************************************************************************************************** // Fichier DEBUG.C // // Contient toutes les fonctions de debug et de logs. // ********************************************************************************************************************************************************************************** // Include : #include "main.h" // Prototypes : void clrscr(void); void affichage_debug_bus(uint8_t bus, char * sens, char *commande, uint8_t output); void affichage_debug(char *fichier, int ligne, char *message, char type); void affichage_debug_creation_ligne(char * chaine, char *fichier, int ligne, char *message, char type); int8_t init_affichage_debug(void); void append_chaine_fichier(char * chaine, char * fichier); char * nom_type_carte(uint8_t type); // Variables globales : struct Struct_debug debug; // Valeurs récupérées au démarrage dans la champs 'Mode_debug' de la table TB_Configuation dans la BDD. //********************************************************************************************************************************************************************************** // Fonction CLRSCR // // Efface l'écran en mode console //********************************************************************************************************************************************************************************** void clrscr(void) { printf("\033[H\033[2J"); //Clear Screen cf page http://pub.phyks.me/sdz/sdz/des-couleurs-dans-la-console-linux.html } // ***************************************************************************************************************************************************************** // Fonction : Créé une chaine formattée avec la commande reçue. L'affichage se fait soit sur rien selon la valeur 'output' (0=rien, 1=que écran, 2=que fichier, 3=les deux). // Reçoit : Le type de bus (cf 'debug.h' pour la liste), une chaine indiquant le sens de l'échange (par exemple : "Tx" ou "Tx-Down"), la commande et le type d'output. // Renvoit : Rien // ****************************************************************************************************************************************************************** void affichage_debug_bus(uint8_t bus, char * sens, char *commande, uint8_t output) { char chaine[MAX_LONGUEUR_LIGNE_FICHIER_LOG]; char date_formatee[MAX_LONGUEUR_DATE_COURANTE]; char nom_bus[30]; char prefixe_couleur[20] = ""; char suffixe_couleur[20] = ""; char prefixe_commande[10] = ""; if (output == 0) return; // Préparation de la chaine de date : date_courante(date_formatee, DATE_COURANTE_AVEC_MS, FORMAT_DATE_COURANTE_USER); // Préparation du nom de bus : switch(bus) { case TYPE_BUS_DEBUG_C_BUS : { strcpy(nom_bus, "C-Bus"); if (strstr(sens, "Up") != NULL) strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_CYAN); else strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_BLUE); if (strstr(sens, "Rx") != NULL) strcpy(prefixe_commande, "<\t\t"); else strcpy(prefixe_commande, ">\t"); break; } case TYPE_BUS_DEBUG_M_BUS : { strcpy(nom_bus, "M-Bus"); if (strstr(sens, "Rx") != NULL) { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_CYAN); strcpy(prefixe_commande, "<\t\t"); } else { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_PURPLE); strcpy(prefixe_commande, ">\t"); } strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } default : { strcpy(nom_bus, "Unknown"); strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_RED); strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } } // Génération de la chaine complète pour l'écran : if ((output == AFFICHAGE_DEBUG_ECRAN) || (output == AFFICHAGE_DEBUG_ECRAN_ET_FICHIER)) printf("[%s] [%5s] %s %s%s %s \n", date_formatee, nom_bus, prefixe_couleur, prefixe_commande, commande, suffixe_couleur); // Génération de la chaine complète pour le fichier : if ((output == AFFICHAGE_DEBUG_FICHIER) || (output == AFFICHAGE_DEBUG_ECRAN_ET_FICHIER)) { sprintf(chaine, "[%s] [%5s] %s%s", date_formatee, nom_bus, prefixe_commande, commande); append_chaine_fichier(chaine, NOM_FICHIER_DEBUG_BUS); } } // ***************************************************************************************************************************************************************** // Fonction : Envoi le message de debug reçu vers l'écran et/ou le fichier de log après l'avoir formaté et horodaté. // Reçoit : Le fichier d'origine de la demande, la ligne où la demande a été faite dans ce fichier, le contenu du message à afficher et le type (donc sa couleur à l'écran). // Renvoit : Rien // ****************************************************************************************************************************************************************** void affichage_debug(char *fichier, int ligne, char *message, char type) { char chaine[MAX_LONGUEUR_LIGNE_FICHIER_LOG]; if (debug.mode == AFFICHAGE_DEBUG_AUCUN) return; // Affichage écran : if ((debug.mode == AFFICHAGE_DEBUG_ECRAN) || (debug.mode == AFFICHAGE_DEBUG_ECRAN_ET_FICHIER)) { affichage_debug_creation_ligne(chaine, fichier, ligne, message, type); printf("%s \n", chaine); } // Affichage fichier : if ((debug.mode == AFFICHAGE_DEBUG_ECRAN_ET_FICHIER) || (debug.mode == AFFICHAGE_DEBUG_FICHIER)) { affichage_debug_creation_ligne(chaine, fichier, ligne, message, TYPE_MESSAGE_DEBUG_FICHIER_SEULEMENT); append_chaine_fichier(chaine, debug.nom_fichier); } } // ***************************************************************************************************************************************************************** // Fonction : Renvoit la ligne de debug formatée sous la forme '[JJ/MM/AAAA HH:mm:ss.mmm][ : ] '. De plus, la partie // du est colorée en fonction du 'type' de message si l'affichage est destiné à l'écran. // Reçoit : Le pointeur sur la chaine à créer, le fichier d'origine de la demande, la ligne dans el fichier où la demande a été faite, le message et le type de message. // Renvoit : Rien // ****************************************************************************************************************************************************************** void affichage_debug_creation_ligne(char * chaine, char *fichier, int ligne, char *message, char type) { char date_formatee[MAX_LONGUEUR_DATE_COURANTE]; char *fichier_court = ""; char prefixe_couleur[20]; char suffixe_couleur[20]; // Préparation de la chaine de date : date_courante(date_formatee, DATE_COURANTE_AVEC_MS, FORMAT_DATE_COURANTE_USER); // Calcul du préfixe et du suffixe de couleur à utiliser pour l'écran en fonction du type de message : switch(type) { case TYPE_MESSAGE_DEBUG_OK: { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_GREEN); strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } case TYPE_MESSAGE_DEBUG_WARNING: { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_YELLOW); strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } case TYPE_MESSAGE_DEBUG_ERREUR: { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_RED); strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } case TYPE_MESSAGE_DEBUG_DEBUG: { strcpy(prefixe_couleur, DEBUG_TEXT_COLOR_PURPLE); strcpy(suffixe_couleur, DEBUG_TEXT_COLOR_RESET); break; } case TYPE_MESSAGE_DEBUG_PAR_DEFAUT: case TYPE_MESSAGE_DEBUG_FICHIER_SEULEMENT: default: { strcpy(prefixe_couleur, ""); strcpy(suffixe_couleur, ""); break; } // Couleur de police par défaut } if (fichier[0] != 0) // Si le nom de fichier est vide, on n'affichera pas l'entête de ligne... { // Préparation du nom de fichier : fichier_court = strrchr (fichier, '/'); // Positionne le pointeur 'fichier_court' sur la première occurence de '\' en partant de la fin de la chaine 'fichier'. if (fichier_court == NULL) fichier_court = fichier; else fichier_court ++; // Le '+1' permet d'éliminer le '/' de début de chaine... } // Génération de la chaine complète : sprintf(chaine, "[%s] [%15s : %4i] %s %s %s", date_formatee, fichier_court, ligne, prefixe_couleur, message, suffixe_couleur); } /********************************************************************************************************************************************************************************** Fonction INIT_AFFICHAGE_DEBUG En fonction de la l'état de la variable "debug", affiche ou non les messages qui lui sont adressés **********************************************************************************************************************************************************************************/ int8_t init_affichage_debug(void) { char date_formatee[MAX_LONGUEUR_DATE_COURANTE]; uint32_t no_ligne; uint32_t nb_lignes; FILE * ptr_fichier_tmp; char ligne[MAX_LONGUEUR_LIGNE_FICHIER_LOG]; switch (debug.mode) // NB : la valeur de 'debug' est évaluée à l'initialisation en fonction du champs 'Mode_debug' de TB_Configuration. { // ****************************************************************************************************** case AFFICHAGE_DEBUG_AUCUN: // Ni sortie sur écran ni sortie sur fichier. { break; } // ****************************************************************************************************** case AFFICHAGE_DEBUG_ECRAN: // Sortie sur écran mais pas sur fichier. case AFFICHAGE_DEBUG_ECRAN_ET_FICHIER: // Sortie sur écran et sur fichier : { clrscr(); // Effacement de l'écran printf("\n----------------- Début d'initialisation --------------------\n\n"); if (debug.mode == AFFICHAGE_DEBUG_ECRAN) break; // Dans ce cas, on n'effectue pas la partie Fichier ci-dessous... } // ****************************************************************************************************** case AFFICHAGE_DEBUG_FICHIER: // Sortie sur fichier mais pas sur écran : { // Purge du fichier : debug.ptr_fichier = fopen(debug.nom_fichier, "a+"); // Ouverture fichier de log en mode "append et lecture" qui permet, s'il n'existe pas, qu'il soit créé (sinon, avec "r", il n'est pas créé tout seul) if (debug.ptr_fichier == NULL) { printf("Ouverture du fichier %s impossible. L'initialisation est arrêtée !\n", debug.nom_fichier); exit(0); // NB : le 'return(-1)' ne semble pas fonctionner. Comme on est sur des cas de démarrage, je n'ai pas cherché plus loin... break; } // Recherche du nombre de lignes du fichier : nb_lignes = 0; if (debug.ptr_fichier != NULL) { rewind(debug.ptr_fichier); // Retour au début du fichier de logs puisque l'ouverture en 'append' nous a amené à la fin... while (fgets(ligne, MAX_LONGUEUR_LIGNE_FICHIER_LOG, debug.ptr_fichier) != NULL) nb_lignes ++; } // Si NULL, on considère que le fichier est nouveau et le test suivant sera négatif (nb_lignes = 0)... // Vérification si besoin de purger le fichier : if (nb_lignes > MAX_NOMBRE_LIGNES_FICHIER_LOG) { no_ligne = 0; rewind(debug.ptr_fichier); // Retour au début du fichier de logs puisque le comptage nous a amené à la fin... // Lecture du fichier jusqu'à MAX_NOMBRE_LIGNES_FICHIER_LOG avant la fin : while (fgets(ligne, MAX_LONGUEUR_LIGNE_FICHIER_LOG, debug.ptr_fichier) != NULL) // Lecture d'une ligne { no_ligne ++; if (no_ligne == (nb_lignes - MAX_NOMBRE_LIGNES_FICHIER_LOG)) break; } ptr_fichier_tmp = fopen(NOM_FICHIER_DEBUG_TMP, "w"); // Ouverture fichier de log temporaire en mode "overwrite"... if (ptr_fichier_tmp != NULL) { // Réécriture complète du fichier en ne gardant que le nombre de lignes souhaité (en supprimant les premières) : date_courante(date_formatee, DATE_COURANTE_SANS_MS, FORMAT_DATE_COURANTE_USER); fprintf(ptr_fichier_tmp, "#### Fichier de log tronqué le %s (nombre de lignes ramené de %i à %i) #### \n\n", date_formatee, nb_lignes, MAX_NOMBRE_LIGNES_FICHIER_LOG); // Lecture de la fin du fichier : while (fgets(ligne, MAX_LONGUEUR_LIGNE_FICHIER_LOG, debug.ptr_fichier) != NULL) // Lecture d'une ligne { fputs(ligne, ptr_fichier_tmp); } fclose(ptr_fichier_tmp); fclose(debug.ptr_fichier); // Copie du fichier temporaire dans le fichier de logs : debug.ptr_fichier = fopen(debug.nom_fichier, "w"); // Ouverture fichier de log en mode "overwrite"... ptr_fichier_tmp = fopen(NOM_FICHIER_DEBUG_TMP, "r"); // Ouverture fichier de log temporaire en mode "read"... while (fgets(ligne, MAX_LONGUEUR_LIGNE_FICHIER_LOG, ptr_fichier_tmp) != NULL) // Lecture d'une ligne { fputs(ligne, debug.ptr_fichier); // Copie de la ligne } fclose(ptr_fichier_tmp); // Fermeture du fichier temporaire de logs fclose(debug.ptr_fichier); // Fermeture du fichier de logs } else { // Message d'erreur 'brut' car le mode débug n'est pas encore activé : printf("\033[31m"); // Police en rouge... printf("ERREUR d'ouverture du fichier temporaire [%s]....!", NOM_FICHIER_DEBUG_TMP); printf("\033[0m \n"); // Police par défaut et retour à la ligne... return(-1); } } else fclose(debug.ptr_fichier); // Ecriture de la ligne d'inititalisation : debug.ptr_fichier = fopen(debug.nom_fichier, "a"); // Ouverture fichier de log en mode "append"... if (debug.ptr_fichier == NULL) { // Message d'erreur 'brut' car le mode débug n'est pas encore activé : printf("\033[31m"); // Police en rouge... printf("ERREUR d'ouverture du fichier de Logs [%s]....!", debug.nom_fichier); printf("\033[0m \n"); // Police par défaut et retour à la ligne... return(-1); } fprintf(debug.ptr_fichier, "\n----------------- Début d'initialisation --------------------\n\n") ; fclose(debug.ptr_fichier); if (nb_lignes > MAX_NOMBRE_LIGNES_FICHIER_LOG) sprintf(ligne, "Purge du fichier de log effectuée. Fichier ramené de %i à %i lignes", nb_lignes, MAX_NOMBRE_LIGNES_FICHIER_LOG); else sprintf(ligne, "Fichier de log ouvert [%s]. Contient actuellement %i lignes (max = %i)", debug.nom_fichier, nb_lignes, MAX_NOMBRE_LIGNES_FICHIER_LOG); affichage_debug(__FILE__, __LINE__, ligne, TYPE_MESSAGE_DEBUG_OK); break; } } // Vidage du fichier de log de bus : ptr_fichier_tmp = fopen(NOM_FICHIER_DEBUG_BUS, "w"); // Le fichier est juste ouvert en écriture (donc il est créé s'il n'existe pas et il est vidé s'il existe) if (ptr_fichier_tmp != NULL) fclose(ptr_fichier_tmp); // S'il existait, on le referme immédiatement. return(0); } // ***************************************************************************************************************************************************************** // Fonction : Ouvre le fichier dont le nom est passé en paramètre, ajoute à la fin la chaine reçue et referme le fichier. // Reçoit : Le pointeur sur la chaine à ajouter et le nom du fichier de log. // Renvoit : Rien // ****************************************************************************************************************************************************************** void append_chaine_fichier(char * chaine, char * fichier) { FILE * ptr_fichier; ptr_fichier = fopen(fichier, "a"); // Ouverture fichier de log en mode "append"... if (ptr_fichier != NULL) { fprintf(ptr_fichier, "%s \n", chaine); fclose(ptr_fichier); } } // ***************************************************************************************************************************************************************** // Fonction : Retourne sous forme de chaine le type de carte passé en paramètre // Reçoit : Le type de carte (sous forme d'entier, selon les valeurs dans 'systeme.c') // Renvoit : Le pointeur sur la chaine de nom // ****************************************************************************************************************************************************************** char * nom_type_carte(uint8_t type) { switch(type) { case TYPE_CARTE_SHIPBASE : { return("ShipBase"); break; } case TYPE_CARTE_SP812 : { return("ShipPower812"); break; } case TYPE_CARTE_SBS : { return("ShipBS"); break; } case TYPE_CARTE_SP4AC : { return("ShipPower4AC"); break; } case TYPE_CARTE_SP8DC : { return("ShipPower8DC"); break; } default : { return("Inconnu..."); break; } } }